|
|
|
#include <math.h>
|
|
|
|
#include <wchar.h> // wchar_t, wcslen
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
|
|
|
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
|
|
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
|
|
|
|
|
|
#define MAX_INTERSECTIONS 16
|
|
|
|
#define F32EPS 1e-5f
|
|
|
|
#define MAX_CONTOURS 256
|
|
|
|
|
|
|
|
#define TTF_ENGINE_STACK 4096
|
|
|
|
|
|
|
|
#define ASSERT(expr) if (!(expr)) { fprintf(stderr, "[ASSERT] Assertion fail %s:%d\n", __FILE__, __LINE__); abort(); }
|
|
|
|
|
|
|
|
struct v2 {
|
|
|
|
int x;
|
|
|
|
int y;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct v2u32 {
|
|
|
|
u32 x;
|
|
|
|
u32 y;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct v2f {
|
|
|
|
f32 x;
|
|
|
|
f32 y;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct line {
|
|
|
|
struct v2f a;
|
|
|
|
struct v2f b;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct line_contour {
|
|
|
|
int ncontours;
|
|
|
|
int from[MAX_CONTOURS];
|
|
|
|
struct line *data;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct intersection {
|
|
|
|
f32 x;
|
|
|
|
int dir;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum rgb_channel {
|
|
|
|
RED = 0x000000FF,
|
|
|
|
GREEN = 0x0000FF00,
|
|
|
|
BLUE = 0x00FF0000,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct font_buffer {
|
|
|
|
u8 *data;
|
|
|
|
u64 offset;
|
|
|
|
u64 size;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct font_directory {
|
|
|
|
u32 cmap_offset;
|
|
|
|
u32 head_offset;
|
|
|
|
u32 hhea_offset;
|
|
|
|
u32 loca_offset;
|
|
|
|
u32 glyf_offset;
|
|
|
|
u32 hmtx_offset;
|
|
|
|
u32 maxp_offset;
|
|
|
|
u32 post_offset;
|
|
|
|
|
|
|
|
u32 cvt_offset;
|
|
|
|
u32 cvt_size;
|
|
|
|
|
|
|
|
u32 prep_offset;
|
|
|
|
u32 prep_size;
|
|
|
|
|
|
|
|
u32 fpgm_offset;
|
|
|
|
u32 fpgm_size;
|
|
|
|
};
|
|
|
|
|
|
|
|
union glyph_flag {
|
|
|
|
struct {
|
|
|
|
u8 on_curve : 1;
|
|
|
|
u8 x_short : 1;
|
|
|
|
u8 y_short : 1;
|
|
|
|
u8 repeat : 1;
|
|
|
|
u8 x_short_pos : 1;
|
|
|
|
u8 y_short_pos : 1;
|
|
|
|
u8 reserved1 : 1;
|
|
|
|
u8 reserved2 : 1;
|
|
|
|
};
|
|
|
|
u8 flag;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum compund_glyph_flag {
|
|
|
|
ARG_1_AND_2_ARE_WORDS = 0x1,
|
|
|
|
ARGS_ARE_XY_VALUES = 0x2,
|
|
|
|
ROUND_XY_TO_GRID = 0x4,
|
|
|
|
WE_HAVE_A_SCALE = 0x8,
|
|
|
|
|
|
|
|
MORE_COMPONENTS = 0x20,
|
|
|
|
WE_HAVE_AN_X_AND_Y_SCALE = 0x40,
|
|
|
|
WE_HAVE_A_TWO_BY_TWO = 0x80,
|
|
|
|
WE_HAVE_INSTRUCTIONS = 0x100,
|
|
|
|
USE_MY_METRICS = 0x200,
|
|
|
|
OVERLAP_COMPOUND = 0x400
|
|
|
|
};
|
|
|
|
|
|
|
|
struct maxp_table {
|
|
|
|
u16 max_component_points;
|
|
|
|
u16 max_component_contours;
|
|
|
|
u16 max_storage;
|
|
|
|
u16 max_fdefs;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct head_table {
|
|
|
|
int itl_format;
|
|
|
|
int units_per_em;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct hhea_table {
|
|
|
|
int ascent;
|
|
|
|
int descent;
|
|
|
|
int line_gap;
|
|
|
|
int max_advance;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct glyph_point {
|
|
|
|
s16 x;
|
|
|
|
s16 y;
|
|
|
|
bool on_curve;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct glyph_segment {
|
|
|
|
bool is_curve;
|
|
|
|
struct v2f p0;
|
|
|
|
struct v2f p1;
|
|
|
|
struct v2f p2;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct glyph {
|
|
|
|
s16 xmin, ymin;
|
|
|
|
s16 xmax, ymax;
|
|
|
|
|
|
|
|
s32 baseline;
|
|
|
|
u16 advance;
|
|
|
|
s16 lsb;
|
|
|
|
|
|
|
|
u16 ncontours;
|
|
|
|
u16 *end_pts_of_contours;
|
|
|
|
struct glyph_point *points;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct ttf_font {
|
|
|
|
struct font_buffer file;
|
|
|
|
|
|
|
|
struct maxp_table maxp;
|
|
|
|
struct head_table head;
|
|
|
|
struct hhea_table hhea;
|
|
|
|
|
|
|
|
s16 *cvt;
|
|
|
|
int cmap_format;
|
|
|
|
int is_monospace;
|
|
|
|
|
|
|
|
struct font_directory dir;
|
|
|
|
struct ttf_function *functions;
|
|
|
|
|
|
|
|
u32 *storage;
|
|
|
|
|
|
|
|
char *name;
|
|
|
|
};
|
|
|
|
|
|
|
|
static int
|
|
|
|
clamp_u32(u32 val, u32 cap)
|
|
|
|
{
|
|
|
|
u32 result = val;
|
|
|
|
if (val > cap) result = cap;
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static f32
|
|
|
|
abs_f32(f32 v)
|
|
|
|
{
|
|
|
|
f32 result = (v > 0 ? v : -v);
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
round_f32(f32 v)
|
|
|
|
{
|
|
|
|
int towards_zero = (int) v;
|
|
|
|
f32 diff = abs_f32(v - towards_zero);
|
|
|
|
|
|
|
|
if (diff >= 0.5f) {
|
|
|
|
return(v > 0 ? towards_zero + 1 : towards_zero - 1);
|
|
|
|
} else {
|
|
|
|
return(towards_zero);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
ceil_f32(f32 v)
|
|
|
|
{
|
|
|
|
int trunc = v;
|
|
|
|
if (v - trunc < F32EPS) {
|
|
|
|
return(trunc);
|
|
|
|
}
|
|
|
|
return(trunc + 1);
|
|
|
|
}
|