163 lines
3.7 KiB
C
163 lines
3.7 KiB
C
|
#include "render.h"
|
||
|
#include "decoder.h"
|
||
|
#include "display.h"
|
||
|
#include "fonts.h"
|
||
|
#include "smallfonts.h"
|
||
|
|
||
|
#include <string.h>
|
||
|
|
||
|
/* Global Variables */
|
||
|
static const struct FONT_DEF *font = NULL;
|
||
|
|
||
|
static struct EXTFONT efont;
|
||
|
|
||
|
static uint8_t color_bg = 0xff; /* background color */
|
||
|
static uint8_t color_fg = 0x00; /* foreground color */
|
||
|
|
||
|
/* Exported Functions */
|
||
|
void rad1o_setTextColor(uint8_t bg, uint8_t fg)
|
||
|
{
|
||
|
color_bg = bg;
|
||
|
color_fg = fg;
|
||
|
}
|
||
|
|
||
|
void rad1o_setIntFont(const struct FONT_DEF *newfont)
|
||
|
{
|
||
|
memcpy(&efont.def, newfont, sizeof(struct FONT_DEF));
|
||
|
efont.type = FONT_INTERNAL;
|
||
|
font = &efont.def;
|
||
|
}
|
||
|
|
||
|
int rad1o_getFontHeight(void)
|
||
|
{
|
||
|
if (font)
|
||
|
return font->u8Height;
|
||
|
return 8; // XXX: Should be done right.
|
||
|
}
|
||
|
|
||
|
static int _getIndex(int c)
|
||
|
{
|
||
|
#define ERRCHR (font->u8FirstChar + 1)
|
||
|
/* Does this font provide this character? */
|
||
|
if (c < font->u8FirstChar)
|
||
|
c = ERRCHR;
|
||
|
if (c > font->u8LastChar && efont.type != FONT_EXTERNAL &&
|
||
|
font->charExtra == NULL)
|
||
|
c = ERRCHR;
|
||
|
|
||
|
if (c > font->u8LastChar &&
|
||
|
(efont.type == FONT_EXTERNAL || font->charExtra != NULL)) {
|
||
|
int cc = 0;
|
||
|
while (font->charExtra[cc] < c)
|
||
|
cc++;
|
||
|
if (font->charExtra[cc] > c)
|
||
|
c = ERRCHR;
|
||
|
else
|
||
|
c = font->u8LastChar + cc + 1;
|
||
|
};
|
||
|
c -= font->u8FirstChar;
|
||
|
return c;
|
||
|
}
|
||
|
|
||
|
int rad1o_DoChar(int sx, int sy, int c)
|
||
|
{
|
||
|
if (font == NULL) {
|
||
|
font = &Font_7x8;
|
||
|
};
|
||
|
|
||
|
/* how many bytes is it high? */
|
||
|
char height = (font->u8Height - 1) / 8 + 1;
|
||
|
char hoff = (8 - (font->u8Height % 8)) % 8;
|
||
|
|
||
|
const uint8_t *data;
|
||
|
int width, preblank = 0, postblank = 0;
|
||
|
do { /* Get Character data */
|
||
|
/* Get intex into character list */
|
||
|
c = _getIndex(c);
|
||
|
|
||
|
/* starting offset into character source data */
|
||
|
int toff = 0;
|
||
|
|
||
|
if (font->u8Width == 0) {
|
||
|
for (int y = 0; y < c; y++)
|
||
|
toff += font->charInfo[y].widthBits;
|
||
|
width = font->charInfo[c].widthBits;
|
||
|
|
||
|
toff *= height;
|
||
|
data = &font->au8FontTable[toff];
|
||
|
postblank = 1;
|
||
|
} else if (font->u8Width == 1) { // NEW CODE
|
||
|
// Find offset and length for our character
|
||
|
for (int y = 0; y < c; y++)
|
||
|
toff += font->charInfo[y].widthBits;
|
||
|
width = font->charInfo[c].widthBits;
|
||
|
if (font->au8FontTable[toff] >> 4 ==
|
||
|
15) { // It's a raw character!
|
||
|
preblank = font->au8FontTable[toff + 1];
|
||
|
postblank = font->au8FontTable[toff + 2];
|
||
|
data = &font->au8FontTable[toff + 3];
|
||
|
width = (width - 3 / height);
|
||
|
} else {
|
||
|
data = rad1o_pk_decode(
|
||
|
&font->au8FontTable[toff], &width);
|
||
|
}
|
||
|
} else {
|
||
|
toff = (c)*font->u8Width * 1;
|
||
|
width = font->u8Width;
|
||
|
data = &font->au8FontTable[toff];
|
||
|
};
|
||
|
|
||
|
} while (0);
|
||
|
|
||
|
#define xy_(x, y) \
|
||
|
((x < 0 || y < 0 || x >= RESX || y >= RESY) ? 0 : (y)*RESX + (x))
|
||
|
#define gPx(x, y) (data[x * height + (height - y / 8 - 1)] & (1 << (y % 8)))
|
||
|
|
||
|
int x = 0;
|
||
|
|
||
|
/* Fonts may not be byte-aligned, shift up so the top matches */
|
||
|
sy -= hoff;
|
||
|
|
||
|
sx += preblank;
|
||
|
|
||
|
uint8_t *lcdBuffer = rad1o_lcdGetBuffer();
|
||
|
/* per line */
|
||
|
for (int y = hoff; y < height * 8; y++) {
|
||
|
if (sy + y >= RESY)
|
||
|
continue;
|
||
|
|
||
|
/* Optional: empty space to the left */
|
||
|
for (int b = 1; b <= preblank; b++) {
|
||
|
if (sx >= RESX)
|
||
|
continue;
|
||
|
lcdBuffer[xy_(sx - b, sy + y)] = color_bg;
|
||
|
};
|
||
|
/* Render character */
|
||
|
for (x = 0; x < width; x++) {
|
||
|
if (sx + x >= RESX)
|
||
|
continue;
|
||
|
if (gPx(x, y)) {
|
||
|
lcdBuffer[xy_(sx + x, sy + y)] = color_fg;
|
||
|
} else {
|
||
|
lcdBuffer[xy_(sx + x, sy + y)] = color_bg;
|
||
|
};
|
||
|
};
|
||
|
/* Optional: empty space to the right */
|
||
|
for (int m = 0; m < postblank; m++) {
|
||
|
if (sx + x + m >= RESX)
|
||
|
continue;
|
||
|
lcdBuffer[xy_(sx + x + m, sy + y)] = color_bg;
|
||
|
};
|
||
|
};
|
||
|
return sx + (width + postblank);
|
||
|
}
|
||
|
|
||
|
int rad1o_DoString(int sx, int sy, const char *s)
|
||
|
{
|
||
|
const char *c;
|
||
|
for (c = s; *c != 0; c++) {
|
||
|
sx = rad1o_DoChar(sx, sy, *c);
|
||
|
};
|
||
|
return sx;
|
||
|
}
|