Coverage Report

Created: 2026-05-16 09:25

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