107 lines
2.5 KiB
C++
107 lines
2.5 KiB
C++
|
#include "hershey_fonts.hpp"
|
||
|
#include <cmath>
|
||
|
|
||
|
namespace hershey {
|
||
|
std::map<std::string, const font_t*> fonts = {
|
||
|
{ "sans", &futural },
|
||
|
//{ "sans_bold", &futuram },
|
||
|
{ "gothic", &gothgbt },
|
||
|
//{ "cursive_bold", &scriptc },
|
||
|
{ "cursive", &scripts },
|
||
|
{ "serif_italic", ×i },
|
||
|
{ "serif", ×r },
|
||
|
//{ "serif_bold", ×rb }
|
||
|
};
|
||
|
|
||
|
inline float deg2rad(float degrees) {
|
||
|
return (degrees * M_PI) / 180.0f;
|
||
|
}
|
||
|
|
||
|
const font_glyph_t* glyph_data(const font_t* font, unsigned char c) {
|
||
|
if(c < 32 || c > 127) {
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
return &font->chars[c - 32];
|
||
|
}
|
||
|
|
||
|
int32_t measure_glyph(const font_t* font, unsigned char c, float s) {
|
||
|
const font_glyph_t *gd = glyph_data(font, c);
|
||
|
|
||
|
// if glyph data not found (id too great) then skip
|
||
|
if(!gd) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return gd->width * s;
|
||
|
}
|
||
|
|
||
|
int32_t measure_text(const font_t* font, std::string message, float s) {
|
||
|
int32_t width = 0;
|
||
|
for(auto &c : message) {
|
||
|
width += measure_glyph(font, c, s);
|
||
|
}
|
||
|
return width;
|
||
|
}
|
||
|
|
||
|
int32_t glyph(const font_t* font, line_func line, unsigned char c, int32_t x, int32_t y, float s, float a) {
|
||
|
const font_glyph_t *gd = glyph_data(font, c);
|
||
|
|
||
|
// if glyph data not found (id too great) then skip
|
||
|
if(!gd) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
a = deg2rad(a);
|
||
|
float as = sin(a);
|
||
|
float ac = cos(a);
|
||
|
|
||
|
const int8_t *pv = gd->vertices;
|
||
|
int8_t cx = (*pv++) * s;
|
||
|
int8_t cy = (*pv++) * s;
|
||
|
bool pen_down = true;
|
||
|
|
||
|
for(uint32_t i = 1; i < gd->vertex_count; i++) {
|
||
|
if(pv[0] == -128 && pv[1] == -128) {
|
||
|
pen_down = false;
|
||
|
pv += 2;
|
||
|
}else{
|
||
|
int8_t nx = (*pv++) * s;
|
||
|
int8_t ny = (*pv++) * s;
|
||
|
|
||
|
int rcx = (cx * ac - cy * as) + 0.5f;
|
||
|
int rcy = (cx * as + cy * ac) + 0.5f;
|
||
|
|
||
|
int rnx = (nx * ac - ny * as) + 0.5f;
|
||
|
int rny = (nx * as + ny * ac) + 0.5f;
|
||
|
|
||
|
if(pen_down) {
|
||
|
line(rcx + x, rcy + y, rnx + x, rny + y);
|
||
|
}
|
||
|
|
||
|
cx = nx;
|
||
|
cy = ny;
|
||
|
pen_down = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return gd->width * s;
|
||
|
}
|
||
|
|
||
|
void text(const font_t* font, line_func line, std::string message, int32_t x, int32_t y, float s, float a) {
|
||
|
int32_t cx = x;
|
||
|
int32_t cy = y;
|
||
|
|
||
|
int32_t ox = 0;
|
||
|
|
||
|
float as = sin(deg2rad(a));
|
||
|
float ac = cos(deg2rad(a));
|
||
|
|
||
|
for(auto &c : message) {
|
||
|
int rcx = (ox * ac) + 0.5f;
|
||
|
int rcy = (ox * as) + 0.5f;
|
||
|
|
||
|
ox += glyph(font, line, c, cx + rcx, cy + rcy, s, a);
|
||
|
}
|
||
|
}
|
||
|
}
|