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.

355 lines
9.4 KiB

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