TTF parser and rasterizer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

207 lines
3.3 KiB

#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);
}