Files
LoraSA/lib/charts/Font.cpp

148 lines
3.6 KiB
C++

#include "charts.h"
extern const uint8_t ArialMT_Plain_10[]; // borrowed from OLEDDisplayFonts.h
uint8_t *ArialMT_Plain_10_Vert = NULL;
uint64_t _horz_line(const uint8_t *font, size_t chr_off, size_t height, size_t bytes,
size_t ln)
{
size_t raster_height = (height + 7) / 8;
uint8_t b = 1 << (ln & 7);
uint64_t ret = 0;
uint64_t mask = 1;
for (size_t y = ln / 8; y < bytes; y += raster_height, mask <<= 1)
{
if (font[chr_off + y] & b)
{
ret |= mask;
}
}
return ret;
}
uint64_t _flip(uint64_t v, size_t width)
{
for (uint64_t b = 1, e = 1 << (width - 1); b < e; b <<= 1, e >>= 1)
{
if (!!(v & b) != !!(v & e))
{
v = v ^ (b | e);
}
}
return v;
}
uint8_t *_rot(const uint8_t *font)
{
size_t sz = 10000;
size_t p = 0;
uint8_t *vert = (uint8_t *)malloc(sz);
size_t height = font[1];
vert[0] = (uint8_t)height; // height -> width
vert[1] = font[0]; // width -> height
vert[2] = font[2]; // first char
size_t chars = font[3]; // char count
vert[3] = (uint8_t)chars;
size_t map_off = chars * 4 + 4;
for (int i = 0; i < chars; i++)
{
uint32_t v = ((uint32_t *)font)[i + 1];
size_t chr_off = ((v & 0xff) << 8) | ((v >> 8) & 0xff);
if (chr_off != 0xffff)
{
size_t bs = (v >> 16) & 0xff;
size_t width = (v >> 24) & 0xff;
size_t raster_height =
(width + 7) / 8; // how many bytes needed to store one vertical line
size_t bytes = height * raster_height;
v = (v & 0xff000000L) | (bytes << 16) | ((p >> 8) & 0xff) | ((p & 0xff) << 8);
chr_off += map_off;
if (map_off + p + bytes > sz)
{
uint8_t *vv = vert;
sz += 1000;
vert = (uint8_t *)malloc(sz);
memcpy(vert, vv, sz - 1000);
free(vv);
}
for (size_t j = 0; j < height; j++)
{
uint64_t ln = _flip(_horz_line(font, chr_off, height, bs, j), width);
for (size_t k = 0; k < raster_height; k++, p++, ln >>= 8)
{
vert[map_off + p] = (uint8_t)ln;
}
}
}
((uint32_t *)vert)[i + 1] = v;
}
if (map_off + p < sz)
{
uint8_t *vv = vert;
sz = map_off + p;
vert = (uint8_t *)malloc(sz);
memcpy(vert, vv, sz);
free(vv);
}
return vert;
}
void init_fonts()
{
if (ArialMT_Plain_10_Vert != NULL)
{
free(ArialMT_Plain_10_Vert);
ArialMT_Plain_10_Vert = NULL;
}
ArialMT_Plain_10_Vert = _rot(ArialMT_Plain_10);
}
void drawVerticalString(Display_t &display, const uint8_t *v_font, int x, int y, String s)
{
if (v_font == NULL)
return;
size_t w = v_font[0];
char init_ch = v_font[2];
size_t chars = v_font[3];
const uint8_t *v_chars = v_font + (chars + 1) * 4;
for (int i = s.length(); i-- > 0;)
{
char c = s.charAt(i);
if (c < init_ch)
continue;
c -= init_ch;
if (c >= chars)
continue;
size_t map_off = (c + 1) * 4;
size_t chr_off = (((uint16_t)v_font[map_off]) << 8) | (v_font[map_off + 1]);
size_t bs = v_font[map_off + 2];
size_t h = v_font[map_off + 3];
if (chr_off == 0xffff)
{
y += h;
continue;
}
display.drawFastImage(x, y, w, h, v_chars + chr_off);
y += h;
}
}