| 1 | /***************************************************************************/ | 
|---|
| 2 | /*                                                                         */ | 
|---|
| 3 | /*  ttsubpix.c                                                             */ | 
|---|
| 4 | /*                                                                         */ | 
|---|
| 5 | /*    TrueType Subpixel Hinting.                                           */ | 
|---|
| 6 | /*                                                                         */ | 
|---|
| 7 | /*  Copyright 2010-2018 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 | #include <ft2build.h> | 
|---|
| 19 | #include FT_INTERNAL_DEBUG_H | 
|---|
| 20 | #include FT_INTERNAL_CALC_H | 
|---|
| 21 | #include FT_INTERNAL_STREAM_H | 
|---|
| 22 | #include FT_INTERNAL_SFNT_H | 
|---|
| 23 | #include FT_TRUETYPE_TAGS_H | 
|---|
| 24 | #include FT_OUTLINE_H | 
|---|
| 25 | #include FT_DRIVER_H | 
|---|
| 26 |  | 
|---|
| 27 | #include "ttsubpix.h" | 
|---|
| 28 |  | 
|---|
| 29 |  | 
|---|
| 30 | #if defined( TT_USE_BYTECODE_INTERPRETER )            && \ | 
|---|
| 31 | defined( TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY ) | 
|---|
| 32 |  | 
|---|
| 33 | /*************************************************************************/ | 
|---|
| 34 | /*                                                                       */ | 
|---|
| 35 | /* These rules affect how the TT Interpreter does hinting, with the      */ | 
|---|
| 36 | /* goal of doing subpixel hinting by (in general) ignoring x moves.      */ | 
|---|
| 37 | /* Some of these rules are fixes that go above and beyond the            */ | 
|---|
| 38 | /* stated techniques in the MS whitepaper on Cleartype, due to           */ | 
|---|
| 39 | /* artifacts in many glyphs.  So, these rules make some glyphs render    */ | 
|---|
| 40 | /* better than they do in the MS rasterizer.                             */ | 
|---|
| 41 | /*                                                                       */ | 
|---|
| 42 | /* "" string or 0 int/char indicates to apply to all glyphs.             */ | 
|---|
| 43 | /* "-" used as dummy placeholders, but any non-matching string works.    */ | 
|---|
| 44 | /*                                                                       */ | 
|---|
| 45 | /* Some of this could arguably be implemented in fontconfig, however:    */ | 
|---|
| 46 | /*                                                                       */ | 
|---|
| 47 | /*  - Fontconfig can't set things on a glyph-by-glyph basis.             */ | 
|---|
| 48 | /*  - The tweaks that happen here are very low-level, from an average    */ | 
|---|
| 49 | /*    user's point of view and are best implemented in the hinter.       */ | 
|---|
| 50 | /*                                                                       */ | 
|---|
| 51 | /* The goal is to make the subpixel hinting techniques as generalized    */ | 
|---|
| 52 | /* as possible across all fonts to prevent the need for extra rules such */ | 
|---|
| 53 | /* as these.                                                             */ | 
|---|
| 54 | /*                                                                       */ | 
|---|
| 55 | /* The rule structure is designed so that entirely new rules can easily  */ | 
|---|
| 56 | /* be added when a new compatibility feature is discovered.              */ | 
|---|
| 57 | /*                                                                       */ | 
|---|
| 58 | /* The rule structures could also use some enhancement to handle ranges. */ | 
|---|
| 59 | /*                                                                       */ | 
|---|
| 60 | /*     ****************** WORK IN PROGRESS *******************           */ | 
|---|
| 61 | /*                                                                       */ | 
|---|
| 62 |  | 
|---|
| 63 | /* These are `classes' of fonts that can be grouped together and used in */ | 
|---|
| 64 | /* rules below.  A blank entry "" is required at the end of these!       */ | 
|---|
| 65 | #define FAMILY_CLASS_RULES_SIZE  7 | 
|---|
| 66 |  | 
|---|
| 67 | static const SPH_Font_Class  FAMILY_CLASS_Rules | 
|---|
| 68 | [FAMILY_CLASS_RULES_SIZE] = | 
|---|
| 69 | { | 
|---|
| 70 | { "MS Legacy Fonts", | 
|---|
| 71 | { "Aharoni", | 
|---|
| 72 | "Andale Mono", | 
|---|
| 73 | "Andalus", | 
|---|
| 74 | "Angsana New", | 
|---|
| 75 | "AngsanaUPC", | 
|---|
| 76 | "Arabic Transparent", | 
|---|
| 77 | "Arial Black", | 
|---|
| 78 | "Arial Narrow", | 
|---|
| 79 | "Arial Unicode MS", | 
|---|
| 80 | "Arial", | 
|---|
| 81 | "Batang", | 
|---|
| 82 | "Browallia New", | 
|---|
| 83 | "BrowalliaUPC", | 
|---|
| 84 | "Comic Sans MS", | 
|---|
| 85 | "Cordia New", | 
|---|
| 86 | "CordiaUPC", | 
|---|
| 87 | "Courier New", | 
|---|
| 88 | "DFKai-SB", | 
|---|
| 89 | "David Transparent", | 
|---|
| 90 | "David", | 
|---|
| 91 | "DilleniaUPC", | 
|---|
| 92 | "Estrangelo Edessa", | 
|---|
| 93 | "EucrosiaUPC", | 
|---|
| 94 | "FangSong_GB2312", | 
|---|
| 95 | "Fixed Miriam Transparent", | 
|---|
| 96 | "FrankRuehl", | 
|---|
| 97 | "Franklin Gothic Medium", | 
|---|
| 98 | "FreesiaUPC", | 
|---|
| 99 | "Garamond", | 
|---|
| 100 | "Gautami", | 
|---|
| 101 | "Georgia", | 
|---|
| 102 | "Gulim", | 
|---|
| 103 | "Impact", | 
|---|
| 104 | "IrisUPC", | 
|---|
| 105 | "JasmineUPC", | 
|---|
| 106 | "KaiTi_GB2312", | 
|---|
| 107 | "KodchiangUPC", | 
|---|
| 108 | "Latha", | 
|---|
| 109 | "Levenim MT", | 
|---|
| 110 | "LilyUPC", | 
|---|
| 111 | "Lucida Console", | 
|---|
| 112 | "Lucida Sans Unicode", | 
|---|
| 113 | "MS Gothic", | 
|---|
| 114 | "MS Mincho", | 
|---|
| 115 | "MV Boli", | 
|---|
| 116 | "Mangal", | 
|---|
| 117 | "Marlett", | 
|---|
| 118 | "Microsoft Sans Serif", | 
|---|
| 119 | "Mingliu", | 
|---|
| 120 | "Miriam Fixed", | 
|---|
| 121 | "Miriam Transparent", | 
|---|
| 122 | "Miriam", | 
|---|
| 123 | "Narkisim", | 
|---|
| 124 | "Palatino Linotype", | 
|---|
| 125 | "Raavi", | 
|---|
| 126 | "Rod Transparent", | 
|---|
| 127 | "Rod", | 
|---|
| 128 | "Shruti", | 
|---|
| 129 | "SimHei", | 
|---|
| 130 | "Simplified Arabic Fixed", | 
|---|
| 131 | "Simplified Arabic", | 
|---|
| 132 | "Simsun", | 
|---|
| 133 | "Sylfaen", | 
|---|
| 134 | "Symbol", | 
|---|
| 135 | "Tahoma", | 
|---|
| 136 | "Times New Roman", | 
|---|
| 137 | "Traditional Arabic", | 
|---|
| 138 | "Trebuchet MS", | 
|---|
| 139 | "Tunga", | 
|---|
| 140 | "Verdana", | 
|---|
| 141 | "Webdings", | 
|---|
| 142 | "Wingdings", | 
|---|
| 143 | "", | 
|---|
| 144 | }, | 
|---|
| 145 | }, | 
|---|
| 146 | { "Core MS Legacy Fonts", | 
|---|
| 147 | { "Arial Black", | 
|---|
| 148 | "Arial Narrow", | 
|---|
| 149 | "Arial Unicode MS", | 
|---|
| 150 | "Arial", | 
|---|
| 151 | "Comic Sans MS", | 
|---|
| 152 | "Courier New", | 
|---|
| 153 | "Garamond", | 
|---|
| 154 | "Georgia", | 
|---|
| 155 | "Impact", | 
|---|
| 156 | "Lucida Console", | 
|---|
| 157 | "Lucida Sans Unicode", | 
|---|
| 158 | "Microsoft Sans Serif", | 
|---|
| 159 | "Palatino Linotype", | 
|---|
| 160 | "Tahoma", | 
|---|
| 161 | "Times New Roman", | 
|---|
| 162 | "Trebuchet MS", | 
|---|
| 163 | "Verdana", | 
|---|
| 164 | "", | 
|---|
| 165 | }, | 
|---|
| 166 | }, | 
|---|
| 167 | { "Apple Legacy Fonts", | 
|---|
| 168 | { "Geneva", | 
|---|
| 169 | "Times", | 
|---|
| 170 | "Monaco", | 
|---|
| 171 | "Century", | 
|---|
| 172 | "Chalkboard", | 
|---|
| 173 | "Lobster", | 
|---|
| 174 | "Century Gothic", | 
|---|
| 175 | "Optima", | 
|---|
| 176 | "Lucida Grande", | 
|---|
| 177 | "Gill Sans", | 
|---|
| 178 | "Baskerville", | 
|---|
| 179 | "Helvetica", | 
|---|
| 180 | "Helvetica Neue", | 
|---|
| 181 | "", | 
|---|
| 182 | }, | 
|---|
| 183 | }, | 
|---|
| 184 | { "Legacy Sans Fonts", | 
|---|
| 185 | { "Andale Mono", | 
|---|
| 186 | "Arial Unicode MS", | 
|---|
| 187 | "Arial", | 
|---|
| 188 | "Century Gothic", | 
|---|
| 189 | "Comic Sans MS", | 
|---|
| 190 | "Franklin Gothic Medium", | 
|---|
| 191 | "Geneva", | 
|---|
| 192 | "Lucida Console", | 
|---|
| 193 | "Lucida Grande", | 
|---|
| 194 | "Lucida Sans Unicode", | 
|---|
| 195 | "Lucida Sans Typewriter", | 
|---|
| 196 | "Microsoft Sans Serif", | 
|---|
| 197 | "Monaco", | 
|---|
| 198 | "Tahoma", | 
|---|
| 199 | "Trebuchet MS", | 
|---|
| 200 | "Verdana", | 
|---|
| 201 | "", | 
|---|
| 202 | }, | 
|---|
| 203 | }, | 
|---|
| 204 |  | 
|---|
| 205 | { "Misc Legacy Fonts", | 
|---|
| 206 | { "Dark Courier", "", }, }, | 
|---|
| 207 | { "Verdana Clones", | 
|---|
| 208 | { "DejaVu Sans", | 
|---|
| 209 | "Bitstream Vera Sans", "", }, }, | 
|---|
| 210 | { "Verdana and Clones", | 
|---|
| 211 | { "DejaVu Sans", | 
|---|
| 212 | "Bitstream Vera Sans", | 
|---|
| 213 | "Verdana", "", }, }, | 
|---|
| 214 | }; | 
|---|
| 215 |  | 
|---|
| 216 |  | 
|---|
| 217 | /* Define this to force natural (i.e. not bitmap-compatible) widths.     */ | 
|---|
| 218 | /* The default leans strongly towards natural widths except for a few    */ | 
|---|
| 219 | /* legacy fonts where a selective combination produces nicer results.    */ | 
|---|
| 220 | /* #define FORCE_NATURAL_WIDTHS   */ | 
|---|
| 221 |  | 
|---|
| 222 |  | 
|---|
| 223 | /* Define `classes' of styles that can be grouped together and used in   */ | 
|---|
| 224 | /* rules below.  A blank entry "" is required at the end of these!       */ | 
|---|
| 225 | #define STYLE_CLASS_RULES_SIZE  5 | 
|---|
| 226 |  | 
|---|
| 227 | static const SPH_Font_Class  STYLE_CLASS_Rules | 
|---|
| 228 | [STYLE_CLASS_RULES_SIZE] = | 
|---|
| 229 | { | 
|---|
| 230 | { "Regular Class", | 
|---|
| 231 | { "Regular", | 
|---|
| 232 | "Book", | 
|---|
| 233 | "Medium", | 
|---|
| 234 | "Roman", | 
|---|
| 235 | "Normal", | 
|---|
| 236 | "", | 
|---|
| 237 | }, | 
|---|
| 238 | }, | 
|---|
| 239 | { "Regular/Italic Class", | 
|---|
| 240 | { "Regular", | 
|---|
| 241 | "Book", | 
|---|
| 242 | "Medium", | 
|---|
| 243 | "Italic", | 
|---|
| 244 | "Oblique", | 
|---|
| 245 | "Roman", | 
|---|
| 246 | "Normal", | 
|---|
| 247 | "", | 
|---|
| 248 | }, | 
|---|
| 249 | }, | 
|---|
| 250 | { "Bold/BoldItalic Class", | 
|---|
| 251 | { "Bold", | 
|---|
| 252 | "Bold Italic", | 
|---|
| 253 | "Black", | 
|---|
| 254 | "", | 
|---|
| 255 | }, | 
|---|
| 256 | }, | 
|---|
| 257 | { "Bold/Italic/BoldItalic Class", | 
|---|
| 258 | { "Bold", | 
|---|
| 259 | "Bold Italic", | 
|---|
| 260 | "Black", | 
|---|
| 261 | "Italic", | 
|---|
| 262 | "Oblique", | 
|---|
| 263 | "", | 
|---|
| 264 | }, | 
|---|
| 265 | }, | 
|---|
| 266 | { "Regular/Bold Class", | 
|---|
| 267 | { "Regular", | 
|---|
| 268 | "Book", | 
|---|
| 269 | "Medium", | 
|---|
| 270 | "Normal", | 
|---|
| 271 | "Roman", | 
|---|
| 272 | "Bold", | 
|---|
| 273 | "Black", | 
|---|
| 274 | "", | 
|---|
| 275 | }, | 
|---|
| 276 | }, | 
|---|
| 277 | }; | 
|---|
| 278 |  | 
|---|
| 279 |  | 
|---|
| 280 | /* Force special legacy fixes for fonts.                                 */ | 
|---|
| 281 | #define COMPATIBILITY_MODE_RULES_SIZE  1 | 
|---|
| 282 |  | 
|---|
| 283 | static const SPH_TweakRule  COMPATIBILITY_MODE_Rules | 
|---|
| 284 | [COMPATIBILITY_MODE_RULES_SIZE] = | 
|---|
| 285 | { | 
|---|
| 286 | { "Verdana Clones", 0, "", 0 }, | 
|---|
| 287 | }; | 
|---|
| 288 |  | 
|---|
| 289 |  | 
|---|
| 290 | /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting.         */ | 
|---|
| 291 | #define PIXEL_HINTING_RULES_SIZE  2 | 
|---|
| 292 |  | 
|---|
| 293 | static const SPH_TweakRule  PIXEL_HINTING_Rules | 
|---|
| 294 | [PIXEL_HINTING_RULES_SIZE] = | 
|---|
| 295 | { | 
|---|
| 296 | /* these characters are almost always safe */ | 
|---|
| 297 | { "Courier New", 12, "Italic", 'z' }, | 
|---|
| 298 | { "Courier New", 11, "Italic", 'z' }, | 
|---|
| 299 | }; | 
|---|
| 300 |  | 
|---|
| 301 |  | 
|---|
| 302 | /* Subpixel hinting ignores SHPIX rules on X.  Force SHPIX for these.    */ | 
|---|
| 303 | #define DO_SHPIX_RULES_SIZE  1 | 
|---|
| 304 |  | 
|---|
| 305 | static const SPH_TweakRule  DO_SHPIX_Rules | 
|---|
| 306 | [DO_SHPIX_RULES_SIZE] = | 
|---|
| 307 | { | 
|---|
| 308 | { "-", 0, "", 0 }, | 
|---|
| 309 | }; | 
|---|
| 310 |  | 
|---|
| 311 |  | 
|---|
| 312 | /* Skip Y moves that start with a point that is not on a Y pixel         */ | 
|---|
| 313 | /* boundary and don't move that point to a Y pixel boundary.             */ | 
|---|
| 314 | #define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE  4 | 
|---|
| 315 |  | 
|---|
| 316 | static const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules | 
|---|
| 317 | [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] = | 
|---|
| 318 | { | 
|---|
| 319 | /* fix vwxyz thinness*/ | 
|---|
| 320 | { "Consolas", 0, "", 0 }, | 
|---|
| 321 | /* Fix thin middle stems */ | 
|---|
| 322 | { "Core MS Legacy Fonts", 0, "Regular", 0 }, | 
|---|
| 323 | /* Cyrillic small letter I */ | 
|---|
| 324 | { "Legacy Sans Fonts", 0, "", 0 }, | 
|---|
| 325 | /* Fix artifacts with some Regular & Bold */ | 
|---|
| 326 | { "Verdana Clones", 0, "", 0 }, | 
|---|
| 327 | }; | 
|---|
| 328 |  | 
|---|
| 329 |  | 
|---|
| 330 | #define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1 | 
|---|
| 331 |  | 
|---|
| 332 | static const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions | 
|---|
| 333 | [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = | 
|---|
| 334 | { | 
|---|
| 335 | /* Fixes < and > */ | 
|---|
| 336 | { "Courier New", 0, "Regular", 0 }, | 
|---|
| 337 | }; | 
|---|
| 338 |  | 
|---|
| 339 |  | 
|---|
| 340 | /* Skip Y moves that start with a point that is not on a Y pixel         */ | 
|---|
| 341 | /* boundary and don't move that point to a Y pixel boundary.             */ | 
|---|
| 342 | #define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE  2 | 
|---|
| 343 |  | 
|---|
| 344 | static const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules | 
|---|
| 345 | [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] = | 
|---|
| 346 | { | 
|---|
| 347 | /* Maintain thickness of diagonal in 'N' */ | 
|---|
| 348 | { "Times New Roman", 0, "Regular/Bold Class", 'N' }, | 
|---|
| 349 | { "Georgia", 0, "Regular/Bold Class", 'N' }, | 
|---|
| 350 | }; | 
|---|
| 351 |  | 
|---|
| 352 |  | 
|---|
| 353 | /* Skip Y moves that move a point off a Y pixel boundary.                */ | 
|---|
| 354 | #define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE  1 | 
|---|
| 355 |  | 
|---|
| 356 | static const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules | 
|---|
| 357 | [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] = | 
|---|
| 358 | { | 
|---|
| 359 | { "-", 0, "", 0 }, | 
|---|
| 360 | }; | 
|---|
| 361 |  | 
|---|
| 362 |  | 
|---|
| 363 | #define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1 | 
|---|
| 364 |  | 
|---|
| 365 | static const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions | 
|---|
| 366 | [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = | 
|---|
| 367 | { | 
|---|
| 368 | { "-", 0, "", 0 }, | 
|---|
| 369 | }; | 
|---|
| 370 |  | 
|---|
| 371 |  | 
|---|
| 372 | /* Round moves that don't move a point to a Y pixel boundary.            */ | 
|---|
| 373 | #define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE  2 | 
|---|
| 374 |  | 
|---|
| 375 | static const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules | 
|---|
| 376 | [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] = | 
|---|
| 377 | { | 
|---|
| 378 | /* Droid font instructions don't snap Y to pixels */ | 
|---|
| 379 | { "Droid Sans", 0, "Regular/Italic Class", 0 }, | 
|---|
| 380 | { "Droid Sans Mono", 0, "", 0 }, | 
|---|
| 381 | }; | 
|---|
| 382 |  | 
|---|
| 383 |  | 
|---|
| 384 | #define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1 | 
|---|
| 385 |  | 
|---|
| 386 | static const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions | 
|---|
| 387 | [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] = | 
|---|
| 388 | { | 
|---|
| 389 | { "-", 0, "", 0 }, | 
|---|
| 390 | }; | 
|---|
| 391 |  | 
|---|
| 392 |  | 
|---|
| 393 | /* Allow a Direct_Move along X freedom vector if matched.                */ | 
|---|
| 394 | #define ALLOW_X_DMOVE_RULES_SIZE  1 | 
|---|
| 395 |  | 
|---|
| 396 | static const SPH_TweakRule  ALLOW_X_DMOVE_Rules | 
|---|
| 397 | [ALLOW_X_DMOVE_RULES_SIZE] = | 
|---|
| 398 | { | 
|---|
| 399 | /* Fixes vanishing diagonal in 4 */ | 
|---|
| 400 | { "Verdana", 0, "Regular", '4' }, | 
|---|
| 401 | }; | 
|---|
| 402 |  | 
|---|
| 403 |  | 
|---|
| 404 | /* Return MS rasterizer version 35 if matched.                           */ | 
|---|
| 405 | #define RASTERIZER_35_RULES_SIZE  8 | 
|---|
| 406 |  | 
|---|
| 407 | static const SPH_TweakRule  RASTERIZER_35_Rules | 
|---|
| 408 | [RASTERIZER_35_RULES_SIZE] = | 
|---|
| 409 | { | 
|---|
| 410 | /* This seems to be the only way to make these look good */ | 
|---|
| 411 | { "Times New Roman", 0, "Regular", 'i' }, | 
|---|
| 412 | { "Times New Roman", 0, "Regular", 'j' }, | 
|---|
| 413 | { "Times New Roman", 0, "Regular", 'm' }, | 
|---|
| 414 | { "Times New Roman", 0, "Regular", 'r' }, | 
|---|
| 415 | { "Times New Roman", 0, "Regular", 'a' }, | 
|---|
| 416 | { "Times New Roman", 0, "Regular", 'n' }, | 
|---|
| 417 | { "Times New Roman", 0, "Regular", 'p' }, | 
|---|
| 418 | { "Times", 0, "", 0 }, | 
|---|
| 419 | }; | 
|---|
| 420 |  | 
|---|
| 421 |  | 
|---|
| 422 | /* Don't round to the subpixel grid.  Round to pixel grid.               */ | 
|---|
| 423 | #define NORMAL_ROUND_RULES_SIZE  1 | 
|---|
| 424 |  | 
|---|
| 425 | static const SPH_TweakRule  NORMAL_ROUND_Rules | 
|---|
| 426 | [NORMAL_ROUND_RULES_SIZE] = | 
|---|
| 427 | { | 
|---|
| 428 | /* Fix serif thickness for certain ppems */ | 
|---|
| 429 | /* Can probably be generalized somehow   */ | 
|---|
| 430 | { "Courier New", 0, "", 0 }, | 
|---|
| 431 | }; | 
|---|
| 432 |  | 
|---|
| 433 |  | 
|---|
| 434 | /* Skip IUP instructions if matched.                                     */ | 
|---|
| 435 | #define SKIP_IUP_RULES_SIZE  1 | 
|---|
| 436 |  | 
|---|
| 437 | static const SPH_TweakRule  SKIP_IUP_Rules | 
|---|
| 438 | [SKIP_IUP_RULES_SIZE] = | 
|---|
| 439 | { | 
|---|
| 440 | { "Arial", 13, "Regular", 'a' }, | 
|---|
| 441 | }; | 
|---|
| 442 |  | 
|---|
| 443 |  | 
|---|
| 444 | /* Skip MIAP Twilight hack if matched.                                   */ | 
|---|
| 445 | #define MIAP_HACK_RULES_SIZE  1 | 
|---|
| 446 |  | 
|---|
| 447 | static const SPH_TweakRule  MIAP_HACK_Rules | 
|---|
| 448 | [MIAP_HACK_RULES_SIZE] = | 
|---|
| 449 | { | 
|---|
| 450 | { "Geneva", 12, "", 0 }, | 
|---|
| 451 | }; | 
|---|
| 452 |  | 
|---|
| 453 |  | 
|---|
| 454 | /* Skip DELTAP instructions if matched.                                  */ | 
|---|
| 455 | #define ALWAYS_SKIP_DELTAP_RULES_SIZE  23 | 
|---|
| 456 |  | 
|---|
| 457 | static const SPH_TweakRule  ALWAYS_SKIP_DELTAP_Rules | 
|---|
| 458 | [ALWAYS_SKIP_DELTAP_RULES_SIZE] = | 
|---|
| 459 | { | 
|---|
| 460 | { "Georgia", 0, "Regular", 'k' }, | 
|---|
| 461 | /* fix various problems with e in different versions */ | 
|---|
| 462 | { "Trebuchet MS", 14, "Regular", 'e' }, | 
|---|
| 463 | { "Trebuchet MS", 13, "Regular", 'e' }, | 
|---|
| 464 | { "Trebuchet MS", 15, "Regular", 'e' }, | 
|---|
| 465 | { "Trebuchet MS", 0, "Italic", 'v' }, | 
|---|
| 466 | { "Trebuchet MS", 0, "Italic", 'w' }, | 
|---|
| 467 | { "Trebuchet MS", 0, "Regular", 'Y' }, | 
|---|
| 468 | { "Arial", 11, "Regular", 's' }, | 
|---|
| 469 | /* prevent problems with '3' and others */ | 
|---|
| 470 | { "Verdana", 10, "Regular", 0 }, | 
|---|
| 471 | { "Verdana", 9, "Regular", 0 }, | 
|---|
| 472 | /* Cyrillic small letter short I */ | 
|---|
| 473 | { "Legacy Sans Fonts", 0, "", 0x438 }, | 
|---|
| 474 | { "Legacy Sans Fonts", 0, "", 0x439 }, | 
|---|
| 475 | { "Arial", 10, "Regular", '6' }, | 
|---|
| 476 | { "Arial", 0, "Bold/BoldItalic Class", 'a' }, | 
|---|
| 477 | /* Make horizontal stems consistent with the rest */ | 
|---|
| 478 | { "Arial", 24, "Bold", 'a' }, | 
|---|
| 479 | { "Arial", 25, "Bold", 'a' }, | 
|---|
| 480 | { "Arial", 24, "Bold", 's' }, | 
|---|
| 481 | { "Arial", 25, "Bold", 's' }, | 
|---|
| 482 | { "Arial", 34, "Bold", 's' }, | 
|---|
| 483 | { "Arial", 35, "Bold", 's' }, | 
|---|
| 484 | { "Arial", 36, "Bold", 's' }, | 
|---|
| 485 | { "Arial", 25, "Regular", 's' }, | 
|---|
| 486 | { "Arial", 26, "Regular", 's' }, | 
|---|
| 487 | }; | 
|---|
| 488 |  | 
|---|
| 489 |  | 
|---|
| 490 | /* Always do DELTAP instructions if matched.                             */ | 
|---|
| 491 | #define ALWAYS_DO_DELTAP_RULES_SIZE  1 | 
|---|
| 492 |  | 
|---|
| 493 | static const SPH_TweakRule  ALWAYS_DO_DELTAP_Rules | 
|---|
| 494 | [ALWAYS_DO_DELTAP_RULES_SIZE] = | 
|---|
| 495 | { | 
|---|
| 496 | { "-", 0, "", 0 }, | 
|---|
| 497 | }; | 
|---|
| 498 |  | 
|---|
| 499 |  | 
|---|
| 500 | /* Don't allow ALIGNRP after IUP.                                        */ | 
|---|
| 501 | #define NO_ALIGNRP_AFTER_IUP_RULES_SIZE  1 | 
|---|
| 502 |  | 
|---|
| 503 | static const SPH_TweakRule  NO_ALIGNRP_AFTER_IUP_Rules | 
|---|
| 504 | [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] = | 
|---|
| 505 | { | 
|---|
| 506 | /* Prevent creation of dents in outline */ | 
|---|
| 507 | { "-", 0, "", 0 }, | 
|---|
| 508 | }; | 
|---|
| 509 |  | 
|---|
| 510 |  | 
|---|
| 511 | /* Don't allow DELTAP after IUP.                                         */ | 
|---|
| 512 | #define NO_DELTAP_AFTER_IUP_RULES_SIZE  1 | 
|---|
| 513 |  | 
|---|
| 514 | static const SPH_TweakRule  NO_DELTAP_AFTER_IUP_Rules | 
|---|
| 515 | [NO_DELTAP_AFTER_IUP_RULES_SIZE] = | 
|---|
| 516 | { | 
|---|
| 517 | { "-", 0, "", 0 }, | 
|---|
| 518 | }; | 
|---|
| 519 |  | 
|---|
| 520 |  | 
|---|
| 521 | /* Don't allow CALL after IUP.                                           */ | 
|---|
| 522 | #define NO_CALL_AFTER_IUP_RULES_SIZE  1 | 
|---|
| 523 |  | 
|---|
| 524 | static const SPH_TweakRule  NO_CALL_AFTER_IUP_Rules | 
|---|
| 525 | [NO_CALL_AFTER_IUP_RULES_SIZE] = | 
|---|
| 526 | { | 
|---|
| 527 | /* Prevent creation of dents in outline */ | 
|---|
| 528 | { "-", 0, "", 0 }, | 
|---|
| 529 | }; | 
|---|
| 530 |  | 
|---|
| 531 |  | 
|---|
| 532 | /* De-embolden these glyphs slightly.                                    */ | 
|---|
| 533 | #define DEEMBOLDEN_RULES_SIZE  9 | 
|---|
| 534 |  | 
|---|
| 535 | static const SPH_TweakRule  DEEMBOLDEN_Rules | 
|---|
| 536 | [DEEMBOLDEN_RULES_SIZE] = | 
|---|
| 537 | { | 
|---|
| 538 | { "Courier New", 0, "Bold", 'A' }, | 
|---|
| 539 | { "Courier New", 0, "Bold", 'W' }, | 
|---|
| 540 | { "Courier New", 0, "Bold", 'w' }, | 
|---|
| 541 | { "Courier New", 0, "Bold", 'M' }, | 
|---|
| 542 | { "Courier New", 0, "Bold", 'X' }, | 
|---|
| 543 | { "Courier New", 0, "Bold", 'K' }, | 
|---|
| 544 | { "Courier New", 0, "Bold", 'x' }, | 
|---|
| 545 | { "Courier New", 0, "Bold", 'z' }, | 
|---|
| 546 | { "Courier New", 0, "Bold", 'v' }, | 
|---|
| 547 | }; | 
|---|
| 548 |  | 
|---|
| 549 |  | 
|---|
| 550 | /* Embolden these glyphs slightly.                                       */ | 
|---|
| 551 | #define EMBOLDEN_RULES_SIZE  2 | 
|---|
| 552 |  | 
|---|
| 553 | static const SPH_TweakRule  EMBOLDEN_Rules | 
|---|
| 554 | [EMBOLDEN_RULES_SIZE] = | 
|---|
| 555 | { | 
|---|
| 556 | { "Courier New", 0, "Regular", 0 }, | 
|---|
| 557 | { "Courier New", 0, "Italic", 0 }, | 
|---|
| 558 | }; | 
|---|
| 559 |  | 
|---|
| 560 |  | 
|---|
| 561 | /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7       */ | 
|---|
| 562 | /* similar to Windows XP.                                                */ | 
|---|
| 563 | #define TIMES_NEW_ROMAN_HACK_RULES_SIZE  12 | 
|---|
| 564 |  | 
|---|
| 565 | static const SPH_TweakRule  TIMES_NEW_ROMAN_HACK_Rules | 
|---|
| 566 | [TIMES_NEW_ROMAN_HACK_RULES_SIZE] = | 
|---|
| 567 | { | 
|---|
| 568 | { "Times New Roman", 16, "Italic", '2' }, | 
|---|
| 569 | { "Times New Roman", 16, "Italic", '5' }, | 
|---|
| 570 | { "Times New Roman", 16, "Italic", '7' }, | 
|---|
| 571 | { "Times New Roman", 16, "Regular", '2' }, | 
|---|
| 572 | { "Times New Roman", 16, "Regular", '5' }, | 
|---|
| 573 | { "Times New Roman", 16, "Regular", '7' }, | 
|---|
| 574 | { "Times New Roman", 17, "Italic", '2' }, | 
|---|
| 575 | { "Times New Roman", 17, "Italic", '5' }, | 
|---|
| 576 | { "Times New Roman", 17, "Italic", '7' }, | 
|---|
| 577 | { "Times New Roman", 17, "Regular", '2' }, | 
|---|
| 578 | { "Times New Roman", 17, "Regular", '5' }, | 
|---|
| 579 | { "Times New Roman", 17, "Regular", '7' }, | 
|---|
| 580 | }; | 
|---|
| 581 |  | 
|---|
| 582 |  | 
|---|
| 583 | /* This fudges distance on 2 to get rid of the vanishing stem issue.     */ | 
|---|
| 584 | /* A real solution to this is certainly welcome.                         */ | 
|---|
| 585 | #define COURIER_NEW_2_HACK_RULES_SIZE  15 | 
|---|
| 586 |  | 
|---|
| 587 | static const SPH_TweakRule  COURIER_NEW_2_HACK_Rules | 
|---|
| 588 | [COURIER_NEW_2_HACK_RULES_SIZE] = | 
|---|
| 589 | { | 
|---|
| 590 | { "Courier New", 10, "Regular", '2' }, | 
|---|
| 591 | { "Courier New", 11, "Regular", '2' }, | 
|---|
| 592 | { "Courier New", 12, "Regular", '2' }, | 
|---|
| 593 | { "Courier New", 13, "Regular", '2' }, | 
|---|
| 594 | { "Courier New", 14, "Regular", '2' }, | 
|---|
| 595 | { "Courier New", 15, "Regular", '2' }, | 
|---|
| 596 | { "Courier New", 16, "Regular", '2' }, | 
|---|
| 597 | { "Courier New", 17, "Regular", '2' }, | 
|---|
| 598 | { "Courier New", 18, "Regular", '2' }, | 
|---|
| 599 | { "Courier New", 19, "Regular", '2' }, | 
|---|
| 600 | { "Courier New", 20, "Regular", '2' }, | 
|---|
| 601 | { "Courier New", 21, "Regular", '2' }, | 
|---|
| 602 | { "Courier New", 22, "Regular", '2' }, | 
|---|
| 603 | { "Courier New", 23, "Regular", '2' }, | 
|---|
| 604 | { "Courier New", 24, "Regular", '2' }, | 
|---|
| 605 | }; | 
|---|
| 606 |  | 
|---|
| 607 |  | 
|---|
| 608 | #ifndef FORCE_NATURAL_WIDTHS | 
|---|
| 609 |  | 
|---|
| 610 | /* Use compatible widths with these glyphs.  Compatible widths is always */ | 
|---|
| 611 | /* on when doing B/W TrueType instructing, but is used selectively here, */ | 
|---|
| 612 | /* typically on glyphs with 3 or more vertical stems.                    */ | 
|---|
| 613 | #define COMPATIBLE_WIDTHS_RULES_SIZE  38 | 
|---|
| 614 |  | 
|---|
| 615 | static const SPH_TweakRule  COMPATIBLE_WIDTHS_Rules | 
|---|
| 616 | [COMPATIBLE_WIDTHS_RULES_SIZE] = | 
|---|
| 617 | { | 
|---|
| 618 | { "Arial Unicode MS", 12, "Regular Class", 'm' }, | 
|---|
| 619 | { "Arial Unicode MS", 14, "Regular Class", 'm' }, | 
|---|
| 620 | /* Cyrillic small letter sha */ | 
|---|
| 621 | { "Arial", 10, "Regular Class", 0x448 }, | 
|---|
| 622 | { "Arial", 11, "Regular Class", 'm' }, | 
|---|
| 623 | { "Arial", 12, "Regular Class", 'm' }, | 
|---|
| 624 | /* Cyrillic small letter sha */ | 
|---|
| 625 | { "Arial", 12, "Regular Class", 0x448 }, | 
|---|
| 626 | { "Arial", 13, "Regular Class", 0x448 }, | 
|---|
| 627 | { "Arial", 14, "Regular Class", 'm' }, | 
|---|
| 628 | /* Cyrillic small letter sha */ | 
|---|
| 629 | { "Arial", 14, "Regular Class", 0x448 }, | 
|---|
| 630 | { "Arial", 15, "Regular Class", 0x448 }, | 
|---|
| 631 | { "Arial", 17, "Regular Class", 'm' }, | 
|---|
| 632 | { "DejaVu Sans", 15, "Regular Class", 0 }, | 
|---|
| 633 | { "Microsoft Sans Serif", 11, "Regular Class", 0 }, | 
|---|
| 634 | { "Microsoft Sans Serif", 12, "Regular Class", 0 }, | 
|---|
| 635 | { "Segoe UI", 11, "Regular Class", 0 }, | 
|---|
| 636 | { "Monaco", 0, "Regular Class", 0 }, | 
|---|
| 637 | { "Segoe UI", 12, "Regular Class", 'm' }, | 
|---|
| 638 | { "Segoe UI", 14, "Regular Class", 'm' }, | 
|---|
| 639 | { "Tahoma", 11, "Regular Class", 0 }, | 
|---|
| 640 | { "Times New Roman", 16, "Regular Class", 'c' }, | 
|---|
| 641 | { "Times New Roman", 16, "Regular Class", 'm' }, | 
|---|
| 642 | { "Times New Roman", 16, "Regular Class", 'o' }, | 
|---|
| 643 | { "Times New Roman", 16, "Regular Class", 'w' }, | 
|---|
| 644 | { "Trebuchet MS", 11, "Regular Class", 0 }, | 
|---|
| 645 | { "Trebuchet MS", 12, "Regular Class", 0 }, | 
|---|
| 646 | { "Trebuchet MS", 14, "Regular Class", 0 }, | 
|---|
| 647 | { "Trebuchet MS", 15, "Regular Class", 0 }, | 
|---|
| 648 | { "Ubuntu", 12, "Regular Class", 'm' }, | 
|---|
| 649 | /* Cyrillic small letter sha */ | 
|---|
| 650 | { "Verdana", 10, "Regular Class", 0x448 }, | 
|---|
| 651 | { "Verdana", 11, "Regular Class", 0x448 }, | 
|---|
| 652 | { "Verdana and Clones", 12, "Regular Class", 'i' }, | 
|---|
| 653 | { "Verdana and Clones", 12, "Regular Class", 'j' }, | 
|---|
| 654 | { "Verdana and Clones", 12, "Regular Class", 'l' }, | 
|---|
| 655 | { "Verdana and Clones", 12, "Regular Class", 'm' }, | 
|---|
| 656 | { "Verdana and Clones", 13, "Regular Class", 'i' }, | 
|---|
| 657 | { "Verdana and Clones", 13, "Regular Class", 'j' }, | 
|---|
| 658 | { "Verdana and Clones", 13, "Regular Class", 'l' }, | 
|---|
| 659 | { "Verdana and Clones", 14, "Regular Class", 'm' }, | 
|---|
| 660 | }; | 
|---|
| 661 |  | 
|---|
| 662 |  | 
|---|
| 663 | /* Scaling slightly in the x-direction prior to hinting results in       */ | 
|---|
| 664 | /* more visually pleasing glyphs in certain cases.                       */ | 
|---|
| 665 | /* This sometimes needs to be coordinated with compatible width rules.   */ | 
|---|
| 666 | /* A value of 1000 corresponds to a scaled value of 1.0.                 */ | 
|---|
| 667 |  | 
|---|
| 668 | #define X_SCALING_RULES_SIZE  50 | 
|---|
| 669 |  | 
|---|
| 670 | static const SPH_ScaleRule  X_SCALING_Rules[X_SCALING_RULES_SIZE] = | 
|---|
| 671 | { | 
|---|
| 672 | { "DejaVu Sans", 12, "Regular Class", 'm', 950 }, | 
|---|
| 673 | { "Verdana and Clones", 12, "Regular Class", 'a', 1100 }, | 
|---|
| 674 | { "Verdana and Clones", 13, "Regular Class", 'a', 1050 }, | 
|---|
| 675 | { "Arial", 11, "Regular Class", 'm', 975 }, | 
|---|
| 676 | { "Arial", 12, "Regular Class", 'm', 1050 }, | 
|---|
| 677 | /* Cyrillic small letter el */ | 
|---|
| 678 | { "Arial", 13, "Regular Class", 0x43B, 950 }, | 
|---|
| 679 | { "Arial", 13, "Regular Class", 'o', 950 }, | 
|---|
| 680 | { "Arial", 13, "Regular Class", 'e', 950 }, | 
|---|
| 681 | { "Arial", 14, "Regular Class", 'm', 950 }, | 
|---|
| 682 | /* Cyrillic small letter el */ | 
|---|
| 683 | { "Arial", 15, "Regular Class", 0x43B, 925 }, | 
|---|
| 684 | { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 }, | 
|---|
| 685 | { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 }, | 
|---|
| 686 | { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 }, | 
|---|
| 687 | { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 }, | 
|---|
| 688 | { "DejaVu Sans", 12, "Regular Class", 'l', 975 }, | 
|---|
| 689 | { "DejaVu Sans", 12, "Regular Class", 'i', 975 }, | 
|---|
| 690 | { "DejaVu Sans", 12, "Regular Class", 'j', 975 }, | 
|---|
| 691 | { "DejaVu Sans", 13, "Regular Class", 'l', 950 }, | 
|---|
| 692 | { "DejaVu Sans", 13, "Regular Class", 'i', 950 }, | 
|---|
| 693 | { "DejaVu Sans", 13, "Regular Class", 'j', 950 }, | 
|---|
| 694 | { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 }, | 
|---|
| 695 | { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 }, | 
|---|
| 696 | { "Georgia", 10, "", 0, 1050 }, | 
|---|
| 697 | { "Georgia", 11, "", 0, 1100 }, | 
|---|
| 698 | { "Georgia", 12, "", 0, 1025 }, | 
|---|
| 699 | { "Georgia", 13, "", 0, 1050 }, | 
|---|
| 700 | { "Georgia", 16, "", 0, 1050 }, | 
|---|
| 701 | { "Georgia", 17, "", 0, 1030 }, | 
|---|
| 702 | { "Liberation Sans", 12, "Regular Class", 'm', 1100 }, | 
|---|
| 703 | { "Lucida Grande", 11, "Regular Class", 'm', 1100 }, | 
|---|
| 704 | { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 }, | 
|---|
| 705 | { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 }, | 
|---|
| 706 | { "Segoe UI", 12, "Regular Class", 'H', 1050 }, | 
|---|
| 707 | { "Segoe UI", 12, "Regular Class", 'm', 1050 }, | 
|---|
| 708 | { "Segoe UI", 14, "Regular Class", 'm', 1050 }, | 
|---|
| 709 | { "Tahoma", 11, "Regular Class", 'i', 975 }, | 
|---|
| 710 | { "Tahoma", 11, "Regular Class", 'l', 975 }, | 
|---|
| 711 | { "Tahoma", 11, "Regular Class", 'j', 900 }, | 
|---|
| 712 | { "Tahoma", 11, "Regular Class", 'm', 918 }, | 
|---|
| 713 | { "Verdana", 10, "Regular/Italic Class", 0, 1100 }, | 
|---|
| 714 | { "Verdana", 12, "Regular Class", 'm', 975 }, | 
|---|
| 715 | { "Verdana", 12, "Regular/Italic Class", 0, 1050 }, | 
|---|
| 716 | { "Verdana", 13, "Regular/Italic Class", 'i', 950 }, | 
|---|
| 717 | { "Verdana", 13, "Regular/Italic Class", 'j', 950 }, | 
|---|
| 718 | { "Verdana", 13, "Regular/Italic Class", 'l', 950 }, | 
|---|
| 719 | { "Verdana", 16, "Regular Class", 0, 1050 }, | 
|---|
| 720 | { "Verdana", 9, "Regular/Italic Class", 0, 1050 }, | 
|---|
| 721 | { "Times New Roman", 16, "Regular Class", 'm', 918 }, | 
|---|
| 722 | { "Trebuchet MS", 11, "Regular Class", 'm', 800 }, | 
|---|
| 723 | { "Trebuchet MS", 12, "Regular Class", 'm', 800 }, | 
|---|
| 724 | }; | 
|---|
| 725 |  | 
|---|
| 726 | #else | 
|---|
| 727 |  | 
|---|
| 728 | #define COMPATIBLE_WIDTHS_RULES_SIZE  1 | 
|---|
| 729 |  | 
|---|
| 730 | static const SPH_TweakRule  COMPATIBLE_WIDTHS_Rules | 
|---|
| 731 | [COMPATIBLE_WIDTHS_RULES_SIZE] = | 
|---|
| 732 | { | 
|---|
| 733 | { "-", 0, "", 0 }, | 
|---|
| 734 | }; | 
|---|
| 735 |  | 
|---|
| 736 |  | 
|---|
| 737 | #define X_SCALING_RULES_SIZE  1 | 
|---|
| 738 |  | 
|---|
| 739 | static const SPH_ScaleRule  X_SCALING_Rules | 
|---|
| 740 | [X_SCALING_RULES_SIZE] = | 
|---|
| 741 | { | 
|---|
| 742 | { "-", 0, "", 0, 1000 }, | 
|---|
| 743 | }; | 
|---|
| 744 |  | 
|---|
| 745 | #endif /* FORCE_NATURAL_WIDTHS */ | 
|---|
| 746 |  | 
|---|
| 747 |  | 
|---|
| 748 | static FT_Bool | 
|---|
| 749 | is_member_of_family_class( const FT_String*  detected_font_name, | 
|---|
| 750 | const FT_String*  rule_font_name ) | 
|---|
| 751 | { | 
|---|
| 752 | FT_UInt  i, j; | 
|---|
| 753 |  | 
|---|
| 754 |  | 
|---|
| 755 | /* Does font name match rule family? */ | 
|---|
| 756 | if ( ft_strcmp( detected_font_name, rule_font_name ) == 0 ) | 
|---|
| 757 | return TRUE; | 
|---|
| 758 |  | 
|---|
| 759 | /* Is font name a wildcard ""? */ | 
|---|
| 760 | if ( ft_strcmp( rule_font_name, "") == 0 ) | 
|---|
| 761 | return TRUE; | 
|---|
| 762 |  | 
|---|
| 763 | /* Is font name contained in a class list? */ | 
|---|
| 764 | for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ ) | 
|---|
| 765 | { | 
|---|
| 766 | if ( ft_strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 ) | 
|---|
| 767 | { | 
|---|
| 768 | for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) | 
|---|
| 769 | { | 
|---|
| 770 | if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], "") == 0 ) | 
|---|
| 771 | continue; | 
|---|
| 772 | if ( ft_strcmp( FAMILY_CLASS_Rules[i].member[j], | 
|---|
| 773 | detected_font_name ) == 0 ) | 
|---|
| 774 | return TRUE; | 
|---|
| 775 | } | 
|---|
| 776 | } | 
|---|
| 777 | } | 
|---|
| 778 |  | 
|---|
| 779 | return FALSE; | 
|---|
| 780 | } | 
|---|
| 781 |  | 
|---|
| 782 |  | 
|---|
| 783 | static FT_Bool | 
|---|
| 784 | is_member_of_style_class( const FT_String*  detected_font_style, | 
|---|
| 785 | const FT_String*  rule_font_style ) | 
|---|
| 786 | { | 
|---|
| 787 | FT_UInt  i, j; | 
|---|
| 788 |  | 
|---|
| 789 |  | 
|---|
| 790 | /* Does font style match rule style? */ | 
|---|
| 791 | if ( ft_strcmp( detected_font_style, rule_font_style ) == 0 ) | 
|---|
| 792 | return TRUE; | 
|---|
| 793 |  | 
|---|
| 794 | /* Is font style a wildcard ""? */ | 
|---|
| 795 | if ( ft_strcmp( rule_font_style, "") == 0 ) | 
|---|
| 796 | return TRUE; | 
|---|
| 797 |  | 
|---|
| 798 | /* Is font style contained in a class list? */ | 
|---|
| 799 | for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ ) | 
|---|
| 800 | { | 
|---|
| 801 | if ( ft_strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 ) | 
|---|
| 802 | { | 
|---|
| 803 | for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ ) | 
|---|
| 804 | { | 
|---|
| 805 | if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], "") == 0 ) | 
|---|
| 806 | continue; | 
|---|
| 807 | if ( ft_strcmp( STYLE_CLASS_Rules[i].member[j], | 
|---|
| 808 | detected_font_style ) == 0 ) | 
|---|
| 809 | return TRUE; | 
|---|
| 810 | } | 
|---|
| 811 | } | 
|---|
| 812 | } | 
|---|
| 813 |  | 
|---|
| 814 | return FALSE; | 
|---|
| 815 | } | 
|---|
| 816 |  | 
|---|
| 817 |  | 
|---|
| 818 | FT_LOCAL_DEF( FT_Bool ) | 
|---|
| 819 | sph_test_tweak( TT_Face               face, | 
|---|
| 820 | const FT_String*      family, | 
|---|
| 821 | FT_UInt               ppem, | 
|---|
| 822 | const FT_String*      style, | 
|---|
| 823 | FT_UInt               glyph_index, | 
|---|
| 824 | const SPH_TweakRule*  rule, | 
|---|
| 825 | FT_UInt               num_rules ) | 
|---|
| 826 | { | 
|---|
| 827 | FT_UInt  i; | 
|---|
| 828 |  | 
|---|
| 829 |  | 
|---|
| 830 | /* rule checks may be able to be optimized further */ | 
|---|
| 831 | for ( i = 0; i < num_rules; i++ ) | 
|---|
| 832 | { | 
|---|
| 833 | if ( family                                                   && | 
|---|
| 834 | ( is_member_of_family_class ( family, rule[i].family ) ) ) | 
|---|
| 835 | if ( rule[i].ppem == 0    || | 
|---|
| 836 | rule[i].ppem == ppem ) | 
|---|
| 837 | if ( style                                             && | 
|---|
| 838 | is_member_of_style_class ( style, rule[i].style ) ) | 
|---|
| 839 | if ( rule[i].glyph == 0                                || | 
|---|
| 840 | FT_Get_Char_Index( (FT_Face)face, | 
|---|
| 841 | rule[i].glyph ) == glyph_index ) | 
|---|
| 842 | return TRUE; | 
|---|
| 843 | } | 
|---|
| 844 |  | 
|---|
| 845 | return FALSE; | 
|---|
| 846 | } | 
|---|
| 847 |  | 
|---|
| 848 |  | 
|---|
| 849 | static FT_UInt | 
|---|
| 850 | scale_test_tweak( TT_Face               face, | 
|---|
| 851 | const FT_String*      family, | 
|---|
| 852 | FT_UInt               ppem, | 
|---|
| 853 | const FT_String*      style, | 
|---|
| 854 | FT_UInt               glyph_index, | 
|---|
| 855 | const SPH_ScaleRule*  rule, | 
|---|
| 856 | FT_UInt               num_rules ) | 
|---|
| 857 | { | 
|---|
| 858 | FT_UInt  i; | 
|---|
| 859 |  | 
|---|
| 860 |  | 
|---|
| 861 | /* rule checks may be able to be optimized further */ | 
|---|
| 862 | for ( i = 0; i < num_rules; i++ ) | 
|---|
| 863 | { | 
|---|
| 864 | if ( family                                                   && | 
|---|
| 865 | ( is_member_of_family_class ( family, rule[i].family ) ) ) | 
|---|
| 866 | if ( rule[i].ppem == 0    || | 
|---|
| 867 | rule[i].ppem == ppem ) | 
|---|
| 868 | if ( style                                            && | 
|---|
| 869 | is_member_of_style_class( style, rule[i].style ) ) | 
|---|
| 870 | if ( rule[i].glyph == 0                                || | 
|---|
| 871 | FT_Get_Char_Index( (FT_Face)face, | 
|---|
| 872 | rule[i].glyph ) == glyph_index ) | 
|---|
| 873 | return rule[i].scale; | 
|---|
| 874 | } | 
|---|
| 875 |  | 
|---|
| 876 | return 1000; | 
|---|
| 877 | } | 
|---|
| 878 |  | 
|---|
| 879 |  | 
|---|
| 880 | FT_LOCAL_DEF( FT_UInt ) | 
|---|
| 881 | sph_test_tweak_x_scaling( TT_Face           face, | 
|---|
| 882 | const FT_String*  family, | 
|---|
| 883 | FT_UInt           ppem, | 
|---|
| 884 | const FT_String*  style, | 
|---|
| 885 | FT_UInt           glyph_index ) | 
|---|
| 886 | { | 
|---|
| 887 | return scale_test_tweak( face, family, ppem, style, glyph_index, | 
|---|
| 888 | X_SCALING_Rules, X_SCALING_RULES_SIZE ); | 
|---|
| 889 | } | 
|---|
| 890 |  | 
|---|
| 891 |  | 
|---|
| 892 | #define TWEAK_RULES( x )                                       \ | 
|---|
| 893 | if ( sph_test_tweak( face, family, ppem, style, glyph_index, \ | 
|---|
| 894 | x##_Rules, x##_RULES_SIZE ) )           \ | 
|---|
| 895 | loader->exec->sph_tweak_flags |= SPH_TWEAK_##x; | 
|---|
| 896 |  | 
|---|
| 897 | #define TWEAK_RULES_EXCEPTIONS( x )                                        \ | 
|---|
| 898 | if ( sph_test_tweak( face, family, ppem, style, glyph_index,             \ | 
|---|
| 899 | x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \ | 
|---|
| 900 | loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x; | 
|---|
| 901 |  | 
|---|
| 902 |  | 
|---|
| 903 | FT_LOCAL_DEF( void ) | 
|---|
| 904 | sph_set_tweaks( TT_Loader  loader, | 
|---|
| 905 | FT_UInt    glyph_index ) | 
|---|
| 906 | { | 
|---|
| 907 | TT_Face     face   = loader->face; | 
|---|
| 908 | FT_String*  family = face->root.family_name; | 
|---|
| 909 | FT_UInt     ppem   = loader->size->metrics->x_ppem; | 
|---|
| 910 | FT_String*  style  = face->root.style_name; | 
|---|
| 911 |  | 
|---|
| 912 |  | 
|---|
| 913 | /* don't apply rules if style isn't set */ | 
|---|
| 914 | if ( !face->root.style_name ) | 
|---|
| 915 | return; | 
|---|
| 916 |  | 
|---|
| 917 | #ifdef SPH_DEBUG_MORE_VERBOSE | 
|---|
| 918 | printf( "%s,%d,%s,%c=%d ", | 
|---|
| 919 | family, ppem, style, glyph_index, glyph_index ); | 
|---|
| 920 | #endif | 
|---|
| 921 |  | 
|---|
| 922 | TWEAK_RULES( PIXEL_HINTING ); | 
|---|
| 923 |  | 
|---|
| 924 | if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING ) | 
|---|
| 925 | { | 
|---|
| 926 | loader->exec->ignore_x_mode = FALSE; | 
|---|
| 927 | return; | 
|---|
| 928 | } | 
|---|
| 929 |  | 
|---|
| 930 | TWEAK_RULES( ALLOW_X_DMOVE ); | 
|---|
| 931 | TWEAK_RULES( ALWAYS_DO_DELTAP ); | 
|---|
| 932 | TWEAK_RULES( ALWAYS_SKIP_DELTAP ); | 
|---|
| 933 | TWEAK_RULES( DEEMBOLDEN ); | 
|---|
| 934 | TWEAK_RULES( DO_SHPIX ); | 
|---|
| 935 | TWEAK_RULES( EMBOLDEN ); | 
|---|
| 936 | TWEAK_RULES( MIAP_HACK ); | 
|---|
| 937 | TWEAK_RULES( NORMAL_ROUND ); | 
|---|
| 938 | TWEAK_RULES( NO_ALIGNRP_AFTER_IUP ); | 
|---|
| 939 | TWEAK_RULES( NO_CALL_AFTER_IUP ); | 
|---|
| 940 | TWEAK_RULES( NO_DELTAP_AFTER_IUP ); | 
|---|
| 941 | TWEAK_RULES( RASTERIZER_35 ); | 
|---|
| 942 | TWEAK_RULES( SKIP_IUP ); | 
|---|
| 943 |  | 
|---|
| 944 | TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES ); | 
|---|
| 945 | TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES ); | 
|---|
| 946 |  | 
|---|
| 947 | TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP ); | 
|---|
| 948 |  | 
|---|
| 949 | TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES ); | 
|---|
| 950 | TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES ); | 
|---|
| 951 |  | 
|---|
| 952 | TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES ); | 
|---|
| 953 | TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES ); | 
|---|
| 954 |  | 
|---|
| 955 | if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) | 
|---|
| 956 | { | 
|---|
| 957 | if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 ) | 
|---|
| 958 | { | 
|---|
| 959 | loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; | 
|---|
| 960 | loader->exec->size->cvt_ready    = -1; | 
|---|
| 961 |  | 
|---|
| 962 | tt_size_ready_bytecode( | 
|---|
| 963 | loader->exec->size, | 
|---|
| 964 | FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); | 
|---|
| 965 | } | 
|---|
| 966 | else | 
|---|
| 967 | loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35; | 
|---|
| 968 | } | 
|---|
| 969 | else | 
|---|
| 970 | { | 
|---|
| 971 | if ( loader->exec->rasterizer_version  != | 
|---|
| 972 | SPH_OPTION_SET_RASTERIZER_VERSION ) | 
|---|
| 973 | { | 
|---|
| 974 | loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; | 
|---|
| 975 | loader->exec->size->cvt_ready    = -1; | 
|---|
| 976 |  | 
|---|
| 977 | tt_size_ready_bytecode( | 
|---|
| 978 | loader->exec->size, | 
|---|
| 979 | FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) ); | 
|---|
| 980 | } | 
|---|
| 981 | else | 
|---|
| 982 | loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; | 
|---|
| 983 | } | 
|---|
| 984 |  | 
|---|
| 985 | if ( IS_HINTED( loader->load_flags ) ) | 
|---|
| 986 | { | 
|---|
| 987 | TWEAK_RULES( TIMES_NEW_ROMAN_HACK ); | 
|---|
| 988 | TWEAK_RULES( COURIER_NEW_2_HACK ); | 
|---|
| 989 | } | 
|---|
| 990 |  | 
|---|
| 991 | if ( sph_test_tweak( face, family, ppem, style, glyph_index, | 
|---|
| 992 | COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) ) | 
|---|
| 993 | loader->exec->face->sph_compatibility_mode = TRUE; | 
|---|
| 994 |  | 
|---|
| 995 |  | 
|---|
| 996 | if ( IS_HINTED( loader->load_flags ) ) | 
|---|
| 997 | { | 
|---|
| 998 | if ( sph_test_tweak( face, family, ppem, style, glyph_index, | 
|---|
| 999 | COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) ) | 
|---|
| 1000 | loader->exec->compatible_widths |= TRUE; | 
|---|
| 1001 | } | 
|---|
| 1002 | } | 
|---|
| 1003 |  | 
|---|
| 1004 | #else /* !(TT_USE_BYTECODE_INTERPRETER &&          */ | 
|---|
| 1005 | /*   TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ | 
|---|
| 1006 |  | 
|---|
| 1007 | /* ANSI C doesn't like empty source files */ | 
|---|
| 1008 | typedef int  _tt_subpix_dummy; | 
|---|
| 1009 |  | 
|---|
| 1010 | #endif /* !(TT_USE_BYTECODE_INTERPRETER &&          */ | 
|---|
| 1011 | /*   TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY) */ | 
|---|
| 1012 |  | 
|---|
| 1013 |  | 
|---|
| 1014 | /* END */ | 
|---|
| 1015 |  | 
|---|