1 /**************************************************************************** 2 * 3 * ttinterp.h 4 * 5 * TrueType bytecode interpreter (specification). 6 * 7 * Copyright (C) 1996-2023 by 8 * David Turner, Robert Wilhelm, and Werner Lemberg. 9 * 10 * This file is part of the FreeType project, and may only be used, 11 * modified, and distributed under the terms of the FreeType project 12 * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 * this file you indicate that you have read the license and 14 * understand and accept it fully. 15 * 16 */ 17 18 19 #ifndef TTINTERP_H_ 20 #define TTINTERP_H_ 21 22 #include "ttobjs.h" 23 24 25 FT_BEGIN_HEADER 26 27 28 /************************************************************************** 29 * 30 * Rounding mode constants. 31 */ 32 #define TT_Round_Off 5 33 #define TT_Round_To_Half_Grid 0 34 #define TT_Round_To_Grid 1 35 #define TT_Round_To_Double_Grid 2 36 #define TT_Round_Up_To_Grid 4 37 #define TT_Round_Down_To_Grid 3 38 #define TT_Round_Super 6 39 #define TT_Round_Super_45 7 40 41 42 /************************************************************************** 43 * 44 * Function types used by the interpreter, depending on various modes 45 * (e.g. the rounding mode, whether to render a vertical or horizontal 46 * line etc). 47 * 48 */ 49 50 /* Rounding function */ 51 typedef FT_F26Dot6 52 (*TT_Round_Func)( TT_ExecContext exc, 53 FT_F26Dot6 distance, 54 FT_Int color ); 55 56 /* Point displacement along the freedom vector routine */ 57 typedef void 58 (*TT_Move_Func)( TT_ExecContext exc, 59 TT_GlyphZone zone, 60 FT_UShort point, 61 FT_F26Dot6 distance ); 62 63 /* Distance projection along one of the projection vectors */ 64 typedef FT_F26Dot6 65 (*TT_Project_Func)( TT_ExecContext exc, 66 FT_Pos dx, 67 FT_Pos dy ); 68 69 /* getting current ppem. Take care of non-square pixels if necessary */ 70 typedef FT_Long 71 (*TT_Cur_Ppem_Func)( TT_ExecContext exc ); 72 73 /* reading a cvt value. Take care of non-square pixels if necessary */ 74 typedef FT_F26Dot6 75 (*TT_Get_CVT_Func)( TT_ExecContext exc, 76 FT_ULong idx ); 77 78 /* setting or moving a cvt value. Take care of non-square pixels */ 79 /* if necessary */ 80 typedef void 81 (*TT_Set_CVT_Func)( TT_ExecContext exc, 82 FT_ULong idx, 83 FT_F26Dot6 value ); 84 85 86 /************************************************************************** 87 * 88 * This structure defines a call record, used to manage function calls. 89 */ 90 typedef struct TT_CallRec_ 91 { 92 FT_Int Caller_Range; 93 FT_Long Caller_IP; 94 FT_Long Cur_Count; 95 96 TT_DefRecord *Def; /* either FDEF or IDEF */ 97 98 } TT_CallRec, *TT_CallStack; 99 100 101 /************************************************************************** 102 * 103 * The main structure for the interpreter which collects all necessary 104 * variables and states. 105 * 106 * Members that are initialized by `TT_Load_Context` are marked with '!'. 107 * Members that are initialized by `TT_Run_Context` are marked with '@'. 108 */ 109 typedef struct TT_ExecContextRec_ 110 { 111 TT_Face face; /* ! */ 112 TT_Size size; /* ! */ 113 FT_Memory memory; 114 115 /* instructions state */ 116 117 FT_Error error; /* last execution error */ 118 119 FT_Long top; /* @ top of exec. stack */ 120 121 FT_Long stackSize; /* ! size of exec. stack */ 122 FT_Long* stack; /* ! current exec. stack */ 123 124 FT_Long args; 125 FT_Long new_top; /* new top after exec. */ 126 127 TT_GlyphZoneRec zp0, /* @! zone records */ 128 zp1, /* @! */ 129 zp2, /* @! */ 130 pts, /* ! */ 131 twilight; /* ! */ 132 133 FT_Long pointSize; /* ! in 26.6 format */ 134 FT_Size_Metrics metrics; /* ! */ 135 TT_Size_Metrics tt_metrics; /* ! size metrics */ 136 137 TT_GraphicsState GS; /* !@ current graphics state */ 138 139 FT_Int iniRange; /* initial code range number */ 140 FT_Int curRange; /* current code range number */ 141 FT_Byte* code; /* current code range */ 142 FT_Long IP; /* current instruction pointer */ 143 FT_Long codeSize; /* size of current range */ 144 145 FT_Byte opcode; /* current opcode */ 146 FT_Int length; /* length of current opcode */ 147 148 FT_Bool step_ins; /* true if the interpreter must */ 149 /* increment IP after ins. exec */ 150 FT_ULong cvtSize; /* ! */ 151 FT_Long* cvt; /* ! */ 152 FT_ULong glyfCvtSize; 153 FT_Long* glyfCvt; /* cvt working copy for glyph */ 154 155 FT_UInt glyphSize; /* ! glyph instructions buffer size */ 156 FT_Byte* glyphIns; /* ! glyph instructions buffer */ 157 158 FT_UInt numFDefs; /* ! number of function defs */ 159 FT_UInt maxFDefs; /* ! maximum number of function defs */ 160 TT_DefArray FDefs; /* table of FDefs entries */ 161 162 FT_UInt numIDefs; /* ! number of instruction defs */ 163 FT_UInt maxIDefs; /* ! maximum number of ins defs */ 164 TT_DefArray IDefs; /* table of IDefs entries */ 165 166 FT_UInt maxFunc; /* ! maximum function index */ 167 FT_UInt maxIns; /* ! maximum instruction index */ 168 169 FT_Int callTop, /* @ top of call stack during execution */ 170 callSize; /* size of call stack */ 171 TT_CallStack callStack; /* call stack */ 172 173 FT_UShort maxPoints; /* capacity of this context's `pts' */ 174 FT_Short maxContours; /* record, expressed in points and */ 175 /* contours. */ 176 177 TT_CodeRangeTable codeRangeTable; /* ! table of valid code ranges */ 178 /* useful for the debugger */ 179 180 FT_UShort storeSize; /* ! size of current storage */ 181 FT_Long* storage; /* ! storage area */ 182 FT_UShort glyfStoreSize; 183 FT_Long* glyfStorage; /* storage working copy for glyph */ 184 185 FT_F26Dot6 period; /* values used for the */ 186 FT_F26Dot6 phase; /* `SuperRounding' */ 187 FT_F26Dot6 threshold; 188 189 FT_Bool instruction_trap; /* ! If `True', the interpreter */ 190 /* exits after each instruction */ 191 192 TT_GraphicsState default_GS; /* graphics state resulting from */ 193 /* the prep program */ 194 FT_Bool is_composite; /* true if the glyph is composite */ 195 FT_Bool pedantic_hinting; /* true if pedantic interpretation */ 196 197 /* latest interpreter additions */ 198 199 FT_Long F_dot_P; /* dot product of freedom and projection */ 200 /* vectors */ 201 TT_Round_Func func_round; /* current rounding function */ 202 203 TT_Project_Func func_project, /* current projection function */ 204 func_dualproj, /* current dual proj. function */ 205 func_freeProj; /* current freedom proj. func */ 206 207 TT_Move_Func func_move; /* current point move function */ 208 TT_Move_Func func_move_orig; /* move original position function */ 209 210 TT_Cur_Ppem_Func func_cur_ppem; /* get current proj. ppem value */ 211 212 TT_Get_CVT_Func func_read_cvt; /* read a cvt entry */ 213 TT_Set_CVT_Func func_write_cvt; /* write a cvt entry (in pixels) */ 214 TT_Set_CVT_Func func_move_cvt; /* incr a cvt entry (in pixels) */ 215 216 FT_Bool grayscale; /* bi-level hinting and */ 217 /* grayscale rendering */ 218 219 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 220 /* 221 * FreeType supports ClearType-like hinting of TrueType fonts through 222 * the version 40 interpreter. This is achieved through several hacks 223 * in the base (v35) interpreter, as detailed below. 224 * 225 * ClearType is an umbrella term for several rendering techniques 226 * employed by Microsoft's various GUI and rendering toolkit 227 * implementations, most importantly: subpixel rendering for using the 228 * RGB subpixels of LCDs to approximately triple the perceived 229 * resolution on the x-axis and subpixel hinting for positioning stems 230 * on subpixel borders. TrueType programming is explicit, i.e., fonts 231 * must be programmed to take advantage of ClearType's possibilities. 232 * 233 * When ClearType was introduced, it seemed unlikely that all fonts 234 * would be reprogrammed, so Microsoft decided to implement a backward 235 * compatibility mode. It employs several simple to complicated 236 * assumptions and tricks, many of them font-dependent, that modify the 237 * interpretation of the bytecode contained in these fonts to retrofit 238 * them into a ClearType-y look. The quality of the results varies. 239 * Most (web)fonts that were released since then have come to rely on 240 * these hacks to render correctly, even some of Microsoft's flagship 241 * fonts (e.g., Calibri, Cambria, Segoe UI). 242 * 243 * FreeType's minimal subpixel hinting code (interpreter version 40) 244 * employs a small list of font-agnostic hacks loosely based on the 245 * public information available on Microsoft's compatibility mode[2]. 246 * The focus is on modern (web)fonts rather than legacy fonts that were 247 * made for monochrome rendering. It will not match ClearType rendering 248 * exactly. Unlike the `Infinality' code (interpreter version 38) that 249 * came before, it will not try to toggle hacks for specific fonts for 250 * performance and complexity reasons. It will fall back to version 35 251 * behavior for tricky fonts[1] or when monochrome rendering is 252 * requested. 253 * 254 * Major hacks 255 * 256 * - Any point movement on the x axis is ignored (cf. `Direct_Move' and 257 * `Direct_Move_X'). This has the smallest code footprint and single 258 * biggest effect. The ClearType way to increase resolution is 259 * supersampling the x axis, the FreeType way is ignoring instructions 260 * on the x axis, which gives the same result in the majority of 261 * cases. 262 * 263 * - Points are not moved post-IUP (neither on the x nor on the y axis), 264 * except the x component of diagonal moves post-IUP (cf. 265 * `Direct_Move', `Direct_Move_Y', `Move_Zp2_Point'). Post-IUP 266 * changes are commonly used to `fix' pixel patterns which has little 267 * use outside monochrome rendering. 268 * 269 * - SHPIX and DELTAP don't execute unless moving a composite on the 270 * y axis or moving a previously y touched point. SHPIX additionally 271 * denies movement on the x axis (cf. `Ins_SHPIX' and `Ins_DELTAP'). 272 * Both instructions are commonly used to `fix' pixel patterns for 273 * monochrome or Windows's GDI rendering but make little sense for 274 * FreeType rendering. Both can distort the outline. See [2] for 275 * details. 276 * 277 * - The hdmx table and modifications to phantom points are ignored. 278 * Bearings and advance widths remain unchanged (except rounding them 279 * outside the interpreter!), cf. `compute_glyph_metrics' and 280 * `TT_Hint_Glyph'. Letting non-native-ClearType fonts modify spacing 281 * might mess up spacing. 282 * 283 * Minor hacks 284 * 285 * - FLIPRGON, FLIPRGOFF, and FLIPPT don't execute post-IUP. This 286 * prevents dents in e.g. Arial-Regular's `D' and `G' glyphs at 287 * various sizes. 288 * 289 * (Post-IUP is the state after both IUP[x] and IUP[y] have been 290 * executed.) 291 * 292 * The best results are achieved for fonts that were from the outset 293 * designed with ClearType in mind, meaning they leave the x axis mostly 294 * alone and don't mess with the `final' outline to produce more 295 * pleasing pixel patterns. The harder the designer tried to produce 296 * very specific patterns (`superhinting') for pre-ClearType-displays, 297 * the worse the results. 298 * 299 * Microsoft defines a way to turn off backward compatibility and 300 * interpret instructions as before (called `native ClearType')[2][3]. 301 * The font designer then regains full control and is responsible for 302 * making the font work correctly with ClearType without any 303 * hand-holding by the interpreter or rasterizer[4]. The v40 304 * interpreter assumes backward compatibility by default, which can be 305 * turned off the same way by executing the following in the control 306 * program (cf. `Ins_INSTCTRL'). 307 * 308 * #PUSH 4,3 309 * INSTCTRL[] 310 * 311 * [1] Tricky fonts as FreeType defines them rely on the bytecode 312 * interpreter to display correctly. Hacks can interfere with them, 313 * so they get treated like native ClearType fonts (v40 with 314 * backward compatibility turned off). Cf. `TT_RunIns'. 315 * 316 * [2] Proposed by Microsoft's Greg Hitchcock in 317 * https://www.microsoft.com/typography/cleartype/truetypecleartype.aspx 318 * 319 * [3] Beat Stamm describes it in more detail: 320 * http://rastertragedy.com/RTRCh4.htm#Sec12. 321 * 322 * [4] The list of `native ClearType' fonts is small at the time of this 323 * writing; I found the following on a Windows 10 Update 1511 324 * installation: Constantia, Corbel, Sitka, Malgun Gothic, Microsoft 325 * JhengHei (Bold and UI Bold), Microsoft YaHei (Bold and UI Bold), 326 * SimSun, NSimSun, and Yu Gothic. 327 * 328 */ 329 330 /* Using v40 implies subpixel hinting, unless FT_RENDER_MODE_MONO has been 331 * requested. Used to detect interpreter */ 332 /* version switches. `_lean' to differentiate from the Infinality */ 333 /* `subpixel_hinting', which is managed differently. */ 334 FT_Bool subpixel_hinting_lean; 335 336 /* Long side of a LCD subpixel is vertical (e.g., screen is rotated). */ 337 /* `_lean' to differentiate from the Infinality `vertical_lcd', which */ 338 /* is managed differently. */ 339 FT_Bool vertical_lcd_lean; 340 341 /* Default to backward compatibility mode in v40 interpreter. If */ 342 /* this is false, it implies the interpreter is in v35 or in native */ 343 /* ClearType mode. */ 344 FT_Bool backward_compatibility; 345 346 /* Useful for detecting and denying post-IUP trickery that is usually */ 347 /* used to fix pixel patterns (`superhinting'). */ 348 FT_Bool iupx_called; 349 FT_Bool iupy_called; 350 351 /* ClearType hinting and grayscale rendering, as used by Universal */ 352 /* Windows Platform apps (Windows 8 and above). Like the standard */ 353 /* colorful ClearType mode, it utilizes a vastly increased virtual */ 354 /* resolution on the x axis. Different from bi-level hinting and */ 355 /* grayscale rendering, the old mode from Win9x days that roughly */ 356 /* adheres to the physical pixel grid on both axes. */ 357 FT_Bool grayscale_cleartype; 358 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ 359 360 /* We maintain two counters (in addition to the instruction counter) */ 361 /* that act as loop detectors for LOOPCALL and jump opcodes with */ 362 /* negative arguments. */ 363 FT_ULong loopcall_counter; 364 FT_ULong loopcall_counter_max; 365 FT_ULong neg_jump_counter; 366 FT_ULong neg_jump_counter_max; 367 368 } TT_ExecContextRec; 369 370 371 extern const TT_GraphicsState tt_default_graphics_state; 372 373 374 #ifdef TT_USE_BYTECODE_INTERPRETER 375 FT_LOCAL( void ) 376 TT_Goto_CodeRange( TT_ExecContext exec, 377 FT_Int range, 378 FT_Long IP ); 379 380 FT_LOCAL( void ) 381 TT_Set_CodeRange( TT_ExecContext exec, 382 FT_Int range, 383 void* base, 384 FT_Long length ); 385 386 FT_LOCAL( void ) 387 TT_Clear_CodeRange( TT_ExecContext exec, 388 FT_Int range ); 389 #endif /* TT_USE_BYTECODE_INTERPRETER */ 390 391 392 /************************************************************************** 393 * 394 * @Function: 395 * TT_New_Context 396 * 397 * @Description: 398 * Create a `TT_ExecContext`. Note that there is now an execution 399 * context per `TT_Size` that is not shared among faces. 400 * 401 * @Input: 402 * driver :: 403 * A handle to the driver, used for memory allocation. 404 * 405 * @Return: 406 * A handle to a new empty execution context. 407 * 408 * @Note: 409 * Only the glyph loader and debugger should call this function. 410 * (And right now only the glyph loader uses it.) 411 */ 412 FT_EXPORT( TT_ExecContext ) 413 TT_New_Context( TT_Driver driver ); 414 415 416 #ifdef TT_USE_BYTECODE_INTERPRETER 417 FT_LOCAL( void ) 418 TT_Done_Context( TT_ExecContext exec ); 419 420 FT_LOCAL( FT_Error ) 421 TT_Load_Context( TT_ExecContext exec, 422 TT_Face face, 423 TT_Size size ); 424 425 FT_LOCAL( void ) 426 TT_Save_Context( TT_ExecContext exec, 427 TT_Size ins ); 428 429 FT_LOCAL( FT_Error ) 430 TT_Run_Context( TT_ExecContext exec ); 431 #endif /* TT_USE_BYTECODE_INTERPRETER */ 432 433 434 /************************************************************************** 435 * 436 * @Function: 437 * TT_RunIns 438 * 439 * @Description: 440 * Executes one or more instruction in the execution context. This 441 * is the main function of the TrueType opcode interpreter. 442 * 443 * @Input: 444 * exec :: 445 * A handle to the target execution context. 446 * 447 * @Return: 448 * FreeType error code. 0 means success. 449 * 450 * @Note: 451 * Only the object manager and debugger should call this function. 452 * 453 * This function is publicly exported because it is directly 454 * invoked by the TrueType debugger. 455 */ 456 FT_EXPORT( FT_Error ) 457 TT_RunIns( void* exec ); 458 459 460 FT_END_HEADER 461 462 #endif /* TTINTERP_H_ */ 463 464 465 /* END */ 466