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