| 1 | /* | 
| 2 |  * Copyright © 2018 Adobe Inc. | 
| 3 |  * | 
| 4 |  *  This is part of HarfBuzz, a text shaping library. | 
| 5 |  * | 
| 6 |  * Permission is hereby granted, without written agreement and without | 
| 7 |  * license or royalty fees, to use, copy, modify, and distribute this | 
| 8 |  * software and its documentation for any purpose, provided that the | 
| 9 |  * above copyright notice and the following two paragraphs appear in | 
| 10 |  * all copies of this software. | 
| 11 |  * | 
| 12 |  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR | 
| 13 |  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES | 
| 14 |  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN | 
| 15 |  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH | 
| 16 |  * DAMAGE. | 
| 17 |  * | 
| 18 |  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, | 
| 19 |  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND | 
| 20 |  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS | 
| 21 |  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO | 
| 22 |  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | 
| 23 |  * | 
| 24 |  * Adobe Author(s): Michiharu Ariza | 
| 25 |  */ | 
| 26 |  | 
| 27 | #include "hb.hh" | 
| 28 |  | 
| 29 | #ifndef HB_NO_CFF | 
| 30 |  | 
| 31 | #include "hb-draw.hh" | 
| 32 | #include "hb-algs.hh" | 
| 33 | #include "hb-ot-cff1-table.hh" | 
| 34 | #include "hb-cff1-interp-cs.hh" | 
| 35 |  | 
| 36 | using namespace CFF; | 
| 37 |  | 
| 38 | struct sid_to_gid_t | 
| 39 | { | 
| 40 |   uint16_t  sid; | 
| 41 |   uint8_t   gid; | 
| 42 |  | 
| 43 |   int cmp (uint16_t a) const | 
| 44 |   { | 
| 45 |     if (a == sid) return 0; | 
| 46 |     return (a < sid) ? -1 : 1; | 
| 47 |   } | 
| 48 | }; | 
| 49 |  | 
| 50 | /* SID to code */ | 
| 51 | static const uint8_t standard_encoding_to_code [] = | 
| 52 | { | 
| 53 |     0,   32,   33,   34,   35,   36,   37,   38,  39,   40,   41,   42,   43,   44,   45,   46, | 
| 54 |    47,   48,   49,   50,   51,   52,   53,   54,  55,   56,   57,   58,   59,   60,   61,   62, | 
| 55 |    63,   64,   65,   66,   67,   68,   69,   70,  71,   72,   73,   74,   75,   76,   77,   78, | 
| 56 |    79,   80,   81,   82,   83,   84,   85,   86,  87,   88,   89,   90,   91,   92,   93,   94, | 
| 57 |    95,   96,   97,   98,   99,  100,  101,  102, 103,  104,  105,  106,  107,  108,  109,  110, | 
| 58 |   111,  112,  113,  114,  115,  116,  117,  118, 119,  120,  121,  122,  123,  124,  125,  126, | 
| 59 |   161,  162,  163,  164,  165,  166,  167,  168, 169,  170,  171,  172,  173,  174,  175,  177, | 
| 60 |   178,  179,  180,  182,  183,  184,  185,  186, 187,  188,  189,  191,  193,  194,  195,  196, | 
| 61 |   197,  198,  199,  200,  202,  203,  205,  206, 207,  208,  225,  227,  232,  233,  234,  235, | 
| 62 |   241,  245,  248,  249,  250,  251 | 
| 63 | }; | 
| 64 |  | 
| 65 | /* SID to code */ | 
| 66 | static const uint8_t expert_encoding_to_code [] = | 
| 67 | { | 
| 68 |     0,   32,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   44,   45,   46, | 
| 69 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,   58,   59,    0,    0,    0, | 
| 70 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 71 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 72 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 73 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 74 |     0,    0,    0,   47,    0,    0,    0,    0,    0,    0,    0,    0,    0,   87,   88,    0, | 
| 75 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 76 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 77 |     0,    0,    0,    0,    0,    0,  201,    0,    0,    0,    0,  189,    0,    0,  188,    0, | 
| 78 |     0,    0,    0,  190,  202,    0,    0,    0,    0,  203,    0,    0,    0,    0,    0,    0, | 
| 79 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 80 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 81 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 82 |     0,    0,    0,    0,    0,   33,   34,   36,   37,   38,   39,   40,   41,   42,   43,   48, | 
| 83 |    49,   50,   51,   52,   53,   54,   55,   56,   57,   60,   61,   62,   63,   65,   66,   67, | 
| 84 |    68,   69,   73,   76,   77,   78,   79,   82,   83,   84,   86,   89,   90,   91,   93,   94, | 
| 85 |    95,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110, | 
| 86 |   111,  112,  113,  114,  115,  116,  117,  118,  119,  120,  121,  122,  123,  124,  125,  126, | 
| 87 |   161,  162,  163,  166,  167,  168,  169,  170,  172,  175,  178,  179,  182,  183,  184,  191, | 
| 88 |   192,  193,  194,  195,  196,  197,  200,  204,  205,  206,  207,  208,  209,  210,  211,  212, | 
| 89 |   213,  214,  215,  216,  217,  218,  219,  220,  221,  222,  223,  224,  225,  226,  227,  228, | 
| 90 |   229,  230,  231,  232,  233,  234,  235,  236,  237,  238,  239,  240,  241,  242,  243,  244, | 
| 91 |   245,  246,  247,  248,  249,  250,  251,  252,  253,  254,  255 | 
| 92 | }; | 
| 93 |  | 
| 94 | /* glyph ID to SID */ | 
| 95 | static const uint16_t expert_charset_to_sid [] = | 
| 96 | { | 
| 97 |     0,    1,  229,  230,  231,  232,  233,  234,  235,  236,  237,  238,   13,   14,   15,   99, | 
| 98 |   239,  240,  241,  242,  243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  252, | 
| 99 |   253,  254,  255,  256,  257,  258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110, | 
| 100 |   267,  268,  269,  270,  271,  272,  273,  274,  275,  276,  277,  278,  279,  280,  281,  282, | 
| 101 |   283,  284,  285,  286,  287,  288,  289,  290,  291,  292,  293,  294,  295,  296,  297,  298, | 
| 102 |   299,  300,  301,  302,  303,  304,  305,  306,  307,  308,  309,  310,  311,  312,  313,  314, | 
| 103 |   315,  316,  317,  318,  158,  155,  163,  319,  320,  321,  322,  323,  324,  325,  326,  150, | 
| 104 |   164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339,  340, | 
| 105 |   341,  342,  343,  344,  345,  346,  347,  348,  349,  350,  351,  352,  353,  354,  355,  356, | 
| 106 |   357,  358,  359,  360,  361,  362,  363,  364,  365,  366,  367,  368,  369,  370,  371,  372, | 
| 107 |   373,  374,  375,  376,  377,  378 | 
| 108 | }; | 
| 109 |  | 
| 110 | /* glyph ID to SID */ | 
| 111 | static const uint16_t expert_subset_charset_to_sid [] = | 
| 112 | { | 
| 113 |     0,    1,  231,  232,  235,  236,  237,  238,   13,   14,   15,   99,  239,  240,  241,  242, | 
| 114 |   243,  244,  245,  246,  247,  248,   27,   28,  249,  250,  251,  253,  254,  255,  256,  257, | 
| 115 |   258,  259,  260,  261,  262,  263,  264,  265,  266,  109,  110,  267,  268,  269,  270,  272, | 
| 116 |   300,  301,  302,  305,  314,  315,  158,  155,  163,  320,  321,  322,  323,  324,  325,  326, | 
| 117 |   150,  164,  169,  327,  328,  329,  330,  331,  332,  333,  334,  335,  336,  337,  338,  339, | 
| 118 |   340,  341,  342,  343,  344,  345,  346 | 
| 119 | }; | 
| 120 |  | 
| 121 | /* SID to glyph ID */ | 
| 122 | static const sid_to_gid_t expert_charset_sid_to_gid [] = | 
| 123 | { | 
| 124 |     { 1, 1 },     { 13, 12 },   { 14, 13 },   { 15, 14 }, | 
| 125 |     { 27, 26 },   { 28, 27 },   { 99, 15 },   { 109, 46 }, | 
| 126 |     { 110, 47 },  { 150, 111 }, { 155, 101 }, { 158, 100 }, | 
| 127 |     { 163, 102 }, { 164, 112 }, { 169, 113 }, { 229, 2 }, | 
| 128 |     { 230, 3 },   { 231, 4 },   { 232, 5 },   { 233, 6 }, | 
| 129 |     { 234, 7 },   { 235, 8 },   { 236, 9 },   { 237, 10 }, | 
| 130 |     { 238, 11 },  { 239, 16 },  { 240, 17 },  { 241, 18 }, | 
| 131 |     { 242, 19 },  { 243, 20 },  { 244, 21 },  { 245, 22 }, | 
| 132 |     { 246, 23 },  { 247, 24 },  { 248, 25 },  { 249, 28 }, | 
| 133 |     { 250, 29 },  { 251, 30 },  { 252, 31 },  { 253, 32 }, | 
| 134 |     { 254, 33 },  { 255, 34 },  { 256, 35 },  { 257, 36 }, | 
| 135 |     { 258, 37 },  { 259, 38 },  { 260, 39 },  { 261, 40 }, | 
| 136 |     { 262, 41 },  { 263, 42 },  { 264, 43 },  { 265, 44 }, | 
| 137 |     { 266, 45 },  { 267, 48 },  { 268, 49 },  { 269, 50 }, | 
| 138 |     { 270, 51 },  { 271, 52 },  { 272, 53 },  { 273, 54 }, | 
| 139 |     { 274, 55 },  { 275, 56 },  { 276, 57 },  { 277, 58 }, | 
| 140 |     { 278, 59 },  { 279, 60 },  { 280, 61 },  { 281, 62 }, | 
| 141 |     { 282, 63 },  { 283, 64 },  { 284, 65 },  { 285, 66 }, | 
| 142 |     { 286, 67 },  { 287, 68 },  { 288, 69 },  { 289, 70 }, | 
| 143 |     { 290, 71 },  { 291, 72 },  { 292, 73 },  { 293, 74 }, | 
| 144 |     { 294, 75 },  { 295, 76 },  { 296, 77 },  { 297, 78 }, | 
| 145 |     { 298, 79 },  { 299, 80 },  { 300, 81 },  { 301, 82 }, | 
| 146 |     { 302, 83 },  { 303, 84 },  { 304, 85 },  { 305, 86 }, | 
| 147 |     { 306, 87 },  { 307, 88 },  { 308, 89 },  { 309, 90 }, | 
| 148 |     { 310, 91 },  { 311, 92 },  { 312, 93 },  { 313, 94 }, | 
| 149 |     { 314, 95 },  { 315, 96 },  { 316, 97 },  { 317, 98 }, | 
| 150 |     { 318, 99 },  { 319, 103 }, { 320, 104 }, { 321, 105 }, | 
| 151 |     { 322, 106 }, { 323, 107 }, { 324, 108 }, { 325, 109 }, | 
| 152 |     { 326, 110 }, { 327, 114 }, { 328, 115 }, { 329, 116 }, | 
| 153 |     { 330, 117 }, { 331, 118 }, { 332, 119 }, { 333, 120 }, | 
| 154 |     { 334, 121 }, { 335, 122 }, { 336, 123 }, { 337, 124 }, | 
| 155 |     { 338, 125 }, { 339, 126 }, { 340, 127 }, { 341, 128 }, | 
| 156 |     { 342, 129 }, { 343, 130 }, { 344, 131 }, { 345, 132 }, | 
| 157 |     { 346, 133 }, { 347, 134 }, { 348, 135 }, { 349, 136 }, | 
| 158 |     { 350, 137 }, { 351, 138 }, { 352, 139 }, { 353, 140 }, | 
| 159 |     { 354, 141 }, { 355, 142 }, { 356, 143 }, { 357, 144 }, | 
| 160 |     { 358, 145 }, { 359, 146 }, { 360, 147 }, { 361, 148 }, | 
| 161 |     { 362, 149 }, { 363, 150 }, { 364, 151 }, { 365, 152 }, | 
| 162 |     { 366, 153 }, { 367, 154 }, { 368, 155 }, { 369, 156 }, | 
| 163 |     { 370, 157 }, { 371, 158 }, { 372, 159 }, { 373, 160 }, | 
| 164 |     { 374, 161 }, { 375, 162 }, { 376, 163 }, { 377, 164 }, | 
| 165 |     { 378, 165 } | 
| 166 | }; | 
| 167 |  | 
| 168 | /* SID to glyph ID */ | 
| 169 | static const sid_to_gid_t expert_subset_charset_sid_to_gid [] = | 
| 170 | { | 
| 171 |   { 1, 1 },       { 13, 8 },      { 14, 9 },      { 15, 10 }, | 
| 172 |   { 27, 22 },     { 28, 23 },     { 99, 11 },     { 109, 41 }, | 
| 173 |   { 110, 42 },    { 150, 64 },    { 155, 55 },    { 158, 54 }, | 
| 174 |   { 163, 56 },    { 164, 65 },    { 169, 66 },    { 231, 2 }, | 
| 175 |   { 232, 3 },     { 235, 4 },     { 236, 5 },     { 237, 6 }, | 
| 176 |   { 238, 7 },     { 239, 12 },    { 240, 13 },    { 241, 14 }, | 
| 177 |   { 242, 15 },    { 243, 16 },    { 244, 17 },    { 245, 18 }, | 
| 178 |   { 246, 19 },    { 247, 20 },    { 248, 21 },    { 249, 24 }, | 
| 179 |   { 250, 25 },    { 251, 26 },    { 253, 27 },    { 254, 28 }, | 
| 180 |   { 255, 29 },    { 256, 30 },    { 257, 31 },    { 258, 32 }, | 
| 181 |   { 259, 33 },    { 260, 34 },    { 261, 35 },    { 262, 36 }, | 
| 182 |   { 263, 37 },    { 264, 38 },    { 265, 39 },    { 266, 40 }, | 
| 183 |   { 267, 43 },    { 268, 44 },    { 269, 45 },    { 270, 46 }, | 
| 184 |   { 272, 47 },    { 300, 48 },    { 301, 49 },    { 302, 50 }, | 
| 185 |   { 305, 51 },    { 314, 52 },    { 315, 53 },    { 320, 57 }, | 
| 186 |   { 321, 58 },    { 322, 59 },    { 323, 60 },    { 324, 61 }, | 
| 187 |   { 325, 62 },    { 326, 63 },    { 327, 67 },    { 328, 68 }, | 
| 188 |   { 329, 69 },    { 330, 70 },    { 331, 71 },    { 332, 72 }, | 
| 189 |   { 333, 73 },    { 334, 74 },    { 335, 75 },    { 336, 76 }, | 
| 190 |   { 337, 77 },    { 338, 78 },    { 339, 79 },    { 340, 80 }, | 
| 191 |   { 341, 81 },    { 342, 82 },    { 343, 83 },    { 344, 84 }, | 
| 192 |   { 345, 85 },    { 346, 86 } | 
| 193 | }; | 
| 194 |  | 
| 195 | /* code to SID */ | 
| 196 | static const uint8_t standard_encoding_to_sid [] = | 
| 197 | { | 
| 198 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 199 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 200 |     1,    2,    3,    4,    5,    6,    7,    8,    9,   10,   11,   12,   13,   14,   15,   16, | 
| 201 |     17,  18,   19,   20,   21,   22,   23,   24,   25,   26,   27,   28,   29,   30,   31,   32, | 
| 202 |     33,  34,   35,   36,   37,   38,   39,   40,   41,   42,   43,   44,   45,   46,   47,   48, | 
| 203 |     49,  50,   51,   52,   53,   54,   55,   56,   57,   58,   59,   60,   61,   62,   63,   64, | 
| 204 |     65,  66,   67,   68,   69,   70,   71,   72,   73,   74,   75,   76,   77,   78,   79,   80, | 
| 205 |     81,  82,   83,   84,   85,   86,   87,   88,   89,   90,   91,   92,   93,   94,   95,    0, | 
| 206 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 207 |     0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 208 |     0,   96,   97,   98,   99,  100,  101,  102,  103,  104,  105,  106,  107,  108,  109,  110, | 
| 209 |     0,  111,  112,  113,  114,    0,  115,  116,  117,  118,  119,  120,  121,  122,    0,  123, | 
| 210 |     0,  124,  125,  126,  127,  128,  129,  130,  131,    0,  132,  133,    0,  134,  135,  136, | 
| 211 |   137,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0,    0, | 
| 212 |     0,   138,   0,  139,    0,    0,    0,    0,  140,  141,  142,  143,    0,    0,    0,    0, | 
| 213 |     0,   144,   0,    0,    0,  145,    0,    0,  146,  147,  148,  149,    0,    0,    0,    0 | 
| 214 | }; | 
| 215 |  | 
| 216 | hb_codepoint_t OT::cff1::lookup_standard_encoding_for_code (hb_codepoint_t sid) | 
| 217 | { | 
| 218 |   if (sid < ARRAY_LENGTH (standard_encoding_to_code)) | 
| 219 |     return (hb_codepoint_t)standard_encoding_to_code[sid]; | 
| 220 |   else | 
| 221 |     return 0; | 
| 222 | } | 
| 223 |  | 
| 224 | hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid) | 
| 225 | { | 
| 226 |   if (sid < ARRAY_LENGTH (expert_encoding_to_code)) | 
| 227 |     return (hb_codepoint_t)expert_encoding_to_code[sid]; | 
| 228 |   else | 
| 229 |     return 0; | 
| 230 | } | 
| 231 |  | 
| 232 | hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph) | 
| 233 | { | 
| 234 |   if (glyph < ARRAY_LENGTH (expert_charset_to_sid)) | 
| 235 |     return (hb_codepoint_t)expert_charset_to_sid[glyph]; | 
| 236 |   else | 
| 237 |     return 0; | 
| 238 | } | 
| 239 |  | 
| 240 | hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph) | 
| 241 | { | 
| 242 |   if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid)) | 
| 243 |     return (hb_codepoint_t)expert_subset_charset_to_sid[glyph]; | 
| 244 |   else | 
| 245 |     return 0; | 
| 246 | } | 
| 247 |  | 
| 248 | hb_codepoint_t OT::cff1::lookup_expert_charset_for_glyph (hb_codepoint_t sid) | 
| 249 | { | 
| 250 |   const auto *pair = hb_sorted_array (expert_charset_sid_to_gid).bsearch (sid); | 
| 251 |   return pair ? pair->gid : 0; | 
| 252 | } | 
| 253 |  | 
| 254 | hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid) | 
| 255 | { | 
| 256 |   const auto *pair = hb_sorted_array (expert_subset_charset_sid_to_gid).bsearch (sid); | 
| 257 |   return pair ? pair->gid : 0; | 
| 258 | } | 
| 259 |  | 
| 260 | hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code) | 
| 261 | { | 
| 262 |   if (code < ARRAY_LENGTH (standard_encoding_to_sid)) | 
| 263 |     return (hb_codepoint_t)standard_encoding_to_sid[code]; | 
| 264 |   else | 
| 265 |     return CFF_UNDEF_SID; | 
| 266 | } | 
| 267 |  | 
| 268 | struct bounds_t | 
| 269 | { | 
| 270 |   void init () | 
| 271 |   { | 
| 272 |     min.set_int (INT_MAX, INT_MAX); | 
| 273 |     max.set_int (INT_MIN, INT_MIN); | 
| 274 |   } | 
| 275 |  | 
| 276 |   void update (const point_t &pt) | 
| 277 |   { | 
| 278 |     if (pt.x < min.x) min.x = pt.x; | 
| 279 |     if (pt.x > max.x) max.x = pt.x; | 
| 280 |     if (pt.y < min.y) min.y = pt.y; | 
| 281 |     if (pt.y > max.y) max.y = pt.y; | 
| 282 |   } | 
| 283 |  | 
| 284 |   void merge (const bounds_t &b) | 
| 285 |   { | 
| 286 |     if (empty ()) | 
| 287 |       *this = b; | 
| 288 |     else if (!b.empty ()) | 
| 289 |     { | 
| 290 |       if (b.min.x < min.x) min.x = b.min.x; | 
| 291 |       if (b.max.x > max.x) max.x = b.max.x; | 
| 292 |       if (b.min.y < min.y) min.y = b.min.y; | 
| 293 |       if (b.max.y > max.y) max.y = b.max.y; | 
| 294 |     } | 
| 295 |   } | 
| 296 |  | 
| 297 |   void offset (const point_t &delta) | 
| 298 |   { | 
| 299 |     if (!empty ()) | 
| 300 |     { | 
| 301 |       min.move (delta); | 
| 302 |       max.move (delta); | 
| 303 |     } | 
| 304 |   } | 
| 305 |  | 
| 306 |   bool empty () const { return (min.x >= max.x) || (min.y >= max.y); } | 
| 307 |  | 
| 308 |   point_t min; | 
| 309 |   point_t max; | 
| 310 | }; | 
| 311 |  | 
| 312 | struct cff1_extents_param_t | 
| 313 | { | 
| 314 |   void init (const OT::cff1::accelerator_t *_cff) | 
| 315 |   { | 
| 316 |     path_open = false; | 
| 317 |     cff = _cff; | 
| 318 |     bounds.init (); | 
| 319 |   } | 
| 320 |  | 
| 321 |   void start_path   ()       { path_open = true; } | 
| 322 |   void end_path     ()       { path_open = false; } | 
| 323 |   bool is_path_open () const { return path_open; } | 
| 324 |  | 
| 325 |   bool path_open; | 
| 326 |   bounds_t bounds; | 
| 327 |  | 
| 328 |   const OT::cff1::accelerator_t *cff; | 
| 329 | }; | 
| 330 |  | 
| 331 | struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t> | 
| 332 | { | 
| 333 |   static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt) | 
| 334 |   { | 
| 335 |     param.end_path (); | 
| 336 |     env.moveto (pt); | 
| 337 |   } | 
| 338 |  | 
| 339 |   static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1) | 
| 340 |   { | 
| 341 |     if (!param.is_path_open ()) | 
| 342 |     { | 
| 343 |       param.start_path (); | 
| 344 |       param.bounds.update (env.get_pt ()); | 
| 345 |     } | 
| 346 |     env.moveto (pt1); | 
| 347 |     param.bounds.update (env.get_pt ()); | 
| 348 |   } | 
| 349 |  | 
| 350 |   static void curve (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1, const point_t &pt2, const point_t &pt3) | 
| 351 |   { | 
| 352 |     if (!param.is_path_open ()) | 
| 353 |     { | 
| 354 |       param.start_path (); | 
| 355 |       param.bounds.update (env.get_pt ()); | 
| 356 |     } | 
| 357 |     /* include control points */ | 
| 358 |     param.bounds.update (pt1); | 
| 359 |     param.bounds.update (pt2); | 
| 360 |     env.moveto (pt3); | 
| 361 |     param.bounds.update (env.get_pt ()); | 
| 362 |   } | 
| 363 | }; | 
| 364 |  | 
| 365 | static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false); | 
| 366 |  | 
| 367 | struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, cff1_extents_param_t, cff1_path_procs_extents_t> | 
| 368 | { | 
| 369 |   static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param) | 
| 370 |   { | 
| 371 |     unsigned int  n = env.argStack.get_count (); | 
| 372 |     point_t delta; | 
| 373 |     delta.x = env.argStack[n-4]; | 
| 374 |     delta.y = env.argStack[n-3]; | 
| 375 |     hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ()); | 
| 376 |     hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ()); | 
| 377 |  | 
| 378 |     bounds_t  base_bounds, accent_bounds; | 
| 379 |     if (likely (!env.in_seac && base && accent | 
| 380 | 	       && _get_bounds (param.cff, base, base_bounds, true) | 
| 381 | 	       && _get_bounds (param.cff, accent, accent_bounds, true))) | 
| 382 |     { | 
| 383 |       param.bounds.merge (base_bounds); | 
| 384 |       accent_bounds.offset (delta); | 
| 385 |       param.bounds.merge (accent_bounds); | 
| 386 |     } | 
| 387 |     else | 
| 388 |       env.set_error (); | 
| 389 |   } | 
| 390 | }; | 
| 391 |  | 
| 392 | bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac) | 
| 393 | { | 
| 394 |   bounds.init (); | 
| 395 |   if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; | 
| 396 |  | 
| 397 |   unsigned int fd = cff->fdSelect->get_fd (glyph); | 
| 398 |   cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp; | 
| 399 |   const byte_str_t str = (*cff->charStrings)[glyph]; | 
| 400 |   interp.env.init (str, *cff, fd); | 
| 401 |   interp.env.set_in_seac (in_seac); | 
| 402 |   cff1_extents_param_t  param; | 
| 403 |   param.init (cff); | 
| 404 |   if (unlikely (!interp.interpret (param))) return false; | 
| 405 |   bounds = param.bounds; | 
| 406 |   return true; | 
| 407 | } | 
| 408 |  | 
| 409 | bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const | 
| 410 | { | 
| 411 | #ifdef HB_NO_OT_FONT_CFF | 
| 412 |   /* XXX Remove check when this code moves to .hh file. */ | 
| 413 |   return true; | 
| 414 | #endif | 
| 415 |  | 
| 416 |   bounds_t bounds; | 
| 417 |  | 
| 418 |   if (!_get_bounds (this, glyph, bounds)) | 
| 419 |     return false; | 
| 420 |  | 
| 421 |   if (bounds.min.x >= bounds.max.x) | 
| 422 |   { | 
| 423 |     extents->width = 0; | 
| 424 |     extents->x_bearing = 0; | 
| 425 |   } | 
| 426 |   else | 
| 427 |   { | 
| 428 |     extents->x_bearing = font->em_scalef_x (bounds.min.x.to_real ()); | 
| 429 |     extents->width = font->em_scalef_x (bounds.max.x.to_real () - bounds.min.x.to_real ()); | 
| 430 |   } | 
| 431 |   if (bounds.min.y >= bounds.max.y) | 
| 432 |   { | 
| 433 |     extents->height = 0; | 
| 434 |     extents->y_bearing = 0; | 
| 435 |   } | 
| 436 |   else | 
| 437 |   { | 
| 438 |     extents->y_bearing = font->em_scalef_y (bounds.max.y.to_real ()); | 
| 439 |     extents->height = font->em_scalef_y (bounds.min.y.to_real () - bounds.max.y.to_real ()); | 
| 440 |   } | 
| 441 |  | 
| 442 |   return true; | 
| 443 | } | 
| 444 |  | 
| 445 | #ifdef HB_EXPERIMENTAL_API | 
| 446 | struct cff1_path_param_t | 
| 447 | { | 
| 448 |   cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_, | 
| 449 | 		     draw_helper_t &draw_helper_, point_t *delta_) | 
| 450 |   { | 
| 451 |     draw_helper = &draw_helper_; | 
| 452 |     cff = cff_; | 
| 453 |     font = font_; | 
| 454 |     delta = delta_; | 
| 455 |   } | 
| 456 |  | 
| 457 |   void move_to (const point_t &p) | 
| 458 |   { | 
| 459 |     point_t point = p; | 
| 460 |     if (delta) point.move (*delta); | 
| 461 |     draw_helper->move_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ())); | 
| 462 |   } | 
| 463 |  | 
| 464 |   void line_to (const point_t &p) | 
| 465 |   { | 
| 466 |     point_t point = p; | 
| 467 |     if (delta) point.move (*delta); | 
| 468 |     draw_helper->line_to (font->em_scalef_x (point.x.to_real ()), font->em_scalef_y (point.y.to_real ())); | 
| 469 |   } | 
| 470 |  | 
| 471 |   void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3) | 
| 472 |   { | 
| 473 |     point_t point1 = p1, point2 = p2, point3 = p3; | 
| 474 |     if (delta) | 
| 475 |     { | 
| 476 |       point1.move (*delta); | 
| 477 |       point2.move (*delta); | 
| 478 |       point3.move (*delta); | 
| 479 |     } | 
| 480 |     draw_helper->cubic_to (font->em_scalef_x (point1.x.to_real ()), font->em_scalef_y (point1.y.to_real ()), | 
| 481 | 			   font->em_scalef_x (point2.x.to_real ()), font->em_scalef_y (point2.y.to_real ()), | 
| 482 | 			   font->em_scalef_x (point3.x.to_real ()), font->em_scalef_y (point3.y.to_real ())); | 
| 483 |   } | 
| 484 |  | 
| 485 |   void end_path () { draw_helper->end_path (); } | 
| 486 |  | 
| 487 |   hb_font_t *font; | 
| 488 |   draw_helper_t *draw_helper; | 
| 489 |   point_t *delta; | 
| 490 |  | 
| 491 |   const OT::cff1::accelerator_t *cff; | 
| 492 | }; | 
| 493 |  | 
| 494 | struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t> | 
| 495 | { | 
| 496 |   static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt) | 
| 497 |   { | 
| 498 |     param.move_to (pt); | 
| 499 |     env.moveto (pt); | 
| 500 |   } | 
| 501 |  | 
| 502 |   static void line (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1) | 
| 503 |   { | 
| 504 |     param.line_to (pt1); | 
| 505 |     env.moveto (pt1); | 
| 506 |   } | 
| 507 |  | 
| 508 |   static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t ¶m, const point_t &pt1, const point_t &pt2, const point_t &pt3) | 
| 509 |   { | 
| 510 |     param.cubic_to (pt1, pt2, pt3); | 
| 511 |     env.moveto (pt3); | 
| 512 |   } | 
| 513 | }; | 
| 514 |  | 
| 515 | static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, | 
| 516 | 		       draw_helper_t &draw_helper, bool in_seac = false, point_t *delta = nullptr); | 
| 517 |  | 
| 518 | struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t> | 
| 519 | { | 
| 520 |   static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param) | 
| 521 |   { | 
| 522 |     /* End previous path */ | 
| 523 |     param.end_path (); | 
| 524 |  | 
| 525 |     unsigned int n = env.argStack.get_count (); | 
| 526 |     point_t delta; | 
| 527 |     delta.x = env.argStack[n-4]; | 
| 528 |     delta.y = env.argStack[n-3]; | 
| 529 |     hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ()); | 
| 530 |     hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ()); | 
| 531 |  | 
| 532 |     if (unlikely (!(!env.in_seac && base && accent | 
| 533 | 		    && _get_path (param.cff, param.font, base, *param.draw_helper, true) | 
| 534 | 		    && _get_path (param.cff, param.font, accent, *param.draw_helper, true, &delta)))) | 
| 535 |       env.set_error (); | 
| 536 |   } | 
| 537 | }; | 
| 538 |  | 
| 539 | bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph, | 
| 540 | 		draw_helper_t &draw_helper, bool in_seac, point_t *delta) | 
| 541 | { | 
| 542 |   if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false; | 
| 543 |  | 
| 544 |   unsigned int fd = cff->fdSelect->get_fd (glyph); | 
| 545 |   cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp; | 
| 546 |   const byte_str_t str = (*cff->charStrings)[glyph]; | 
| 547 |   interp.env.init (str, *cff, fd); | 
| 548 |   interp.env.set_in_seac (in_seac); | 
| 549 |   cff1_path_param_t param (cff, font, draw_helper, delta); | 
| 550 |   if (unlikely (!interp.interpret (param))) return false; | 
| 551 |  | 
| 552 |   /* Let's end the path specially since it is called inside seac also */ | 
| 553 |   param.end_path (); | 
| 554 |  | 
| 555 |   return true; | 
| 556 | } | 
| 557 |  | 
| 558 | bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, draw_helper_t &draw_helper) const | 
| 559 | { | 
| 560 | #ifdef HB_NO_OT_FONT_CFF | 
| 561 |   /* XXX Remove check when this code moves to .hh file. */ | 
| 562 |   return true; | 
| 563 | #endif | 
| 564 |  | 
| 565 |   return _get_path (this, font, glyph, draw_helper); | 
| 566 | } | 
| 567 | #endif | 
| 568 |  | 
| 569 | struct get_seac_param_t | 
| 570 | { | 
| 571 |   void init (const OT::cff1::accelerator_t *_cff) | 
| 572 |   { | 
| 573 |     cff = _cff; | 
| 574 |     base = 0; | 
| 575 |     accent = 0; | 
| 576 |   } | 
| 577 |  | 
| 578 |   bool has_seac () const { return base && accent; } | 
| 579 |  | 
| 580 |   const OT::cff1::accelerator_t *cff; | 
| 581 |   hb_codepoint_t  base; | 
| 582 |   hb_codepoint_t  accent; | 
| 583 | }; | 
| 584 |  | 
| 585 | struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t> | 
| 586 | { | 
| 587 |   static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param) | 
| 588 |   { | 
| 589 |     unsigned int  n = env.argStack.get_count (); | 
| 590 |     hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int (); | 
| 591 |     hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int (); | 
| 592 |  | 
| 593 |     param.base = param.cff->std_code_to_glyph (base_char); | 
| 594 |     param.accent = param.cff->std_code_to_glyph (accent_char); | 
| 595 |   } | 
| 596 | }; | 
| 597 |  | 
| 598 | bool OT::cff1::accelerator_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const | 
| 599 | { | 
| 600 |   if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false; | 
| 601 |  | 
| 602 |   unsigned int fd = fdSelect->get_fd (glyph); | 
| 603 |   cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp; | 
| 604 |   const byte_str_t str = (*charStrings)[glyph]; | 
| 605 |   interp.env.init (str, *this, fd); | 
| 606 |   get_seac_param_t  param; | 
| 607 |   param.init (this); | 
| 608 |   if (unlikely (!interp.interpret (param))) return false; | 
| 609 |  | 
| 610 |   if (param.has_seac ()) | 
| 611 |   { | 
| 612 |     *base = param.base; | 
| 613 |     *accent = param.accent; | 
| 614 |     return true; | 
| 615 |   } | 
| 616 |   return false; | 
| 617 | } | 
| 618 |  | 
| 619 |  | 
| 620 | #endif | 
| 621 |  |