Coverage Report

Created: 2026-05-16 09:25

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/vcl/source/fontsubset/cff.cxx
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This file is part of the LibreOffice project.
4
 *
5
 * This Source Code Form is subject to the terms of the Mozilla Public
6
 * License, v. 2.0. If a copy of the MPL was not distributed with this
7
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8
 *
9
 * This file incorporates work covered by the following license notice:
10
 *
11
 *   Licensed to the Apache Software Foundation (ASF) under one or more
12
 *   contributor license agreements. See the NOTICE file distributed
13
 *   with this work for additional information regarding copyright
14
 *   ownership. The ASF licenses this file to you under the Apache
15
 *   License, Version 2.0 (the "License"); you may not use this file
16
 *   except in compliance with the License. You may obtain a copy of
17
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18
 */
19
20
#include <cstdio>
21
#include <cstring>
22
#include <vector>
23
#include <assert.h>
24
25
#include <font/TrueTypeFont.hxx>
26
#include <fontsubset.hxx>
27
#include <glyphid.hxx>
28
29
#include <comphelper/flagguard.hxx>
30
#include <o3tl/safeint.hxx>
31
#include <o3tl/sprintf.hxx>
32
#include <rtl/math.hxx>
33
#include <rtl/strbuf.hxx>
34
#include <rtl/string.hxx>
35
#include <strhelper.hxx>
36
#include <sal/log.hxx>
37
#include <tools/stream.hxx>
38
39
typedef sal_uInt8 U8;
40
typedef sal_uInt16 U16;
41
typedef sal_Int64 S64;
42
43
typedef double RealType;
44
typedef RealType ValType;
45
46
constexpr OString tok_notdef = ".notdef"_ostr;
47
constexpr OString tok_space = "space"_ostr;
48
constexpr OString tok_exclam = "exclam"_ostr;
49
constexpr OString tok_quotedbl = "quotedbl"_ostr;
50
constexpr OString tok_numbersign = "numbersign"_ostr;
51
constexpr OString tok_dollar = "dollar"_ostr;
52
constexpr OString tok_percent = "percent"_ostr;
53
constexpr OString tok_ampersand = "ampersand"_ostr;
54
constexpr OString tok_quoteright = "quoteright"_ostr;
55
constexpr OString tok_parenleft = "parenleft"_ostr;
56
constexpr OString tok_parenright = "parenright"_ostr;
57
constexpr OString tok_asterisk = "asterisk"_ostr;
58
constexpr OString tok_plus = "plus"_ostr;
59
constexpr OString tok_comma = "comma"_ostr;
60
constexpr OString tok_hyphen = "hyphen"_ostr;
61
constexpr OString tok_period = "period"_ostr;
62
constexpr OString tok_slash = "slash"_ostr;
63
constexpr OString tok_zero = "zero"_ostr;
64
constexpr OString tok_one = "one"_ostr;
65
constexpr OString tok_two = "two"_ostr;
66
constexpr OString tok_three = "three"_ostr;
67
constexpr OString tok_four = "four"_ostr;
68
constexpr OString tok_five = "five"_ostr;
69
constexpr OString tok_six = "six"_ostr;
70
constexpr OString tok_seven = "seven"_ostr;
71
constexpr OString tok_eight = "eight"_ostr;
72
constexpr OString tok_nine = "nine"_ostr;
73
constexpr OString tok_colon = "colon"_ostr;
74
constexpr OString tok_semicolon = "semicolon"_ostr;
75
constexpr OString tok_less = "less"_ostr;
76
constexpr OString tok_equal = "equal"_ostr;
77
constexpr OString tok_greater = "greater"_ostr;
78
constexpr OString tok_question = "question"_ostr;
79
constexpr OString tok_at = "at"_ostr;
80
constexpr OString tok_A = "A"_ostr;
81
constexpr OString tok_B = "B"_ostr;
82
constexpr OString tok_C = "C"_ostr;
83
constexpr OString tok_D = "D"_ostr;
84
constexpr OString tok_E = "E"_ostr;
85
constexpr OString tok_F = "F"_ostr;
86
constexpr OString tok_G = "G"_ostr;
87
constexpr OString tok_H = "H"_ostr;
88
constexpr OString tok_I = "I"_ostr;
89
constexpr OString tok_J = "J"_ostr;
90
constexpr OString tok_K = "K"_ostr;
91
constexpr OString tok_L = "L"_ostr;
92
constexpr OString tok_M = "M"_ostr;
93
constexpr OString tok_N = "N"_ostr;
94
constexpr OString tok_O = "O"_ostr;
95
constexpr OString tok_P = "P"_ostr;
96
constexpr OString tok_Q = "Q"_ostr;
97
constexpr OString tok_R = "R"_ostr;
98
constexpr OString tok_S = "S"_ostr;
99
constexpr OString tok_T = "T"_ostr;
100
constexpr OString tok_U = "U"_ostr;
101
constexpr OString tok_V = "V"_ostr;
102
constexpr OString tok_W = "W"_ostr;
103
constexpr OString tok_X = "X"_ostr;
104
constexpr OString tok_Y = "Y"_ostr;
105
constexpr OString tok_Z = "Z"_ostr;
106
constexpr OString tok_bracketleft = "bracketleft"_ostr;
107
constexpr OString tok_backslash = "backslash"_ostr;
108
constexpr OString tok_bracketright = "bracketright"_ostr;
109
constexpr OString tok_asciicircum = "asciicircum"_ostr;
110
constexpr OString tok_underscore = "underscore"_ostr;
111
constexpr OString tok_quoteleft = "quoteleft"_ostr;
112
constexpr OString tok_a = "a"_ostr;
113
constexpr OString tok_b = "b"_ostr;
114
constexpr OString tok_c = "c"_ostr;
115
constexpr OString tok_d = "d"_ostr;
116
constexpr OString tok_e = "e"_ostr;
117
constexpr OString tok_f = "f"_ostr;
118
constexpr OString tok_g = "g"_ostr;
119
constexpr OString tok_h = "h"_ostr;
120
constexpr OString tok_i = "i"_ostr;
121
constexpr OString tok_j = "j"_ostr;
122
constexpr OString tok_k = "k"_ostr;
123
constexpr OString tok_l = "l"_ostr;
124
constexpr OString tok_m = "m"_ostr;
125
constexpr OString tok_n = "n"_ostr;
126
constexpr OString tok_o = "o"_ostr;
127
constexpr OString tok_p = "p"_ostr;
128
constexpr OString tok_q = "q"_ostr;
129
constexpr OString tok_r = "r"_ostr;
130
constexpr OString tok_s = "s"_ostr;
131
constexpr OString tok_t = "t"_ostr;
132
constexpr OString tok_u = "u"_ostr;
133
constexpr OString tok_v = "v"_ostr;
134
constexpr OString tok_w = "w"_ostr;
135
constexpr OString tok_x = "x"_ostr;
136
constexpr OString tok_y = "y"_ostr;
137
constexpr OString tok_z = "z"_ostr;
138
constexpr OString tok_braceleft = "braceleft"_ostr;
139
constexpr OString tok_bar = "bar"_ostr;
140
constexpr OString tok_braceright = "braceright"_ostr;
141
constexpr OString tok_asciitilde = "asciitilde"_ostr;
142
constexpr OString tok_exclamdown = "exclamdown"_ostr;
143
constexpr OString tok_cent = "cent"_ostr;
144
constexpr OString tok_sterlin = "sterlin"_ostr;
145
constexpr OString tok_fraction = "fraction"_ostr;
146
constexpr OString tok_yen = "yen"_ostr;
147
constexpr OString tok_florin = "florin"_ostr;
148
constexpr OString tok_section = "section"_ostr;
149
constexpr OString tok_currency = "currency"_ostr;
150
constexpr OString tok_quotesingle = "quotesingle"_ostr;
151
constexpr OString tok_quotedblleft = "quotedblleft"_ostr;
152
constexpr OString tok_guillemotleft = "guillemotleft"_ostr;
153
constexpr OString tok_guilsinglleft = "guilsinglleft"_ostr;
154
constexpr OString tok_guilsinglright = "guilsinglright"_ostr;
155
constexpr OString tok_fi = "fi"_ostr;
156
constexpr OString tok_fl = "fl"_ostr;
157
constexpr OString tok_endash = "endash"_ostr;
158
constexpr OString tok_dagger = "dagger"_ostr;
159
constexpr OString tok_daggerdbl = "daggerdbl"_ostr;
160
constexpr OString tok_periodcentered = "periodcentered"_ostr;
161
constexpr OString tok_paragraph = "paragraph"_ostr;
162
constexpr OString tok_bullet = "bullet"_ostr;
163
constexpr OString tok_quotesinglbase = "quotesinglbase"_ostr;
164
constexpr OString tok_quotedblbase = "quotedblbase"_ostr;
165
constexpr OString tok_quotedblright = "quotedblright"_ostr;
166
constexpr OString tok_guillemotright = "guillemotright"_ostr;
167
constexpr OString tok_ellipsis = "ellipsis"_ostr;
168
constexpr OString tok_perthousand = "perthousand"_ostr;
169
constexpr OString tok_questiondown = "questiondown"_ostr;
170
constexpr OString tok_grave = "grave"_ostr;
171
constexpr OString tok_acute = "acute"_ostr;
172
constexpr OString tok_circumflex = "circumflex"_ostr;
173
constexpr OString tok_tilde = "tilde"_ostr;
174
constexpr OString tok_macron = "macron"_ostr;
175
constexpr OString tok_breve = "breve"_ostr;
176
constexpr OString tok_dotaccent = "dotaccent"_ostr;
177
constexpr OString tok_dieresis = "dieresis"_ostr;
178
constexpr OString tok_ring = "ring"_ostr;
179
constexpr OString tok_cedilla = "cedilla"_ostr;
180
constexpr OString tok_hungarumlaut = "hungarumlaut"_ostr;
181
constexpr OString tok_ogonek = "ogonek"_ostr;
182
constexpr OString tok_caron = "caron"_ostr;
183
constexpr OString tok_emdash = "emdash"_ostr;
184
constexpr OString tok_AE = "AE"_ostr;
185
constexpr OString tok_ordfeminine = "ordfeminine"_ostr;
186
constexpr OString tok_Lslash = "Lslash"_ostr;
187
constexpr OString tok_Oslash = "Oslash"_ostr;
188
constexpr OString tok_OE = "OE"_ostr;
189
constexpr OString tok_ordmasculine = "ordmasculine"_ostr;
190
constexpr OString tok_ae = "ae"_ostr;
191
constexpr OString tok_dotlessi = "dotlessi"_ostr;
192
constexpr OString tok_lslash = "lslash"_ostr;
193
constexpr OString tok_oslash = "oslash"_ostr;
194
constexpr OString tok_oe = "oe"_ostr;
195
constexpr OString tok_germandbls = "germandbls"_ostr;
196
constexpr OString tok_onesuperior = "onesuperior"_ostr;
197
constexpr OString tok_logicalnot = "logicalnot"_ostr;
198
constexpr OString tok_mu = "mu"_ostr;
199
constexpr OString tok_trademark = "trademark"_ostr;
200
constexpr OString tok_Eth = "Eth"_ostr;
201
constexpr OString tok_onehalf = "onehalf"_ostr;
202
constexpr OString tok_plusminus = "plusminus"_ostr;
203
constexpr OString tok_Thorn = "Thorn"_ostr;
204
constexpr OString tok_onequarter = "onequarter"_ostr;
205
constexpr OString tok_divide = "divide"_ostr;
206
constexpr OString tok_brokenbar = "brokenbar"_ostr;
207
constexpr OString tok_degree = "degree"_ostr;
208
constexpr OString tok_thorn = "thorn"_ostr;
209
constexpr OString tok_threequarters = "threequarters"_ostr;
210
constexpr OString tok_twosuperior = "twosuperior"_ostr;
211
constexpr OString tok_registered = "registered"_ostr;
212
constexpr OString tok_minus = "minus"_ostr;
213
constexpr OString tok_eth = "eth"_ostr;
214
constexpr OString tok_multiply = "multiply"_ostr;
215
constexpr OString tok_threesuperior = "threesuperior"_ostr;
216
constexpr OString tok_copyright = "copyright"_ostr;
217
constexpr OString tok_Aacute = "Aacute"_ostr;
218
constexpr OString tok_Acircumflex = "Acircumflex"_ostr;
219
constexpr OString tok_Adieresis = "Adieresis"_ostr;
220
constexpr OString tok_Agrave = "Agrave"_ostr;
221
constexpr OString tok_Aring = "Aring"_ostr;
222
constexpr OString tok_Atilde = "Atilde"_ostr;
223
constexpr OString tok_Ccedilla = "Ccedilla"_ostr;
224
constexpr OString tok_Eacute = "Eacute"_ostr;
225
constexpr OString tok_Ecircumflex = "Ecircumflex"_ostr;
226
constexpr OString tok_Edieresis = "Edieresis"_ostr;
227
constexpr OString tok_Egrave = "Egrave"_ostr;
228
constexpr OString tok_Iacute = "Iacute"_ostr;
229
constexpr OString tok_Icircumflex = "Icircumflex"_ostr;
230
constexpr OString tok_Idieresis = "Idieresis"_ostr;
231
constexpr OString tok_Igrave = "Igrave"_ostr;
232
constexpr OString tok_Ntilde = "Ntilde"_ostr;
233
constexpr OString tok_Oacute = "Oacute"_ostr;
234
constexpr OString tok_Ocircumflex = "Ocircumflex"_ostr;
235
constexpr OString tok_Odieresis = "Odieresis"_ostr;
236
constexpr OString tok_Ograve = "Ograve"_ostr;
237
constexpr OString tok_Otilde = "Otilde"_ostr;
238
constexpr OString tok_Scaron = "Scaron"_ostr;
239
constexpr OString tok_Uacute = "Uacute"_ostr;
240
constexpr OString tok_Ucircumflex = "Ucircumflex"_ostr;
241
constexpr OString tok_Udieresis = "Udieresis"_ostr;
242
constexpr OString tok_Ugrave = "Ugrave"_ostr;
243
constexpr OString tok_Yacute = "Yacute"_ostr;
244
constexpr OString tok_Ydieresis = "Ydieresis"_ostr;
245
constexpr OString tok_Zcaron = "Zcaron"_ostr;
246
constexpr OString tok_aacute = "aacute"_ostr;
247
constexpr OString tok_acircumflex = "acircumflex"_ostr;
248
constexpr OString tok_adieresis = "adieresis"_ostr;
249
constexpr OString tok_agrave = "agrave"_ostr;
250
constexpr OString tok_aring = "aring"_ostr;
251
constexpr OString tok_atilde = "atilde"_ostr;
252
constexpr OString tok_ccedilla = "ccedilla"_ostr;
253
constexpr OString tok_eacute = "eacute"_ostr;
254
constexpr OString tok_ecircumflex = "ecircumflex"_ostr;
255
constexpr OString tok_edieresis = "edieresis"_ostr;
256
constexpr OString tok_egrave = "egrave"_ostr;
257
constexpr OString tok_iacute = "iacute"_ostr;
258
constexpr OString tok_icircumflex = "icircumflex"_ostr;
259
constexpr OString tok_idieresis = "idieresis"_ostr;
260
constexpr OString tok_igrave = "igrave"_ostr;
261
constexpr OString tok_ntilde = "ntilde"_ostr;
262
constexpr OString tok_oacute = "oacute"_ostr;
263
constexpr OString tok_ocircumflex = "ocircumflex"_ostr;
264
constexpr OString tok_odieresis = "odieresis"_ostr;
265
constexpr OString tok_ograve = "ograve"_ostr;
266
constexpr OString tok_otilde = "otilde"_ostr;
267
constexpr OString tok_scaron = "scaron"_ostr;
268
constexpr OString tok_uacute = "uacute"_ostr;
269
constexpr OString tok_ucircumflex = "ucircumflex"_ostr;
270
constexpr OString tok_udieresis = "udieresis"_ostr;
271
constexpr OString tok_ugrave = "ugrave"_ostr;
272
constexpr OString tok_yacute = "yacute"_ostr;
273
constexpr OString tok_ydieresis = "ydieresis"_ostr;
274
constexpr OString tok_zcaron = "zcaron"_ostr;
275
constexpr OString tok_exclamsmall = "exclamsmall"_ostr;
276
constexpr OString tok_Hungarumlautsmall = "Hungarumlautsmall"_ostr;
277
constexpr OString tok_dollaroldstyle = "dollaroldstyle"_ostr;
278
constexpr OString tok_dollarsuperior = "dollarsuperior"_ostr;
279
constexpr OString tok_ampersandsmall = "ampersandsmall"_ostr;
280
constexpr OString tok_Acutesmall = "Acutesmall"_ostr;
281
constexpr OString tok_parenleftsuperior = "parenleftsuperior"_ostr;
282
constexpr OString tok_parenrightsuperior = "parenrightsuperior"_ostr;
283
constexpr OString tok_twodotenleader = "twodotenleader"_ostr;
284
constexpr OString tok_onedotenleader = "onedotenleader"_ostr;
285
constexpr OString tok_zerooldstyle = "zerooldstyle"_ostr;
286
constexpr OString tok_oneoldstyle = "oneoldstyle"_ostr;
287
constexpr OString tok_twooldstyle = "twooldstyle"_ostr;
288
constexpr OString tok_threeoldstyle = "threeoldstyle"_ostr;
289
constexpr OString tok_fouroldstyle = "fouroldstyle"_ostr;
290
constexpr OString tok_fiveoldstyle = "fiveoldstyle"_ostr;
291
constexpr OString tok_sixoldstyle = "sixoldstyle"_ostr;
292
constexpr OString tok_sevenoldstyle = "sevenoldstyle"_ostr;
293
constexpr OString tok_eightoldstyle = "eightoldstyle"_ostr;
294
constexpr OString tok_nineoldstile = "nineoldstile"_ostr;
295
constexpr OString tok_commasuperior = "commasuperior"_ostr;
296
constexpr OString tok_threequartersemdash = "threequartersemdash"_ostr;
297
constexpr OString tok_periodsuperior = "periodsuperior"_ostr;
298
constexpr OString tok_questionsmall = "questionsmall"_ostr;
299
constexpr OString tok_asuperior = "asuperior"_ostr;
300
constexpr OString tok_bsuperior = "bsuperior"_ostr;
301
constexpr OString tok_centsuperior = "centsuperior"_ostr;
302
constexpr OString tok_dsuperior = "dsuperior"_ostr;
303
constexpr OString tok_esuperior = "esuperior"_ostr;
304
constexpr OString tok_isuperior = "isuperior"_ostr;
305
constexpr OString tok_lsuperior = "lsuperior"_ostr;
306
constexpr OString tok_msuperior = "msuperior"_ostr;
307
constexpr OString tok_nsuperior = "nsuperior"_ostr;
308
constexpr OString tok_osuperior = "osuperior"_ostr;
309
constexpr OString tok_rsuperior = "rsuperior"_ostr;
310
constexpr OString tok_ssuperior = "ssuperior"_ostr;
311
constexpr OString tok_tsuperior = "tsuperior"_ostr;
312
constexpr OString tok_ff = "ff"_ostr;
313
constexpr OString tok_ffi = "ffi"_ostr;
314
constexpr OString tok_ffl = "ffl"_ostr;
315
constexpr OString tok_parenleftinferior = "parenleftinferior"_ostr;
316
constexpr OString tok_parenrightinferior = "parenrightinferior"_ostr;
317
constexpr OString tok_Circumflexsmall = "Circumflexsmall"_ostr;
318
constexpr OString tok_hyphensuperior = "hyphensuperior"_ostr;
319
constexpr OString tok_Gravesmall = "Gravesmall"_ostr;
320
constexpr OString tok_Asmall = "Asmall"_ostr;
321
constexpr OString tok_Bsmall = "Bsmall"_ostr;
322
constexpr OString tok_Csmall = "Csmall"_ostr;
323
constexpr OString tok_Dsmall = "Dsmall"_ostr;
324
constexpr OString tok_Esmall = "Esmall"_ostr;
325
constexpr OString tok_Fsmall = "Fsmall"_ostr;
326
constexpr OString tok_Gsmall = "Gsmall"_ostr;
327
constexpr OString tok_Hsmall = "Hsmall"_ostr;
328
constexpr OString tok_Ismall = "Ismall"_ostr;
329
constexpr OString tok_Jsmall = "Jsmall"_ostr;
330
constexpr OString tok_Ksmall = "Ksmall"_ostr;
331
constexpr OString tok_Lsmall = "Lsmall"_ostr;
332
constexpr OString tok_Msmall = "Msmall"_ostr;
333
constexpr OString tok_Nsmall = "Nsmall"_ostr;
334
constexpr OString tok_Osmall = "Osmall"_ostr;
335
constexpr OString tok_Psmall = "Psmall"_ostr;
336
constexpr OString tok_Qsmall = "Qsmall"_ostr;
337
constexpr OString tok_Rsmall = "Rsmall"_ostr;
338
constexpr OString tok_Ssmall = "Ssmall"_ostr;
339
constexpr OString tok_Tsmall = "Tsmall"_ostr;
340
constexpr OString tok_Usmall = "Usmall"_ostr;
341
constexpr OString tok_Vsmall = "Vsmall"_ostr;
342
constexpr OString tok_Wsmall = "Wsmall"_ostr;
343
constexpr OString tok_Xsmall = "Xsmall"_ostr;
344
constexpr OString tok_Ysmall = "Ysmall"_ostr;
345
constexpr OString tok_Zsmall = "Zsmall"_ostr;
346
constexpr OString tok_colonmonetary = "colonmonetary"_ostr;
347
constexpr OString tok_onefitted = "onefitted"_ostr;
348
constexpr OString tok_rupia = "rupia"_ostr;
349
constexpr OString tok_Tildesmall = "Tildesmall"_ostr;
350
constexpr OString tok_exclamdownsmall = "exclamdownsmall"_ostr;
351
constexpr OString tok_centoldstyle = "centoldstyle"_ostr;
352
constexpr OString tok_Lslashsmall = "Lslashsmall"_ostr;
353
constexpr OString tok_Scaronsmall = "Scaronsmall"_ostr;
354
constexpr OString tok_Zcaronsmall = "Zcaronsmall"_ostr;
355
constexpr OString tok_Dieresissmall = "Dieresissmall"_ostr;
356
constexpr OString tok_Brevesmall = "Brevesmall"_ostr;
357
constexpr OString tok_Caronsmall = "Caronsmall"_ostr;
358
constexpr OString tok_Dotaccentsmall = "Dotaccentsmall"_ostr;
359
constexpr OString tok_Macronsmall = "Macronsmall"_ostr;
360
constexpr OString tok_figuredash = "figuredash"_ostr;
361
constexpr OString tok_hypheninferior = "hypheninferior"_ostr;
362
constexpr OString tok_Ogoneksmall = "Ogoneksmall"_ostr;
363
constexpr OString tok_Ringsmall = "Ringsmall"_ostr;
364
constexpr OString tok_Cedillasmall = "Cedillasmall"_ostr;
365
constexpr OString tok_questiondownsmall = "questiondownsmall"_ostr;
366
constexpr OString tok_oneeight = "oneeight"_ostr;
367
constexpr OString tok_threeeights = "threeeights"_ostr;
368
constexpr OString tok_fiveeights = "fiveeights"_ostr;
369
constexpr OString tok_seveneights = "seveneights"_ostr;
370
constexpr OString tok_onethird = "onethird"_ostr;
371
constexpr OString tok_twothirds = "twothirds"_ostr;
372
constexpr OString tok_zerosuperior = "zerosuperior"_ostr;
373
constexpr OString tok_foursuperior = "foursuperior"_ostr;
374
constexpr OString tok_fivesuperior = "fivesuperior"_ostr;
375
constexpr OString tok_sixsuperior = "sixsuperior"_ostr;
376
constexpr OString tok_sevensuperior = "sevensuperior"_ostr;
377
constexpr OString tok_eightsuperior = "eightsuperior"_ostr;
378
constexpr OString tok_ninesuperior = "ninesuperior"_ostr;
379
constexpr OString tok_zeroinferior = "zeroinferior"_ostr;
380
constexpr OString tok_oneinferior = "oneinferior"_ostr;
381
constexpr OString tok_twoinferior = "twoinferior"_ostr;
382
constexpr OString tok_threeinferior = "threeinferior"_ostr;
383
constexpr OString tok_fourinferior = "fourinferior"_ostr;
384
constexpr OString tok_fiveinferior = "fiveinferior"_ostr;
385
constexpr OString tok_sixinferior = "sixinferior"_ostr;
386
constexpr OString tok_seveninferior = "seveninferior"_ostr;
387
constexpr OString tok_eightinferior = "eightinferior"_ostr;
388
constexpr OString tok_nineinferior = "nineinferior"_ostr;
389
constexpr OString tok_centinferior = "centinferior"_ostr;
390
constexpr OString tok_dollarinferior = "dollarinferior"_ostr;
391
constexpr OString tok_periodinferior = "periodinferior"_ostr;
392
constexpr OString tok_commainferior = "commainferior"_ostr;
393
constexpr OString tok_Agravesmall = "Agravesmall"_ostr;
394
constexpr OString tok_Aacutesmall = "Aacutesmall"_ostr;
395
constexpr OString tok_Acircumflexsmall = "Acircumflexsmall"_ostr;
396
constexpr OString tok_Atildesmall = "Atildesmall"_ostr;
397
constexpr OString tok_Adieresissmall = "Adieresissmall"_ostr;
398
constexpr OString tok_Aringsmall = "Aringsmall"_ostr;
399
constexpr OString tok_AEsmall = "AEsmall"_ostr;
400
constexpr OString tok_Ccedillasmall = "Ccedillasmall"_ostr;
401
constexpr OString tok_Egravesmall = "Egravesmall"_ostr;
402
constexpr OString tok_Eacutesmall = "Eacutesmall"_ostr;
403
constexpr OString tok_Ecircumflexsmall = "Ecircumflexsmall"_ostr;
404
constexpr OString tok_Edieresissmall = "Edieresissmall"_ostr;
405
constexpr OString tok_Igravesmall = "Igravesmall"_ostr;
406
constexpr OString tok_Iacutesmall = "Iacutesmall"_ostr;
407
constexpr OString tok_Icircumflexsmall = "Icircumflexsmall"_ostr;
408
constexpr OString tok_Idieresissmall = "Idieresissmall"_ostr;
409
constexpr OString tok_Ethsmall = "Ethsmall"_ostr;
410
constexpr OString tok_Ntildesmall = "Ntildesmall"_ostr;
411
constexpr OString tok_Ogravesmall = "Ogravesmall"_ostr;
412
constexpr OString tok_Oacutesmall = "Oacutesmall"_ostr;
413
constexpr OString tok_Ocircumflexsmall = "Ocircumflexsmall"_ostr;
414
constexpr OString tok_Otildesmall = "Otildesmall"_ostr;
415
constexpr OString tok_Odieressissmall = "Odieressissmall"_ostr;
416
constexpr OString tok_OEsmall = "OEsmall"_ostr;
417
constexpr OString tok_Oslashsmall = "Oslashsmall"_ostr;
418
constexpr OString tok_Ugravesmall = "Ugravesmall"_ostr;
419
constexpr OString tok_Uacutesmall = "Uacutesmall"_ostr;
420
constexpr OString tok_Ucircumflexsmall = "Ucircumflexsmall"_ostr;
421
constexpr OString tok_Udieresissmall = "Udieresissmall"_ostr;
422
constexpr OString tok_Yacutesmall = "Yacutesmall"_ostr;
423
constexpr OString tok_Thornsmall = "Thornsmall"_ostr;
424
constexpr OString tok_Ydieresissmall = "Ydieresissmall"_ostr;
425
constexpr OString tok_001_000 = "001.000"_ostr;
426
constexpr OString tok_001_001 = "001.001"_ostr;
427
constexpr OString tok_001_002 = "001.002"_ostr;
428
constexpr OString tok_001_003 = "001.003"_ostr;
429
constexpr OString tok_Black = "Black"_ostr;
430
constexpr OString tok_Bold = "Bold"_ostr;
431
constexpr OString tok_Book = "Book"_ostr;
432
constexpr OString tok_Light = "Light"_ostr;
433
constexpr OString tok_Medium = "Medium"_ostr;
434
constexpr OString tok_Regular = "Regular"_ostr;
435
constexpr OString tok_Roman = "Roman"_ostr;
436
constexpr OString tok_Semibold = "Semibold"_ostr;
437
438
constexpr OString pStringIds[] = {
439
    /*0*/ tok_notdef,
440
    tok_space,
441
    tok_exclam,
442
    tok_quotedbl,
443
    tok_numbersign,
444
    tok_dollar,
445
    tok_percent,
446
    tok_ampersand,
447
    tok_quoteright,
448
    tok_parenleft,
449
    tok_parenright,
450
    tok_asterisk,
451
    tok_plus,
452
    tok_comma,
453
    tok_hyphen,
454
    tok_period,
455
    /*16*/ tok_slash,
456
    tok_zero,
457
    tok_one,
458
    tok_two,
459
    tok_three,
460
    tok_four,
461
    tok_five,
462
    tok_six,
463
    tok_seven,
464
    tok_eight,
465
    tok_nine,
466
    tok_colon,
467
    tok_semicolon,
468
    tok_less,
469
    tok_equal,
470
    tok_greater,
471
    /*32*/ tok_question,
472
    tok_at,
473
    tok_A,
474
    tok_B,
475
    tok_C,
476
    tok_D,
477
    tok_E,
478
    tok_F,
479
    tok_G,
480
    tok_H,
481
    tok_I,
482
    tok_J,
483
    tok_K,
484
    tok_L,
485
    tok_M,
486
    tok_N,
487
    /*48*/ tok_O,
488
    tok_P,
489
    tok_Q,
490
    tok_R,
491
    tok_S,
492
    tok_T,
493
    tok_U,
494
    tok_V,
495
    tok_W,
496
    tok_X,
497
    tok_Y,
498
    tok_Z,
499
    tok_bracketleft,
500
    tok_backslash,
501
    tok_bracketright,
502
    tok_asciicircum,
503
    /*64*/ tok_underscore,
504
    tok_quoteleft,
505
    tok_a,
506
    tok_b,
507
    tok_c,
508
    tok_d,
509
    tok_e,
510
    tok_f,
511
    tok_g,
512
    tok_h,
513
    tok_i,
514
    tok_j,
515
    tok_k,
516
    tok_l,
517
    tok_m,
518
    tok_n,
519
    /*80*/ tok_o,
520
    tok_p,
521
    tok_q,
522
    tok_r,
523
    tok_s,
524
    tok_t,
525
    tok_u,
526
    tok_v,
527
    tok_w,
528
    tok_x,
529
    tok_y,
530
    tok_z,
531
    tok_braceleft,
532
    tok_bar,
533
    tok_braceright,
534
    tok_asciitilde,
535
    /*96*/ tok_exclamdown,
536
    tok_cent,
537
    tok_sterlin,
538
    tok_fraction,
539
    tok_yen,
540
    tok_florin,
541
    tok_section,
542
    tok_currency,
543
    tok_quotesingle,
544
    tok_quotedblleft,
545
    tok_guillemotleft,
546
    tok_guilsinglleft,
547
    tok_guilsinglright,
548
    tok_fi,
549
    tok_fl,
550
    tok_endash,
551
    /*112*/ tok_dagger,
552
    tok_daggerdbl,
553
    tok_periodcentered,
554
    tok_paragraph,
555
    tok_bullet,
556
    tok_quotesinglbase,
557
    tok_quotedblbase,
558
    tok_quotedblright,
559
    tok_guillemotright,
560
    tok_ellipsis,
561
    tok_perthousand,
562
    tok_questiondown,
563
    tok_grave,
564
    tok_acute,
565
    tok_circumflex,
566
    tok_tilde,
567
    /*128*/ tok_macron,
568
    tok_breve,
569
    tok_dotaccent,
570
    tok_dieresis,
571
    tok_ring,
572
    tok_cedilla,
573
    tok_hungarumlaut,
574
    tok_ogonek,
575
    tok_caron,
576
    tok_emdash,
577
    tok_AE,
578
    tok_ordfeminine,
579
    tok_Lslash,
580
    tok_Oslash,
581
    tok_OE,
582
    tok_ordmasculine,
583
    /*144*/ tok_ae,
584
    tok_dotlessi,
585
    tok_lslash,
586
    tok_oslash,
587
    tok_oe,
588
    tok_germandbls,
589
    tok_onesuperior,
590
    tok_logicalnot,
591
    tok_mu,
592
    tok_trademark,
593
    tok_Eth,
594
    tok_onehalf,
595
    tok_plusminus,
596
    tok_Thorn,
597
    tok_onequarter,
598
    tok_divide,
599
    /*160*/ tok_brokenbar,
600
    tok_degree,
601
    tok_thorn,
602
    tok_threequarters,
603
    tok_twosuperior,
604
    tok_registered,
605
    tok_minus,
606
    tok_eth,
607
    tok_multiply,
608
    tok_threesuperior,
609
    tok_copyright,
610
    tok_Aacute,
611
    tok_Acircumflex,
612
    tok_Adieresis,
613
    tok_Agrave,
614
    tok_Aring,
615
    /*176*/ tok_Atilde,
616
    tok_Ccedilla,
617
    tok_Eacute,
618
    tok_Ecircumflex,
619
    tok_Edieresis,
620
    tok_Egrave,
621
    tok_Iacute,
622
    tok_Icircumflex,
623
    tok_Idieresis,
624
    tok_Igrave,
625
    tok_Ntilde,
626
    tok_Oacute,
627
    tok_Ocircumflex,
628
    tok_Odieresis,
629
    tok_Ograve,
630
    tok_Otilde,
631
    /*192*/ tok_Scaron,
632
    tok_Uacute,
633
    tok_Ucircumflex,
634
    tok_Udieresis,
635
    tok_Ugrave,
636
    tok_Yacute,
637
    tok_Ydieresis,
638
    tok_Zcaron,
639
    tok_aacute,
640
    tok_acircumflex,
641
    tok_adieresis,
642
    tok_agrave,
643
    tok_aring,
644
    tok_atilde,
645
    tok_ccedilla,
646
    tok_eacute,
647
    /*208*/ tok_ecircumflex,
648
    tok_edieresis,
649
    tok_egrave,
650
    tok_iacute,
651
    tok_icircumflex,
652
    tok_idieresis,
653
    tok_igrave,
654
    tok_ntilde,
655
    tok_oacute,
656
    tok_ocircumflex,
657
    tok_odieresis,
658
    tok_ograve,
659
    tok_otilde,
660
    tok_scaron,
661
    tok_uacute,
662
    tok_ucircumflex,
663
    /*224*/ tok_udieresis,
664
    tok_ugrave,
665
    tok_yacute,
666
    tok_ydieresis,
667
    tok_zcaron,
668
    tok_exclamsmall,
669
    tok_Hungarumlautsmall,
670
    tok_dollaroldstyle,
671
    tok_dollarsuperior,
672
    tok_ampersandsmall,
673
    tok_Acutesmall,
674
    tok_parenleftsuperior,
675
    tok_parenrightsuperior,
676
    tok_twodotenleader,
677
    tok_onedotenleader,
678
    tok_zerooldstyle,
679
    /*240*/ tok_oneoldstyle,
680
    tok_twooldstyle,
681
    tok_threeoldstyle,
682
    tok_fouroldstyle,
683
    tok_fiveoldstyle,
684
    tok_sixoldstyle,
685
    tok_sevenoldstyle,
686
    tok_eightoldstyle,
687
    tok_nineoldstile,
688
    tok_commasuperior,
689
    tok_threequartersemdash,
690
    tok_periodsuperior,
691
    tok_questionsmall,
692
    tok_asuperior,
693
    tok_bsuperior,
694
    tok_centsuperior,
695
    /*256*/ tok_dsuperior,
696
    tok_esuperior,
697
    tok_isuperior,
698
    tok_lsuperior,
699
    tok_msuperior,
700
    tok_nsuperior,
701
    tok_osuperior,
702
    tok_rsuperior,
703
    tok_ssuperior,
704
    tok_tsuperior,
705
    tok_ff,
706
    tok_ffi,
707
    tok_ffl,
708
    tok_parenleftinferior,
709
    tok_parenrightinferior,
710
    tok_Circumflexsmall,
711
    /*272*/ tok_hyphensuperior,
712
    tok_Gravesmall,
713
    tok_Asmall,
714
    tok_Bsmall,
715
    tok_Csmall,
716
    tok_Dsmall,
717
    tok_Esmall,
718
    tok_Fsmall,
719
    tok_Gsmall,
720
    tok_Hsmall,
721
    tok_Ismall,
722
    tok_Jsmall,
723
    tok_Ksmall,
724
    tok_Lsmall,
725
    tok_Msmall,
726
    tok_Nsmall,
727
    /*288*/ tok_Osmall,
728
    tok_Psmall,
729
    tok_Qsmall,
730
    tok_Rsmall,
731
    tok_Ssmall,
732
    tok_Tsmall,
733
    tok_Usmall,
734
    tok_Vsmall,
735
    tok_Wsmall,
736
    tok_Xsmall,
737
    tok_Ysmall,
738
    tok_Zsmall,
739
    tok_colonmonetary,
740
    tok_onefitted,
741
    tok_rupia,
742
    tok_Tildesmall,
743
    /*304*/ tok_exclamdownsmall,
744
    tok_centoldstyle,
745
    tok_Lslashsmall,
746
    tok_Scaronsmall,
747
    tok_Zcaronsmall,
748
    tok_Dieresissmall,
749
    tok_Brevesmall,
750
    tok_Caronsmall,
751
    tok_Dotaccentsmall,
752
    tok_Macronsmall,
753
    tok_figuredash,
754
    tok_hypheninferior,
755
    tok_Ogoneksmall,
756
    tok_Ringsmall,
757
    tok_Cedillasmall,
758
    tok_questiondownsmall,
759
    /*320*/ tok_oneeight,
760
    tok_threeeights,
761
    tok_fiveeights,
762
    tok_seveneights,
763
    tok_onethird,
764
    tok_twothirds,
765
    tok_zerosuperior,
766
    tok_foursuperior,
767
    tok_fivesuperior,
768
    tok_sixsuperior,
769
    tok_sevensuperior,
770
    tok_eightsuperior,
771
    tok_ninesuperior,
772
    tok_zeroinferior,
773
    tok_oneinferior,
774
    tok_twoinferior,
775
    /*336*/ tok_threeinferior,
776
    tok_fourinferior,
777
    tok_fiveinferior,
778
    tok_sixinferior,
779
    tok_seveninferior,
780
    tok_eightinferior,
781
    tok_nineinferior,
782
    tok_centinferior,
783
    tok_dollarinferior,
784
    tok_periodinferior,
785
    tok_commainferior,
786
    tok_Agravesmall,
787
    tok_Aacutesmall,
788
    tok_Acircumflexsmall,
789
    tok_Atildesmall,
790
    tok_Adieresissmall,
791
    /*352*/ tok_Aringsmall,
792
    tok_AEsmall,
793
    tok_Ccedillasmall,
794
    tok_Egravesmall,
795
    tok_Eacutesmall,
796
    tok_Ecircumflexsmall,
797
    tok_Edieresissmall,
798
    tok_Igravesmall,
799
    tok_Iacutesmall,
800
    tok_Icircumflexsmall,
801
    tok_Idieresissmall,
802
    tok_Ethsmall,
803
    tok_Ntildesmall,
804
    tok_Ogravesmall,
805
    tok_Oacutesmall,
806
    tok_Ocircumflexsmall,
807
    /*368*/ tok_Otildesmall,
808
    tok_Odieressissmall,
809
    tok_OEsmall,
810
    tok_Oslashsmall,
811
    tok_Ugravesmall,
812
    tok_Uacutesmall,
813
    tok_Ucircumflexsmall,
814
    tok_Udieresissmall,
815
    tok_Yacutesmall,
816
    tok_Thornsmall,
817
    tok_Ydieresissmall,
818
    tok_001_000,
819
    tok_001_001,
820
    tok_001_002,
821
    tok_001_003,
822
    tok_Black,
823
    /*384*/ tok_Bold,
824
    tok_Book,
825
    tok_Light,
826
    tok_Medium,
827
    tok_Regular,
828
    tok_Roman,
829
    tok_Semibold
830
};
831
832
// TOP DICT keywords (also covers PRIV DICT keywords)
833
const char* const pDictOps[] = { "sVersion",
834
                                 "sNotice",
835
                                 "sFullName",
836
                                 "sFamilyName",
837
                                 "sWeight",
838
                                 "aFontBBox",
839
                                 "dBlueValues",
840
                                 "dOtherBlues",
841
                                 "dFamilyBlues",
842
                                 "dFamilyOtherBlues",
843
                                 "nStdHW",
844
                                 "nStdVW",
845
                                 "xESC",
846
                                 "nUniqueID",
847
                                 "aXUID",
848
                                 "nCharset",
849
                                 "nEncoding",
850
                                 "nCharStrings",
851
                                 "PPrivate",
852
                                 "nSubrs",
853
                                 "nDefaultWidthX",
854
                                 "nNominalWidthX",
855
                                 nullptr,
856
                                 nullptr,
857
                                 nullptr,
858
                                 nullptr,
859
                                 nullptr,
860
                                 nullptr,
861
                                 "shortint",
862
                                 "longint",
863
                                 "BCD",
864
                                 nullptr };
865
866
// TOP DICT escapes (also covers PRIV DICT escapes)
867
const char* const pDictEscs[] = { "sCopyright",
868
                                  "bIsFixedPitch",
869
                                  "nItalicAngle",
870
                                  "nUnderlinePosition",
871
                                  "nUnderlineThickness",
872
                                  "nPaintType",
873
                                  "tCharstringType",
874
                                  "aFontMatrix",
875
                                  "nStrokeWidth",
876
                                  "nBlueScale",
877
                                  "nBlueShift",
878
                                  "nBlueFuzz",
879
                                  "dStemSnapH",
880
                                  "dStemSnapV",
881
                                  "bForceBold",
882
                                  nullptr,
883
                                  nullptr,
884
                                  "nLanguageGroup",
885
                                  "nExpansionFactor",
886
                                  "nInitialRandomSeed",
887
                                  "nSyntheticBase",
888
                                  "sPostScript",
889
                                  "sBaseFontName",
890
                                  "dBaseFontBlend",
891
                                  nullptr,
892
                                  nullptr,
893
                                  nullptr,
894
                                  nullptr,
895
                                  nullptr,
896
                                  nullptr,
897
                                  "rROS",
898
                                  "nCIDFontVersion",
899
                                  "nCIDFontRevision",
900
                                  "nCIDFontType",
901
                                  "nCIDCount",
902
                                  "nUIDBase",
903
                                  "nFDArray",
904
                                  "nFDSelect",
905
                                  "sFontName" };
906
907
const char* const pStandardEncoding[] = { ".notdef",
908
                                          ".notdef",
909
                                          ".notdef",
910
                                          ".notdef",
911
                                          ".notdef",
912
                                          ".notdef",
913
                                          ".notdef",
914
                                          ".notdef",
915
                                          ".notdef",
916
                                          ".notdef",
917
                                          ".notdef",
918
                                          ".notdef",
919
                                          ".notdef",
920
                                          ".notdef",
921
                                          ".notdef",
922
                                          ".notdef",
923
                                          ".notdef",
924
                                          ".notdef",
925
                                          ".notdef",
926
                                          ".notdef",
927
                                          ".notdef",
928
                                          ".notdef",
929
                                          ".notdef",
930
                                          ".notdef",
931
                                          ".notdef",
932
                                          ".notdef",
933
                                          ".notdef",
934
                                          ".notdef",
935
                                          ".notdef",
936
                                          ".notdef",
937
                                          ".notdef",
938
                                          ".notdef",
939
                                          "space",
940
                                          "exclam",
941
                                          "quotedbl",
942
                                          "numbersign",
943
                                          "dollar",
944
                                          "percent",
945
                                          "ampersand",
946
                                          "quoteright",
947
                                          "parenleft",
948
                                          "parenright",
949
                                          "asterisk",
950
                                          "plus",
951
                                          "comma",
952
                                          "hyphen",
953
                                          "period",
954
                                          "slash",
955
                                          "zero",
956
                                          "one",
957
                                          "two",
958
                                          "three",
959
                                          "four",
960
                                          "five",
961
                                          "six",
962
                                          "seven",
963
                                          "eight",
964
                                          "nine",
965
                                          "colon",
966
                                          "semicolon",
967
                                          "less",
968
                                          "equal",
969
                                          "greater",
970
                                          "question",
971
                                          "at",
972
                                          "A",
973
                                          "B",
974
                                          "C",
975
                                          "D",
976
                                          "E",
977
                                          "F",
978
                                          "G",
979
                                          "H",
980
                                          "I",
981
                                          "J",
982
                                          "K",
983
                                          "L",
984
                                          "M",
985
                                          "N",
986
                                          "O",
987
                                          "P",
988
                                          "Q",
989
                                          "R",
990
                                          "S",
991
                                          "T",
992
                                          "U",
993
                                          "V",
994
                                          "W",
995
                                          "X",
996
                                          "Y",
997
                                          "Z",
998
                                          "bracketleft",
999
                                          "backslash",
1000
                                          "bracketright",
1001
                                          "asciicircum",
1002
                                          "underscore",
1003
                                          "quoteleft",
1004
                                          "a",
1005
                                          "b",
1006
                                          "c",
1007
                                          "d",
1008
                                          "e",
1009
                                          "f",
1010
                                          "g",
1011
                                          "h",
1012
                                          "i",
1013
                                          "j",
1014
                                          "k",
1015
                                          "l",
1016
                                          "m",
1017
                                          "n",
1018
                                          "o",
1019
                                          "p",
1020
                                          "q",
1021
                                          "r",
1022
                                          "s",
1023
                                          "t",
1024
                                          "u",
1025
                                          "v",
1026
                                          "w",
1027
                                          "x",
1028
                                          "y",
1029
                                          "z",
1030
                                          "braceleft",
1031
                                          "bar",
1032
                                          "braceright",
1033
                                          "asciitilde",
1034
                                          ".notdef",
1035
                                          ".notdef",
1036
                                          ".notdef",
1037
                                          ".notdef",
1038
                                          ".notdef",
1039
                                          ".notdef",
1040
                                          ".notdef",
1041
                                          ".notdef",
1042
                                          ".notdef",
1043
                                          ".notdef",
1044
                                          ".notdef",
1045
                                          ".notdef",
1046
                                          ".notdef",
1047
                                          ".notdef",
1048
                                          ".notdef",
1049
                                          ".notdef",
1050
                                          ".notdef",
1051
                                          ".notdef",
1052
                                          ".notdef",
1053
                                          ".notdef",
1054
                                          ".notdef",
1055
                                          ".notdef",
1056
                                          ".notdef",
1057
                                          ".notdef",
1058
                                          ".notdef",
1059
                                          ".notdef",
1060
                                          ".notdef",
1061
                                          ".notdef",
1062
                                          ".notdef",
1063
                                          ".notdef",
1064
                                          ".notdef",
1065
                                          ".notdef",
1066
                                          ".notdef",
1067
                                          ".notdef",
1068
                                          "exclamdown",
1069
                                          "cent",
1070
                                          "sterling",
1071
                                          "fraction",
1072
                                          "yen",
1073
                                          "florin",
1074
                                          "section",
1075
                                          "currency",
1076
                                          "quotesingle",
1077
                                          "quotedblleft",
1078
                                          "guillemotleft",
1079
                                          "guilsinglleft",
1080
                                          "guilsinglright",
1081
                                          "fi",
1082
                                          "fl",
1083
                                          ".notdef",
1084
                                          "endash",
1085
                                          "dagger",
1086
                                          "daggerdbl",
1087
                                          "periodcentered",
1088
                                          ".notdef",
1089
                                          "paragraph",
1090
                                          "bullet",
1091
                                          "quotesinglbase",
1092
                                          "quotedblbase",
1093
                                          "quotedblright",
1094
                                          "guillemotright",
1095
                                          "ellipsis",
1096
                                          "perthousand",
1097
                                          ".notdef",
1098
                                          "questiondown",
1099
                                          ".notdef",
1100
                                          "grave",
1101
                                          "acute",
1102
                                          "circumflex",
1103
                                          "tilde",
1104
                                          "macron",
1105
                                          "breve",
1106
                                          "dotaccent",
1107
                                          "dieresis",
1108
                                          ".notdef",
1109
                                          "ring",
1110
                                          "cedilla",
1111
                                          ".notdef",
1112
                                          "hungarumlaut",
1113
                                          "ogonek",
1114
                                          "caron",
1115
                                          "emdash",
1116
                                          ".notdef",
1117
                                          ".notdef",
1118
                                          ".notdef",
1119
                                          ".notdef",
1120
                                          ".notdef",
1121
                                          ".notdef",
1122
                                          ".notdef",
1123
                                          ".notdef",
1124
                                          ".notdef",
1125
                                          ".notdef",
1126
                                          ".notdef",
1127
                                          ".notdef",
1128
                                          ".notdef",
1129
                                          ".notdef",
1130
                                          ".notdef",
1131
                                          ".notdef",
1132
                                          "AE",
1133
                                          ".notdef",
1134
                                          "ordfeminine",
1135
                                          ".notdef",
1136
                                          ".notdef",
1137
                                          ".notdef",
1138
                                          ".notdef",
1139
                                          "Lslash",
1140
                                          "Oslash",
1141
                                          "OE",
1142
                                          "ordmasculine",
1143
                                          ".notdef",
1144
                                          ".notdef",
1145
                                          ".notdef",
1146
                                          ".notdef",
1147
                                          ".notdef",
1148
                                          "ae",
1149
                                          ".notdef",
1150
                                          ".notdef",
1151
                                          ".notdef",
1152
                                          "dotlessi",
1153
                                          ".notdef",
1154
                                          ".notdef",
1155
                                          "lslash",
1156
                                          "oslash",
1157
                                          "oe",
1158
                                          "germandbls",
1159
                                          ".notdef",
1160
                                          ".notdef",
1161
                                          ".notdef",
1162
                                          ".notdef" };
1163
1164
namespace
1165
{
1166
namespace TYPE1OP
1167
{
1168
enum OPS
1169
{
1170
    HSTEM = 1,
1171
    VSTEM = 3,
1172
    VMOVETO = 4,
1173
    RLINETO = 5,
1174
    HLINETO = 6,
1175
    VLINETO = 7,
1176
    RCURVETO = 8,
1177
    CLOSEPATH = 9,
1178
    CALLSUBR = 10,
1179
    RETURN = 11,
1180
    T1ESC = 12,
1181
    HSBW = 13,
1182
    ENDCHAR = 14,
1183
    RMOVETO = 21,
1184
    HMOVETO = 22,
1185
    VHCURVETO = 30,
1186
    HVCURVETO = 31
1187
};
1188
1189
enum ESCS
1190
{
1191
    DOTSECTION = 0,
1192
    VSTEM3 = 1,
1193
    HSTEM3 = 2,
1194
    SEAC = 6,
1195
    SBW = 7,
1196
    ABS = 9,
1197
    ADD = 10,
1198
    SUB = 11,
1199
    DIV = 12,
1200
    CALLOTHERSUBR = 16,
1201
    POP = 17,
1202
    SETCURRENTPOINT = 33
1203
};
1204
}
1205
1206
namespace TYPE2OP
1207
{
1208
enum OPS
1209
{
1210
    HSTEM = 1,
1211
    VSTEM = 3,
1212
    VMOVETO = 4,
1213
    RLINETO = 5,
1214
    HLINETO = 6,
1215
    VLINETO = 7,
1216
    RCURVETO = 8,
1217
    CALLSUBR = 10,
1218
    RETURN = 11,
1219
    T2ESC = 12,
1220
    ENDCHAR = 14,
1221
    HSTEMHM = 18,
1222
    HINTMASK = 19,
1223
    CNTRMASK = 20,
1224
    RMOVETO = 21,
1225
    HMOVETO = 22,
1226
    VSTEMHM = 23,
1227
    RCURVELINE = 24,
1228
    RLINECURVE = 25,
1229
    VVCURVETO = 26,
1230
    HHCURVETO = 27,
1231
    SHORTINT = 28,
1232
    CALLGSUBR = 29,
1233
    VHCURVETO = 30,
1234
    HVCURVETO = 31
1235
};
1236
1237
enum ESCS
1238
{
1239
    AND = 3,
1240
    OR = 4,
1241
    NOT = 5,
1242
    ABS = 9,
1243
    ADD = 10,
1244
    SUB = 11,
1245
    DIV = 12,
1246
    NEG = 14,
1247
    EQ = 15,
1248
    DROP = 18,
1249
    PUT = 20,
1250
    GET = 21,
1251
    IFELSE = 22,
1252
    RANDOM = 23,
1253
    MUL = 24,
1254
    SQRT = 26,
1255
    DUP = 27,
1256
    EXCH = 28,
1257
    INDEX = 29,
1258
    ROLL = 30,
1259
    HFLEX = 34,
1260
    FLEX = 35,
1261
    HFLEX1 = 36,
1262
    FLEX1 = 37
1263
};
1264
}
1265
1266
struct CffGlobal
1267
{
1268
    explicit CffGlobal();
1269
1270
    int mnNameIdxBase;
1271
    int mnStringIdxBase;
1272
    bool mbCIDFont;
1273
    int mnCharStrBase;
1274
    int mnCharStrCount;
1275
    int mnCharsetBase;
1276
    int mnGlobalSubrBase;
1277
    int mnGlobalSubrCount;
1278
    int mnGlobalSubrBias;
1279
    int mnFDSelectBase;
1280
    int mnFontDictBase;
1281
    int mnFDAryCount;
1282
1283
    std::vector<ValType> maFontMatrix;
1284
};
1285
1286
struct CffLocal
1287
{
1288
    explicit CffLocal();
1289
1290
    int mnPrivDictBase;
1291
    int mnPrivDictSize;
1292
    int mnLocalSubrOffs;
1293
    int mnLocalSubrBase;
1294
    int mnLocalSubrBias;
1295
1296
    ValType maNominalWidth;
1297
    ValType maDefaultWidth;
1298
1299
    // ATM hinting related values
1300
    ValType maStemStdHW;
1301
    ValType maStemStdVW;
1302
    std::vector<ValType> maStemSnapH;
1303
    std::vector<ValType> maStemSnapV;
1304
    std::vector<ValType> maBlueValues;
1305
    std::vector<ValType> maOtherBlues;
1306
    std::vector<ValType> maFamilyBlues;
1307
    std::vector<ValType> maFamilyOtherBlues;
1308
    RealType mfBlueScale;
1309
    RealType mfBlueShift;
1310
    RealType mfBlueFuzz;
1311
    RealType mfExpFactor;
1312
    int mnLangGroup;
1313
    bool mbForceBold;
1314
};
1315
1316
const int MAX_T1OPS_SIZE = 81920; // TODO: use dynamic value
1317
1318
struct CharString
1319
{
1320
    int nLen;
1321
    U8 aOps[MAX_T1OPS_SIZE];
1322
    int nCffGlyphId;
1323
};
1324
1325
class CffContext : private CffGlobal
1326
{
1327
public:
1328
    static const int NMAXSTACK = 48; // see CFF.appendixB
1329
    static const int NMAXHINTS = 2 * 96; // see CFF.appendixB
1330
    static const int NMAXTRANS = 32; // see CFF.appendixB
1331
1332
    explicit CffContext(const U8* pBasePtr, int nBaseLen);
1333
1334
    bool initialCffRead();
1335
    bool emitAsType1(class Type1Emitter&, FontSubsetInfo&);
1336
1337
private:
1338
    bool convertCharStrings(std::vector<CharString>& rCharStrings, int nGlyphCount,
1339
                            const sal_GlyphId* pGlyphIds = nullptr);
1340
    int convert2Type1Ops(CffLocal*, const U8* pType2Ops, int nType2Len, U8* pType1Ops);
1341
    bool convertOneTypeOp();
1342
    bool convertOneTypeEsc();
1343
    bool callType2Subr(bool bGlobal, int nSubrNumber);
1344
0
    sal_Int32 getReadOfs() const { return static_cast<sal_Int32>(mpReadPtr - mpBasePtr); }
1345
1346
    const U8* mpBasePtr;
1347
    const U8* mpBaseEnd;
1348
1349
    const U8* mpReadPtr;
1350
    const U8* mpReadEnd;
1351
1352
    U8* mpWritePtr;
1353
    bool mbNeedClose;
1354
    bool mbIgnoreHints;
1355
    sal_Int32 mnCntrMask;
1356
1357
    int seekIndexData(int nIndexBase, int nDataIndex);
1358
    bool seekIndexEnd(int nIndexBase);
1359
1360
    CffLocal maCffLocal[256];
1361
    CffLocal* mpCffLocal;
1362
1363
    void readDictOp();
1364
    RealType readRealVal();
1365
    OString getString(int nStringID);
1366
    int getFDSelect(int nGlyphIndex) const;
1367
    int getGlyphSID(int nGlyphIndex) const;
1368
    OString getGlyphName(int nGlyphIndex);
1369
    bool getBaseAccent(ValType aBase, ValType aAccent, int* nBase, int* nAccent);
1370
1371
    void read2push();
1372
    void writeType1Val(ValType);
1373
    void writeTypeOp(int nTypeOp);
1374
    void writeTypeEsc(int nTypeOp);
1375
    void writeCurveTo(int nStackPos, int nIX1, int nIY1, int nIX2, int nIY2, int nIX3, int nIY3);
1376
    void pop2MultiWrite(int nArgsPerTypo, int nTypeOp, int nTypeXor = 0);
1377
    void popAll2Write(int nTypeOp);
1378
1379
public: // TODO: is public really needed?
1380
    // accessing the value stack
1381
    // TODO: add more checks
1382
0
    void push(ValType nVal) { mnValStack[mnStackIdx++] = nVal; }
1383
0
    ValType popVal() { return ((mnStackIdx > 0) ? mnValStack[--mnStackIdx] : 0); }
1384
0
    ValType getVal(int nIndex) const { return mnValStack[nIndex]; }
1385
    int popInt();
1386
0
    int size() const { return mnStackIdx; }
1387
0
    void clear() { mnStackIdx = 0; }
1388
1389
    // accessing the charstring hints
1390
    bool addHints(bool bVerticalHints);
1391
1392
    // accessing other charstring specifics
1393
    void updateWidth(bool bUseFirstVal);
1394
1395
private:
1396
    // typeop execution context
1397
    int mnStackIdx;
1398
    ValType mnValStack[NMAXSTACK + 4];
1399
    ValType mnTransVals[NMAXTRANS];
1400
1401
    int mnHintSize;
1402
    int mnHorzHintSize;
1403
    ValType mnHintStack[NMAXHINTS];
1404
1405
    ValType maCharWidth;
1406
1407
    bool mbDoSeac;
1408
    std::vector<sal_GlyphId> maExtraGlyphIds;
1409
};
1410
}
1411
1412
CffContext::CffContext(const U8* pBasePtr, int nBaseLen)
1413
9.57k
    : mpBasePtr(pBasePtr)
1414
9.57k
    , mpBaseEnd(pBasePtr + nBaseLen)
1415
9.57k
    , mpReadPtr(nullptr)
1416
9.57k
    , mpReadEnd(nullptr)
1417
9.57k
    , mpWritePtr(nullptr)
1418
9.57k
    , mbNeedClose(false)
1419
9.57k
    , mbIgnoreHints(false)
1420
9.57k
    , mnCntrMask(0)
1421
9.57k
    , mnStackIdx(0)
1422
9.57k
    , mnValStack{}
1423
9.57k
    , mnTransVals{}
1424
9.57k
    , mnHintSize(0)
1425
9.57k
    , mnHorzHintSize(0)
1426
9.57k
    , mnHintStack{}
1427
9.57k
    , maCharWidth(-1)
1428
9.57k
    , mbDoSeac(true)
1429
9.57k
{
1430
    //  setCharStringType( 1);
1431
    // TODO: new CffLocal[ mnFDAryCount];
1432
9.57k
    mpCffLocal = &maCffLocal[0];
1433
9.57k
}
1434
1435
inline int CffContext::popInt()
1436
0
{
1437
0
    const ValType aVal = popVal();
1438
0
    const int nInt = static_cast<int>(aVal);
1439
0
    assert(nInt == aVal);
1440
0
    return nInt;
1441
0
}
1442
1443
inline void CffContext::updateWidth(bool bUseFirstVal)
1444
0
{
1445
    // the first value is not a hint but the charwidth
1446
0
    if (maCharWidth > 0)
1447
0
        return;
1448
1449
0
    if (bUseFirstVal)
1450
0
    {
1451
0
        maCharWidth = mpCffLocal->maNominalWidth + mnValStack[0];
1452
        // remove bottom stack entry
1453
0
        --mnStackIdx;
1454
0
        for (int i = 0; i < mnStackIdx; ++i)
1455
0
            mnValStack[i] = mnValStack[i + 1];
1456
0
    }
1457
0
    else
1458
0
    {
1459
0
        maCharWidth = mpCffLocal->maDefaultWidth;
1460
0
    }
1461
0
}
1462
1463
bool CffContext::addHints(bool bVerticalHints)
1464
0
{
1465
    // the first charstring value may a charwidth instead of a charwidth
1466
0
    updateWidth((mnStackIdx & 1) != 0);
1467
    // return early (e.g. no implicit hints for hintmask)
1468
0
    if (!mnStackIdx)
1469
0
        return true;
1470
1471
    // copy the remaining values to the hint arrays
1472
0
    if (mnStackIdx & 1)
1473
0
        --mnStackIdx; //#######
1474
1475
0
    if ((mnHintSize + mnStackIdx) > 2 * NMAXHINTS)
1476
0
        return false;
1477
1478
0
    ValType nHintOfs = 0;
1479
0
    for (int i = 0; i < mnStackIdx; ++i)
1480
0
    {
1481
0
        nHintOfs += mnValStack[i];
1482
0
        mnHintStack[mnHintSize++] = nHintOfs;
1483
0
    }
1484
1485
0
    if (!bVerticalHints)
1486
0
        mnHorzHintSize = mnHintSize;
1487
1488
    // clear all values from the stack
1489
0
    mnStackIdx = 0;
1490
0
    return true;
1491
0
}
1492
1493
void CffContext::readDictOp()
1494
0
{
1495
0
    const U8 c = *mpReadPtr;
1496
0
    if (c <= 21)
1497
0
    {
1498
0
        int nOpId = *(mpReadPtr++);
1499
0
        const char* pCmdName = nullptr;
1500
0
        if (nOpId != 12)
1501
0
            pCmdName = pDictOps[nOpId];
1502
0
        else
1503
0
        {
1504
0
            const U8 nExtId = *(mpReadPtr++);
1505
0
            if (nExtId < 39)
1506
0
                pCmdName = pDictEscs[nExtId];
1507
0
            nOpId = 900 + nExtId;
1508
0
        }
1509
1510
0
        if (!pCmdName) // skip reserved operators
1511
0
            return;
1512
1513
        //TODO: if( nStackIdx > 0)
1514
0
        int nInt = 0;
1515
0
        switch (*pCmdName)
1516
0
        {
1517
0
            default:
1518
0
                SAL_WARN("vcl.fonts.cff", "unsupported DictOp.type='" << *pCmdName << "'.");
1519
0
                break;
1520
0
            case 'b': // bool
1521
0
                nInt = popInt();
1522
0
                switch (nOpId)
1523
0
                {
1524
0
                    case 915:
1525
0
                        mpCffLocal->mbForceBold = nInt;
1526
0
                        break; // "ForceBold"
1527
0
                    default:
1528
0
                        break; // TODO: handle more boolean dictops?
1529
0
                }
1530
0
                break;
1531
0
            case 'n':
1532
0
            { // dict-op number
1533
0
                ValType nVal = popVal();
1534
0
                nInt = static_cast<int>(nVal);
1535
0
                switch (nOpId)
1536
0
                {
1537
0
                    case 10:
1538
0
                        mpCffLocal->maStemStdHW = nVal;
1539
0
                        break; // "StdHW"
1540
0
                    case 11:
1541
0
                        mpCffLocal->maStemStdVW = nVal;
1542
0
                        break; // "StdVW"
1543
0
                    case 15:
1544
0
                        mnCharsetBase = nInt;
1545
0
                        break; // "charset"
1546
0
                    case 16:
1547
0
                        break; // "nEncoding"
1548
0
                    case 17:
1549
0
                        mnCharStrBase = nInt;
1550
0
                        break; // "nCharStrings"
1551
0
                    case 19:
1552
0
                        mpCffLocal->mnLocalSubrOffs = nInt;
1553
0
                        break; // "nSubrs"
1554
0
                    case 20:
1555
0
                        mpCffLocal->maDefaultWidth = nVal;
1556
0
                        break; // "defaultWidthX"
1557
0
                    case 21:
1558
0
                        mpCffLocal->maNominalWidth = nVal;
1559
0
                        break; // "nominalWidthX"
1560
0
                    case 909:
1561
0
                        mpCffLocal->mfBlueScale = nVal;
1562
0
                        break; // "BlueScale"
1563
0
                    case 910:
1564
0
                        mpCffLocal->mfBlueShift = nVal;
1565
0
                        break; // "BlueShift"
1566
0
                    case 911:
1567
0
                        mpCffLocal->mfBlueFuzz = nVal;
1568
0
                        break; // "BlueFuzz"
1569
0
                    case 912:
1570
0
                        mpCffLocal->mfExpFactor = nVal;
1571
0
                        break; // "ExpansionFactor"
1572
0
                    case 917:
1573
0
                        mpCffLocal->mnLangGroup = nInt;
1574
0
                        break; // "LanguageGroup"
1575
0
                    case 936:
1576
0
                        mnFontDictBase = nInt;
1577
0
                        break; // "nFDArray"
1578
0
                    case 937:
1579
0
                        mnFDSelectBase = nInt;
1580
0
                        break; // "nFDSelect"
1581
0
                    default:
1582
0
                        break; // TODO: handle more numeric dictops?
1583
0
                }
1584
0
            }
1585
0
            break;
1586
0
            case 'a':
1587
0
            { // array
1588
0
                switch (nOpId)
1589
0
                {
1590
0
                    case 5:
1591
0
                        break; // "FontBBox"
1592
0
                    case 907:
1593
0
                        maFontMatrix.clear();
1594
0
                        break; // "FontMatrix"
1595
0
                    default:
1596
0
                        break; // TODO: reset other arrays?
1597
0
                }
1598
0
                for (int i = 0; i < size(); ++i)
1599
0
                {
1600
0
                    ValType nVal = getVal(i);
1601
0
                    switch (nOpId)
1602
0
                    {
1603
0
                        case 5:
1604
0
                            break; // "FontBBox"
1605
0
                        case 907:
1606
0
                            maFontMatrix.push_back(nVal);
1607
0
                            break; // "FontMatrix"
1608
0
                        default:
1609
0
                            break; // TODO: handle more array dictops?
1610
0
                    }
1611
0
                }
1612
0
                clear();
1613
0
            }
1614
0
            break;
1615
0
            case 'd':
1616
0
            { // delta array
1617
0
                ValType nVal = 0;
1618
0
                for (int i = 0; i < size(); ++i)
1619
0
                {
1620
0
                    nVal += getVal(i);
1621
0
                    switch (nOpId)
1622
0
                    {
1623
0
                        case 6:
1624
0
                            mpCffLocal->maBlueValues.push_back(nVal);
1625
0
                            break; // "BlueValues"
1626
0
                        case 7:
1627
0
                            mpCffLocal->maOtherBlues.push_back(nVal);
1628
0
                            break; // "OtherBlues"
1629
0
                        case 8:
1630
0
                            mpCffLocal->maFamilyBlues.push_back(nVal);
1631
0
                            break; // "FamilyBlues"
1632
0
                        case 9:
1633
0
                            mpCffLocal->maFamilyOtherBlues.push_back(nVal);
1634
0
                            break; // "FamilyOtherBlues"
1635
0
                        case 912:
1636
0
                            mpCffLocal->maStemSnapH.push_back(nVal);
1637
0
                            break; // "StemSnapH"
1638
0
                        case 913:
1639
0
                            mpCffLocal->maStemSnapV.push_back(nVal);
1640
0
                            break; // "StemSnapV"
1641
0
                        default:
1642
0
                            break; // TODO: handle more delta-array dictops?
1643
0
                    }
1644
0
                }
1645
0
                clear();
1646
0
            }
1647
0
            break;
1648
0
            case 's': // stringid (SID)
1649
0
                nInt = popInt();
1650
0
                switch (nOpId)
1651
0
                {
1652
0
                    case 2:
1653
0
                        break; // "FullName"
1654
0
                    case 3:
1655
0
                        break; // "FamilyName"
1656
0
                    case 938:
1657
0
                        break; // "FontName"
1658
0
                    default:
1659
0
                        break; // TODO: handle more string dictops?
1660
0
                }
1661
0
                break;
1662
0
            case 'P': // private dict
1663
0
                mpCffLocal->mnPrivDictBase = popInt();
1664
0
                mpCffLocal->mnPrivDictSize = popInt();
1665
0
                break;
1666
0
            case 'r':
1667
0
            { // ROS operands
1668
0
                popInt(); // TODO: use sid1
1669
0
                popInt(); // TODO: use sid2
1670
0
                popVal();
1671
0
                mbCIDFont = true;
1672
0
            }
1673
0
            break;
1674
0
            case 't': // CharstringType
1675
0
                popInt();
1676
0
                break;
1677
0
        }
1678
0
    }
1679
0
    else if ((c >= 32) || (c == 28))
1680
0
    {
1681
        //      --mpReadPtr;
1682
0
        read2push();
1683
0
    }
1684
0
    else if (c == 29)
1685
0
    { // longint
1686
0
        ++mpReadPtr; // skip 29
1687
0
        sal_Int32 nS32 = mpReadPtr[0] << 24;
1688
0
        nS32 += mpReadPtr[1] << 16;
1689
0
        nS32 += mpReadPtr[2] << 8;
1690
0
        nS32 += mpReadPtr[3] << 0;
1691
0
        mpReadPtr += 4;
1692
0
        ValType nVal = static_cast<ValType>(nS32);
1693
0
        push(nVal);
1694
0
    }
1695
0
    else if (c == 30)
1696
0
    { // real number
1697
0
        ++mpReadPtr; // skip 30
1698
0
        const RealType fReal = readRealVal();
1699
        // push value onto stack
1700
0
        ValType nVal = fReal;
1701
0
        push(nVal);
1702
0
    }
1703
0
    else
1704
0
    {
1705
        // bytes 22-27, 31 and 255 are reserved in CFF DICT encoding
1706
        // (Adobe Technical Note #5176, section 4 "DICT Data")
1707
        // https://adobe-type-tools.github.io/font-tech-notes/pdfs/5176.CFF.pdf
1708
        // skip to avoid infinite loop
1709
0
        SAL_WARN("vcl.fonts.cff", "undefined CFF DICT byte: " << int(c));
1710
0
        ++mpReadPtr;
1711
0
    }
1712
0
}
1713
1714
void CffContext::read2push()
1715
0
{
1716
0
    ValType aVal = 0;
1717
1718
0
    const U8*& p = mpReadPtr;
1719
0
    const U8 c = *p;
1720
0
    if (c == 28)
1721
0
    {
1722
0
        sal_Int16 nS16 = (p[1] << 8) + p[2];
1723
0
        aVal = nS16;
1724
0
        p += 3;
1725
0
    }
1726
0
    else if (c <= 246)
1727
0
    { // -107..+107
1728
0
        aVal = static_cast<ValType>(p[0] - 139);
1729
0
        p += 1;
1730
0
    }
1731
0
    else if (c <= 250)
1732
0
    { // +108..+1131
1733
0
        aVal = static_cast<ValType>(((p[0] << 8) + p[1]) - 63124);
1734
0
        p += 2;
1735
0
    }
1736
0
    else if (c <= 254)
1737
0
    { // -108..-1131
1738
0
        aVal = static_cast<ValType>(64148 - ((p[0] << 8) + p[1]));
1739
0
        p += 2;
1740
0
    }
1741
0
    else /*if( c == 255)*/
1742
0
    { // Fixed16.16
1743
0
        int nS32 = (p[1] << 24) + (p[2] << 16) + (p[3] << 8) + p[4];
1744
0
        if ((sizeof(nS32) != 2) && (nS32 & (1U << 31)))
1745
0
            nS32 |= (~0U) << 31; // assuming 2s complement
1746
0
        aVal = static_cast<ValType>(nS32 * (1.0 / 0x10000));
1747
0
        p += 5;
1748
0
    }
1749
1750
0
    push(aVal);
1751
0
}
1752
1753
void CffContext::writeType1Val(ValType aVal)
1754
0
{
1755
0
    U8* pOut = mpWritePtr;
1756
1757
    // tdf#126242
1758
    // Type2 has 16.16 fixed numbers, but Type1 does not. To represent values
1759
    // with fractions we multiply it by a factor then use “div” operator to
1760
    // divide it back and keep the fractions.
1761
    // Code Adapted from:
1762
    // https://github.com/fontforge/fontforge/blob/f152f12e567ea5bd737a2907c318ae26cfaabd08/fontforge/splinesave.c#L378
1763
0
    int nDiv = 0;
1764
0
    aVal = rint(aVal * 1024) / 1024;
1765
0
    if (aVal != floor(aVal))
1766
0
    {
1767
0
        if (aVal == rint(aVal * 64) / 64)
1768
0
            nDiv = 64;
1769
0
        else
1770
0
            nDiv = 1024;
1771
0
        aVal *= nDiv;
1772
0
    }
1773
1774
0
    int nInt = static_cast<int>(rint(aVal));
1775
0
    if (nDiv && floor(nInt) / nDiv == floor(nInt / nDiv))
1776
0
    {
1777
0
        nInt = rint(nInt / nDiv);
1778
0
        nDiv = 0;
1779
0
    }
1780
1781
0
    if ((nInt >= -107) && (nInt <= +107))
1782
0
    {
1783
0
        *(pOut++) = static_cast<U8>(nInt + 139); // -107..+107
1784
0
    }
1785
0
    else if ((nInt >= -1131) && (nInt <= +1131))
1786
0
    {
1787
0
        if (nInt >= 0)
1788
0
            nInt += 63124; // +108..+1131
1789
0
        else
1790
0
            nInt = 64148 - nInt; // -108..-1131
1791
0
        *(pOut++) = static_cast<U8>(nInt >> 8);
1792
0
        *(pOut++) = static_cast<U8>(nInt);
1793
0
    }
1794
0
    else
1795
0
    {
1796
        // numtype==255 means int32 for Type1, but 16.16 for Type2 charstrings!!!
1797
0
        *(pOut++) = 255;
1798
0
        *(pOut++) = static_cast<U8>(nInt >> 24);
1799
0
        *(pOut++) = static_cast<U8>(nInt >> 16);
1800
0
        *(pOut++) = static_cast<U8>(nInt >> 8);
1801
0
        *(pOut++) = static_cast<U8>(nInt);
1802
0
    }
1803
1804
0
    mpWritePtr = pOut;
1805
1806
0
    if (nDiv)
1807
0
    {
1808
0
        writeType1Val(nDiv);
1809
0
        writeTypeEsc(TYPE1OP::DIV);
1810
0
    }
1811
0
}
1812
1813
0
inline void CffContext::writeTypeOp(int nTypeOp) { *(mpWritePtr++) = static_cast<U8>(nTypeOp); }
1814
1815
inline void CffContext::writeTypeEsc(int nTypeEsc)
1816
0
{
1817
0
    *(mpWritePtr++) = TYPE1OP::T1ESC;
1818
0
    *(mpWritePtr++) = static_cast<U8>(nTypeEsc);
1819
0
}
1820
1821
void CffContext::pop2MultiWrite(int nArgsPerTypo, int nTypeOp, int nTypeXor)
1822
0
{
1823
0
    for (int i = 0; i < mnStackIdx;)
1824
0
    {
1825
0
        for (int j = 0; j < nArgsPerTypo; ++j)
1826
0
        {
1827
0
            const ValType aVal = mnValStack[i + j];
1828
0
            writeType1Val(aVal);
1829
0
        }
1830
0
        i += nArgsPerTypo;
1831
0
        writeTypeOp(nTypeOp);
1832
0
        nTypeOp ^= nTypeXor; // for toggling vlineto/hlineto
1833
0
    }
1834
0
    clear();
1835
0
}
1836
1837
void CffContext::popAll2Write(int nTypeOp)
1838
0
{
1839
    // pop in reverse order, then write
1840
0
    for (int i = 0; i < mnStackIdx; ++i)
1841
0
    {
1842
0
        const ValType aVal = mnValStack[i];
1843
0
        writeType1Val(aVal);
1844
0
    }
1845
0
    clear();
1846
0
    writeTypeOp(nTypeOp);
1847
0
}
1848
1849
void CffContext::writeCurveTo(int nStackPos, int nIX1, int nIY1, int nIX2, int nIY2, int nIX3,
1850
                              int nIY3)
1851
0
{
1852
    // get the values from the stack
1853
0
    const ValType nDX1 = nIX1 ? mnValStack[nStackPos + nIX1] : 0;
1854
0
    const ValType nDY1 = nIY1 ? mnValStack[nStackPos + nIY1] : 0;
1855
0
    const ValType nDX2 = nIX2 ? mnValStack[nStackPos + nIX2] : 0;
1856
0
    const ValType nDY2 = nIY2 ? mnValStack[nStackPos + nIY2] : 0;
1857
0
    const ValType nDX3 = nIX3 ? mnValStack[nStackPos + nIX3] : 0;
1858
0
    const ValType nDY3 = nIY3 ? mnValStack[nStackPos + nIY3] : 0;
1859
1860
    // emit the curveto operator and operands
1861
    // TODO: determine the most efficient curveto operator
1862
    // TODO: depending on type1op or type2op target
1863
0
    writeType1Val(nDX1);
1864
0
    writeType1Val(nDY1);
1865
0
    writeType1Val(nDX2);
1866
0
    writeType1Val(nDY2);
1867
0
    writeType1Val(nDX3);
1868
0
    writeType1Val(nDY3);
1869
0
    writeTypeOp(TYPE1OP::RCURVETO);
1870
0
}
1871
1872
bool CffContext::convertOneTypeOp()
1873
0
{
1874
0
    const int nType2Op = *(mpReadPtr++);
1875
1876
0
    int i, nInt; // prevent WAE for declarations inside switch cases
1877
    // convert each T2op
1878
0
    switch (nType2Op)
1879
0
    {
1880
0
        case TYPE2OP::T2ESC:
1881
0
            if (!convertOneTypeEsc())
1882
0
                return false;
1883
0
            break;
1884
0
        case TYPE2OP::HSTEM:
1885
0
        case TYPE2OP::VSTEM:
1886
0
            if (!addHints(nType2Op == TYPE2OP::VSTEM))
1887
0
                return false;
1888
0
            for (i = 0; i < mnHintSize; i += 2)
1889
0
            {
1890
0
                writeType1Val(mnHintStack[i]);
1891
0
                writeType1Val(mnHintStack[i + 1] - mnHintStack[i]);
1892
0
                writeTypeOp(nType2Op);
1893
0
            }
1894
0
            break;
1895
0
        case TYPE2OP::HSTEMHM:
1896
0
        case TYPE2OP::VSTEMHM:
1897
0
            if (!addHints(nType2Op == TYPE2OP::VSTEMHM))
1898
0
                return false;
1899
0
            break;
1900
0
        case TYPE2OP::CNTRMASK:
1901
            // TODO: replace cntrmask with vstem3/hstem3
1902
0
            if (!addHints(true))
1903
0
                return false;
1904
0
            {
1905
0
                U8 nMaskBit = 0;
1906
0
                U8 nMaskByte = 0;
1907
0
                for (i = 0; i < mnHintSize; i += 2, nMaskBit >>= 1)
1908
0
                {
1909
0
                    if (!nMaskBit)
1910
0
                    {
1911
0
                        nMaskByte = *(mpReadPtr++);
1912
0
                        nMaskBit = 0x80;
1913
0
                    }
1914
0
                    if (!(nMaskByte & nMaskBit))
1915
0
                        continue;
1916
0
                    if (i >= 8 * int(sizeof(mnCntrMask)))
1917
0
                        mbIgnoreHints = true;
1918
0
                    if (mbIgnoreHints)
1919
0
                        continue;
1920
0
                    mnCntrMask |= (1U << i);
1921
0
                }
1922
0
            }
1923
0
            break;
1924
0
        case TYPE2OP::HINTMASK:
1925
0
            if (!addHints(true))
1926
0
                return false;
1927
0
            {
1928
0
                sal_Int32 nHintMask = 0;
1929
0
                int nCntrBits[2] = { 0, 0 };
1930
0
                U8 nMaskBit = 0;
1931
0
                U8 nMaskByte = 0;
1932
0
                int const MASK_BITS = 8 * sizeof(nHintMask);
1933
0
                for (i = 0; i < mnHintSize; i += 2, nMaskBit >>= 1)
1934
0
                {
1935
0
                    if (!nMaskBit)
1936
0
                    {
1937
0
                        nMaskByte = *(mpReadPtr++);
1938
0
                        nMaskBit = 0x80;
1939
0
                    }
1940
0
                    if (!(nMaskByte & nMaskBit))
1941
0
                        continue;
1942
0
                    if (i >= MASK_BITS)
1943
0
                        mbIgnoreHints = true;
1944
0
                    if (mbIgnoreHints)
1945
0
                        continue;
1946
0
                    nHintMask |= (1U << i);
1947
0
                    nCntrBits[i < mnHorzHintSize] += (mnCntrMask >> i) & 1;
1948
0
                }
1949
1950
0
                mbIgnoreHints |= (nCntrBits[0] && (nCntrBits[0] != 3));
1951
0
                mbIgnoreHints |= (nCntrBits[1] && (nCntrBits[1] != 3));
1952
0
                if (mbIgnoreHints)
1953
0
                    break;
1954
1955
0
                for (i = 0; i < mnHintSize; i += 2)
1956
0
                {
1957
0
                    if (i >= MASK_BITS || !(nHintMask & (1U << i)))
1958
0
                        continue;
1959
0
                    writeType1Val(mnHintStack[i]);
1960
0
                    writeType1Val(mnHintStack[i + 1] - mnHintStack[i]);
1961
0
                    const bool bHorz = (i < mnHorzHintSize);
1962
0
                    if (!nCntrBits[bHorz])
1963
0
                        writeTypeOp(bHorz ? TYPE1OP::HSTEM : TYPE1OP::VSTEM);
1964
0
                    else if (!--nCntrBits[bHorz])
1965
0
                        writeTypeEsc(bHorz ? TYPE1OP::HSTEM3 : TYPE1OP::VSTEM3);
1966
0
                }
1967
0
            }
1968
0
            break;
1969
0
        case TYPE2OP::CALLSUBR:
1970
0
        case TYPE2OP::CALLGSUBR:
1971
0
        {
1972
0
            nInt = popInt();
1973
0
            const bool bGlobal = (nType2Op == TYPE2OP::CALLGSUBR);
1974
0
            if (!callType2Subr(bGlobal, nInt))
1975
0
                return false;
1976
0
        }
1977
0
        break;
1978
0
        case TYPE2OP::RETURN:
1979
            // TODO: check that we are in a subroutine
1980
0
            return true;
1981
0
        case TYPE2OP::VMOVETO:
1982
0
        case TYPE2OP::HMOVETO:
1983
0
            if (mbNeedClose)
1984
0
                writeTypeOp(TYPE1OP::CLOSEPATH);
1985
0
            else
1986
0
                updateWidth(size() > 1);
1987
0
            mbNeedClose = true;
1988
0
            pop2MultiWrite(1, nType2Op);
1989
0
            break;
1990
0
        case TYPE2OP::VLINETO:
1991
0
        case TYPE2OP::HLINETO:
1992
0
            pop2MultiWrite(1, nType2Op, TYPE1OP::VLINETO ^ TYPE1OP::HLINETO);
1993
0
            break;
1994
0
        case TYPE2OP::RMOVETO:
1995
            // TODO: convert rmoveto to vlineto/hlineto if possible
1996
0
            if (mbNeedClose)
1997
0
                writeTypeOp(TYPE1OP::CLOSEPATH);
1998
0
            else
1999
0
                updateWidth(size() > 2);
2000
0
            mbNeedClose = true;
2001
0
            pop2MultiWrite(2, nType2Op);
2002
0
            break;
2003
0
        case TYPE2OP::RLINETO:
2004
            // TODO: convert rlineto to vlineto/hlineto if possible
2005
0
            pop2MultiWrite(2, nType2Op);
2006
0
            break;
2007
0
        case TYPE2OP::RCURVETO:
2008
            // TODO: convert rcurveto to vh/hv/hh/vv-curveto if possible
2009
0
            pop2MultiWrite(6, nType2Op);
2010
0
            break;
2011
0
        case TYPE2OP::RCURVELINE:
2012
0
            i = 0;
2013
0
            while ((i += 6) <= mnStackIdx)
2014
0
                writeCurveTo(i, -6, -5, -4, -3, -2, -1);
2015
0
            i -= 6;
2016
0
            while ((i += 2) <= mnStackIdx)
2017
0
            {
2018
0
                writeType1Val(mnValStack[i - 2]);
2019
0
                writeType1Val(mnValStack[i - 1]);
2020
0
                writeTypeOp(TYPE2OP::RLINETO);
2021
0
            }
2022
0
            clear();
2023
0
            break;
2024
0
        case TYPE2OP::RLINECURVE:
2025
0
            i = 0;
2026
0
            while ((i += 2) <= mnStackIdx - 6)
2027
0
            {
2028
0
                writeType1Val(mnValStack[i - 2]);
2029
0
                writeType1Val(mnValStack[i - 1]);
2030
0
                writeTypeOp(TYPE2OP::RLINETO);
2031
0
            }
2032
0
            i -= 2;
2033
0
            while ((i += 6) <= mnStackIdx)
2034
0
                writeCurveTo(i, -6, -5, -4, -3, -2, -1);
2035
0
            clear();
2036
0
            break;
2037
0
        case TYPE2OP::VHCURVETO:
2038
0
        case TYPE2OP::HVCURVETO:
2039
0
        {
2040
0
            bool bVert = (nType2Op == TYPE2OP::VHCURVETO);
2041
0
            i = 0;
2042
0
            nInt = 0;
2043
0
            if (mnStackIdx & 1)
2044
0
                nInt = static_cast<int>(mnValStack[--mnStackIdx]);
2045
0
            while ((i += 4) <= mnStackIdx)
2046
0
            {
2047
                // TODO: use writeCurveTo()
2048
0
                if (bVert)
2049
0
                    writeType1Val(0);
2050
0
                writeType1Val(mnValStack[i - 4]);
2051
0
                if (!bVert)
2052
0
                    writeType1Val(0);
2053
0
                writeType1Val(mnValStack[i - 3]);
2054
0
                writeType1Val(mnValStack[i - 2]);
2055
0
                if (!bVert)
2056
0
                    writeType1Val(static_cast<ValType>((i == mnStackIdx) ? nInt : 0));
2057
0
                writeType1Val(mnValStack[i - 1]);
2058
0
                if (bVert)
2059
0
                    writeType1Val(static_cast<ValType>((i == mnStackIdx) ? nInt : 0));
2060
0
                bVert = !bVert;
2061
0
                writeTypeOp(TYPE2OP::RCURVETO);
2062
0
            }
2063
0
        }
2064
0
            clear();
2065
0
            break;
2066
0
        case TYPE2OP::HHCURVETO:
2067
0
            i = (mnStackIdx & 1);
2068
0
            while ((i += 4) <= mnStackIdx)
2069
0
            {
2070
0
                if (i != 5)
2071
0
                    writeCurveTo(i, -4, 0, -3, -2, -1, 0);
2072
0
                else
2073
0
                    writeCurveTo(i, -4, -5, -3, -2, -1, 0);
2074
0
            }
2075
0
            clear();
2076
0
            break;
2077
0
        case TYPE2OP::VVCURVETO:
2078
0
            i = (mnStackIdx & 1);
2079
0
            while ((i += 4) <= mnStackIdx)
2080
0
            {
2081
0
                if (i != 5)
2082
0
                    writeCurveTo(i, 0, -4, -3, -2, 0, -1);
2083
0
                else
2084
0
                    writeCurveTo(i, -5, -4, -3, -2, 0, -1);
2085
0
            }
2086
0
            clear();
2087
0
            break;
2088
0
        case TYPE2OP::ENDCHAR:
2089
0
            if (size() >= 4 && mbDoSeac)
2090
0
            {
2091
                // Deprecated seac-like use of endchar (Adobe Technical Note #5177,
2092
                // Appendix C).
2093
0
                auto achar = popVal();
2094
0
                auto bchar = popVal();
2095
0
                auto ady = popVal();
2096
0
                auto adx = popVal();
2097
0
                int nBase = {}, nAccent = {};
2098
0
                if (getBaseAccent(bchar, achar, &nBase, &nAccent))
2099
0
                {
2100
0
                    maExtraGlyphIds.push_back(nBase);
2101
0
                    maExtraGlyphIds.push_back(nAccent);
2102
0
                    writeType1Val(0); // TODO accent sb
2103
0
                    writeType1Val(adx);
2104
0
                    writeType1Val(ady);
2105
0
                    writeType1Val(bchar);
2106
0
                    writeType1Val(achar);
2107
0
                    writeTypeEsc(TYPE1OP::SEAC);
2108
0
                }
2109
0
            }
2110
0
            if (mbNeedClose)
2111
0
                writeTypeOp(TYPE1OP::CLOSEPATH);
2112
0
            else
2113
0
                updateWidth(size() >= 1);
2114
            // mbNeedClose = true;
2115
0
            writeTypeOp(TYPE1OP::ENDCHAR);
2116
0
            break;
2117
0
        default:
2118
0
            if (((nType2Op >= 32) && (nType2Op <= 255)) || (nType2Op == 28))
2119
0
            {
2120
0
                --mpReadPtr;
2121
0
                read2push();
2122
0
            }
2123
0
            else
2124
0
            {
2125
0
                popAll2Write(nType2Op);
2126
0
                SAL_WARN("vcl.fonts.cff", "unhandled type2op " << nType2Op);
2127
0
                return false;
2128
0
            }
2129
0
            break;
2130
0
    }
2131
0
    return true;
2132
0
}
2133
2134
bool CffContext::convertOneTypeEsc()
2135
0
{
2136
0
    const int nType2Esc = *(mpReadPtr++);
2137
0
    ValType* pTop = &mnValStack[mnStackIdx - 1];
2138
    // convert each T2op
2139
0
    switch (nType2Esc)
2140
0
    {
2141
0
        case TYPE2OP::AND:
2142
0
            if (mnStackIdx < 2)
2143
0
                return false;
2144
0
            pTop[0] = static_cast<ValType>(static_cast<int>(pTop[0]) & static_cast<int>(pTop[-1]));
2145
0
            --mnStackIdx;
2146
0
            break;
2147
0
        case TYPE2OP::OR:
2148
0
            if (mnStackIdx < 2)
2149
0
                return false;
2150
0
            pTop[0] = static_cast<ValType>(static_cast<int>(pTop[0]) | static_cast<int>(pTop[-1]));
2151
0
            --mnStackIdx;
2152
0
            break;
2153
0
        case TYPE2OP::NOT:
2154
0
            if (mnStackIdx < 1)
2155
0
                return false;
2156
0
            pTop[0] = ValType(pTop[0] == 0);
2157
0
            break;
2158
0
        case TYPE2OP::ABS:
2159
0
            if (mnStackIdx < 1)
2160
0
                return false;
2161
0
            if (pTop[0] >= 0)
2162
0
                break;
2163
0
            [[fallthrough]];
2164
0
        case TYPE2OP::NEG:
2165
0
            if (mnStackIdx < 1)
2166
0
                return false;
2167
0
            pTop[0] = -pTop[0];
2168
0
            break;
2169
0
        case TYPE2OP::ADD:
2170
0
            if (mnStackIdx < 2)
2171
0
                return false;
2172
0
            pTop[0] += pTop[-1];
2173
0
            --mnStackIdx;
2174
0
            break;
2175
0
        case TYPE2OP::SUB:
2176
0
            if (mnStackIdx < 2)
2177
0
                return false;
2178
0
            pTop[0] -= pTop[-1];
2179
0
            --mnStackIdx;
2180
0
            break;
2181
0
        case TYPE2OP::MUL:
2182
0
            if (mnStackIdx < 2)
2183
0
                return false;
2184
0
            if (pTop[-1])
2185
0
                pTop[0] *= pTop[-1];
2186
0
            --mnStackIdx;
2187
0
            break;
2188
0
        case TYPE2OP::DIV:
2189
0
            if (mnStackIdx < 2)
2190
0
                return false;
2191
0
            if (pTop[-1])
2192
0
                pTop[0] /= pTop[-1];
2193
0
            --mnStackIdx;
2194
0
            break;
2195
0
        case TYPE2OP::EQ:
2196
0
            if (mnStackIdx < 2)
2197
0
                return false;
2198
0
            pTop[0] = ValType(pTop[0] == pTop[-1]);
2199
0
            --mnStackIdx;
2200
0
            break;
2201
0
        case TYPE2OP::DROP:
2202
0
            if (mnStackIdx < 1)
2203
0
                return false;
2204
0
            --mnStackIdx;
2205
0
            break;
2206
0
        case TYPE2OP::PUT:
2207
0
        {
2208
0
            if (mnStackIdx < 2)
2209
0
                return false;
2210
0
            const int nIdx = static_cast<int>(pTop[0]);
2211
0
            if (nIdx < 0 || nIdx >= NMAXTRANS)
2212
0
                return false;
2213
0
            mnTransVals[nIdx] = pTop[-1];
2214
0
            mnStackIdx -= 2;
2215
0
            break;
2216
0
        }
2217
0
        case TYPE2OP::GET:
2218
0
        {
2219
0
            if (mnStackIdx < 1)
2220
0
                return false;
2221
0
            const int nIdx = static_cast<int>(pTop[0]);
2222
0
            if (nIdx < 0 || nIdx >= NMAXTRANS)
2223
0
                return false;
2224
0
            pTop[0] = mnTransVals[nIdx];
2225
0
            break;
2226
0
        }
2227
0
        case TYPE2OP::IFELSE:
2228
0
        {
2229
0
            if (mnStackIdx < 4)
2230
0
                return false;
2231
0
            if (pTop[-1] > pTop[0])
2232
0
                pTop[-3] = pTop[-2];
2233
0
            mnStackIdx -= 3;
2234
0
            break;
2235
0
        }
2236
0
        case TYPE2OP::RANDOM:
2237
0
            pTop[+1] = 1234; // TODO
2238
0
            ++mnStackIdx;
2239
0
            break;
2240
0
        case TYPE2OP::SQRT:
2241
            // TODO: implement
2242
0
            break;
2243
0
        case TYPE2OP::DUP:
2244
0
            if (mnStackIdx < 1)
2245
0
                return false;
2246
0
            pTop[+1] = pTop[0];
2247
0
            ++mnStackIdx;
2248
0
            break;
2249
0
        case TYPE2OP::EXCH:
2250
0
        {
2251
0
            if (mnStackIdx < 2)
2252
0
                return false;
2253
0
            const ValType nVal = pTop[0];
2254
0
            pTop[0] = pTop[-1];
2255
0
            pTop[-1] = nVal;
2256
0
            break;
2257
0
        }
2258
0
        case TYPE2OP::INDEX:
2259
0
        {
2260
0
            if (mnStackIdx < 1)
2261
0
                return false;
2262
0
            const int nVal = static_cast<int>(pTop[0]);
2263
0
            if (nVal < 0 || nVal >= mnStackIdx - 1)
2264
0
                return false;
2265
0
            pTop[0] = pTop[-1 - nVal];
2266
0
            break;
2267
0
        }
2268
0
        case TYPE2OP::ROLL:
2269
0
        {
2270
0
            if (mnStackIdx < 1)
2271
0
                return false;
2272
0
            const int nNum = static_cast<int>(pTop[0]);
2273
0
            if (nNum < 0 || nNum >= mnStackIdx - 2)
2274
0
                return false;
2275
            // (void)nNum; // TODO: implement
2276
            // TODO: implement: const int nOfs = static_cast<int>(pTop[-1]);
2277
0
            mnStackIdx -= 2;
2278
0
            break;
2279
0
        }
2280
0
        case TYPE2OP::HFLEX1:
2281
0
        {
2282
0
            if (mnStackIdx != 9)
2283
0
                return false;
2284
2285
0
            writeCurveTo(mnStackIdx, -9, -8, -7, -6, -5, 0);
2286
0
            writeCurveTo(mnStackIdx, -4, 0, -3, -2, -1, 0);
2287
            // TODO: emulate hflex1 using othersubr call
2288
2289
0
            mnStackIdx -= 9;
2290
0
        }
2291
0
        break;
2292
0
        case TYPE2OP::HFLEX:
2293
0
        {
2294
0
            if (mnStackIdx != 7)
2295
0
                return false;
2296
0
            ValType* pX = &mnValStack[mnStackIdx];
2297
2298
0
            pX[+1] = -pX[-5]; // temp: +dy5==-dy2
2299
0
            writeCurveTo(mnStackIdx, -7, 0, -6, -5, -4, 0);
2300
0
            writeCurveTo(mnStackIdx, -3, 0, -2, +1, -1, 0);
2301
            // TODO: emulate hflex using othersubr call
2302
2303
0
            mnStackIdx -= 7;
2304
0
        }
2305
0
        break;
2306
0
        case TYPE2OP::FLEX:
2307
0
        {
2308
0
            if (mnStackIdx != 13)
2309
0
                return false;
2310
0
            writeCurveTo(mnStackIdx, -13, -12, -11, -10, -9, -8);
2311
0
            writeCurveTo(mnStackIdx, -7, -6, -5, -4, -3, -2);
2312
            // ignoring ValType nFlexDepth = mnValStack[ mnStackIdx-1 ];
2313
0
            mnStackIdx -= 13;
2314
0
        }
2315
0
        break;
2316
0
        case TYPE2OP::FLEX1:
2317
0
        {
2318
0
            if (mnStackIdx != 11)
2319
0
                return false;
2320
            // write the first part of the flex1-hinted curve
2321
0
            writeCurveTo(mnStackIdx, -11, -10, -9, -8, -7, -6);
2322
2323
            // determine if nD6 is horizontal or vertical
2324
0
            const int i = mnStackIdx;
2325
0
            ValType nDeltaX = mnValStack[i - 11] + mnValStack[i - 9] + mnValStack[i - 7]
2326
0
                              + mnValStack[i - 5] + mnValStack[i - 3];
2327
0
            if (nDeltaX < 0)
2328
0
                nDeltaX = -nDeltaX;
2329
0
            ValType nDeltaY = mnValStack[i - 10] + mnValStack[i - 8] + mnValStack[i - 6]
2330
0
                              + mnValStack[i - 4] + mnValStack[i - 2];
2331
0
            if (nDeltaY < 0)
2332
0
                nDeltaY = -nDeltaY;
2333
0
            const bool bVertD6 = (nDeltaY > nDeltaX);
2334
2335
            // write the second part of the flex1-hinted curve
2336
0
            if (!bVertD6)
2337
0
                writeCurveTo(mnStackIdx, -5, -4, -3, -2, -1, 0);
2338
0
            else
2339
0
                writeCurveTo(mnStackIdx, -5, -4, -3, -2, 0, -1);
2340
0
            mnStackIdx -= 11;
2341
0
        }
2342
0
        break;
2343
0
        default:
2344
0
            SAL_WARN("vcl.fonts.cff", "unhandled type2esc " << nType2Esc);
2345
0
            return false;
2346
0
    }
2347
0
    return true;
2348
0
}
2349
2350
bool CffContext::callType2Subr(bool bGlobal, int nSubrNumber)
2351
0
{
2352
0
    const U8* const pOldReadPtr = mpReadPtr;
2353
0
    const U8* const pOldReadEnd = mpReadEnd;
2354
2355
0
    if (bGlobal)
2356
0
    {
2357
0
        nSubrNumber += mnGlobalSubrBias;
2358
0
        if (seekIndexData(mnGlobalSubrBase, nSubrNumber) < 0)
2359
0
            return false;
2360
0
    }
2361
0
    else
2362
0
    {
2363
0
        nSubrNumber += mpCffLocal->mnLocalSubrBias;
2364
0
        if (seekIndexData(mpCffLocal->mnLocalSubrBase, nSubrNumber) < 0)
2365
0
            return false;
2366
0
    }
2367
2368
0
    while (mpReadPtr < mpReadEnd)
2369
0
    {
2370
0
        if (!convertOneTypeOp())
2371
0
            return false;
2372
0
    }
2373
2374
0
    mpReadPtr = pOldReadPtr;
2375
0
    mpReadEnd = pOldReadEnd;
2376
0
    return true;
2377
0
}
2378
2379
int CffContext::convert2Type1Ops(CffLocal* pCffLocal, const U8* const pT2Ops, int nT2Len,
2380
                                 U8* const pT1Ops)
2381
0
{
2382
0
    mpCffLocal = pCffLocal;
2383
2384
    // prepare the charstring conversion
2385
0
    mpWritePtr = pT1Ops;
2386
0
    U8 aType1Ops[MAX_T1OPS_SIZE];
2387
0
    if (!pT1Ops)
2388
0
        mpWritePtr = aType1Ops;
2389
0
    *const_cast<U8**>(&pT1Ops) = mpWritePtr;
2390
2391
    // prepend random seed for T1crypt
2392
0
    *(mpWritePtr++) = 0x48;
2393
0
    *(mpWritePtr++) = 0x44;
2394
0
    *(mpWritePtr++) = 0x55;
2395
0
    *(mpWritePtr++) = ' ';
2396
2397
    // convert the Type2 charstring to Type1
2398
0
    mpReadPtr = pT2Ops;
2399
0
    mpReadEnd = pT2Ops + nT2Len;
2400
    // prepend "hsbw" or "sbw"
2401
    // TODO: only emit hsbw when charwidth is known
2402
0
    writeType1Val(0); // TODO: aContext.getLeftSideBearing();
2403
0
    U8* pCharWidthPtr = mpWritePtr; // need to overwrite that later
2404
    // pad out 5 bytes for the char width with default val 1000 (to be
2405
    // filled with the actual value below)
2406
0
    *(mpWritePtr++) = 255;
2407
0
    *(mpWritePtr++) = static_cast<U8>(0);
2408
0
    *(mpWritePtr++) = static_cast<U8>(0);
2409
0
    *(mpWritePtr++) = static_cast<U8>(250);
2410
0
    *(mpWritePtr++) = static_cast<U8>(124);
2411
0
    writeTypeOp(TYPE1OP::HSBW);
2412
0
    mbNeedClose = false;
2413
0
    mbIgnoreHints = false;
2414
0
    mnHintSize = mnHorzHintSize = mnStackIdx = 0;
2415
0
    maCharWidth = -1; //#######
2416
0
    mnCntrMask = 0;
2417
0
    while (mpReadPtr < mpReadEnd)
2418
0
    {
2419
0
        if (!convertOneTypeOp())
2420
0
            return -1;
2421
0
    }
2422
0
    if (maCharWidth != -1)
2423
0
    {
2424
        // overwrite earlier charWidth value, which we only now have
2425
        // parsed out of mpReadPtr buffer (by way of
2426
        // convertOneTypeOp()s above)
2427
0
        const int nInt = static_cast<int>(maCharWidth);
2428
0
        *(pCharWidthPtr++) = 255;
2429
0
        *(pCharWidthPtr++) = static_cast<U8>(nInt >> 24);
2430
0
        *(pCharWidthPtr++) = static_cast<U8>(nInt >> 16);
2431
0
        *(pCharWidthPtr++) = static_cast<U8>(nInt >> 8);
2432
0
        *(pCharWidthPtr++) = static_cast<U8>(nInt);
2433
0
    }
2434
2435
0
    const int nType1Len = mpWritePtr - pT1Ops;
2436
2437
    // encrypt the Type1 charstring
2438
0
    unsigned nRDCryptR = 4330; // TODO: mnRDCryptSeed;
2439
0
    for (U8* p = pT1Ops; p < mpWritePtr; ++p)
2440
0
    {
2441
0
        *p ^= (nRDCryptR >> 8);
2442
0
        nRDCryptR = (*p + nRDCryptR) * 52845 + 22719;
2443
0
    }
2444
2445
0
    return nType1Len;
2446
0
}
2447
2448
RealType CffContext::readRealVal()
2449
0
{
2450
    // TODO: more thorough number validity test
2451
0
    bool bComma = false;
2452
0
    int nExpVal = 0;
2453
0
    int nExpSign = 0;
2454
0
    S64 nNumber = 0;
2455
0
    RealType fReal = +1.0;
2456
0
    for (;;)
2457
0
    {
2458
0
        const U8 c = *(mpReadPtr++); // read nibbles
2459
        // parse high nibble
2460
0
        const U8 nH = c >> 4U;
2461
0
        if (nH <= 9)
2462
0
        {
2463
0
            nNumber = nNumber * 10 + nH;
2464
0
            --nExpVal;
2465
0
        }
2466
0
        else if (nH == 10)
2467
0
        { // comma
2468
0
            nExpVal = 0;
2469
0
            bComma = true;
2470
0
        }
2471
0
        else if (nH == 11)
2472
0
        { // +exp
2473
0
            fReal *= nNumber;
2474
0
            nExpSign = +1;
2475
0
            nNumber = 0;
2476
0
        }
2477
0
        else if (nH == 12)
2478
0
        { // -exp
2479
0
            fReal *= nNumber;
2480
0
            nExpSign = -1;
2481
0
            nNumber = 0;
2482
0
        }
2483
0
        else if (nH == 13)
2484
0
        { // reserved
2485
            // TODO: ignore or error?
2486
0
        }
2487
0
        else if (nH == 14) // minus
2488
0
            fReal = -fReal;
2489
0
        else if (nH == 15) // end
2490
0
            break;
2491
        // parse low nibble
2492
0
        const U8 nL = c & 0x0F;
2493
0
        if (nL <= 9)
2494
0
        {
2495
0
            nNumber = nNumber * 10 + nL;
2496
0
            --nExpVal;
2497
0
        }
2498
0
        else if (nL == 10)
2499
0
        { // comma
2500
0
            nExpVal = 0;
2501
0
            bComma = true;
2502
0
        }
2503
0
        else if (nL == 11)
2504
0
        { // +exp
2505
0
            fReal *= nNumber;
2506
0
            nNumber = 0;
2507
0
            nExpSign = +1;
2508
0
        }
2509
0
        else if (nL == 12)
2510
0
        { // -exp
2511
0
            fReal *= nNumber;
2512
0
            nNumber = 0;
2513
0
            nExpSign = -1;
2514
0
        }
2515
0
        else if (nL == 13)
2516
0
        { // reserved
2517
            // TODO: ignore or error?
2518
0
        }
2519
0
        else if (nL == 14) // minus
2520
0
            fReal = -fReal;
2521
0
        else if (nL == 15) // end
2522
0
            break;
2523
0
    }
2524
2525
    // merge exponents
2526
0
    if (!bComma)
2527
0
        nExpVal = 0;
2528
0
    if (!nExpSign)
2529
0
    {
2530
0
        fReal *= nNumber;
2531
0
    }
2532
0
    else if (nExpSign > 0)
2533
0
    {
2534
0
        nExpVal += static_cast<int>(nNumber);
2535
0
    }
2536
0
    else if (nExpSign < 0)
2537
0
    {
2538
0
        nExpVal -= static_cast<int>(nNumber);
2539
0
    }
2540
2541
    // apply exponents
2542
0
    if (!nExpVal)
2543
0
    { /*nothing to apply*/
2544
0
    }
2545
0
    else if (nExpVal > 0)
2546
0
    {
2547
0
        while (--nExpVal >= 0)
2548
0
            fReal *= 10.0;
2549
0
    }
2550
0
    else if (nExpVal < 0)
2551
0
    {
2552
0
        while (++nExpVal <= 0)
2553
0
            fReal /= 10.0;
2554
0
    }
2555
0
    return fReal;
2556
0
}
2557
2558
// prepare to access an element inside a CFF/CID index table
2559
int CffContext::seekIndexData(int nIndexBase, int nDataIndex)
2560
0
{
2561
0
    if (nIndexBase <= 0 || mpBasePtr + nIndexBase + 3 > mpBaseEnd)
2562
0
        return -1;
2563
0
    if (nDataIndex < 0)
2564
0
        return -1;
2565
0
    mpReadPtr = mpBasePtr + nIndexBase;
2566
0
    const int nDataCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
2567
0
    if (nDataIndex >= nDataCount)
2568
0
        return -1;
2569
0
    const int nDataOfsSz = mpReadPtr[2];
2570
0
    mpReadPtr += 3 + (nDataOfsSz * nDataIndex);
2571
0
    int nOfs1 = 0;
2572
0
    switch (nDataOfsSz)
2573
0
    {
2574
0
        default:
2575
0
            SAL_WARN("vcl.fonts.cff", "\tINVALID nDataOfsSz=" << nDataOfsSz);
2576
0
            return -1;
2577
0
        case 1:
2578
0
            nOfs1 = mpReadPtr[0];
2579
0
            break;
2580
0
        case 2:
2581
0
            nOfs1 = (mpReadPtr[0] << 8) + mpReadPtr[1];
2582
0
            break;
2583
0
        case 3:
2584
0
            nOfs1 = (mpReadPtr[0] << 16) + (mpReadPtr[1] << 8) + mpReadPtr[2];
2585
0
            break;
2586
0
        case 4:
2587
0
            nOfs1
2588
0
                = (mpReadPtr[0] << 24) + (mpReadPtr[1] << 16) + (mpReadPtr[2] << 8) + mpReadPtr[3];
2589
0
            break;
2590
0
    }
2591
0
    mpReadPtr += nDataOfsSz;
2592
2593
0
    int nOfs2 = 0;
2594
0
    switch (nDataOfsSz)
2595
0
    {
2596
0
        case 1:
2597
0
            nOfs2 = mpReadPtr[0];
2598
0
            break;
2599
0
        case 2:
2600
0
            nOfs2 = (mpReadPtr[0] << 8) + mpReadPtr[1];
2601
0
            break;
2602
0
        case 3:
2603
0
            nOfs2 = (mpReadPtr[0] << 16) + (mpReadPtr[1] << 8) + mpReadPtr[2];
2604
0
            break;
2605
0
        case 4:
2606
0
            nOfs2
2607
0
                = (mpReadPtr[0] << 24) + (mpReadPtr[1] << 16) + (mpReadPtr[2] << 8) + mpReadPtr[3];
2608
0
            break;
2609
0
    }
2610
2611
0
    mpReadPtr = mpBasePtr + (nIndexBase + 2) + nDataOfsSz * (nDataCount + 1) + nOfs1;
2612
0
    mpReadEnd = mpReadPtr + (nOfs2 - nOfs1);
2613
0
    if (nOfs1 < 0 || nOfs2 < nOfs1 || mpReadPtr > mpBaseEnd || mpReadEnd > mpBaseEnd)
2614
0
        return -1;
2615
0
    return (nOfs2 - nOfs1);
2616
0
}
2617
2618
// skip over a CFF/CID index table
2619
bool CffContext::seekIndexEnd(int nIndexBase)
2620
54
{
2621
54
    if (nIndexBase <= 0 || mpBasePtr + nIndexBase + 3 > mpBaseEnd)
2622
41
        return false;
2623
13
    mpReadPtr = mpBasePtr + nIndexBase;
2624
13
    const int nDataCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
2625
13
    const int nDataOfsSz = mpReadPtr[2];
2626
13
    mpReadPtr += 3 + nDataOfsSz * nDataCount;
2627
13
    if (mpReadPtr > mpBaseEnd)
2628
7
        return false;
2629
6
    int nEndOfs = 0;
2630
6
    switch (nDataOfsSz)
2631
6
    {
2632
6
        default:
2633
6
            SAL_WARN("vcl.fonts.cff", "\tINVALID nDataOfsSz=" << nDataOfsSz);
2634
6
            return false;
2635
0
        case 1:
2636
0
            nEndOfs = mpReadPtr[0];
2637
0
            break;
2638
0
        case 2:
2639
0
            nEndOfs = (mpReadPtr[0] << 8) + mpReadPtr[1];
2640
0
            break;
2641
0
        case 3:
2642
0
            nEndOfs = (mpReadPtr[0] << 16) + (mpReadPtr[1] << 8) + mpReadPtr[2];
2643
0
            break;
2644
0
        case 4:
2645
0
            nEndOfs
2646
0
                = (mpReadPtr[0] << 24) + (mpReadPtr[1] << 16) + (mpReadPtr[2] << 8) + mpReadPtr[3];
2647
0
            break;
2648
6
    }
2649
0
    mpReadPtr += nDataOfsSz;
2650
0
    mpReadPtr += nEndOfs - 1;
2651
0
    mpReadEnd = mpBaseEnd;
2652
0
    if (nEndOfs < 0)
2653
0
        return false;
2654
0
    if (mpReadEnd > mpBaseEnd)
2655
0
        return false;
2656
0
    return true;
2657
0
}
2658
2659
// initialize FONTDICT specific values
2660
CffLocal::CffLocal()
2661
2.45M
    : mnPrivDictBase(0)
2662
2.45M
    , mnPrivDictSize(0)
2663
2.45M
    , mnLocalSubrOffs(0)
2664
2.45M
    , mnLocalSubrBase(0)
2665
2.45M
    , mnLocalSubrBias(0)
2666
2.45M
    , maNominalWidth(0)
2667
2.45M
    , maDefaultWidth(0)
2668
2.45M
    , maStemStdHW(0)
2669
2.45M
    , maStemStdVW(0)
2670
2.45M
    , mfBlueScale(0.0)
2671
2.45M
    , mfBlueShift(0.0)
2672
2.45M
    , mfBlueFuzz(0.0)
2673
2.45M
    , mfExpFactor(0.0)
2674
2.45M
    , mnLangGroup(0)
2675
2.45M
    , mbForceBold(false)
2676
2.45M
{
2677
2.45M
}
2678
2679
CffGlobal::CffGlobal()
2680
9.57k
    : mnNameIdxBase(0)
2681
9.57k
    , mnStringIdxBase(0)
2682
9.57k
    , mbCIDFont(false)
2683
9.57k
    , mnCharStrBase(0)
2684
9.57k
    , mnCharStrCount(0)
2685
9.57k
    , mnCharsetBase(0)
2686
9.57k
    , mnGlobalSubrBase(0)
2687
9.57k
    , mnGlobalSubrCount(0)
2688
9.57k
    , mnGlobalSubrBias(0)
2689
9.57k
    , mnFDSelectBase(0)
2690
9.57k
    , mnFontDictBase(0)
2691
9.57k
    , mnFDAryCount(1)
2692
9.57k
{
2693
9.57k
}
2694
2695
bool CffContext::initialCffRead()
2696
9.57k
{
2697
    // get the CFFHeader
2698
9.57k
    mpReadPtr = mpBasePtr;
2699
9.57k
    const U8 nVerMajor = *(mpReadPtr++);
2700
9.57k
    const U8 nVerMinor = *(mpReadPtr++);
2701
9.57k
    const U8 nHeaderSize = *(mpReadPtr++);
2702
9.57k
    const U8 nOffsetSize = *(mpReadPtr++);
2703
9.57k
    if (nVerMajor != 1 || nVerMinor != 0)
2704
9.44k
    {
2705
9.44k
        SAL_WARN("vcl.fonts.cff",
2706
9.44k
                 "Unsupported CFF version: " << int(nVerMajor) << "." << int(nVerMinor));
2707
9.44k
        return false;
2708
9.44k
    }
2709
135
    if (!nOffsetSize)
2710
81
        return false;
2711
2712
    // prepare access to the NameIndex
2713
54
    mnNameIdxBase = nHeaderSize;
2714
54
    mpReadPtr = mpBasePtr + nHeaderSize;
2715
54
    if (!seekIndexEnd(mnNameIdxBase))
2716
54
        return false;
2717
2718
    // get the TopDict index
2719
0
    const sal_Int32 nTopDictBase = getReadOfs();
2720
0
    const int nTopDictCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
2721
0
    if (nTopDictCount)
2722
0
    {
2723
0
        for (int i = 0; i < nTopDictCount; ++i)
2724
0
        {
2725
0
            if (seekIndexData(nTopDictBase, i) < 0)
2726
0
                return false;
2727
0
            while (mpReadPtr < mpReadEnd)
2728
0
                readDictOp();
2729
0
            if (mpReadPtr != mpReadEnd)
2730
0
                return false;
2731
0
        }
2732
0
    }
2733
2734
    // prepare access to the String index
2735
0
    mnStringIdxBase = getReadOfs();
2736
0
    if (!seekIndexEnd(mnStringIdxBase))
2737
0
        return false;
2738
2739
    // prepare access to the GlobalSubr index
2740
0
    mnGlobalSubrBase = getReadOfs();
2741
0
    mnGlobalSubrCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
2742
0
    mnGlobalSubrBias
2743
0
        = (mnGlobalSubrCount < 1240) ? 107 : (mnGlobalSubrCount < 33900) ? 1131 : 32768;
2744
    // skip past the last GlobalSubr entry
2745
    //  seekIndexEnd( mnGlobalSubrBase);
2746
2747
    // get/skip the Encodings (we got mnEncodingBase from TOPDICT)
2748
    //  seekEncodingsEnd( mnEncodingBase);
2749
    // get/skip the Charsets (we got mnCharsetBase from TOPDICT)
2750
    //  seekCharsetsEnd( mnCharStrBase);
2751
    // get/skip FDSelect (CID only) data
2752
2753
    // prepare access to the CharStrings index (we got the base from TOPDICT)
2754
0
    mpReadPtr = mpBasePtr + mnCharStrBase;
2755
0
    mnCharStrCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
2756
    //  seekIndexEnd( mnCharStrBase);
2757
2758
    // read the FDArray index (CID only)
2759
0
    if (mbCIDFont)
2760
0
    {
2761
0
        mpReadPtr = mpBasePtr + mnFontDictBase;
2762
0
        mnFDAryCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
2763
0
        if (o3tl::make_unsigned(mnFDAryCount) >= SAL_N_ELEMENTS(maCffLocal))
2764
0
        {
2765
0
            SAL_INFO("vcl.fonts.cff", "CffContext: too many CFF in font");
2766
0
            return false;
2767
0
        }
2768
2769
        // read FDArray details to get access to the PRIVDICTs
2770
0
        for (int i = 0; i < mnFDAryCount; ++i)
2771
0
        {
2772
0
            mpCffLocal = &maCffLocal[i];
2773
0
            if (seekIndexData(mnFontDictBase, i) < 0)
2774
0
                return false;
2775
0
            while (mpReadPtr < mpReadEnd)
2776
0
                readDictOp();
2777
0
            if (mpReadPtr != mpReadEnd)
2778
0
                return false;
2779
0
        }
2780
0
    }
2781
2782
0
    for (int i = 0; i < mnFDAryCount; ++i)
2783
0
    {
2784
0
        mpCffLocal = &maCffLocal[i];
2785
2786
        // get the PrivateDict index
2787
        // (we got mnPrivDictSize and mnPrivDictBase from TOPDICT or FDArray)
2788
0
        if (mpCffLocal->mnPrivDictSize != 0)
2789
0
        {
2790
0
            if (mpCffLocal->mnPrivDictSize <= 0)
2791
0
                return false;
2792
            // get the PrivDict data
2793
0
            mpReadPtr = mpBasePtr + mpCffLocal->mnPrivDictBase;
2794
0
            mpReadEnd = mpReadPtr + mpCffLocal->mnPrivDictSize;
2795
0
            if (mpReadEnd > mpBaseEnd)
2796
0
                return false;
2797
            // read PrivDict details
2798
0
            while (mpReadPtr < mpReadEnd)
2799
0
                readDictOp();
2800
0
        }
2801
2802
        // prepare access to the LocalSubrs (we got mnLocalSubrOffs from PRIVDICT)
2803
0
        if (mpCffLocal->mnLocalSubrOffs)
2804
0
        {
2805
            // read LocalSubrs summary
2806
0
            mpCffLocal->mnLocalSubrBase = mpCffLocal->mnPrivDictBase + mpCffLocal->mnLocalSubrOffs;
2807
0
            mpReadPtr = mpBasePtr + mpCffLocal->mnLocalSubrBase;
2808
0
            const int nSubrCount = (mpReadPtr[0] << 8) + mpReadPtr[1];
2809
0
            mpCffLocal->mnLocalSubrBias
2810
0
                = (nSubrCount < 1240) ? 107 : (nSubrCount < 33900) ? 1131 : 32768;
2811
            //          seekIndexEnd( mpCffLocal->mnLocalSubrBase);
2812
0
        }
2813
0
    }
2814
2815
    // ignore the Notices info
2816
2817
0
    return true;
2818
0
}
2819
2820
// get a cstring from a StringID
2821
OString CffContext::getString(int nStringID)
2822
0
{
2823
    // get a standard string if possible
2824
0
    const static int nStdStrings = SAL_N_ELEMENTS(pStringIds);
2825
0
    if ((nStringID >= 0) && (nStringID < nStdStrings))
2826
0
        return pStringIds[nStringID];
2827
2828
    // else get the string from the StringIndex table
2829
0
    comphelper::ValueRestorationGuard pReadPtr(mpReadPtr);
2830
0
    comphelper::ValueRestorationGuard pReadEnd(mpReadEnd);
2831
0
    nStringID -= nStdStrings;
2832
0
    int nLen = seekIndexData(mnStringIdxBase, nStringID);
2833
    // TODO: just return the undecorated name
2834
0
    if (nLen < 0)
2835
0
    {
2836
0
        return "name[" + OString::number(nStringID) + "].notfound!";
2837
0
    }
2838
0
    else
2839
0
    {
2840
0
        const int nMaxLen = 2560 - 1;
2841
0
        if (nLen >= nMaxLen)
2842
0
            nLen = nMaxLen; // TODO: still needed?
2843
0
        return OString(reinterpret_cast<char const*>(mpReadPtr), nLen);
2844
0
    }
2845
0
}
2846
2847
// access a CID's FDSelect table
2848
int CffContext::getFDSelect(int nGlyphIndex) const
2849
0
{
2850
0
    if (nGlyphIndex < 0 || nGlyphIndex >= mnCharStrCount)
2851
0
        return -1;
2852
2853
0
    if (!mbCIDFont)
2854
0
        return 0;
2855
2856
0
    const U8* pReadPtr = mpBasePtr + mnFDSelectBase;
2857
0
    const U8 nFDSelFormat = *(pReadPtr++);
2858
0
    switch (nFDSelFormat)
2859
0
    {
2860
0
        case 0:
2861
0
        { // FDSELECT format 0
2862
0
            pReadPtr += nGlyphIndex;
2863
0
            const U8 nFDIdx = *(pReadPtr++);
2864
0
            return nFDIdx;
2865
0
        } //break;
2866
0
        case 3:
2867
0
        { // FDSELECT format 3
2868
0
            const U16 nRangeCount = (pReadPtr[0] << 8) + pReadPtr[1];
2869
0
            if (nRangeCount <= 0)
2870
0
                return -1;
2871
0
            if (nRangeCount > mnCharStrCount)
2872
0
                return -1;
2873
0
            U16 nPrev = (pReadPtr[2] << 8) + pReadPtr[3];
2874
0
            if (nPrev != 0)
2875
0
                return -1;
2876
0
            pReadPtr += 4;
2877
            // TODO? binary search
2878
0
            for (int i = 0; i < nRangeCount; ++i)
2879
0
            {
2880
0
                const U8 nFDIdx = pReadPtr[0];
2881
0
                const U16 nNext = (pReadPtr[1] << 8) + pReadPtr[2];
2882
0
                if (nPrev >= nNext)
2883
0
                    return -1;
2884
0
                if (nGlyphIndex < nNext)
2885
0
                    return nFDIdx;
2886
0
                pReadPtr += 3;
2887
0
                nPrev = nNext;
2888
0
            }
2889
0
        }
2890
0
        break;
2891
0
        default: // invalid FDselect format
2892
0
            SAL_WARN("vcl.fonts.cff", "invalid CFF.FdselType=" << nFDSelFormat);
2893
0
            break;
2894
0
    }
2895
2896
0
    return -1;
2897
0
}
2898
2899
int CffContext::getGlyphSID(int nGlyphIndex) const
2900
0
{
2901
0
    if (nGlyphIndex == 0)
2902
0
        return 0; // ".notdef"
2903
0
    if ((nGlyphIndex < 0) || (nGlyphIndex >= mnCharStrCount))
2904
0
        return -1;
2905
2906
    // get the SID/CID from the Charset table
2907
0
    const U8* pReadPtr = mpBasePtr + mnCharsetBase;
2908
0
    const U8 nCSetFormat = *(pReadPtr++);
2909
0
    int nGlyphsToSkip = nGlyphIndex - 1;
2910
0
    switch (nCSetFormat)
2911
0
    {
2912
0
        case 0: // charset format 0
2913
0
            pReadPtr += 2 * nGlyphsToSkip;
2914
0
            nGlyphsToSkip = 0;
2915
0
            break;
2916
0
        case 1: // charset format 1
2917
0
            while (nGlyphsToSkip >= 0)
2918
0
            {
2919
0
                const int nLeft = pReadPtr[2];
2920
0
                if (nGlyphsToSkip <= nLeft)
2921
0
                    break;
2922
0
                nGlyphsToSkip -= nLeft + 1;
2923
0
                pReadPtr += 3;
2924
0
            }
2925
0
            break;
2926
0
        case 2: // charset format 2
2927
0
            while (nGlyphsToSkip >= 0)
2928
0
            {
2929
0
                const int nLeft = (pReadPtr[2] << 8) + pReadPtr[3];
2930
0
                if (nGlyphsToSkip <= nLeft)
2931
0
                    break;
2932
0
                nGlyphsToSkip -= nLeft + 1;
2933
0
                pReadPtr += 4;
2934
0
            }
2935
0
            break;
2936
0
        default:
2937
0
            SAL_WARN("vcl.fonts.cff", "ILLEGAL CFF-Charset format " << nCSetFormat);
2938
0
            return -2;
2939
0
    }
2940
2941
0
    int nSID = (pReadPtr[0] << 8) + pReadPtr[1];
2942
0
    nSID += nGlyphsToSkip;
2943
    // NOTE: for CID-fonts the resulting SID is interpreted as CID
2944
0
    return nSID;
2945
0
}
2946
2947
// NOTE: the result becomes invalid with the next call to this method
2948
OString CffContext::getGlyphName(int nGlyphIndex)
2949
0
{
2950
    // the first glyph is always the .notdef glyph
2951
0
    if (nGlyphIndex == 0)
2952
0
        return tok_notdef;
2953
2954
    // get the glyph specific name
2955
0
    const int nSID = getGlyphSID(nGlyphIndex);
2956
0
    if (nSID < 0) // default glyph name
2957
0
    {
2958
0
        char aDefaultGlyphName[64];
2959
0
        o3tl::sprintf(aDefaultGlyphName, "gly%03d", nGlyphIndex);
2960
0
        return aDefaultGlyphName;
2961
0
    }
2962
0
    else if (mbCIDFont) // default glyph name in CIDs
2963
0
    {
2964
0
        char aDefaultGlyphName[64];
2965
0
        o3tl::sprintf(aDefaultGlyphName, "cid%03d", nSID);
2966
0
        return aDefaultGlyphName;
2967
0
    }
2968
0
    else
2969
0
    { // glyph name from string table
2970
0
        auto const pSidName = getString(nSID);
2971
        // check validity of glyph name
2972
0
        const char* p = pSidName.getStr();
2973
0
        while ((*p >= '0') && (*p <= 'z'))
2974
0
            ++p;
2975
0
        if ((p >= pSidName.getStr() + 1) && (*p == '\0'))
2976
0
            return pSidName;
2977
        // if needed invent a fallback name
2978
0
        char aDefaultGlyphName[64];
2979
0
        o3tl::sprintf(aDefaultGlyphName, "bad%03d", nSID);
2980
0
        return aDefaultGlyphName;
2981
0
    }
2982
0
}
2983
2984
bool CffContext::getBaseAccent(ValType aBase, ValType aAccent, int* nBase, int* nAccent)
2985
0
{
2986
0
    bool bBase = false, bAccent = false;
2987
0
    for (int i = 0; i < mnCharStrCount; i++)
2988
0
    {
2989
0
        OString pGlyphName = getGlyphName(i);
2990
0
        if (pGlyphName == pStandardEncoding[int(aBase)])
2991
0
        {
2992
0
            *nBase = i;
2993
0
            bBase = true;
2994
0
        }
2995
0
        if (pGlyphName == pStandardEncoding[int(aAccent)])
2996
0
        {
2997
0
            *nAccent = i;
2998
0
            bAccent = true;
2999
0
        }
3000
0
        if (bBase && bAccent)
3001
0
            return true;
3002
0
    }
3003
0
    return false;
3004
0
}
3005
3006
namespace
3007
{
3008
class Type1Emitter
3009
{
3010
public:
3011
    explicit Type1Emitter(SvMemoryStream& rStream);
3012
3013
    size_t emitRawData(const char* pData, size_t nLength) const;
3014
    void emitAllRaw();
3015
    void emitAllCrypted();
3016
    int tellPos() const;
3017
    void updateLen(int nTellPos, size_t nLength);
3018
    void emitValVector(const char* pLineHead, const char* pLineTail, const std::vector<ValType>&);
3019
3020
private:
3021
    SvMemoryStream& mrStream;
3022
    unsigned mnEECryptR;
3023
3024
public:
3025
    OStringBuffer maBuffer;
3026
};
3027
}
3028
3029
Type1Emitter::Type1Emitter(SvMemoryStream& rStream)
3030
0
    : mrStream(rStream)
3031
0
    , mnEECryptR(55665) // default eexec seed, TODO: mnEECryptSeed
3032
0
{
3033
0
}
3034
3035
int Type1Emitter::tellPos() const
3036
0
{
3037
0
    int nTellPos = mrStream.Tell();
3038
0
    return nTellPos;
3039
0
}
3040
3041
void Type1Emitter::updateLen(int nTellPos, size_t nLength)
3042
0
{
3043
    // update PFB segment header length
3044
0
    U8 cData[4];
3045
0
    cData[0] = static_cast<U8>(nLength >> 0);
3046
0
    cData[1] = static_cast<U8>(nLength >> 8);
3047
0
    cData[2] = static_cast<U8>(nLength >> 16);
3048
0
    cData[3] = static_cast<U8>(nLength >> 24);
3049
0
    const tools::Long nCurrPos = mrStream.Tell();
3050
0
    if (nCurrPos < 0)
3051
0
        return;
3052
0
    if (mrStream.Seek(nTellPos) != static_cast<sal_uInt64>(nTellPos))
3053
0
        return;
3054
0
    mrStream.WriteBytes(cData, sizeof(cData));
3055
0
    mrStream.Seek(nCurrPos);
3056
0
}
3057
3058
inline size_t Type1Emitter::emitRawData(const char* pData, size_t nLength) const
3059
0
{
3060
0
    return mrStream.WriteBytes(pData, nLength);
3061
0
}
3062
3063
inline void Type1Emitter::emitAllRaw()
3064
0
{
3065
    // writeout raw data
3066
0
    emitRawData(maBuffer.getStr(), maBuffer.getLength());
3067
    // reset the raw buffer
3068
0
    maBuffer.setLength(0);
3069
0
}
3070
3071
void Type1Emitter::emitAllCrypted()
3072
0
{
3073
    // apply t1crypt
3074
0
    for (sal_Int32 i = 0; i < maBuffer.getLength(); ++i)
3075
0
    {
3076
0
        maBuffer[i] ^= (mnEECryptR >> 8);
3077
0
        mnEECryptR = (static_cast<U8>(maBuffer[i]) + mnEECryptR) * 52845 + 22719;
3078
0
    }
3079
3080
    // emit the t1crypt result
3081
0
    emitAllRaw();
3082
0
}
3083
3084
// #i110387# quick-and-dirty double->ascii conversion
3085
// also strip off trailing zeros in fraction while we are at it
3086
static OString dbl2str(double fVal)
3087
0
{
3088
0
    return rtl::math::doubleToString(fVal, rtl_math_StringFormat_G, 6, '.', true);
3089
0
}
3090
3091
void Type1Emitter::emitValVector(const char* pLineHead, const char* pLineTail,
3092
                                 const std::vector<ValType>& rVector)
3093
0
{
3094
    // ignore empty vectors
3095
0
    if (rVector.empty())
3096
0
        return;
3097
3098
    // emit the line head
3099
0
    maBuffer.append(pLineHead);
3100
    // emit the vector values
3101
0
    std::vector<ValType>::value_type aVal = 0;
3102
0
    for (std::vector<ValType>::const_iterator it = rVector.begin();;)
3103
0
    {
3104
0
        aVal = *it;
3105
0
        if (++it == rVector.end())
3106
0
            break;
3107
0
        maBuffer.append(dbl2str(aVal));
3108
0
        maBuffer.append(' ');
3109
0
    }
3110
    // emit the last value
3111
0
    maBuffer.append(dbl2str(aVal));
3112
    // emit the line tail
3113
0
    maBuffer.append(pLineTail);
3114
0
}
3115
3116
bool CffContext::convertCharStrings(std::vector<CharString>& rCharStrings, int nGlyphCount,
3117
                                    const sal_GlyphId* pGlyphIds)
3118
0
{
3119
    // If we are doing extra glyphs used for seac operator, check for already
3120
    // converted glyphs.
3121
0
    bool bCheckDuplicates = !rCharStrings.empty();
3122
0
    rCharStrings.reserve(rCharStrings.size() + nGlyphCount);
3123
0
    for (int i = 0; i < nGlyphCount; ++i)
3124
0
    {
3125
0
        const int nCffGlyphId = pGlyphIds ? pGlyphIds[i] : i;
3126
0
        if ((nCffGlyphId < 0) || (nCffGlyphId >= mnCharStrCount))
3127
0
            return false;
3128
3129
0
        if (!bCheckDuplicates)
3130
0
        {
3131
0
            const auto it
3132
0
                = std::find_if(rCharStrings.begin(), rCharStrings.end(),
3133
0
                               [&](const CharString& c) { return c.nCffGlyphId == nCffGlyphId; });
3134
0
            if (it != rCharStrings.end())
3135
0
                continue;
3136
0
        }
3137
3138
        // get privdict context matching to the glyph
3139
0
        const int nFDSelect = getFDSelect(nCffGlyphId);
3140
0
        if (nFDSelect < 0)
3141
0
            return false;
3142
0
        mpCffLocal = &maCffLocal[nFDSelect];
3143
3144
        // convert the Type2op charstring to its Type1op counterpart
3145
0
        const int nT2Len = seekIndexData(mnCharStrBase, nCffGlyphId);
3146
0
        if (nT2Len <= 0)
3147
0
            return false;
3148
3149
0
        CharString aCharString;
3150
0
        const int nT1Len = convert2Type1Ops(mpCffLocal, mpReadPtr, nT2Len, aCharString.aOps);
3151
0
        if (nT1Len < 0)
3152
0
            return false;
3153
0
        aCharString.nLen = nT1Len;
3154
0
        aCharString.nCffGlyphId = nCffGlyphId;
3155
3156
0
        rCharStrings.push_back(aCharString);
3157
0
    }
3158
0
    return true;
3159
0
}
3160
3161
bool CffContext::emitAsType1(Type1Emitter& rEmitter, FontSubsetInfo& rFSInfo)
3162
0
{
3163
0
    OString aFontName = rFSInfo.m_aPSName.toUtf8();
3164
0
    if (aFontName.getLength() > 255)
3165
0
        aFontName = aFontName.copy(0, 255);
3166
3167
    // prepare some fontdirectory details
3168
0
    static const int nUniqueIdBase = 4100000; // using private-interchange UniqueIds
3169
0
    static int nUniqueId = nUniqueIdBase;
3170
0
    ++nUniqueId;
3171
3172
    // create a PFB+Type1 header
3173
0
    static const char aPfbHeader[] = "\x80\x01\x00\x00\x00\x00";
3174
0
    rEmitter.emitRawData(aPfbHeader, sizeof(aPfbHeader) - 1);
3175
3176
0
    rEmitter.maBuffer.append("%!FontType1-1.0: " + OString::Concat(aFontName) + " 001.003\n");
3177
    // emit TOPDICT
3178
0
    rEmitter.maBuffer.append("11 dict begin\n" // TODO: dynamic entry count for TOPDICT
3179
0
                             "/FontType 1 def\n"
3180
0
                             "/PaintType 0 def\n");
3181
0
    rEmitter.maBuffer.append("/FontName /" + OString::Concat(aFontName) + " def\n");
3182
0
    rEmitter.maBuffer.append("/UniqueID " + OString::number(nUniqueId) + " def\n");
3183
    // emit FontMatrix
3184
0
    if (maFontMatrix.size() == 6)
3185
0
        rEmitter.emitValVector("/FontMatrix [", "]readonly def\n", maFontMatrix);
3186
0
    else // emit default FontMatrix if needed
3187
0
        rEmitter.maBuffer.append("/FontMatrix [0.001 0 0 0.001 0 0]readonly def\n");
3188
3189
    // emit FontBBox
3190
0
    ValType fXFactor = 1.0;
3191
0
    ValType fYFactor = 1.0;
3192
0
    if (maFontMatrix.size() >= 4)
3193
0
    {
3194
0
        fXFactor = 1000.0F * maFontMatrix[0];
3195
0
        fYFactor = 1000.0F * maFontMatrix[3];
3196
0
    }
3197
3198
0
    auto aFontBBox
3199
0
        = { rFSInfo.m_aFontBBox.Left() / fXFactor, rFSInfo.m_aFontBBox.Top() / fYFactor,
3200
0
            rFSInfo.m_aFontBBox.Right() / fXFactor, (rFSInfo.m_aFontBBox.Bottom() + 1) / fYFactor };
3201
3202
0
    rEmitter.emitValVector("/FontBBox {", "}readonly def\n", aFontBBox);
3203
    // emit FONTINFO into TOPDICT
3204
0
    rEmitter.maBuffer.append("/FontInfo 2 dict dup begin\n" // TODO: check fontinfo entry count
3205
0
                             " /FullName ("
3206
0
                             + OString::Concat(aFontName)
3207
0
                             + ") readonly def\n"
3208
0
                               " /FamilyName ("
3209
0
                             + aFontName
3210
0
                             + ") readonly def\n"
3211
0
                               "end readonly def\n");
3212
3213
0
    rEmitter.maBuffer.append("/Encoding 256 array\n"
3214
0
                             "0 1 255 {1 index exch /.notdef put} for\n");
3215
0
    for (int i = 1; (i < mnCharStrCount) && (i < 256); ++i)
3216
0
    {
3217
0
        OString pGlyphName = getGlyphName(i);
3218
0
        rEmitter.maBuffer.append("dup " + OString::number(i) + " /" + pGlyphName + " put\n");
3219
0
    }
3220
0
    rEmitter.maBuffer.append("readonly def\n");
3221
0
    rEmitter.maBuffer.append(
3222
        // TODO: more topdict entries
3223
0
        "currentdict end\n"
3224
0
        "currentfile eexec\n");
3225
3226
    // emit PFB header
3227
0
    rEmitter.emitAllRaw();
3228
    // update PFB header segment
3229
0
    const int nPfbHeaderLen = rEmitter.tellPos() - 6;
3230
0
    rEmitter.updateLen(2, nPfbHeaderLen);
3231
3232
    // prepare start of eexec segment
3233
0
    rEmitter.emitRawData("\x80\x02\x00\x00\x00\x00", 6); // segment start
3234
0
    const int nEExecSegTell = rEmitter.tellPos();
3235
3236
    // which always starts with a privdict
3237
    // count the privdict entries
3238
0
    int nPrivEntryCount = 9;
3239
    // emit blue hints only if non-default values
3240
0
    nPrivEntryCount += int(!mpCffLocal->maOtherBlues.empty());
3241
0
    nPrivEntryCount += int(!mpCffLocal->maFamilyBlues.empty());
3242
0
    nPrivEntryCount += int(!mpCffLocal->maFamilyOtherBlues.empty());
3243
0
    nPrivEntryCount += int(mpCffLocal->mfBlueScale != 0.0);
3244
0
    nPrivEntryCount += int(mpCffLocal->mfBlueShift != 0.0);
3245
0
    nPrivEntryCount += int(mpCffLocal->mfBlueFuzz != 0.0);
3246
    // emit stem hints only if non-default values
3247
0
    nPrivEntryCount += int(mpCffLocal->maStemStdHW != 0);
3248
0
    nPrivEntryCount += int(mpCffLocal->maStemStdVW != 0);
3249
0
    nPrivEntryCount += int(!mpCffLocal->maStemSnapH.empty());
3250
0
    nPrivEntryCount += int(!mpCffLocal->maStemSnapV.empty());
3251
    // emit other hints only if non-default values
3252
0
    nPrivEntryCount += int(mpCffLocal->mfExpFactor != 0.0);
3253
0
    nPrivEntryCount += int(mpCffLocal->mnLangGroup != 0);
3254
0
    nPrivEntryCount += int(mpCffLocal->mnLangGroup == 1);
3255
0
    nPrivEntryCount += int(mpCffLocal->mbForceBold);
3256
    // emit the privdict header
3257
0
    rEmitter.maBuffer.append("\110\104\125 "
3258
0
                             "dup\n/Private "
3259
0
                             + OString::number(nPrivEntryCount)
3260
0
                             + " dict dup begin\n"
3261
0
                               "/RD{string currentfile exch readstring pop}executeonly def\n"
3262
0
                               "/ND{noaccess def}executeonly def\n"
3263
0
                               "/NP{noaccess put}executeonly def\n"
3264
0
                               "/MinFeature{16 16}ND\n"
3265
0
                               "/password 5839 def\n"); // TODO: mnRDCryptSeed?
3266
3267
    // emit blue hint related privdict entries
3268
0
    if (!mpCffLocal->maBlueValues.empty())
3269
0
        rEmitter.emitValVector("/BlueValues [", "]ND\n", mpCffLocal->maBlueValues);
3270
0
    else
3271
0
        rEmitter.maBuffer.append("/BlueValues []ND\n"); // default to empty BlueValues
3272
0
    rEmitter.emitValVector("/OtherBlues [", "]ND\n", mpCffLocal->maOtherBlues);
3273
0
    rEmitter.emitValVector("/FamilyBlues [", "]ND\n", mpCffLocal->maFamilyBlues);
3274
0
    rEmitter.emitValVector("/FamilyOtherBlues [", "]ND\n", mpCffLocal->maFamilyOtherBlues);
3275
3276
0
    if (mpCffLocal->mfBlueScale)
3277
0
    {
3278
0
        rEmitter.maBuffer.append("/BlueScale ");
3279
0
        rEmitter.maBuffer.append(dbl2str(mpCffLocal->mfBlueScale));
3280
0
        rEmitter.maBuffer.append(" def\n");
3281
0
    }
3282
0
    if (mpCffLocal->mfBlueShift)
3283
0
    { // default BlueShift==7
3284
0
        rEmitter.maBuffer.append("/BlueShift ");
3285
0
        rEmitter.maBuffer.append(dbl2str(mpCffLocal->mfBlueShift));
3286
0
        rEmitter.maBuffer.append(" def\n");
3287
0
    }
3288
0
    if (mpCffLocal->mfBlueFuzz)
3289
0
    { // default BlueFuzz==1
3290
0
        rEmitter.maBuffer.append("/BlueFuzz ");
3291
0
        rEmitter.maBuffer.append(dbl2str(mpCffLocal->mfBlueFuzz));
3292
0
        rEmitter.maBuffer.append(" def\n");
3293
0
    }
3294
3295
    // emit stem hint related privdict entries
3296
0
    if (mpCffLocal->maStemStdHW)
3297
0
    {
3298
0
        rEmitter.maBuffer.append("/StdHW [");
3299
0
        rEmitter.maBuffer.append(dbl2str(mpCffLocal->maStemStdHW));
3300
0
        rEmitter.maBuffer.append("] def\n");
3301
0
    }
3302
0
    if (mpCffLocal->maStemStdVW)
3303
0
    {
3304
0
        rEmitter.maBuffer.append("/StdVW [");
3305
0
        rEmitter.maBuffer.append(dbl2str(mpCffLocal->maStemStdVW));
3306
0
        rEmitter.maBuffer.append("] def\n");
3307
0
    }
3308
0
    rEmitter.emitValVector("/StemSnapH [", "]ND\n", mpCffLocal->maStemSnapH);
3309
0
    rEmitter.emitValVector("/StemSnapV [", "]ND\n", mpCffLocal->maStemSnapV);
3310
3311
    // emit other hints
3312
0
    if (mpCffLocal->mbForceBold)
3313
0
        rEmitter.maBuffer.append("/ForceBold true def\n");
3314
0
    if (mpCffLocal->mnLangGroup != 0)
3315
0
        rEmitter.maBuffer.append("/LanguageGroup " + OString::number(mpCffLocal->mnLangGroup)
3316
0
                                 + " def\n");
3317
0
    if (mpCffLocal->mnLangGroup == 1) // compatibility with ancient printers
3318
0
        rEmitter.maBuffer.append("/RndStemUp false def\n");
3319
0
    if (mpCffLocal->mfExpFactor)
3320
0
    {
3321
0
        rEmitter.maBuffer.append("/ExpansionFactor ");
3322
0
        rEmitter.maBuffer.append(dbl2str(mpCffLocal->mfExpFactor));
3323
0
        rEmitter.maBuffer.append(" def\n");
3324
0
    }
3325
3326
    // emit remaining privdict entries
3327
0
    rEmitter.maBuffer.append("/UniqueID " + OString::number(nUniqueId) + " def\n");
3328
    // TODO?: more privdict entries?
3329
3330
0
    rEmitter.maBuffer.append("/OtherSubrs\n"
3331
0
                             "% Dummy code for faking flex hints\n"
3332
0
                             "[ {} {} {} {systemdict /internaldict known not {pop 3}\n"
3333
0
                             "{1183615869 systemdict /internaldict get exec\n"
3334
0
                             "dup /startlock known\n"
3335
0
                             "{/startlock get exec}\n"
3336
0
                             "{dup /strtlck known\n"
3337
0
                             "{/strtlck get exec}\n"
3338
0
                             "{pop 3}\nifelse}\nifelse}\nifelse\n} executeonly\n"
3339
0
                             "] ND\n");
3340
3341
    // emit used GlobalSubr charstrings
3342
    // these are the just the default subrs
3343
    // TODO: do we need them as the flex hints are resolved differently?
3344
0
    rEmitter.maBuffer.append(
3345
0
        "/Subrs 5 array\n"
3346
0
        "dup 0 15 RD \x5F\x3D\x6B\xAC\x3C\xBD\x74\x3D\x3E\x17\xA0\x86\x58\x08\x85 NP\n"
3347
0
        "dup 1 9 RD \x5F\x3D\x6B\xD8\xA6\xB5\x68\xB6\xA2 NP\n"
3348
0
        "dup 2 9 RD \x5F\x3D\x6B\xAC\x39\x46\xB9\x43\xF9 NP\n"
3349
0
        "dup 3 5 RD \x5F\x3D\x6B\xAC\xB9 NP\n"
3350
0
        "dup 4 12 RD \x5F\x3D\x6B\xAC\x3E\x5D\x48\x54\x62\x76\x39\x03 NP\n"
3351
0
        "ND\n");
3352
3353
    // TODO: emit more GlobalSubr charstrings?
3354
    // TODO: emit used LocalSubr charstrings?
3355
3356
    // emit the CharStrings for the requested glyphs
3357
0
    std::vector<CharString> aCharStrings;
3358
0
    mbDoSeac = true;
3359
0
    if (!convertCharStrings(aCharStrings, mnCharStrCount))
3360
0
        return false;
3361
3362
    // The previous convertCharStrings might collect extra glyphs used in seac
3363
    // operator, convert them as well
3364
0
    if (!maExtraGlyphIds.empty())
3365
0
    {
3366
0
        mbDoSeac = false;
3367
0
        if (!convertCharStrings(aCharStrings, maExtraGlyphIds.size(), maExtraGlyphIds.data()))
3368
0
            return false;
3369
0
    }
3370
0
    rEmitter.maBuffer.append("2 index /CharStrings " + OString::number(aCharStrings.size())
3371
0
                             + " dict dup begin\n");
3372
0
    rEmitter.emitAllCrypted();
3373
0
    for (const auto& rCharString : aCharStrings)
3374
0
    {
3375
        // get the glyph name
3376
0
        OString pGlyphName = getGlyphName(rCharString.nCffGlyphId);
3377
        // emit the encrypted Type1op charstring
3378
0
        rEmitter.maBuffer.append("/" + pGlyphName + " " + OString::number(rCharString.nLen)
3379
0
                                 + " RD ");
3380
0
        rEmitter.maBuffer.append(reinterpret_cast<char const*>(rCharString.aOps), rCharString.nLen);
3381
0
        rEmitter.maBuffer.append(" ND\n");
3382
0
        rEmitter.emitAllCrypted();
3383
        // provide individual glyphwidths if requested
3384
0
    }
3385
0
    rEmitter.maBuffer.append("end end\nreadonly put\nput\n");
3386
0
    rEmitter.maBuffer.append("dup/FontName get exch definefont pop\n");
3387
0
    rEmitter.maBuffer.append("mark currentfile closefile\n");
3388
0
    rEmitter.emitAllCrypted();
3389
3390
    // mark stop of eexec encryption
3391
0
    const int nEExecLen = rEmitter.tellPos() - nEExecSegTell;
3392
0
    rEmitter.updateLen(nEExecSegTell - 4, nEExecLen);
3393
3394
    // create PFB footer
3395
0
    static const char aPfxFooter[]
3396
0
        = "\x80\x01\x14\x02\x00\x00\n" // TODO: check segment len
3397
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3398
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3399
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3400
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3401
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3402
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3403
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3404
0
          "0000000000000000000000000000000000000000000000000000000000000000\n"
3405
0
          "cleartomark\n"
3406
0
          "\x80\x03";
3407
0
    rEmitter.emitRawData(aPfxFooter, sizeof(aPfxFooter) - 1);
3408
3409
0
    rFSInfo.m_nFontType = FontType::TYPE1_PFB;
3410
3411
0
    return true;
3412
0
}
3413
3414
namespace vcl
3415
{
3416
bool ConvertCFFfontToType1(const unsigned char* pFontBytes, int nByteLength,
3417
                           std::vector<sal_uInt8>& rOutBuffer, FontSubsetInfo& rInfo)
3418
9.57k
{
3419
9.57k
    CffContext aCff(pFontBytes, nByteLength);
3420
9.57k
    if (!aCff.initialCffRead())
3421
9.57k
        return false;
3422
3423
0
    SvMemoryStream aStream;
3424
3425
    // emit Type1 font from the CFF input
3426
0
    Type1Emitter aType1Emitter(aStream);
3427
0
    if (!aCff.emitAsType1(aType1Emitter, rInfo))
3428
0
        return false;
3429
3430
0
    rOutBuffer.assign(static_cast<const sal_uInt8*>(aStream.GetData()),
3431
0
                      static_cast<const sal_uInt8*>(aStream.GetData()) + aStream.Tell());
3432
3433
0
    return true;
3434
0
}
3435
} // namespace vcl
3436
3437
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */