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