Browse Source

FIXED THE BASELINE ISSUSES!!!!!!!!!!

master
A.Olokhtonov 3 years ago
parent
commit
3a5d8848ba
  1. 184
      main.c
  2. 1053
      ttf2.c
  3. 355
      ttf_engine.c

184
main.c

@ -22,28 +22,14 @@
#define ASSERT(expr) if (!expr) { fprintf(stderr, "[ASSERT] Assertion fail %s:%d\n", __FILE__, __LINE__); abort(); } #define ASSERT(expr) if (!expr) { fprintf(stderr, "[ASSERT] Assertion fail %s:%d\n", __FILE__, __LINE__); abort(); }
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#define MAX_INTERSECTIONS 16 #define MAX_INTERSECTIONS 16
#define F32EPS 1e-5f #define F32EPS 1e-5f
#define MAX_CONTOURS 16 #define MAX_CONTOURS 256
#define DEBUG_SHOW_POINTS 0
/* #define TTF_ENGINE_STACK 4096
int total_hits = 0;
for (int yy = 1; yy <= oversample_y; ++yy) {
for (int xx = 1; xx <= oversample_x; ++xx) {
u32 ncross = intersect_glyph(g, scale, x + norm_x * xx , y + norm_y * yy, width);
if (ncross) {
++total_hits;
}
}
}
if (total_hits) {
u32 brightness = (256 - total_hits * 256 / (oversample_x * oversample_y)) * 0.99f;
pixels[(y - baseline_correction) * width + x] = 0xFF000000 | brightness << 16 | brightness << 8 | brightness;
}
*/
typedef int64_t s64; typedef int64_t s64;
typedef int32_t s32; typedef int32_t s32;
@ -66,6 +52,11 @@ struct v2 {
int y; int y;
}; };
struct v2u32 {
u32 x;
u32 y;
};
struct v2f { struct v2f {
f32 x; f32 x;
f32 y; f32 y;
@ -107,6 +98,15 @@ struct font_directory {
u32 glyf_offset; u32 glyf_offset;
u32 hmtx_offset; u32 hmtx_offset;
u32 maxp_offset; u32 maxp_offset;
u32 cvt_offset;
u32 cvt_size;
u32 prep_offset;
u32 prep_size;
u32 fpgm_offset;
u32 fpgm_size;
}; };
union glyph_flag { union glyph_flag {
@ -140,6 +140,8 @@ enum compund_glyph_flag {
struct maxp_table { struct maxp_table {
u16 max_component_points; u16 max_component_points;
u16 max_component_contours; u16 max_component_contours;
u16 max_storage;
u16 max_fdefs;
}; };
struct head_table { struct head_table {
@ -171,6 +173,7 @@ struct glyph {
s16 xmin, ymin; s16 xmin, ymin;
s16 xmax, ymax; s16 xmax, ymax;
s32 baseline;
u16 advance; u16 advance;
s16 lsb; s16 lsb;
@ -186,26 +189,18 @@ struct ttf_font {
struct head_table head; struct head_table head;
struct hhea_table hhea; struct hhea_table hhea;
char *name; s16 *cvt;
int cmap_format; int cmap_format;
int glyf_offset; struct font_directory dir;
int loca_offset; struct ttf_function *functions;
int cmap_offset;
int hmtx_offset;
};
/*******************************/
#include "ttf2.c" u32 *storage;
static Display *display; char *name;
static Window window; };
static GC default_gc;
static XImage* xwindow_buffer;
/*******************************/
static int static int
clamp_u32(u32 val, u32 cap) clamp_u32(u32 val, u32 cap)
{ {
@ -221,12 +216,10 @@ abs_f32(f32 v)
return(result); return(result);
} }
static f32 static int
round_f32(f32 v) round_f32(f32 v)
{ {
return(v); #if 1
#if 0
int towards_zero = (int) v; int towards_zero = (int) v;
f32 diff = abs_f32(v - towards_zero); f32 diff = abs_f32(v - towards_zero);
@ -235,9 +228,30 @@ round_f32(f32 v)
} else { } else {
return(towards_zero); return(towards_zero);
} }
#else
return(v);
#endif #endif
} }
static int
ceil_f32(f32 v)
{
int trunc = v;
if (v - trunc < F32EPS) {
return(trunc);
}
return(trunc + 1);
}
#include "ttf_engine.c"
#include "ttf2.c"
static Display *display;
static Window window;
static GC default_gc;
static XImage* xwindow_buffer;
static int static int
scanline_intersects_line(f32 y, struct v2f p0, struct v2f p1, f32 lasty, f32 *vx) scanline_intersects_line(f32 y, struct v2f p0, struct v2f p1, f32 lasty, f32 *vx)
{ {
@ -441,20 +455,24 @@ sort_intersections(struct intersection *intersections, int size)
} }
static void static void
render_glyph(struct glyph g, struct line_contour *lines, render_glyph(struct glyph g, int px_size, struct line_contour *lines,
f32 scale, u32 *pixels, int width, int height, int at_x, int at_y) f32 scale, u32 *pixels, int width, int at_x, int at_y)
{ {
int gwidth = round_f32((g.xmax - g.xmin) * scale) + 1; int oversample_y = 4;
int gheight = round_f32((g.ymax - g.ymin) * scale) + 1; if (px_size <= 12) {
oversample_y = 8;
}
f32 oversample_step = 1.0f / (oversample_y + 1);
f32 oversample_norm = 1.0f / oversample_y;
int gwidth = ceil_f32((g.xmax - g.xmin) * scale);
int gheight = px_size;
struct intersection *intersections = malloc(lines->from[lines->ncontours] * sizeof(struct intersection)); struct intersection *intersections = malloc(lines->from[lines->ncontours] * sizeof(struct intersection));
f32 *accumulator = calloc(1, gwidth * gheight * sizeof(f32)); f32 *accumulator = calloc(1, gwidth * gheight * sizeof(f32));
int oversample_y = 5;
f32 oversample_step = 1.0f / (oversample_y + 1);
f32 oversample_norm = 1.0f / oversample_y;
for (int y = 0; y < gheight; ++y) { for (int y = 0; y < gheight; ++y) {
for (int yy = 1; yy <= oversample_y; ++yy) { for (int yy = 1; yy <= oversample_y; ++yy) {
u32 ncross = intersect_glyph(lines, y + oversample_step * yy, intersections); u32 ncross = intersect_glyph(lines, y + oversample_step * yy, intersections);
@ -463,7 +481,7 @@ render_glyph(struct glyph g, struct line_contour *lines,
int state = 0; int state = 0;
for (int i = 0; i < ncross - 1; ++i) { for (u32 i = 0; i < ncross - 1; ++i) {
struct intersection inter = intersections[i]; struct intersection inter = intersections[i];
struct intersection next_inter = intersections[i + 1]; struct intersection next_inter = intersections[i + 1];
@ -474,7 +492,7 @@ render_glyph(struct glyph g, struct line_contour *lines,
f32 x1 = next_inter.x; f32 x1 = next_inter.x;
int x_from = x0; int x_from = x0;
int x_to = x1; int x_to = (x1 > gwidth - 1 ? gwidth - 1 : x1);
f32 start_brightness = (x_from + 1 - x0); f32 start_brightness = (x_from + 1 - x0);
f32 end_brightness = (x1 - x_to); f32 end_brightness = (x1 - x_to);
@ -491,19 +509,21 @@ render_glyph(struct glyph g, struct line_contour *lines,
} }
} }
#if 1
for (int y = 0; y < gheight; ++y) { for (int y = 0; y < gheight; ++y) {
for (int x = 0; x < gwidth; ++x) { for (int x = 0; x < gwidth; ++x) {
//printf(" %.2f", accumulator[y * gwidth + x]); //printf(" %.2f", accumulator[y * gwidth + x]);
u32 brightness = clamp_u32(accumulator[y * gwidth + x] * 255.99f, 255); u32 brightness = clamp_u32(accumulator[y * gwidth + x] * 255.99f, 255);
u32 white = 0xFF000000 | brightness << 16 | brightness << 8 | brightness; u32 white = 0xFF000000 | brightness << 16 | brightness << 8 | brightness;
pixels[(at_y + y) * width + (at_x + x)] = white;
if (brightness > 0) {
pixels[(at_y + (gheight - 1 - y)) * width + (at_x + x)] = white;
} else {
//pixels[(at_y + (gheight - 1 - y)) * width + (at_x + x)] = 0xFFFF0000;
}
} }
//printf("\n");
} }
free(accumulator); free(accumulator);
#endif
//exit(1); //exit(1);
@ -511,7 +531,7 @@ render_glyph(struct glyph g, struct line_contour *lines,
} }
static void static void
outline_to_lines(struct glyph g, f32 scale, struct line_contour *dest, int *cnt) outline_to_lines(struct glyph g, f32 scale, int max_descent, struct line_contour *dest, int *cnt)
{ {
int nlines = 0; int nlines = 0;
int points_from = 0; int points_from = 0;
@ -528,11 +548,11 @@ outline_to_lines(struct glyph g, f32 scale, struct line_contour *dest, int *cnt)
continue; continue;
} }
f32 x1 = round_f32((gp.x - g.xmin) * scale); f32 x1 = gp.x * scale;
f32 y1 = round_f32(gp.y * scale); f32 y1 = (gp.y - g.baseline - max_descent) * scale;
f32 x2 = round_f32((nextgp.x - g.xmin) * scale); f32 x2 = nextgp.x * scale;
f32 y2 = round_f32(nextgp.y * scale); f32 y2 = (nextgp.y - g.baseline - max_descent) * scale;
if (nextgp.on_curve) { if (nextgp.on_curve) {
if (gp.y != nextgp.y) { if (gp.y != nextgp.y) {
@ -546,8 +566,8 @@ outline_to_lines(struct glyph g, f32 scale, struct line_contour *dest, int *cnt)
int nextnexti = (nexti + 1 < g.end_pts_of_contours[c] + 1 ? nexti + 1 : points_from); int nextnexti = (nexti + 1 < g.end_pts_of_contours[c] + 1 ? nexti + 1 : points_from);
struct glyph_point nextnextgp = g.points[nextnexti]; struct glyph_point nextnextgp = g.points[nextnexti];
f32 x3 = round_f32((nextnextgp.x - g.xmin) * scale); f32 x3 = nextnextgp.x * scale;
f32 y3 = round_f32(nextnextgp.y * scale); f32 y3 = (nextnextgp.y - g.baseline - max_descent) * scale;
/* P(t) = P0*t^2 + P1*2*t*(1-t) + P2*(1-t)^2 */ /* P(t) = P0*t^2 + P1*2*t*(1-t) + P2*(1-t)^2 */
f32 t_step = 1.0f / curve_segments; f32 t_step = 1.0f / curve_segments;
@ -603,7 +623,7 @@ outline_to_lines(struct glyph g, f32 scale, struct line_contour *dest, int *cnt)
} }
static void static void
render_utf_string(struct ttf_font font, int px_size, u32 *pixels, u32 width, u32 height, wchar_t *string, int at_x, int at_y) render_utf_string(struct ttf_font font, int px_size, u32 *pixels, u32 width, wchar_t *string, int at_x, int at_y)
{ {
u32 offset_x = at_x; u32 offset_x = at_x;
u32 offset_y = at_y; u32 offset_y = at_y;
@ -616,15 +636,21 @@ render_utf_string(struct ttf_font font, int px_size, u32 *pixels, u32 width, u32
if (codepoint != ' ') { if (codepoint != ' ') {
struct glyph g = get_outline(&font, codepoint); struct glyph g = get_outline(&font, codepoint);
//exit(0);
struct line_contour lines = { 0 }; struct line_contour lines = { 0 };
int nlines = 0; int nlines = 0;
outline_to_lines(g, scale, &lines, &nlines); outline_to_lines(g, scale, font.hhea.descent, &lines, &nlines);
lines.data = malloc(nlines * sizeof(struct line)); lines.data = malloc(nlines * sizeof(struct line));
outline_to_lines(g, scale, &lines, 0); outline_to_lines(g, scale, font.hhea.descent, &lines, 0);
int baseline_correction = round_f32(scale * g.ymax); render_glyph(g, px_size, &lines, scale, pixels, width, offset_x + g.lsb * scale, offset_y);
render_glyph(g, &lines, scale, pixels, width, height, offset_x + round_f32(g.lsb * scale), offset_y - baseline_correction);
offset_x += scale * g.advance; #if 1
offset_x += round_f32(scale * g.advance);
#else
offset_x += px_size * 2;
#endif
free(lines.data); free(lines.data);
} else { } else {
@ -698,17 +724,35 @@ main(int argc, char **argv)
int t = 0; int t = 0;
for (;;) { for (;;) {
//memset(pixels, 0xFF, width * height * 4);
//memset(pixels, 0xFF, width * height * 4); //memset(pixels, 0xFF, width * height * 4);
memset(pixels, 0x00, width * height * 4); memset(pixels, 0x00, width * height * 4);
#if 1 int at = 75;
render_utf_string(font, 24, pixels, width, height, L"Пельмени - это очень просто! Много фарша, мало мяса...", 100, 100); //render_utf_string(font, 18, pixels, width, L"The quick brown fox jumps over the lazy dog", 100, 150);
render_utf_string(font, 24, pixels, width, height, L"Good pelmeni are very simple! Much meat, little dough...", 100, 150); //render_utf_string(font, 12, pixels, width, L"This text is seriously small", 100, at); at += 12;
#endif //render_utf_string(font, 13, pixels, width, L"This text is seriously small", 100, at); at += 13;
//render_utf_string(font, 14, pixels, width, L"This text is seriously small", 100, at); at += 14;
//render_utf_string(font, 15, pixels, width, L"This text is seriously small", 100, at); at += 14;
render_utf_string(font, 20, pixels, width, L"result = XCreateImage(display, visinfo.visual, visinfo.depth, ZPixmap, 0, hc_vram, width, height, pixel_bits, 0);", 100, at); at += 20;
render_utf_string(font, 24, pixels, width, L"The quick brown fox jumps over the lazy dog", 100, at); at += 24;
wchar_t *string1 = L"iiiiiiiiil";
wchar_t *string2 = L"something-some";
wchar_t *string3 = L"MORE MORE";
int w1 = get_string_width(&font, 32, string1, wcslen(string1));
int w2 = get_string_width(&font, 32, string2, wcslen(string2));
render_utf_string(font, 32, pixels, width, string1, 100, at);
render_utf_string(font, 32, pixels, width, string2, 100 + w1, at);
render_utf_string(font, 32, pixels, width, string3, 100 + w1 + w2, at);
at += 80;
render_utf_string(font, 80, pixels, width, L"~!@#$%^&*()_+;:,./\\|", 100, at);
XPutImage(display, window, default_gc, xwindow_buffer, 0, 0, 0, 0, width, height); XPutImage(display, window, default_gc, xwindow_buffer, 0, 0, 0, 0, width, height);
usleep(100000); sleep(1);
++t; ++t;
} }

1053
ttf2.c

File diff suppressed because it is too large Load Diff

355
ttf_engine.c

@ -0,0 +1,355 @@
struct ttf_graphics_state {
u32 stack[TTF_ENGINE_STACK];
u32 stack_head;
bool auto_flip;
f32 control_value_cut_in; // f26dot6
u32 delta_base;
u32 delta_shift;
struct v2f projection_vector;
struct v2f freedom_vector;
struct v2f dual_projection_vector;
int gep0;
int gep1;
int gep2;
u32 instruction_control;
int loop;
f32 minimum_distance; // 1/64-th of a pixel, f26dot6
int round_state;
int rp0;
int rp1;
int rp2;
bool scan_control;
f32 single_width_cut_in; // 1/64-th of a pixel, f26dot6
int single_width_value; // Funits
};
struct ttf_function {
u32 from;
u32 to;
};
enum ttf_instruction {
/* Pushing data onto the interpreter stack */
NPUSHB = 0x40,
NPUSHW = 0x41,
PUSHB = 0xB0, PUSHB_TOP = 0xB7,
PUSHW = 0xB8, PUSHW_TOP = 0xBF,
/* Managing the Storage Area */
RS = 0x43,
WS = 0x42,
WCVTP = 0x44,
WCVTF = 0x70,
RCVT = 0x45,
/* Managing the Graphics State */
SVTCA = 0x00, SVTCA_TOP = 0x01,
SPVTCA = 0x02, SPVTCA_TOP = 0x03,
SFVTCA = 0x04, SFVTCA_TOP = 0x05,
SPVTL = 0x06, SPVTL_TOP = 0x07,
SFVTL = 0x08, SFVTL_TOP = 0x09,
SFVTPV = 0x0E,
SDPVTL = 0x86, SDPVTL_TOP = 0x87,
SPVFS = 0x0A,
SFVFS = 0x0B,
GPV = 0x0C,
GFV = 0x0D,
SRP0 = 0x10,
SRP1 = 0x11,
SRP2 = 0x12,
SZP0 = 0x13,
SZP1 = 0x14,
SZP2 = 0x15,
SZPS = 0x16,
RTHG = 0x19,
RTG = 0x18,
RTDG = 0x3D,
RDTG = 0x7D,
RUTG = 0x7C,
ROFF = 0x7A,
SROUND = 0x76,
S45ROUND = 0x77,
SLOOP = 0x17,
SMD = 0x1A,
INSTCTRL = 0x8E,
SCANCTRL = 0x85,
SCANTYPE = 0x8D,
SCVTCI = 0x1D,
SSWCI = 0x1E,
SSW = 0x1F,
FLIPON = 0x4D,
FLIPOFF = 0x4E,
SANGW = 0x7E,
SDB = 0x5E,
SDS = 0x5F,
/* Reading and writing data */
GC_ = 0x46, GC_TOP = 0x47, // name collisiton with GC from Xlib.h
SCFS = 0x48,
MD = 0x49, MD_TOP = 0x4A,
MPPEM = 0x4B,
MPS = 0x4C,
/* Managing outlines */
FLIPPT = 0x80,
FLIPRGON = 0x81,
FLIPRGOFF = 0x82,
SHP = 0x32, SHP_TOP = 0x33,
SHC = 0x34, SHC_TOP = 0x35,
SHZ = 0x36, SHZ_TOP = 0x37,
SHPIX = 0x38,
MSIRP = 0x3A, MSIRP_TOP = 0x3B,
MDAP = 0x2E, MDAP_TOP = 0x2F,
MIAP = 0x3E, MIAP_TOP = 0x3F,
MDRP = 0xC0, MDRP_TOP = 0xDF,
MIRP = 0xE0, MIRP_TOP = 0xFF,
ALIGNRP = 0x3C,
ISECT = 0x0F,
ALIGNPTS = 0x27,
IP = 0x39,
UTP = 0x29,
IUP = 0x30, IUP_TOP = 0x31,
/* Managing exceptions */
DELTAP1 = 0x5D,
DELTAP2 = 0x71,
DELTAP3 = 0x72,
DELTAC1 = 0x73,
DELTAC2 = 0x74,
DELTAC3 = 0x75,
/* Managing the stack */
DUP = 0x20,
POP = 0x21,
CLEAR = 0x22,
SWAP = 0x23,
DEPTH = 0x24,
CINDEX = 0x25,
MINDEX = 0x26,
ROLL = 0x8A,
/* Managing the flow of control */
IF = 0x58,
ELSE = 0x1B,
EIF = 0x59,
JROT = 0x78,
JMPR = 0x1C,
JROF = 0x79,
/* Logical functions */
LT = 0x50,
LTEQ = 0x51,
GT = 0x52,
GTEQ = 0x53,
EQ = 0x54,
NEQ = 0x55,
ODD = 0x56,
EVEN = 0x57,
AND = 0x5A,
OR = 0x5B,
NOT = 0x5C,
/* Arithmetic and math instructions */
ADD = 0x60,
SUB = 0x61,
DIV = 0x62,
MUL = 0x63,
ABS = 0x64,
NEG = 0x65,
FLOOR = 0x66,
CEILING = 0x67,
MAX = 0x8B,
MIN = 0x8C,
/* Compensating for the engine characteristics */
ROUND = 0x68, ROUND_TOP = 0x6B,
NROUND = 0x6C, NROUND_TOP = 0x6F,
/* Defining and using functions and instructions */
FDEF = 0x2C,
ENDF = 0x2D,
CALL = 0x2B,
LOOPCALL = 0x2A,
IDEF = 0x89,
/* Debugging */
DEBUG = 0x4F,
/* Miscellaneous instructions */
GETINFO = 0x88,
GETVARIATION = 0x91,
};
static char *
ttfe_instruction_name(enum ttf_instruction instruction)
{
switch (instruction) {
case NPUSHB: return("NPUSHB");
case NPUSHW: return("NPUSHW");
case PUSHB ... PUSHB_TOP: return("PUSHB");
case PUSHW ... PUSHW_TOP: return("PUSHW");
case RS: return("RS");
case WS: return("WS");
case WCVTP: return("WCVTP");
case WCVTF: return("WCVTF");
case RCVT: return("RCVT");
case SVTCA ... SVTCA_TOP: return("SVTCA");
case SPVTCA ... SPVTCA_TOP: return("SPVTCA");
case SFVTCA ... SFVTCA_TOP: return("SFVTCA");
case SPVTL ... SPVTL_TOP: return("SPVTL");
case SFVTL ... SFVTL_TOP: return("SFVTL");
case SFVTPV: return("SFVTPV");
case SDPVTL ... SDPVTL_TOP: return("SDPVTL");
case SPVFS: return("SPVFS");
case SFVFS: return("SFVFS");
case GPV: return("GPV");
case GFV: return("GFV");
case SRP0: return("SRP0");
case SRP1: return("SRP1");
case SRP2: return("SRP2");
case SZP0: return("SZP0");
case SZP1: return("SZP1");
case SZP2: return("SZP2");
case SZPS: return("SZPS");
case RTHG: return("RTHG");
case RTG: return("RTG");
case RTDG: return("RTDG");
case RDTG: return("RDTG");
case RUTG: return("RUTG");
case ROFF: return("ROFF");
case SROUND: return("SROUND");
case S45ROUND: return("S45ROUND");
case SLOOP: return("SLOOP");
case SMD: return("SMD");
case INSTCTRL: return("INSTCTRL");
case SCANCTRL: return("SCANCTRL");
case SCANTYPE: return("SCANTYPE");
case SCVTCI: return("SCVTCI");
case SSWCI: return("SSWCI");
case SSW: return("SSW");
case FLIPON: return("FLIPON");
case FLIPOFF: return("FLIPOFF");
case SANGW: return("SANGW");
case SDB: return("SDB");
case SDS: return("SDS");
case GC_ ... GC_TOP: return("GC_");
case SCFS: return("SCFS");
case MD ... MD_TOP: return("MD");
case MPPEM: return("MPPEM");
case MPS: return("MPS");
case FLIPPT: return("FLIPPT");
case FLIPRGON: return("FLIPRGON");
case FLIPRGOFF: return("FLIPRGOFF");
case SHP ... SHP_TOP: return("SHP");
case SHC ... SHC_TOP: return("SHC");
case SHZ ... SHZ_TOP: return("SHZ");
case SHPIX: return("SHPIX");
case MSIRP ... MSIRP_TOP: return("MSIRP");
case MDAP ... MDAP_TOP: return("MDAP");
case MIAP ... MIAP_TOP: return("MIAP");
case MDRP ... MDRP_TOP: return("MDRP");
case MIRP ... MIRP_TOP: return("MIRP");
case ALIGNRP: return("ALIGNRP");
case ISECT: return("ISECT");
case ALIGNPTS: return("ALIGNPTS");
case IP: return("IP");
case UTP: return("UTP");
case IUP ... IUP_TOP: return("IUP");
case DELTAP1: return("DELTAP1");
case DELTAP2: return("DELTAP2");
case DELTAP3: return("DELTAP3");
case DELTAC1: return("DELTAC1");
case DELTAC2: return("DELTAC2");
case DELTAC3: return("DELTAC3");
case DUP: return("DUP");
case POP: return("POP");
case CLEAR: return("CLEAR");
case SWAP: return("SWAP");
case DEPTH: return("DEPTH");
case CINDEX: return("CINDEX");
case MINDEX: return("MINDEX");
case ROLL: return("ROLL");
case IF: return("IF");
case ELSE: return("ELSE");
case EIF: return("EIF");
case JROT: return("JROT");
case JMPR: return("JMPR");
case JROF: return("JROF");
case LT: return("LT");
case LTEQ: return("LTEQ");
case GT: return("GT");
case GTEQ: return("GTEQ");
case EQ: return("EQ");
case NEQ: return("NEQ");
case ODD: return("ODD");
case EVEN: return("EVEN");
case AND: return("AND");
case OR: return("OR");
case NOT: return("NOT");
case ADD: return("ADD");
case SUB: return("SUB");
case DIV: return("DIV");
case MUL: return("MUL");
case ABS: return("ABS");
case NEG: return("NEG");
case FLOOR: return("FLOOR");
case CEILING: return("CEILING");
case MAX: return("MAX");
case MIN: return("MIN");
case ROUND ... ROUND_TOP: return("ROUND");
case NROUND ... NROUND_TOP: return("NROUND");
case FDEF: return("FDEF");
case ENDF: return("ENDF");
case CALL: return("CALL");
case LOOPCALL: return("LOOPCALL");
case IDEF: return("IDEF");
case DEBUG: return("DEBUG");
case GETINFO: return("GETINFO");
case GETVARIATION: return("GETVARIATION");
default: return("");
}
}
static struct ttf_graphics_state
default_graphics_state()
{
struct ttf_graphics_state result;
result.stack_head = 0;
result.auto_flip = false;
result.control_value_cut_in = 17.0f / 16.0f;
result.delta_base = 0;
result.delta_shift = 3;
//result.dual_projection_vector
result.freedom_vector = (struct v2f) { 1.0f, 0.0f };
result.projection_vector = (struct v2f) { 1.0f, 0.0f };
result.gep0 = 1;
result.gep1 = 1;
result.gep2 = 1;
result.instruction_control = 0;
result.loop = 1;
result.minimum_distance = 64; // 1/64-th of a pixel, f26dot6
result.round_state = 1;
result.rp0 = 0;
result.rp1 = 0;
result.rp2 = 0;
result.scan_control = 0;
result.single_width_cut_in = 0; // 1/64-th of a pixel, f26dot6
result.single_width_value = 0; // Funits
return(result);
}
Loading…
Cancel
Save