/src/skia/third_party/externals/freetype/src/cff/cffobjs.c
Line | Count | Source (jump to first uncovered line) |
1 | | /**************************************************************************** |
2 | | * |
3 | | * cffobjs.c |
4 | | * |
5 | | * OpenType objects manager (body). |
6 | | * |
7 | | * Copyright (C) 1996-2021 by |
8 | | * David Turner, Robert Wilhelm, and Werner Lemberg. |
9 | | * |
10 | | * This file is part of the FreeType project, and may only be used, |
11 | | * modified, and distributed under the terms of the FreeType project |
12 | | * license, LICENSE.TXT. By continuing to use, modify, or distribute |
13 | | * this file you indicate that you have read the license and |
14 | | * understand and accept it fully. |
15 | | * |
16 | | */ |
17 | | |
18 | | |
19 | | |
20 | | #include <freetype/internal/ftdebug.h> |
21 | | #include <freetype/internal/ftcalc.h> |
22 | | #include <freetype/internal/ftstream.h> |
23 | | #include <freetype/fterrors.h> |
24 | | #include <freetype/ttnameid.h> |
25 | | #include <freetype/tttags.h> |
26 | | #include <freetype/internal/sfnt.h> |
27 | | #include <freetype/ftdriver.h> |
28 | | |
29 | | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
30 | | #include <freetype/ftmm.h> |
31 | | #include <freetype/internal/services/svmm.h> |
32 | | #include <freetype/internal/services/svmetric.h> |
33 | | #endif |
34 | | |
35 | | #include <freetype/internal/cffotypes.h> |
36 | | #include "cffobjs.h" |
37 | | #include "cffload.h" |
38 | | #include "cffcmap.h" |
39 | | |
40 | | #include "cfferrs.h" |
41 | | |
42 | | #include <freetype/internal/psaux.h> |
43 | | #include <freetype/internal/services/svcfftl.h> |
44 | | |
45 | | |
46 | | /************************************************************************** |
47 | | * |
48 | | * The macro FT_COMPONENT is used in trace mode. It is an implicit |
49 | | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
50 | | * messages during execution. |
51 | | */ |
52 | | #undef FT_COMPONENT |
53 | | #define FT_COMPONENT cffobjs |
54 | | |
55 | | |
56 | | /************************************************************************** |
57 | | * |
58 | | * SIZE FUNCTIONS |
59 | | * |
60 | | */ |
61 | | |
62 | | |
63 | | static PSH_Globals_Funcs |
64 | | cff_size_get_globals_funcs( CFF_Size size ) |
65 | 3.63k | { |
66 | 3.63k | CFF_Face face = (CFF_Face)size->root.face; |
67 | 3.63k | CFF_Font font = (CFF_Font)face->extra.data; |
68 | 3.63k | PSHinter_Service pshinter = font->pshinter; |
69 | 3.63k | FT_Module module; |
70 | | |
71 | | |
72 | 3.63k | module = FT_Get_Module( size->root.face->driver->root.library, |
73 | 3.63k | "pshinter" ); |
74 | 3.63k | return ( module && pshinter && pshinter->get_globals_funcs ) |
75 | 3.63k | ? pshinter->get_globals_funcs( module ) |
76 | 0 | : 0; |
77 | 3.63k | } |
78 | | |
79 | | |
80 | | FT_LOCAL_DEF( void ) |
81 | | cff_size_done( FT_Size cffsize ) /* CFF_Size */ |
82 | 1.81k | { |
83 | 1.81k | FT_Memory memory = cffsize->face->memory; |
84 | 1.81k | CFF_Size size = (CFF_Size)cffsize; |
85 | 1.81k | CFF_Face face = (CFF_Face)size->root.face; |
86 | 1.81k | CFF_Font font = (CFF_Font)face->extra.data; |
87 | 1.81k | CFF_Internal internal = (CFF_Internal)cffsize->internal->module_data; |
88 | | |
89 | | |
90 | 1.81k | if ( internal ) |
91 | 1.81k | { |
92 | 1.81k | PSH_Globals_Funcs funcs; |
93 | | |
94 | | |
95 | 1.81k | funcs = cff_size_get_globals_funcs( size ); |
96 | 1.81k | if ( funcs ) |
97 | 1.81k | { |
98 | 1.81k | FT_UInt i; |
99 | | |
100 | | |
101 | 1.81k | funcs->destroy( internal->topfont ); |
102 | | |
103 | 1.81k | for ( i = font->num_subfonts; i > 0; i-- ) |
104 | 0 | funcs->destroy( internal->subfonts[i - 1] ); |
105 | 1.81k | } |
106 | | |
107 | 1.81k | FT_FREE( internal ); |
108 | 1.81k | } |
109 | 1.81k | } |
110 | | |
111 | | |
112 | | /* CFF and Type 1 private dictionaries have slightly different */ |
113 | | /* structures; we need to synthesize a Type 1 dictionary on the fly */ |
114 | | |
115 | | static void |
116 | | cff_make_private_dict( CFF_SubFont subfont, |
117 | | PS_Private priv ) |
118 | 1.81k | { |
119 | 1.81k | CFF_Private cpriv = &subfont->private_dict; |
120 | 1.81k | FT_UInt n, count; |
121 | | |
122 | | |
123 | 1.81k | FT_ZERO( priv ); |
124 | | |
125 | 1.81k | count = priv->num_blue_values = cpriv->num_blue_values; |
126 | 2.07k | for ( n = 0; n < count; n++ ) |
127 | 258 | priv->blue_values[n] = (FT_Short)cpriv->blue_values[n]; |
128 | | |
129 | 1.81k | count = priv->num_other_blues = cpriv->num_other_blues; |
130 | 2.20k | for ( n = 0; n < count; n++ ) |
131 | 388 | priv->other_blues[n] = (FT_Short)cpriv->other_blues[n]; |
132 | | |
133 | 1.81k | count = priv->num_family_blues = cpriv->num_family_blues; |
134 | 5.05k | for ( n = 0; n < count; n++ ) |
135 | 3.24k | priv->family_blues[n] = (FT_Short)cpriv->family_blues[n]; |
136 | | |
137 | 1.81k | count = priv->num_family_other_blues = cpriv->num_family_other_blues; |
138 | 2.08k | for ( n = 0; n < count; n++ ) |
139 | 264 | priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; |
140 | | |
141 | 1.81k | priv->blue_scale = cpriv->blue_scale; |
142 | 1.81k | priv->blue_shift = (FT_Int)cpriv->blue_shift; |
143 | 1.81k | priv->blue_fuzz = (FT_Int)cpriv->blue_fuzz; |
144 | | |
145 | 1.81k | priv->standard_width[0] = (FT_UShort)cpriv->standard_width; |
146 | 1.81k | priv->standard_height[0] = (FT_UShort)cpriv->standard_height; |
147 | | |
148 | 1.81k | count = priv->num_snap_widths = cpriv->num_snap_widths; |
149 | 1.81k | for ( n = 0; n < count; n++ ) |
150 | 0 | priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; |
151 | | |
152 | 1.81k | count = priv->num_snap_heights = cpriv->num_snap_heights; |
153 | 1.81k | for ( n = 0; n < count; n++ ) |
154 | 0 | priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; |
155 | | |
156 | 1.81k | priv->force_bold = cpriv->force_bold; |
157 | 1.81k | priv->language_group = cpriv->language_group; |
158 | 1.81k | priv->lenIV = cpriv->lenIV; |
159 | 1.81k | } |
160 | | |
161 | | |
162 | | FT_LOCAL_DEF( FT_Error ) |
163 | | cff_size_init( FT_Size cffsize ) /* CFF_Size */ |
164 | 1.81k | { |
165 | 1.81k | CFF_Size size = (CFF_Size)cffsize; |
166 | 1.81k | FT_Error error = FT_Err_Ok; |
167 | 1.81k | PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); |
168 | | |
169 | 1.81k | FT_Memory memory = cffsize->face->memory; |
170 | 1.81k | CFF_Internal internal = NULL; |
171 | 1.81k | CFF_Face face = (CFF_Face)cffsize->face; |
172 | 1.81k | CFF_Font font = (CFF_Font)face->extra.data; |
173 | | |
174 | 1.81k | PS_PrivateRec priv; |
175 | | |
176 | 1.81k | FT_UInt i; |
177 | | |
178 | 1.81k | if ( !funcs ) |
179 | 0 | goto Exit; |
180 | | |
181 | 1.81k | if ( FT_NEW( internal ) ) |
182 | 0 | goto Exit; |
183 | | |
184 | 1.81k | cff_make_private_dict( &font->top_font, &priv ); |
185 | 1.81k | error = funcs->create( cffsize->face->memory, &priv, |
186 | 1.81k | &internal->topfont ); |
187 | 1.81k | if ( error ) |
188 | 0 | goto Exit; |
189 | | |
190 | 1.81k | for ( i = font->num_subfonts; i > 0; i-- ) |
191 | 0 | { |
192 | 0 | CFF_SubFont sub = font->subfonts[i - 1]; |
193 | | |
194 | |
|
195 | 0 | cff_make_private_dict( sub, &priv ); |
196 | 0 | error = funcs->create( cffsize->face->memory, &priv, |
197 | 0 | &internal->subfonts[i - 1] ); |
198 | 0 | if ( error ) |
199 | 0 | goto Exit; |
200 | 0 | } |
201 | | |
202 | 1.81k | cffsize->internal->module_data = internal; |
203 | | |
204 | 1.81k | size->strike_index = 0xFFFFFFFFUL; |
205 | | |
206 | 1.81k | Exit: |
207 | 1.81k | if ( error ) |
208 | 0 | { |
209 | 0 | if ( internal ) |
210 | 0 | { |
211 | 0 | for ( i = font->num_subfonts; i > 0; i-- ) |
212 | 0 | FT_FREE( internal->subfonts[i - 1] ); |
213 | 0 | FT_FREE( internal->topfont ); |
214 | 0 | } |
215 | |
|
216 | 0 | FT_FREE( internal ); |
217 | 0 | } |
218 | | |
219 | 1.81k | return error; |
220 | 1.81k | } |
221 | | |
222 | | |
223 | | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
224 | | |
225 | | FT_LOCAL_DEF( FT_Error ) |
226 | | cff_size_select( FT_Size size, |
227 | | FT_ULong strike_index ) |
228 | 0 | { |
229 | 0 | CFF_Size cffsize = (CFF_Size)size; |
230 | 0 | PSH_Globals_Funcs funcs; |
231 | | |
232 | |
|
233 | 0 | cffsize->strike_index = strike_index; |
234 | |
|
235 | 0 | FT_Select_Metrics( size->face, strike_index ); |
236 | |
|
237 | 0 | funcs = cff_size_get_globals_funcs( cffsize ); |
238 | |
|
239 | 0 | if ( funcs ) |
240 | 0 | { |
241 | 0 | CFF_Face face = (CFF_Face)size->face; |
242 | 0 | CFF_Font font = (CFF_Font)face->extra.data; |
243 | 0 | CFF_Internal internal = (CFF_Internal)size->internal->module_data; |
244 | |
|
245 | 0 | FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; |
246 | 0 | FT_UInt i; |
247 | | |
248 | |
|
249 | 0 | funcs->set_scale( internal->topfont, |
250 | 0 | size->metrics.x_scale, size->metrics.y_scale, |
251 | 0 | 0, 0 ); |
252 | |
|
253 | 0 | for ( i = font->num_subfonts; i > 0; i-- ) |
254 | 0 | { |
255 | 0 | CFF_SubFont sub = font->subfonts[i - 1]; |
256 | 0 | FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em; |
257 | 0 | FT_Pos x_scale, y_scale; |
258 | | |
259 | |
|
260 | 0 | if ( top_upm != sub_upm ) |
261 | 0 | { |
262 | 0 | x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); |
263 | 0 | y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); |
264 | 0 | } |
265 | 0 | else |
266 | 0 | { |
267 | 0 | x_scale = size->metrics.x_scale; |
268 | 0 | y_scale = size->metrics.y_scale; |
269 | 0 | } |
270 | |
|
271 | 0 | funcs->set_scale( internal->subfonts[i - 1], |
272 | 0 | x_scale, y_scale, 0, 0 ); |
273 | 0 | } |
274 | 0 | } |
275 | |
|
276 | 0 | return FT_Err_Ok; |
277 | 0 | } |
278 | | |
279 | | #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
280 | | |
281 | | |
282 | | FT_LOCAL_DEF( FT_Error ) |
283 | | cff_size_request( FT_Size size, |
284 | | FT_Size_Request req ) |
285 | 0 | { |
286 | 0 | CFF_Size cffsize = (CFF_Size)size; |
287 | 0 | PSH_Globals_Funcs funcs; |
288 | | |
289 | |
|
290 | 0 | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
291 | |
|
292 | 0 | if ( FT_HAS_FIXED_SIZES( size->face ) ) |
293 | 0 | { |
294 | 0 | CFF_Face cffface = (CFF_Face)size->face; |
295 | 0 | SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; |
296 | 0 | FT_ULong strike_index; |
297 | | |
298 | |
|
299 | 0 | if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) ) |
300 | 0 | cffsize->strike_index = 0xFFFFFFFFUL; |
301 | 0 | else |
302 | 0 | return cff_size_select( size, strike_index ); |
303 | 0 | } |
304 | | |
305 | 0 | #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
306 | | |
307 | 0 | FT_Request_Metrics( size->face, req ); |
308 | |
|
309 | 0 | funcs = cff_size_get_globals_funcs( cffsize ); |
310 | |
|
311 | 0 | if ( funcs ) |
312 | 0 | { |
313 | 0 | CFF_Face cffface = (CFF_Face)size->face; |
314 | 0 | CFF_Font font = (CFF_Font)cffface->extra.data; |
315 | 0 | CFF_Internal internal = (CFF_Internal)size->internal->module_data; |
316 | |
|
317 | 0 | FT_Long top_upm = (FT_Long)font->top_font.font_dict.units_per_em; |
318 | 0 | FT_UInt i; |
319 | | |
320 | |
|
321 | 0 | funcs->set_scale( internal->topfont, |
322 | 0 | size->metrics.x_scale, size->metrics.y_scale, |
323 | 0 | 0, 0 ); |
324 | |
|
325 | 0 | for ( i = font->num_subfonts; i > 0; i-- ) |
326 | 0 | { |
327 | 0 | CFF_SubFont sub = font->subfonts[i - 1]; |
328 | 0 | FT_Long sub_upm = (FT_Long)sub->font_dict.units_per_em; |
329 | 0 | FT_Pos x_scale, y_scale; |
330 | | |
331 | |
|
332 | 0 | if ( top_upm != sub_upm ) |
333 | 0 | { |
334 | 0 | x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm ); |
335 | 0 | y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm ); |
336 | 0 | } |
337 | 0 | else |
338 | 0 | { |
339 | 0 | x_scale = size->metrics.x_scale; |
340 | 0 | y_scale = size->metrics.y_scale; |
341 | 0 | } |
342 | |
|
343 | 0 | funcs->set_scale( internal->subfonts[i - 1], |
344 | 0 | x_scale, y_scale, 0, 0 ); |
345 | 0 | } |
346 | 0 | } |
347 | |
|
348 | 0 | return FT_Err_Ok; |
349 | 0 | } |
350 | | |
351 | | |
352 | | /************************************************************************** |
353 | | * |
354 | | * SLOT FUNCTIONS |
355 | | * |
356 | | */ |
357 | | |
358 | | FT_LOCAL_DEF( void ) |
359 | | cff_slot_done( FT_GlyphSlot slot ) |
360 | 1.81k | { |
361 | 1.81k | if ( slot->internal ) |
362 | 1.81k | slot->internal->glyph_hints = NULL; |
363 | 1.81k | } |
364 | | |
365 | | |
366 | | FT_LOCAL_DEF( FT_Error ) |
367 | | cff_slot_init( FT_GlyphSlot slot ) |
368 | 1.81k | { |
369 | 1.81k | CFF_Face face = (CFF_Face)slot->face; |
370 | 1.81k | CFF_Font font = (CFF_Font)face->extra.data; |
371 | 1.81k | PSHinter_Service pshinter = font->pshinter; |
372 | | |
373 | | |
374 | 1.81k | if ( pshinter ) |
375 | 1.81k | { |
376 | 1.81k | FT_Module module; |
377 | | |
378 | | |
379 | 1.81k | module = FT_Get_Module( slot->face->driver->root.library, |
380 | 1.81k | "pshinter" ); |
381 | 1.81k | if ( module ) |
382 | 1.81k | { |
383 | 1.81k | T2_Hints_Funcs funcs; |
384 | | |
385 | | |
386 | 1.81k | funcs = pshinter->get_t2_funcs( module ); |
387 | 1.81k | slot->internal->glyph_hints = (void*)funcs; |
388 | 1.81k | } |
389 | 1.81k | } |
390 | | |
391 | 1.81k | return FT_Err_Ok; |
392 | 1.81k | } |
393 | | |
394 | | |
395 | | /************************************************************************** |
396 | | * |
397 | | * FACE FUNCTIONS |
398 | | * |
399 | | */ |
400 | | |
401 | | static FT_String* |
402 | | cff_strcpy( FT_Memory memory, |
403 | | const FT_String* source ) |
404 | 554 | { |
405 | 554 | FT_Error error; |
406 | 554 | FT_String* result; |
407 | | |
408 | | |
409 | 554 | (void)FT_STRDUP( result, source ); |
410 | | |
411 | 554 | FT_UNUSED( error ); |
412 | | |
413 | 554 | return result; |
414 | 554 | } |
415 | | |
416 | | |
417 | | /* Strip all subset prefixes of the form `ABCDEF+'. Usually, there */ |
418 | | /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold' */ |
419 | | /* have been seen in the wild. */ |
420 | | |
421 | | static void |
422 | | remove_subset_prefix( FT_String* name ) |
423 | 0 | { |
424 | 0 | FT_Int32 idx = 0; |
425 | 0 | FT_Int32 length = (FT_Int32)ft_strlen( name ) + 1; |
426 | 0 | FT_Bool continue_search = 1; |
427 | | |
428 | |
|
429 | 0 | while ( continue_search ) |
430 | 0 | { |
431 | 0 | if ( length >= 7 && name[6] == '+' ) |
432 | 0 | { |
433 | 0 | for ( idx = 0; idx < 6; idx++ ) |
434 | 0 | { |
435 | | /* ASCII uppercase letters */ |
436 | 0 | if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) ) |
437 | 0 | continue_search = 0; |
438 | 0 | } |
439 | |
|
440 | 0 | if ( continue_search ) |
441 | 0 | { |
442 | 0 | for ( idx = 7; idx < length; idx++ ) |
443 | 0 | name[idx - 7] = name[idx]; |
444 | 0 | length -= 7; |
445 | 0 | } |
446 | 0 | } |
447 | 0 | else |
448 | 0 | continue_search = 0; |
449 | 0 | } |
450 | 0 | } |
451 | | |
452 | | |
453 | | /* Remove the style part from the family name (if present). */ |
454 | | |
455 | | static void |
456 | | remove_style( FT_String* family_name, |
457 | | const FT_String* style_name ) |
458 | 178 | { |
459 | 178 | FT_Int32 family_name_length, style_name_length; |
460 | | |
461 | | |
462 | 178 | family_name_length = (FT_Int32)ft_strlen( family_name ); |
463 | 178 | style_name_length = (FT_Int32)ft_strlen( style_name ); |
464 | | |
465 | 178 | if ( family_name_length > style_name_length ) |
466 | 145 | { |
467 | 145 | FT_Int idx; |
468 | | |
469 | | |
470 | 145 | for ( idx = 1; idx <= style_name_length; idx++ ) |
471 | 145 | { |
472 | 145 | if ( family_name[family_name_length - idx] != |
473 | 145 | style_name[style_name_length - idx] ) |
474 | 145 | break; |
475 | 145 | } |
476 | | |
477 | 145 | if ( idx > style_name_length ) |
478 | 0 | { |
479 | | /* family_name ends with style_name; remove it */ |
480 | 0 | idx = family_name_length - style_name_length - 1; |
481 | | |
482 | | /* also remove special characters */ |
483 | | /* between real family name and style */ |
484 | 0 | while ( idx > 0 && |
485 | 0 | ( family_name[idx] == '-' || |
486 | 0 | family_name[idx] == ' ' || |
487 | 0 | family_name[idx] == '_' || |
488 | 0 | family_name[idx] == '+' ) ) |
489 | 0 | idx--; |
490 | |
|
491 | 0 | if ( idx > 0 ) |
492 | 0 | family_name[idx + 1] = '\0'; |
493 | 0 | } |
494 | 145 | } |
495 | 178 | } |
496 | | |
497 | | |
498 | | FT_LOCAL_DEF( FT_Error ) |
499 | | cff_face_init( FT_Stream stream, |
500 | | FT_Face cffface, /* CFF_Face */ |
501 | | FT_Int face_index, |
502 | | FT_Int num_params, |
503 | | FT_Parameter* params ) |
504 | 5.86k | { |
505 | 5.86k | CFF_Face face = (CFF_Face)cffface; |
506 | 5.86k | FT_Error error; |
507 | 5.86k | SFNT_Service sfnt; |
508 | 5.86k | FT_Service_PsCMaps psnames; |
509 | 5.86k | PSHinter_Service pshinter; |
510 | 5.86k | PSAux_Service psaux; |
511 | 5.86k | FT_Service_CFFLoad cffload; |
512 | 5.86k | FT_Bool pure_cff = 1; |
513 | 5.86k | FT_Bool cff2 = 0; |
514 | 5.86k | FT_Bool sfnt_format = 0; |
515 | 5.86k | FT_Library library = cffface->driver->root.library; |
516 | | |
517 | | |
518 | 5.86k | sfnt = (SFNT_Service)FT_Get_Module_Interface( library, |
519 | 5.86k | "sfnt" ); |
520 | 5.86k | if ( !sfnt ) |
521 | 0 | { |
522 | 0 | FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" )); |
523 | 0 | error = FT_THROW( Missing_Module ); |
524 | 0 | goto Exit; |
525 | 0 | } |
526 | | |
527 | 5.86k | FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); |
528 | | |
529 | 5.86k | pshinter = (PSHinter_Service)FT_Get_Module_Interface( library, |
530 | 5.86k | "pshinter" ); |
531 | | |
532 | 5.86k | psaux = (PSAux_Service)FT_Get_Module_Interface( library, |
533 | 5.86k | "psaux" ); |
534 | 5.86k | if ( !psaux ) |
535 | 0 | { |
536 | 0 | FT_ERROR(( "cff_face_init: cannot access `psaux' module\n" )); |
537 | 0 | error = FT_THROW( Missing_Module ); |
538 | 0 | goto Exit; |
539 | 0 | } |
540 | 5.86k | face->psaux = psaux; |
541 | | |
542 | 5.86k | FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD ); |
543 | | |
544 | 5.86k | FT_TRACE2(( "CFF driver\n" )); |
545 | | |
546 | | /* create input stream from resource */ |
547 | 5.86k | if ( FT_STREAM_SEEK( 0 ) ) |
548 | 0 | goto Exit; |
549 | | |
550 | | /* check whether we have a valid OpenType file */ |
551 | 5.86k | FT_TRACE2(( " " )); |
552 | 5.86k | error = sfnt->init_face( stream, face, face_index, num_params, params ); |
553 | 5.86k | if ( !error ) |
554 | 3.87k | { |
555 | 3.87k | if ( face->format_tag != TTAG_OTTO ) /* `OTTO'; OpenType/CFF font */ |
556 | 0 | { |
557 | 0 | FT_TRACE2(( " not an OpenType/CFF font\n" )); |
558 | 0 | error = FT_THROW( Unknown_File_Format ); |
559 | 0 | goto Exit; |
560 | 0 | } |
561 | | |
562 | | /* if we are performing a simple font format check, exit immediately */ |
563 | 3.87k | if ( face_index < 0 ) |
564 | 0 | return FT_Err_Ok; |
565 | | |
566 | 3.87k | sfnt_format = 1; |
567 | | |
568 | | /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ |
569 | | /* font; in the latter case it doesn't have a `head' table */ |
570 | 3.87k | error = face->goto_table( face, TTAG_head, stream, 0 ); |
571 | 3.87k | if ( !error ) |
572 | 3.37k | { |
573 | 3.37k | pure_cff = 0; |
574 | | |
575 | | /* load font directory */ |
576 | 3.37k | error = sfnt->load_face( stream, face, face_index, |
577 | 3.37k | num_params, params ); |
578 | 3.37k | if ( error ) |
579 | 815 | goto Exit; |
580 | 496 | } |
581 | 496 | else |
582 | 496 | { |
583 | | /* load the `cmap' table explicitly */ |
584 | 496 | error = sfnt->load_cmap( face, stream ); |
585 | 496 | if ( error ) |
586 | 104 | goto Exit; |
587 | 2.95k | } |
588 | | |
589 | | /* now load the CFF part of the file; */ |
590 | | /* give priority to CFF2 */ |
591 | 2.95k | error = face->goto_table( face, TTAG_CFF2, stream, 0 ); |
592 | 2.95k | if ( !error ) |
593 | 0 | { |
594 | 0 | cff2 = 1; |
595 | 0 | face->is_cff2 = cff2; |
596 | 0 | } |
597 | | |
598 | 2.95k | if ( FT_ERR_EQ( error, Table_Missing ) ) |
599 | 2.95k | error = face->goto_table( face, TTAG_CFF, stream, 0 ); |
600 | | |
601 | 2.95k | if ( error ) |
602 | 19 | goto Exit; |
603 | 1.99k | } |
604 | 1.99k | else |
605 | 1.99k | { |
606 | | /* rewind to start of file; we are going to load a pure-CFF font */ |
607 | 1.99k | if ( FT_STREAM_SEEK( 0 ) ) |
608 | 0 | goto Exit; |
609 | 1.99k | error = FT_Err_Ok; |
610 | 1.99k | } |
611 | | |
612 | | /* now load and parse the CFF table in the file */ |
613 | 4.93k | { |
614 | 4.93k | CFF_Font cff = NULL; |
615 | 4.93k | CFF_FontRecDict dict; |
616 | 4.93k | FT_Memory memory = cffface->memory; |
617 | 4.93k | FT_Int32 flags; |
618 | 4.93k | FT_UInt i; |
619 | | |
620 | | |
621 | 4.93k | if ( FT_NEW( cff ) ) |
622 | 0 | goto Exit; |
623 | | |
624 | 4.93k | face->extra.data = cff; |
625 | 4.93k | error = cff_font_load( library, |
626 | 4.93k | stream, |
627 | 4.93k | face_index, |
628 | 4.93k | cff, |
629 | 4.93k | face, |
630 | 4.93k | pure_cff, |
631 | 4.93k | cff2 ); |
632 | 4.93k | if ( error ) |
633 | 3.11k | goto Exit; |
634 | | |
635 | | /* if we are performing a simple font format check, exit immediately */ |
636 | | /* (this is here for pure CFF) */ |
637 | 1.81k | if ( face_index < 0 ) |
638 | 0 | { |
639 | 0 | cffface->num_faces = (FT_Long)cff->num_faces; |
640 | 0 | return FT_Err_Ok; |
641 | 0 | } |
642 | | |
643 | 1.81k | cff->pshinter = pshinter; |
644 | 1.81k | cff->psnames = psnames; |
645 | 1.81k | cff->cffload = cffload; |
646 | | |
647 | 1.81k | cffface->face_index = face_index & 0xFFFF; |
648 | | |
649 | | /* Complement the root flags with some interesting information. */ |
650 | | /* Note that this is only necessary for pure CFF and CEF fonts; */ |
651 | | /* SFNT based fonts use the `name' table instead. */ |
652 | | |
653 | 1.81k | cffface->num_glyphs = (FT_Long)cff->num_glyphs; |
654 | | |
655 | 1.81k | dict = &cff->top_font.font_dict; |
656 | | |
657 | | /* we need the `psnames' module for CFF and CEF formats */ |
658 | | /* which aren't CID-keyed */ |
659 | 1.81k | if ( dict->cid_registry == 0xFFFFU && !psnames ) |
660 | 0 | { |
661 | 0 | FT_ERROR(( "cff_face_init:" |
662 | 0 | " cannot open CFF & CEF fonts\n" )); |
663 | 0 | FT_ERROR(( " " |
664 | 0 | " without the `psnames' module\n" )); |
665 | 0 | error = FT_THROW( Missing_Module ); |
666 | 0 | goto Exit; |
667 | 0 | } |
668 | | |
669 | | #ifdef FT_DEBUG_LEVEL_TRACE |
670 | | { |
671 | | FT_UInt idx; |
672 | | FT_String* s; |
673 | | |
674 | | |
675 | | FT_TRACE4(( "SIDs\n" )); |
676 | | |
677 | | /* dump string index, including default strings for convenience */ |
678 | | for ( idx = 0; idx <= 390; idx++ ) |
679 | | { |
680 | | s = cff_index_get_sid_string( cff, idx ); |
681 | | if ( s ) |
682 | | FT_TRACE4(( " %5d %s\n", idx, s )); |
683 | | } |
684 | | |
685 | | /* In Multiple Master CFFs, two SIDs hold the Normalize Design */ |
686 | | /* Vector (NDV) and Convert Design Vector (CDV) charstrings, */ |
687 | | /* which may contain NULL bytes in the middle of the data, too. */ |
688 | | /* We thus access `cff->strings' directly. */ |
689 | | for ( idx = 1; idx < cff->num_strings; idx++ ) |
690 | | { |
691 | | FT_Byte* s1 = cff->strings[idx - 1]; |
692 | | FT_Byte* s2 = cff->strings[idx]; |
693 | | FT_PtrDist s1len = s2 - s1 - 1; /* without the final NULL byte */ |
694 | | FT_PtrDist l; |
695 | | |
696 | | |
697 | | FT_TRACE4(( " %5d ", idx + 390 )); |
698 | | for ( l = 0; l < s1len; l++ ) |
699 | | FT_TRACE4(( "%c", s1[l] )); |
700 | | FT_TRACE4(( "\n" )); |
701 | | } |
702 | | |
703 | | /* print last element */ |
704 | | if ( cff->num_strings ) |
705 | | { |
706 | | FT_Byte* s1 = cff->strings[cff->num_strings - 1]; |
707 | | FT_Byte* s2 = cff->string_pool + cff->string_pool_size; |
708 | | FT_PtrDist s1len = s2 - s1 - 1; |
709 | | FT_PtrDist l; |
710 | | |
711 | | |
712 | | FT_TRACE4(( " %5d ", cff->num_strings + 390 )); |
713 | | for ( l = 0; l < s1len; l++ ) |
714 | | FT_TRACE4(( "%c", s1[l] )); |
715 | | FT_TRACE4(( "\n" )); |
716 | | } |
717 | | } |
718 | | #endif /* FT_DEBUG_LEVEL_TRACE */ |
719 | | |
720 | 1.81k | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
721 | 1.81k | { |
722 | 1.81k | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
723 | 1.81k | FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; |
724 | | |
725 | 1.81k | FT_UInt instance_index = (FT_UInt)face_index >> 16; |
726 | | |
727 | | |
728 | 1.81k | if ( FT_HAS_MULTIPLE_MASTERS( cffface ) && |
729 | 0 | mm && |
730 | 0 | instance_index > 0 ) |
731 | 0 | { |
732 | 0 | error = mm->set_instance( cffface, instance_index ); |
733 | 0 | if ( error ) |
734 | 0 | goto Exit; |
735 | | |
736 | 0 | if ( var ) |
737 | 0 | var->metrics_adjust( cffface ); |
738 | 0 | } |
739 | 1.81k | } |
740 | 1.81k | #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ |
741 | | |
742 | 1.81k | if ( !dict->has_font_matrix ) |
743 | 22 | dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM; |
744 | | |
745 | | /* Normalize the font matrix so that `matrix->yy' is 1; if */ |
746 | | /* it is zero, we use `matrix->yx' instead. The scaling is */ |
747 | | /* done with `units_per_em' then (at this point, it already */ |
748 | | /* contains the scaling factor, but without normalization */ |
749 | | /* of the matrix). */ |
750 | | /* */ |
751 | | /* Note that the offsets must be expressed in integer font */ |
752 | | /* units. */ |
753 | | |
754 | 1.81k | { |
755 | 1.81k | FT_Matrix* matrix = &dict->font_matrix; |
756 | 1.81k | FT_Vector* offset = &dict->font_offset; |
757 | 1.81k | FT_ULong* upm = &dict->units_per_em; |
758 | 1.81k | FT_Fixed temp; |
759 | | |
760 | | |
761 | 1.81k | temp = matrix->yy ? FT_ABS( matrix->yy ) |
762 | 1.81k | : FT_ABS( matrix->yx ); |
763 | | |
764 | 1.81k | if ( temp != 0x10000L ) |
765 | 1.71k | { |
766 | 1.71k | *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp ); |
767 | | |
768 | 1.71k | matrix->xx = FT_DivFix( matrix->xx, temp ); |
769 | 1.71k | matrix->yx = FT_DivFix( matrix->yx, temp ); |
770 | 1.71k | matrix->xy = FT_DivFix( matrix->xy, temp ); |
771 | 1.71k | matrix->yy = FT_DivFix( matrix->yy, temp ); |
772 | 1.71k | offset->x = FT_DivFix( offset->x, temp ); |
773 | 1.71k | offset->y = FT_DivFix( offset->y, temp ); |
774 | 1.71k | } |
775 | | |
776 | 1.81k | offset->x >>= 16; |
777 | 1.81k | offset->y >>= 16; |
778 | 1.81k | } |
779 | | |
780 | 1.81k | for ( i = cff->num_subfonts; i > 0; i-- ) |
781 | 0 | { |
782 | 0 | CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; |
783 | 0 | CFF_FontRecDict top = &cff->top_font.font_dict; |
784 | |
|
785 | 0 | FT_Matrix* matrix; |
786 | 0 | FT_Vector* offset; |
787 | 0 | FT_ULong* upm; |
788 | 0 | FT_Fixed temp; |
789 | | |
790 | |
|
791 | 0 | if ( sub->has_font_matrix ) |
792 | 0 | { |
793 | 0 | FT_Long scaling; |
794 | | |
795 | | |
796 | | /* if we have a top-level matrix, */ |
797 | | /* concatenate the subfont matrix */ |
798 | |
|
799 | 0 | if ( top->has_font_matrix ) |
800 | 0 | { |
801 | 0 | if ( top->units_per_em > 1 && sub->units_per_em > 1 ) |
802 | 0 | scaling = (FT_Long)FT_MIN( top->units_per_em, |
803 | 0 | sub->units_per_em ); |
804 | 0 | else |
805 | 0 | scaling = 1; |
806 | |
|
807 | 0 | FT_Matrix_Multiply_Scaled( &top->font_matrix, |
808 | 0 | &sub->font_matrix, |
809 | 0 | scaling ); |
810 | 0 | FT_Vector_Transform_Scaled( &sub->font_offset, |
811 | 0 | &top->font_matrix, |
812 | 0 | scaling ); |
813 | |
|
814 | 0 | sub->units_per_em = (FT_ULong) |
815 | 0 | FT_MulDiv( (FT_Long)sub->units_per_em, |
816 | 0 | (FT_Long)top->units_per_em, |
817 | 0 | scaling ); |
818 | 0 | } |
819 | 0 | } |
820 | 0 | else |
821 | 0 | { |
822 | 0 | sub->font_matrix = top->font_matrix; |
823 | 0 | sub->font_offset = top->font_offset; |
824 | |
|
825 | 0 | sub->units_per_em = top->units_per_em; |
826 | 0 | } |
827 | |
|
828 | 0 | matrix = &sub->font_matrix; |
829 | 0 | offset = &sub->font_offset; |
830 | 0 | upm = &sub->units_per_em; |
831 | |
|
832 | 0 | temp = matrix->yy ? FT_ABS( matrix->yy ) |
833 | 0 | : FT_ABS( matrix->yx ); |
834 | | |
835 | |
|
836 | 0 | if ( temp != 0x10000L ) |
837 | 0 | { |
838 | 0 | *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp ); |
839 | |
|
840 | 0 | matrix->xx = FT_DivFix( matrix->xx, temp ); |
841 | 0 | matrix->yx = FT_DivFix( matrix->yx, temp ); |
842 | 0 | matrix->xy = FT_DivFix( matrix->xy, temp ); |
843 | 0 | matrix->yy = FT_DivFix( matrix->yy, temp ); |
844 | 0 | offset->x = FT_DivFix( offset->x, temp ); |
845 | 0 | offset->y = FT_DivFix( offset->y, temp ); |
846 | 0 | } |
847 | |
|
848 | 0 | offset->x >>= 16; |
849 | 0 | offset->y >>= 16; |
850 | 0 | } |
851 | | |
852 | 1.81k | if ( pure_cff ) |
853 | 277 | { |
854 | 277 | char* style_name = NULL; |
855 | | |
856 | | |
857 | | /* set up num_faces */ |
858 | 277 | cffface->num_faces = (FT_Long)cff->num_faces; |
859 | | |
860 | | /* compute number of glyphs */ |
861 | 277 | if ( dict->cid_registry != 0xFFFFU ) |
862 | 0 | cffface->num_glyphs = (FT_Long)( cff->charset.max_cid + 1 ); |
863 | 277 | else |
864 | 277 | cffface->num_glyphs = (FT_Long)cff->charstrings_index.count; |
865 | | |
866 | | /* set global bbox, as well as EM size */ |
867 | 277 | cffface->bbox.xMin = dict->font_bbox.xMin >> 16; |
868 | 277 | cffface->bbox.yMin = dict->font_bbox.yMin >> 16; |
869 | | /* no `U' suffix here to 0xFFFF! */ |
870 | 277 | cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16; |
871 | 277 | cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16; |
872 | | |
873 | 277 | cffface->units_per_EM = (FT_UShort)( dict->units_per_em ); |
874 | | |
875 | 277 | cffface->ascender = (FT_Short)( cffface->bbox.yMax ); |
876 | 277 | cffface->descender = (FT_Short)( cffface->bbox.yMin ); |
877 | | |
878 | 277 | cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); |
879 | 277 | if ( cffface->height < cffface->ascender - cffface->descender ) |
880 | 6 | cffface->height = (FT_Short)( cffface->ascender - |
881 | 6 | cffface->descender ); |
882 | | |
883 | 277 | cffface->underline_position = |
884 | 277 | (FT_Short)( dict->underline_position >> 16 ); |
885 | 277 | cffface->underline_thickness = |
886 | 277 | (FT_Short)( dict->underline_thickness >> 16 ); |
887 | | |
888 | | /* retrieve font family & style name */ |
889 | 277 | if ( dict->family_name ) |
890 | 277 | { |
891 | 277 | char* family_name; |
892 | | |
893 | | |
894 | 277 | family_name = cff_index_get_sid_string( cff, dict->family_name ); |
895 | 277 | if ( family_name ) |
896 | 277 | cffface->family_name = cff_strcpy( memory, family_name ); |
897 | 277 | } |
898 | | |
899 | 277 | if ( !cffface->family_name ) |
900 | 0 | { |
901 | 0 | cffface->family_name = cff_index_get_name( |
902 | 0 | cff, |
903 | 0 | (FT_UInt)( face_index & 0xFFFF ) ); |
904 | 0 | if ( cffface->family_name ) |
905 | 0 | remove_subset_prefix( cffface->family_name ); |
906 | 0 | } |
907 | | |
908 | 277 | if ( cffface->family_name ) |
909 | 277 | { |
910 | 277 | char* full = cff_index_get_sid_string( cff, |
911 | 277 | dict->full_name ); |
912 | 277 | char* fullp = full; |
913 | 277 | char* family = cffface->family_name; |
914 | | |
915 | | |
916 | | /* We try to extract the style name from the full name. */ |
917 | | /* We need to ignore spaces and dashes during the search. */ |
918 | 277 | if ( full && family ) |
919 | 277 | { |
920 | 1.88k | while ( *fullp ) |
921 | 1.80k | { |
922 | | /* skip common characters at the start of both strings */ |
923 | 1.80k | if ( *fullp == *family ) |
924 | 1.46k | { |
925 | 1.46k | family++; |
926 | 1.46k | fullp++; |
927 | 1.46k | continue; |
928 | 1.46k | } |
929 | | |
930 | | /* ignore spaces and dashes in full name during comparison */ |
931 | 347 | if ( *fullp == ' ' || *fullp == '-' ) |
932 | 147 | { |
933 | 147 | fullp++; |
934 | 147 | continue; |
935 | 147 | } |
936 | | |
937 | | /* ignore spaces and dashes in family name during comparison */ |
938 | 200 | if ( *family == ' ' || *family == '-' ) |
939 | 3 | { |
940 | 3 | family++; |
941 | 3 | continue; |
942 | 3 | } |
943 | | |
944 | 197 | if ( !*family && *fullp ) |
945 | 178 | { |
946 | | /* The full name begins with the same characters as the */ |
947 | | /* family name, with spaces and dashes removed. In this */ |
948 | | /* case, the remaining string in `fullp' will be used as */ |
949 | | /* the style name. */ |
950 | 178 | style_name = cff_strcpy( memory, fullp ); |
951 | | |
952 | | /* remove the style part from the family name (if present) */ |
953 | 178 | if ( style_name ) |
954 | 178 | remove_style( cffface->family_name, style_name ); |
955 | 178 | } |
956 | 197 | break; |
957 | 197 | } |
958 | 277 | } |
959 | 277 | } |
960 | 0 | else |
961 | 0 | { |
962 | 0 | char *cid_font_name = |
963 | 0 | cff_index_get_sid_string( cff, |
964 | 0 | dict->cid_font_name ); |
965 | | |
966 | | |
967 | | /* do we have a `/FontName' for a CID-keyed font? */ |
968 | 0 | if ( cid_font_name ) |
969 | 0 | cffface->family_name = cff_strcpy( memory, cid_font_name ); |
970 | 0 | } |
971 | | |
972 | 277 | if ( style_name ) |
973 | 178 | cffface->style_name = style_name; |
974 | 99 | else |
975 | | /* assume "Regular" style if we don't know better */ |
976 | 99 | cffface->style_name = cff_strcpy( memory, "Regular" ); |
977 | | |
978 | | /******************************************************************** |
979 | | * |
980 | | * Compute face flags. |
981 | | */ |
982 | 277 | flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ |
983 | 277 | FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ |
984 | 277 | FT_FACE_FLAG_HINTER; /* has native hinter */ |
985 | | |
986 | 277 | if ( sfnt_format ) |
987 | 277 | flags |= FT_FACE_FLAG_SFNT; |
988 | | |
989 | | /* fixed width font? */ |
990 | 277 | if ( dict->is_fixed_pitch ) |
991 | 0 | flags |= FT_FACE_FLAG_FIXED_WIDTH; |
992 | | |
993 | | /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ |
994 | | #if 0 |
995 | | /* kerning available? */ |
996 | | if ( face->kern_pairs ) |
997 | | flags |= FT_FACE_FLAG_KERNING; |
998 | | #endif |
999 | | |
1000 | 277 | cffface->face_flags |= flags; |
1001 | | |
1002 | | /******************************************************************** |
1003 | | * |
1004 | | * Compute style flags. |
1005 | | */ |
1006 | 277 | flags = 0; |
1007 | | |
1008 | 277 | if ( dict->italic_angle ) |
1009 | 0 | flags |= FT_STYLE_FLAG_ITALIC; |
1010 | | |
1011 | 277 | { |
1012 | 277 | char *weight = cff_index_get_sid_string( cff, |
1013 | 277 | dict->weight ); |
1014 | | |
1015 | | |
1016 | 277 | if ( weight ) |
1017 | 271 | if ( !ft_strcmp( weight, "Bold" ) || |
1018 | 271 | !ft_strcmp( weight, "Black" ) ) |
1019 | 0 | flags |= FT_STYLE_FLAG_BOLD; |
1020 | 277 | } |
1021 | | |
1022 | | /* double check */ |
1023 | 277 | if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name ) |
1024 | 277 | if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) || |
1025 | 277 | !ft_strncmp( cffface->style_name, "Black", 5 ) ) |
1026 | 0 | flags |= FT_STYLE_FLAG_BOLD; |
1027 | | |
1028 | 277 | cffface->style_flags = flags; |
1029 | 277 | } |
1030 | | |
1031 | 1.81k | #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES |
1032 | | /* CID-keyed CFF or CFF2 fonts don't have glyph names -- the SFNT */ |
1033 | | /* loader has unset this flag because of the 3.0 `post' table. */ |
1034 | 1.81k | if ( dict->cid_registry == 0xFFFFU && !cff2 ) |
1035 | 1.81k | cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; |
1036 | 1.81k | #endif |
1037 | | |
1038 | 1.81k | if ( dict->cid_registry != 0xFFFFU && pure_cff ) |
1039 | 0 | cffface->face_flags |= FT_FACE_FLAG_CID_KEYED; |
1040 | | |
1041 | | /******************************************************************** |
1042 | | * |
1043 | | * Compute char maps. |
1044 | | */ |
1045 | | |
1046 | | /* Try to synthesize a Unicode charmap if there is none available */ |
1047 | | /* already. If an OpenType font contains a Unicode "cmap", we */ |
1048 | | /* will use it, whatever be in the CFF part of the file. */ |
1049 | 1.81k | { |
1050 | 1.81k | FT_CharMapRec cmaprec; |
1051 | 1.81k | FT_CharMap cmap; |
1052 | 1.81k | FT_UInt nn; |
1053 | 1.81k | CFF_Encoding encoding = &cff->encoding; |
1054 | | |
1055 | | |
1056 | 1.88k | for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) |
1057 | 123 | { |
1058 | 123 | cmap = cffface->charmaps[nn]; |
1059 | | |
1060 | | /* Windows Unicode? */ |
1061 | 123 | if ( cmap->platform_id == TT_PLATFORM_MICROSOFT && |
1062 | 13 | cmap->encoding_id == TT_MS_ID_UNICODE_CS ) |
1063 | 13 | goto Skip_Unicode; |
1064 | | |
1065 | | /* Apple Unicode platform id? */ |
1066 | 110 | if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE ) |
1067 | 40 | goto Skip_Unicode; /* Apple Unicode */ |
1068 | 110 | } |
1069 | | |
1070 | | /* since CID-keyed fonts don't contain glyph names, we can't */ |
1071 | | /* construct a cmap */ |
1072 | 1.76k | if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) |
1073 | 0 | goto Exit; |
1074 | | |
1075 | | /* we didn't find a Unicode charmap -- synthesize one */ |
1076 | 1.76k | cmaprec.face = cffface; |
1077 | 1.76k | cmaprec.platform_id = TT_PLATFORM_MICROSOFT; |
1078 | 1.76k | cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; |
1079 | 1.76k | cmaprec.encoding = FT_ENCODING_UNICODE; |
1080 | | |
1081 | 1.76k | nn = (FT_UInt)cffface->num_charmaps; |
1082 | | |
1083 | 1.76k | error = FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, |
1084 | 1.76k | &cmaprec, NULL ); |
1085 | 1.76k | if ( error && |
1086 | 1.76k | FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) && |
1087 | 1.76k | FT_ERR_NEQ( error, Unimplemented_Feature ) ) |
1088 | 0 | goto Exit; |
1089 | 1.76k | error = FT_Err_Ok; |
1090 | | |
1091 | | /* if no Unicode charmap was previously selected, select this one */ |
1092 | 1.76k | if ( !cffface->charmap && nn != (FT_UInt)cffface->num_charmaps ) |
1093 | 1.30k | cffface->charmap = cffface->charmaps[nn]; |
1094 | | |
1095 | 1.81k | Skip_Unicode: |
1096 | 1.81k | if ( encoding->count > 0 ) |
1097 | 1.27k | { |
1098 | 1.27k | FT_CMap_Class clazz; |
1099 | | |
1100 | | |
1101 | 1.27k | cmaprec.face = cffface; |
1102 | 1.27k | cmaprec.platform_id = TT_PLATFORM_ADOBE; /* Adobe platform id */ |
1103 | | |
1104 | 1.27k | if ( encoding->offset == 0 ) |
1105 | 1.27k | { |
1106 | 1.27k | cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; |
1107 | 1.27k | cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; |
1108 | 1.27k | clazz = &cff_cmap_encoding_class_rec; |
1109 | 1.27k | } |
1110 | 0 | else if ( encoding->offset == 1 ) |
1111 | 0 | { |
1112 | 0 | cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; |
1113 | 0 | cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; |
1114 | 0 | clazz = &cff_cmap_encoding_class_rec; |
1115 | 0 | } |
1116 | 0 | else |
1117 | 0 | { |
1118 | 0 | cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; |
1119 | 0 | cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; |
1120 | 0 | clazz = &cff_cmap_encoding_class_rec; |
1121 | 0 | } |
1122 | | |
1123 | 1.27k | error = FT_CMap_New( clazz, NULL, &cmaprec, NULL ); |
1124 | 1.27k | } |
1125 | 1.81k | } |
1126 | 1.81k | } |
1127 | | |
1128 | 5.86k | Exit: |
1129 | 5.86k | return error; |
1130 | 1.81k | } |
1131 | | |
1132 | | |
1133 | | FT_LOCAL_DEF( void ) |
1134 | | cff_face_done( FT_Face cffface ) /* CFF_Face */ |
1135 | 5.86k | { |
1136 | 5.86k | CFF_Face face = (CFF_Face)cffface; |
1137 | 5.86k | FT_Memory memory; |
1138 | 5.86k | SFNT_Service sfnt; |
1139 | | |
1140 | | |
1141 | 5.86k | if ( !face ) |
1142 | 0 | return; |
1143 | | |
1144 | 5.86k | memory = cffface->memory; |
1145 | 5.86k | sfnt = (SFNT_Service)face->sfnt; |
1146 | | |
1147 | 5.86k | if ( sfnt ) |
1148 | 5.86k | sfnt->done_face( face ); |
1149 | | |
1150 | 5.86k | { |
1151 | 5.86k | CFF_Font cff = (CFF_Font)face->extra.data; |
1152 | | |
1153 | | |
1154 | 5.86k | if ( cff ) |
1155 | 4.93k | { |
1156 | 4.93k | cff_font_done( cff ); |
1157 | 4.93k | FT_FREE( face->extra.data ); |
1158 | 4.93k | } |
1159 | 5.86k | } |
1160 | | |
1161 | 5.86k | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
1162 | 5.86k | cff_done_blend( face ); |
1163 | 5.86k | face->blend = NULL; |
1164 | 5.86k | #endif |
1165 | 5.86k | } |
1166 | | |
1167 | | |
1168 | | FT_LOCAL_DEF( FT_Error ) |
1169 | | cff_driver_init( FT_Module module ) /* CFF_Driver */ |
1170 | 5 | { |
1171 | 5 | PS_Driver driver = (PS_Driver)module; |
1172 | | |
1173 | 5 | FT_UInt32 seed; |
1174 | | |
1175 | | |
1176 | | /* set default property values, cf. `ftcffdrv.h' */ |
1177 | 5 | driver->hinting_engine = FT_HINTING_ADOBE; |
1178 | | |
1179 | 5 | driver->no_stem_darkening = TRUE; |
1180 | | |
1181 | 5 | driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; |
1182 | 5 | driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; |
1183 | 5 | driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; |
1184 | 5 | driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; |
1185 | 5 | driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; |
1186 | 5 | driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; |
1187 | 5 | driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; |
1188 | 5 | driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; |
1189 | | |
1190 | | /* compute random seed from some memory addresses */ |
1191 | 5 | seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ |
1192 | 5 | (FT_Offset)(char*)&module ^ |
1193 | 5 | (FT_Offset)(char*)module->memory ); |
1194 | 5 | seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); |
1195 | | |
1196 | 5 | driver->random_seed = (FT_Int32)seed; |
1197 | 5 | if ( driver->random_seed < 0 ) |
1198 | 0 | driver->random_seed = -driver->random_seed; |
1199 | 5 | else if ( driver->random_seed == 0 ) |
1200 | 0 | driver->random_seed = 123456789; |
1201 | | |
1202 | 5 | return FT_Err_Ok; |
1203 | 5 | } |
1204 | | |
1205 | | |
1206 | | FT_LOCAL_DEF( void ) |
1207 | | cff_driver_done( FT_Module module ) /* CFF_Driver */ |
1208 | 5 | { |
1209 | 5 | FT_UNUSED( module ); |
1210 | 5 | } |
1211 | | |
1212 | | |
1213 | | /* END */ |