jdk

Форк
0
/
hb-ot-cff1-table.cc 
620 строк · 23.5 Кб
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
  cff1_extents_param_t (const OT::cff1::accelerator_t *_cff) : cff (_cff)
315
  {
316
    bounds.init ();
317
  }
318

319
  void start_path   ()       { path_open = true; }
320
  void end_path     ()       { path_open = false; }
321
  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
  {
333
    param.end_path ();
334
    env.moveto (pt);
335
  }
336

337
  static void line (cff1_cs_interp_env_t &env, cff1_extents_param_t& param, const point_t &pt1)
338
  {
339
    if (!param.is_path_open ())
340
    {
341
      param.start_path ();
342
      param.bounds.update (env.get_pt ());
343
    }
344
    env.moveto (pt1);
345
    param.bounds.update (env.get_pt ());
346
  }
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
  {
350
    if (!param.is_path_open ())
351
    {
352
      param.start_path ();
353
      param.bounds.update (env.get_pt ());
354
    }
355
    /* include control points */
356
    param.bounds.update (pt1);
357
    param.bounds.update (pt2);
358
    env.moveto (pt3);
359
    param.bounds.update (env.get_pt ());
360
  }
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
  {
369
    unsigned int  n = env.argStack.get_count ();
370
    point_t delta;
371
    delta.x = env.argStack[n-4];
372
    delta.y = env.argStack[n-3];
373
    hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
374
    hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
375

376
    bounds_t  base_bounds, accent_bounds;
377
    if (likely (!env.in_seac && base && accent
378
               && _get_bounds (param.cff, base, base_bounds, true)
379
               && _get_bounds (param.cff, accent, accent_bounds, true)))
380
    {
381
      param.bounds.merge (base_bounds);
382
      accent_bounds.offset (delta);
383
      param.bounds.merge (accent_bounds);
384
    }
385
    else
386
      env.set_error ();
387
  }
388
};
389

390
bool _get_bounds (const OT::cff1::accelerator_t *cff, hb_codepoint_t glyph, bounds_t &bounds, bool in_seac)
391
{
392
  bounds.init ();
393
  if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
394

395
  unsigned int fd = cff->fdSelect->get_fd (glyph);
396
  const hb_ubytes_t str = (*cff->charStrings)[glyph];
397
  cff1_cs_interp_env_t env (str, *cff, fd);
398
  env.set_in_seac (in_seac);
399
  cff1_cs_interpreter_t<cff1_cs_opset_extents_t, cff1_extents_param_t> interp (env);
400
  cff1_extents_param_t param (cff);
401
  if (unlikely (!interp.interpret (param))) return false;
402
  bounds = param.bounds;
403
  return true;
404
}
405

406
bool OT::cff1::accelerator_t::get_extents (hb_font_t *font, hb_codepoint_t glyph, hb_glyph_extents_t *extents) const
407
{
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
  bounds_t bounds;
414

415
  if (!_get_bounds (this, glyph, bounds))
416
    return false;
417

418
  if (bounds.min.x >= bounds.max.x)
419
  {
420
    extents->width = 0;
421
    extents->x_bearing = 0;
422
  }
423
  else
424
  {
425
    extents->x_bearing = roundf (bounds.min.x.to_real ());
426
    extents->width = roundf (bounds.max.x.to_real () - extents->x_bearing);
427
  }
428
  if (bounds.min.y >= bounds.max.y)
429
  {
430
    extents->height = 0;
431
    extents->y_bearing = 0;
432
  }
433
  else
434
  {
435
    extents->y_bearing = roundf (bounds.max.y.to_real ());
436
    extents->height = roundf (bounds.min.y.to_real () - extents->y_bearing);
437
  }
438

439
  font->scale_glyph_extents (extents);
440

441
  return true;
442
}
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
  {
449
    draw_session = &draw_session_;
450
    cff = cff_;
451
    font = font_;
452
    delta = delta_;
453
  }
454

455
  void move_to (const point_t &p)
456
  {
457
    point_t point = p;
458
    if (delta) point.move (*delta);
459
    draw_session->move_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
460
  }
461

462
  void line_to (const point_t &p)
463
  {
464
    point_t point = p;
465
    if (delta) point.move (*delta);
466
    draw_session->line_to (font->em_fscalef_x (point.x.to_real ()), font->em_fscalef_y (point.y.to_real ()));
467
  }
468

469
  void cubic_to (const point_t &p1, const point_t &p2, const point_t &p3)
470
  {
471
    point_t point1 = p1, point2 = p2, point3 = p3;
472
    if (delta)
473
    {
474
      point1.move (*delta);
475
      point2.move (*delta);
476
      point3.move (*delta);
477
    }
478
    draw_session->cubic_to (font->em_fscalef_x (point1.x.to_real ()), font->em_fscalef_y (point1.y.to_real ()),
479
                           font->em_fscalef_x (point2.x.to_real ()), font->em_fscalef_y (point2.y.to_real ()),
480
                           font->em_fscalef_x (point3.x.to_real ()), font->em_fscalef_y (point3.y.to_real ()));
481
  }
482

483
  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
  {
496
    param.move_to (pt);
497
    env.moveto (pt);
498
  }
499

500
  static void line (cff1_cs_interp_env_t &env, cff1_path_param_t &param, const point_t &pt1)
501
  {
502
    param.line_to (pt1);
503
    env.moveto (pt1);
504
  }
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
  {
508
    param.cubic_to (pt1, pt2, pt3);
509
    env.moveto (pt3);
510
  }
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
  {
520
    /* End previous path */
521
    param.end_path ();
522

523
    unsigned int n = env.argStack.get_count ();
524
    point_t delta;
525
    delta.x = env.argStack[n-4];
526
    delta.y = env.argStack[n-3];
527
    hb_codepoint_t base = param.cff->std_code_to_glyph (env.argStack[n-2].to_int ());
528
    hb_codepoint_t accent = param.cff->std_code_to_glyph (env.argStack[n-1].to_int ());
529

530
    if (unlikely (!(!env.in_seac && base && accent
531
                    && _get_path (param.cff, param.font, base, *param.draw_session, true)
532
                    && _get_path (param.cff, param.font, accent, *param.draw_session, true, &delta))))
533
      env.set_error ();
534
  }
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
{
540
  if (unlikely (!cff->is_valid () || (glyph >= cff->num_glyphs))) return false;
541

542
  unsigned int fd = cff->fdSelect->get_fd (glyph);
543
  const hb_ubytes_t str = (*cff->charStrings)[glyph];
544
  cff1_cs_interp_env_t env (str, *cff, fd);
545
  env.set_in_seac (in_seac);
546
  cff1_cs_interpreter_t<cff1_cs_opset_path_t, cff1_path_param_t> interp (env);
547
  cff1_path_param_t param (cff, font, draw_session, delta);
548
  if (unlikely (!interp.interpret (param))) return false;
549

550
  /* Let's end the path specially since it is called inside seac also */
551
  param.end_path ();
552

553
  return true;
554
}
555

556
bool OT::cff1::accelerator_t::paint_glyph (hb_font_t *font, hb_codepoint_t glyph, hb_paint_funcs_t *funcs, void *data, hb_color_t foreground) const
557
{
558
  funcs->push_clip_glyph (data, glyph, font);
559
  funcs->color (data, true, foreground);
560
  funcs->pop_clip (data);
561

562
  return true;
563
}
564

565
bool OT::cff1::accelerator_t::get_path (hb_font_t *font, hb_codepoint_t glyph, hb_draw_session_t &draw_session) const
566
{
567
#ifdef HB_NO_OT_FONT_CFF
568
  /* XXX Remove check when this code moves to .hh file. */
569
  return true;
570
#endif
571

572
  return _get_path (this, font, glyph, draw_session);
573
}
574

575
struct get_seac_param_t
576
{
577
  get_seac_param_t (const OT::cff1::accelerator_subset_t *_cff) : cff (_cff) {}
578

579
  bool has_seac () const { return base && accent; }
580

581
  const OT::cff1::accelerator_subset_t *cff;
582
  hb_codepoint_t  base = 0;
583
  hb_codepoint_t  accent = 0;
584
};
585

586
struct cff1_cs_opset_seac_t : cff1_cs_opset_t<cff1_cs_opset_seac_t, get_seac_param_t>
587
{
588
  static void process_seac (cff1_cs_interp_env_t &env, get_seac_param_t& param)
589
  {
590
    unsigned int  n = env.argStack.get_count ();
591
    hb_codepoint_t  base_char = (hb_codepoint_t)env.argStack[n-2].to_int ();
592
    hb_codepoint_t  accent_char = (hb_codepoint_t)env.argStack[n-1].to_int ();
593

594
    param.base = param.cff->std_code_to_glyph (base_char);
595
    param.accent = param.cff->std_code_to_glyph (accent_char);
596
  }
597
};
598

599
bool OT::cff1::accelerator_subset_t::get_seac_components (hb_codepoint_t glyph, hb_codepoint_t *base, hb_codepoint_t *accent) const
600
{
601
  if (unlikely (!is_valid () || (glyph >= num_glyphs))) return false;
602

603
  unsigned int fd = fdSelect->get_fd (glyph);
604
  const hb_ubytes_t str = (*charStrings)[glyph];
605
  cff1_cs_interp_env_t env (str, *this, fd);
606
  cff1_cs_interpreter_t<cff1_cs_opset_seac_t, get_seac_param_t> interp (env);
607
  get_seac_param_t  param (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

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.