Coverage Report

Created: 2025-07-01 07:01

/src/harfbuzz/src/hb-ot-cff1-table.cc
Line
Count
Source (jump to first uncovered line)
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
0
  {
45
0
    if (a == sid) return 0;
46
0
    return (a < sid) ? -1 : 1;
47
0
  }
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
0
{
218
0
  if (sid < ARRAY_LENGTH (standard_encoding_to_code))
219
0
    return (hb_codepoint_t)standard_encoding_to_code[sid];
220
0
  else
221
0
    return 0;
222
0
}
223
224
hb_codepoint_t OT::cff1::lookup_expert_encoding_for_code (hb_codepoint_t sid)
225
0
{
226
0
  if (sid < ARRAY_LENGTH (expert_encoding_to_code))
227
0
    return (hb_codepoint_t)expert_encoding_to_code[sid];
228
0
  else
229
0
    return 0;
230
0
}
231
232
hb_codepoint_t OT::cff1::lookup_expert_charset_for_sid (hb_codepoint_t glyph)
233
0
{
234
0
  if (glyph < ARRAY_LENGTH (expert_charset_to_sid))
235
0
    return (hb_codepoint_t)expert_charset_to_sid[glyph];
236
0
  else
237
0
    return 0;
238
0
}
239
240
hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_sid (hb_codepoint_t glyph)
241
0
{
242
0
  if (glyph < ARRAY_LENGTH (expert_subset_charset_to_sid))
243
0
    return (hb_codepoint_t)expert_subset_charset_to_sid[glyph];
244
0
  else
245
0
    return 0;
246
0
}
247
248
hb_codepoint_t OT::cff1::lookup_expert_charset_for_glyph (hb_codepoint_t sid)
249
0
{
250
0
  const auto *pair = hb_sorted_array (expert_charset_sid_to_gid).bsearch (sid);
251
0
  return pair ? pair->gid : 0;
252
0
}
253
254
hb_codepoint_t OT::cff1::lookup_expert_subset_charset_for_glyph (hb_codepoint_t sid)
255
0
{
256
0
  const auto *pair = hb_sorted_array (expert_subset_charset_sid_to_gid).bsearch (sid);
257
0
  return pair ? pair->gid : 0;
258
0
}
259
260
hb_codepoint_t OT::cff1::lookup_standard_encoding_for_sid (hb_codepoint_t code)
261
0
{
262
0
  if (code < ARRAY_LENGTH (standard_encoding_to_sid))
263
0
    return (hb_codepoint_t)standard_encoding_to_sid[code];
264
0
  else
265
0
    return CFF_UNDEF_SID;
266
0
}
267
268
struct bounds_t
269
{
270
  void init ()
271
0
  {
272
0
    min.set_int (INT_MAX, INT_MAX);
273
0
    max.set_int (INT_MIN, INT_MIN);
274
0
  }
275
276
  void update (const point_t &pt)
277
0
  {
278
0
    if (pt.x < min.x) min.x = pt.x;
279
0
    if (pt.x > max.x) max.x = pt.x;
280
0
    if (pt.y < min.y) min.y = pt.y;
281
0
    if (pt.y > max.y) max.y = pt.y;
282
0
  }
283
284
  void merge (const bounds_t &b)
285
0
  {
286
0
    if (empty ())
287
0
      *this = b;
288
0
    else if (!b.empty ())
289
0
    {
290
0
      if (b.min.x < min.x) min.x = b.min.x;
291
0
      if (b.max.x > max.x) max.x = b.max.x;
292
0
      if (b.min.y < min.y) min.y = b.min.y;
293
0
      if (b.max.y > max.y) max.y = b.max.y;
294
0
    }
295
0
  }
296
297
  void offset (const point_t &delta)
298
0
  {
299
0
    if (!empty ())
300
0
    {
301
0
      min.move (delta);
302
0
      max.move (delta);
303
0
    }
304
0
  }
305
306
0
  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
0
  cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
315
0
  {
316
0
    bounds.init ();
317
0
  }
318
319
0
  void start_path   ()       { path_open = true; }
320
0
  void end_path     ()       { path_open = false; }
321
0
  bool is_path_open () const { return path_open; }
322
323
  bool path_open = false;
324
  bounds_t bounds;
325
326
  const OT::cff1::accelerator_t *cff;
327
};
328
329
struct cff1_path_procs_extents_t : path_procs_t<cff1_path_procs_extents_t, cff1_cs_interp_env_t, cff1_extents_param_t>
330
{
331
  static void moveto (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt)
332
0
  {
333
0
    param.end_path ();
334
0
    env.moveto (pt);
335
0
  }
336
337
  static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
338
0
  {
339
0
    if (!param.is_path_open ())
340
0
    {
341
0
      param.start_path ();
342
0
      param.bounds.update (env.get_pt ());
343
0
    }
344
0
    env.moveto (pt1);
345
0
    param.bounds.update (env.get_pt ());
346
0
  }
347
348
  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)
349
0
  {
350
0
    if (!param.is_path_open ())
351
0
    {
352
0
      param.start_path ();
353
0
      param.bounds.update (env.get_pt ());
354
0
    }
355
    /* include control points */
356
0
    param.bounds.update (pt1);
357
0
    param.bounds.update (pt2);
358
0
    env.moveto (pt3);
359
0
    param.bounds.update (env.get_pt ());
360
0
  }
361
};
362
363
static bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac=false);
364
365
struct cff1_cs_opset_extents_t : cff1_cs_opset_t<cff1_cs_opset_extents_t, cff1_extents_param_t, cff1_path_procs_extents_t>
366
{
367
  static void process_seac (cff1_cs_interp_env_t &env, cff1_extents_param_t& param)
368
0
  {
369
0
    unsigned int  n = env.argStack.get_count ();
370
0
    point_t delta;
371
0
    delta.x = env.argStack[n-4];
372
0
    delta.y = env.argStack[n-3];
373
0
    hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
374
0
    hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
375
376
0
    bounds_t  base_bounds, accent_bounds;
377
0
    if (likely (!env.in_seac && base && accent
378
0
         && _get_bounds (param.cff, base, base_bounds, true)
379
0
         && _get_bounds (param.cff, accent, accent_bounds, true)))
380
0
    {
381
0
      param.bounds.merge (base_bounds);
382
0
      accent_bounds.offset (delta);
383
0
      param.bounds.merge (accent_bounds);
384
0
    }
385
0
    else
386
0
      env.set_error ();
387
0
  }
388
};
389
390
bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
391
0
{
392
0
  bounds.init ();
393
0
  if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
394
395
0
  unsigned int fd = cff->fdSelect->get_fd (glyph);
396
0
  const hb_ubytes_t str = (*cff->charStrings)[glyph];
397
0
  cff1_cs_interp_env_t env (str, *cff, fd);
398
0
  env.set_in_seac (in_seac);
399
0
  cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp (env);
400
0
  cff1_extents_param_t param (cff);
401
0
  if (unlikely (!interp.interpret (param))) return false;
402
0
  bounds = param.bounds;
403
0
  return true;
404
0
}
405
406
bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
407
0
{
408
#ifdef HB_NO_OT_FONT_CFF
409
  /* XXX Remove check when this code moves to .hh file. */
410
  return true;
411
#endif
412
413
0
  bounds_t bounds;
414
415
0
  if (!_get_bounds (this, glyph, bounds))
416
0
    return false;
417
418
0
  if (bounds.min.x >= bounds.max.x)
419
0
  {
420
0
    extents->width = 0;
421
0
    extents->x_bearing = 0;
422
0
  }
423
0
  else
424
0
  {
425
0
    extents->x_bearing = roundf (bounds.min.x.to_real ());
426
0
    extents->width = roundf (bounds.max.x.to_real () - extents->x_bearing);
427
0
  }
428
0
  if (bounds.min.y >= bounds.max.y)
429
0
  {
430
0
    extents->height = 0;
431
0
    extents->y_bearing = 0;
432
0
  }
433
0
  else
434
0
  {
435
0
    extents->y_bearing = roundf (bounds.max.y.to_real ());
436
0
    extents->height = roundf (bounds.min.y.to_real () - extents->y_bearing);
437
0
  }
438
439
0
  font->scale_glyph_extents (extents);
440
441
0
  return true;
442
0
}
443
444
struct cff1_path_param_t
445
{
446
  cff1_path_param_t (const OT::cff1::accelerator_t *cff_, hb_font_t *font_,
447
         hb_draw_session_t &draw_session_, point_t *delta_)
448
0
  {
449
0
    draw_session = &draw_session_;
450
0
    cff = cff_;
451
0
    font = font_;
452
0
    delta = delta_;
453
0
  }
454
455
  void move_to (const point_t &p)
456
0
  {
457
0
    point_t point = p;
458
0
    if (delta) point.move (*delta);
459
0
    draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
460
0
  }
461
462
  void line_to (const point_t &p)
463
0
  {
464
0
    point_t point = p;
465
0
    if (delta) point.move (*delta);
466
0
    draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
467
0
  }
468
469
  void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
470
0
  {
471
0
    point_t point1 = p1, point2 = p2, point3 = p3;
472
0
    if (delta)
473
0
    {
474
0
      point1.move (*delta);
475
0
      point2.move (*delta);
476
0
      point3.move (*delta);
477
0
    }
478
0
    draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
479
0
         font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
480
0
         font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
481
0
  }
482
483
0
  void end_path () { draw_session->close_path (); }
484
485
  hb_font_t *font;
486
  hb_draw_session_t *draw_session;
487
  point_t *delta;
488
489
  const OT::cff1::accelerator_t *cff;
490
};
491
492
struct cff1_path_procs_path_t : path_procs_t<cff1_path_procs_path_t, cff1_cs_interp_env_t, cff1_path_param_t>
493
{
494
  static void moveto (cff1_cs_interp_env_t &env, cff1_path_param_t& param, const point_t &pt)
495
0
  {
496
0
    param.move_to (pt);
497
0
    env.moveto (pt);
498
0
  }
499
500
  static void line (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1)
501
0
  {
502
0
    param.line_to (pt1);
503
0
    env.moveto (pt1);
504
0
  }
505
506
  static void curve (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1, const point_t &pt2, const point_t &pt3)
507
0
  {
508
0
    param.cubic_to (pt1, pt2, pt3);
509
0
    env.moveto (pt3);
510
0
  }
511
};
512
513
static bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
514
           hb_draw_session_t &draw_session, bool in_seac = false, point_t *delta = nullptr);
515
516
struct cff1_cs_opset_path_t : cff1_cs_opset_t<cff1_cs_opset_path_t, cff1_path_param_t, cff1_path_procs_path_t>
517
{
518
  static void process_seac (cff1_cs_interp_env_t &env, cff1_path_param_t& param)
519
0
  {
520
    /* End previous path */
521
0
    param.end_path ();
522
523
0
    unsigned int n = env.argStack.get_count ();
524
0
    point_t delta;
525
0
    delta.x = env.argStack[n-4];
526
0
    delta.y = env.argStack[n-3];
527
0
    hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
528
0
    hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
529
530
0
    if (unlikely (!(!env.in_seac && base && accent
531
0
        && _get_path (param.cff, param.font, base, *param.draw_session, true)
532
0
        && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
533
0
      env.set_error ();
534
0
  }
535
};
536
537
bool _get_path (const OT::cff1::accelerator_t *cff, hb_font_t *font, hb_codepoint_t glyph,
538
    hb_draw_session_t &draw_session, bool in_seac, point_t *delta)
539
0
{
540
0
  if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
541
542
0
  unsigned int fd = cff->fdSelect->get_fd (glyph);
543
0
  const hb_ubytes_t str = (*cff->charStrings)[glyph];
544
0
  cff1_cs_interp_env_t env (str, *cff, fd);
545
0
  env.set_in_seac (in_seac);
546
0
  cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp (env);
547
0
  cff1_path_param_t param (cff, font, draw_session, delta);
548
0
  if (unlikely (!interp.interpret (param))) return false;
549
550
  /* Let's end the path specially since it is called inside seac also */
551
0
  param.end_path ();
552
553
0
  return true;
554
0
}
555
556
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
557
0
{
558
#ifdef HB_NO_OT_FONT_CFF
559
  /* XXX Remove check when this code moves to .hh file. */
560
  return true;
561
#endif
562
563
0
  return _get_path (this, font, glyph, draw_session);
564
0
}
565
566
struct get_seac_param_t
567
{
568
0
  get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {}
569
570
0
  bool has_seac () const { return base && accent; }
571
572
  const OT::cff1::accelerator_subset_t *cff;
573
  hb_codepoint_t  base = 0;
574
  hb_codepoint_t  accent = 0;
575
};
576
577
struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
578
{
579
  static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
580
0
  {
581
0
    unsigned int  n = env.argStack.get_count ();
582
0
    hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
583
0
    hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
584
585
0
    param.base = param.cff->std_code_to_glyph (base_char);
586
0
    param.accent = param.cff->std_code_to_glyph (accent_char);
587
0
  }
588
};
589
590
bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
591
0
{
592
0
  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
593
594
0
  unsigned int fd = fdSelect->get_fd (glyph);
595
0
  const hb_ubytes_t str = (*charStrings)[glyph];
596
0
  cff1_cs_interp_env_t env (str, *this, fd);
597
0
  cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp (env);
598
0
  get_seac_param_t  param (this);
599
0
  if (unlikely (!interp.interpret (param))) return false;
600
601
0
  if (param.has_seac ())
602
0
  {
603
0
    *base = param.base;
604
0
    *accent = param.accent;
605
0
    return true;
606
0
  }
607
0
  return false;
608
0
}
609
610
611
#endif