1 | /**************************************************************************** |
2 | * |
3 | * cffdrivr.c |
4 | * |
5 | * OpenType font driver implementation (body). |
6 | * |
7 | * Copyright (C) 1996-2019 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 | #include FT_FREETYPE_H |
21 | #include FT_INTERNAL_DEBUG_H |
22 | #include FT_INTERNAL_STREAM_H |
23 | #include FT_INTERNAL_SFNT_H |
24 | #include FT_INTERNAL_POSTSCRIPT_AUX_H |
25 | #include FT_INTERNAL_POSTSCRIPT_PROPS_H |
26 | #include FT_SERVICE_CID_H |
27 | #include FT_SERVICE_POSTSCRIPT_INFO_H |
28 | #include FT_SERVICE_POSTSCRIPT_NAME_H |
29 | #include FT_SERVICE_TT_CMAP_H |
30 | #include FT_SERVICE_CFF_TABLE_LOAD_H |
31 | |
32 | #include "cffdrivr.h" |
33 | #include "cffgload.h" |
34 | #include "cffload.h" |
35 | #include "cffcmap.h" |
36 | #include "cffparse.h" |
37 | #include "cffobjs.h" |
38 | |
39 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
40 | #include FT_SERVICE_MULTIPLE_MASTERS_H |
41 | #include FT_SERVICE_METRICS_VARIATIONS_H |
42 | #endif |
43 | |
44 | #include "cfferrs.h" |
45 | |
46 | #include FT_SERVICE_FONT_FORMAT_H |
47 | #include FT_SERVICE_GLYPH_DICT_H |
48 | #include FT_SERVICE_PROPERTIES_H |
49 | #include FT_DRIVER_H |
50 | |
51 | |
52 | /************************************************************************** |
53 | * |
54 | * The macro FT_COMPONENT is used in trace mode. It is an implicit |
55 | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
56 | * messages during execution. |
57 | */ |
58 | #undef FT_COMPONENT |
59 | #define FT_COMPONENT cffdriver |
60 | |
61 | |
62 | /*************************************************************************/ |
63 | /*************************************************************************/ |
64 | /*************************************************************************/ |
65 | /**** ****/ |
66 | /**** ****/ |
67 | /**** F A C E S ****/ |
68 | /**** ****/ |
69 | /**** ****/ |
70 | /*************************************************************************/ |
71 | /*************************************************************************/ |
72 | /*************************************************************************/ |
73 | |
74 | |
75 | /************************************************************************** |
76 | * |
77 | * @Function: |
78 | * cff_get_kerning |
79 | * |
80 | * @Description: |
81 | * A driver method used to return the kerning vector between two |
82 | * glyphs of the same face. |
83 | * |
84 | * @Input: |
85 | * face :: |
86 | * A handle to the source face object. |
87 | * |
88 | * left_glyph :: |
89 | * The index of the left glyph in the kern pair. |
90 | * |
91 | * right_glyph :: |
92 | * The index of the right glyph in the kern pair. |
93 | * |
94 | * @Output: |
95 | * kerning :: |
96 | * The kerning vector. This is in font units for |
97 | * scalable formats, and in pixels for fixed-sizes |
98 | * formats. |
99 | * |
100 | * @Return: |
101 | * FreeType error code. 0 means success. |
102 | * |
103 | * @Note: |
104 | * Only horizontal layouts (left-to-right & right-to-left) are |
105 | * supported by this function. Other layouts, or more sophisticated |
106 | * kernings, are out of scope of this method (the basic driver |
107 | * interface is meant to be simple). |
108 | * |
109 | * They can be implemented by format-specific interfaces. |
110 | */ |
111 | FT_CALLBACK_DEF( FT_Error ) |
112 | cff_get_kerning( FT_Face ttface, /* TT_Face */ |
113 | FT_UInt left_glyph, |
114 | FT_UInt right_glyph, |
115 | FT_Vector* kerning ) |
116 | { |
117 | TT_Face face = (TT_Face)ttface; |
118 | SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
119 | |
120 | |
121 | kerning->x = 0; |
122 | kerning->y = 0; |
123 | |
124 | if ( sfnt ) |
125 | kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph ); |
126 | |
127 | return FT_Err_Ok; |
128 | } |
129 | |
130 | |
131 | /************************************************************************** |
132 | * |
133 | * @Function: |
134 | * cff_glyph_load |
135 | * |
136 | * @Description: |
137 | * A driver method used to load a glyph within a given glyph slot. |
138 | * |
139 | * @Input: |
140 | * slot :: |
141 | * A handle to the target slot object where the glyph |
142 | * will be loaded. |
143 | * |
144 | * size :: |
145 | * A handle to the source face size at which the glyph |
146 | * must be scaled, loaded, etc. |
147 | * |
148 | * glyph_index :: |
149 | * The index of the glyph in the font file. |
150 | * |
151 | * load_flags :: |
152 | * A flag indicating what to load for this glyph. The |
153 | * FT_LOAD_??? constants can be used to control the |
154 | * glyph loading process (e.g., whether the outline |
155 | * should be scaled, whether to load bitmaps or not, |
156 | * whether to hint the outline, etc). |
157 | * |
158 | * @Return: |
159 | * FreeType error code. 0 means success. |
160 | */ |
161 | FT_CALLBACK_DEF( FT_Error ) |
162 | cff_glyph_load( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */ |
163 | FT_Size cffsize, /* CFF_Size */ |
164 | FT_UInt glyph_index, |
165 | FT_Int32 load_flags ) |
166 | { |
167 | FT_Error error; |
168 | CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot; |
169 | CFF_Size size = (CFF_Size)cffsize; |
170 | |
171 | |
172 | if ( !slot ) |
173 | return FT_THROW( Invalid_Slot_Handle ); |
174 | |
175 | FT_TRACE1(( "cff_glyph_load: glyph index %d\n" , glyph_index )); |
176 | |
177 | /* check whether we want a scaled outline or bitmap */ |
178 | if ( !size ) |
179 | load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; |
180 | |
181 | /* reset the size object if necessary */ |
182 | if ( load_flags & FT_LOAD_NO_SCALE ) |
183 | size = NULL; |
184 | |
185 | if ( size ) |
186 | { |
187 | /* these two objects must have the same parent */ |
188 | if ( cffsize->face != cffslot->face ) |
189 | return FT_THROW( Invalid_Face_Handle ); |
190 | } |
191 | |
192 | /* now load the glyph outline if necessary */ |
193 | error = cff_slot_load( slot, size, glyph_index, load_flags ); |
194 | |
195 | /* force drop-out mode to 2 - irrelevant now */ |
196 | /* slot->outline.dropout_mode = 2; */ |
197 | |
198 | return error; |
199 | } |
200 | |
201 | |
202 | FT_CALLBACK_DEF( FT_Error ) |
203 | cff_get_advances( FT_Face face, |
204 | FT_UInt start, |
205 | FT_UInt count, |
206 | FT_Int32 flags, |
207 | FT_Fixed* advances ) |
208 | { |
209 | FT_UInt nn; |
210 | FT_Error error = FT_Err_Ok; |
211 | FT_GlyphSlot slot = face->glyph; |
212 | |
213 | |
214 | if ( FT_IS_SFNT( face ) ) |
215 | { |
216 | /* OpenType 1.7 mandates that the data from `hmtx' table be used; */ |
217 | /* it is no longer necessary that those values are identical to */ |
218 | /* the values in the `CFF' table */ |
219 | |
220 | TT_Face ttface = (TT_Face)face; |
221 | FT_Short dummy; |
222 | |
223 | |
224 | if ( flags & FT_LOAD_VERTICAL_LAYOUT ) |
225 | { |
226 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
227 | /* no fast retrieval for blended MM fonts without VVAR table */ |
228 | if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && |
229 | !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) |
230 | return FT_THROW( Unimplemented_Feature ); |
231 | #endif |
232 | |
233 | /* check whether we have data from the `vmtx' table at all; */ |
234 | /* otherwise we extract the info from the CFF glyphstrings */ |
235 | /* (instead of synthesizing a global value using the `OS/2' */ |
236 | /* table) */ |
237 | if ( !ttface->vertical_info ) |
238 | goto Missing_Table; |
239 | |
240 | for ( nn = 0; nn < count; nn++ ) |
241 | { |
242 | FT_UShort ah; |
243 | |
244 | |
245 | ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, |
246 | 1, |
247 | start + nn, |
248 | &dummy, |
249 | &ah ); |
250 | |
251 | FT_TRACE5(( " idx %d: advance height %d font unit%s\n" , |
252 | start + nn, |
253 | ah, |
254 | ah == 1 ? "" : "s" )); |
255 | advances[nn] = ah; |
256 | } |
257 | } |
258 | else |
259 | { |
260 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
261 | /* no fast retrieval for blended MM fonts without HVAR table */ |
262 | if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && |
263 | !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) |
264 | return FT_THROW( Unimplemented_Feature ); |
265 | #endif |
266 | |
267 | /* check whether we have data from the `hmtx' table at all */ |
268 | if ( !ttface->horizontal.number_Of_HMetrics ) |
269 | goto Missing_Table; |
270 | |
271 | for ( nn = 0; nn < count; nn++ ) |
272 | { |
273 | FT_UShort aw; |
274 | |
275 | |
276 | ( (SFNT_Service)ttface->sfnt )->get_metrics( ttface, |
277 | 0, |
278 | start + nn, |
279 | &dummy, |
280 | &aw ); |
281 | |
282 | FT_TRACE5(( " idx %d: advance width %d font unit%s\n" , |
283 | start + nn, |
284 | aw, |
285 | aw == 1 ? "" : "s" )); |
286 | advances[nn] = aw; |
287 | } |
288 | } |
289 | |
290 | return error; |
291 | } |
292 | |
293 | Missing_Table: |
294 | flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY; |
295 | |
296 | for ( nn = 0; nn < count; nn++ ) |
297 | { |
298 | error = cff_glyph_load( slot, face->size, start + nn, flags ); |
299 | if ( error ) |
300 | break; |
301 | |
302 | advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT ) |
303 | ? slot->linearVertAdvance |
304 | : slot->linearHoriAdvance; |
305 | } |
306 | |
307 | return error; |
308 | } |
309 | |
310 | |
311 | /* |
312 | * GLYPH DICT SERVICE |
313 | * |
314 | */ |
315 | |
316 | static FT_Error |
317 | cff_get_glyph_name( CFF_Face face, |
318 | FT_UInt glyph_index, |
319 | FT_Pointer buffer, |
320 | FT_UInt buffer_max ) |
321 | { |
322 | CFF_Font font = (CFF_Font)face->extra.data; |
323 | FT_String* gname; |
324 | FT_UShort sid; |
325 | FT_Error error; |
326 | |
327 | |
328 | /* CFF2 table does not have glyph names; */ |
329 | /* we need to use `post' table method */ |
330 | if ( font->version_major == 2 ) |
331 | { |
332 | FT_Library library = FT_FACE_LIBRARY( face ); |
333 | FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); |
334 | FT_Service_GlyphDict service = |
335 | (FT_Service_GlyphDict)ft_module_get_service( |
336 | sfnt_module, |
337 | FT_SERVICE_ID_GLYPH_DICT, |
338 | 0 ); |
339 | |
340 | |
341 | if ( service && service->get_name ) |
342 | return service->get_name( FT_FACE( face ), |
343 | glyph_index, |
344 | buffer, |
345 | buffer_max ); |
346 | else |
347 | { |
348 | FT_ERROR(( "cff_get_glyph_name:" |
349 | " cannot get glyph name from a CFF2 font\n" |
350 | " " |
351 | " without the `psnames' module\n" )); |
352 | error = FT_THROW( Missing_Module ); |
353 | goto Exit; |
354 | } |
355 | } |
356 | |
357 | if ( !font->psnames ) |
358 | { |
359 | FT_ERROR(( "cff_get_glyph_name:" |
360 | " cannot get glyph name from CFF & CEF fonts\n" |
361 | " " |
362 | " without the `psnames' module\n" )); |
363 | error = FT_THROW( Missing_Module ); |
364 | goto Exit; |
365 | } |
366 | |
367 | /* first, locate the sid in the charset table */ |
368 | sid = font->charset.sids[glyph_index]; |
369 | |
370 | /* now, lookup the name itself */ |
371 | gname = cff_index_get_sid_string( font, sid ); |
372 | |
373 | if ( gname ) |
374 | FT_STRCPYN( buffer, gname, buffer_max ); |
375 | |
376 | error = FT_Err_Ok; |
377 | |
378 | Exit: |
379 | return error; |
380 | } |
381 | |
382 | |
383 | static FT_UInt |
384 | cff_get_name_index( CFF_Face face, |
385 | FT_String* glyph_name ) |
386 | { |
387 | CFF_Font cff; |
388 | CFF_Charset charset; |
389 | FT_Service_PsCMaps psnames; |
390 | FT_String* name; |
391 | FT_UShort sid; |
392 | FT_UInt i; |
393 | |
394 | |
395 | cff = (CFF_FontRec *)face->extra.data; |
396 | charset = &cff->charset; |
397 | |
398 | /* CFF2 table does not have glyph names; */ |
399 | /* we need to use `post' table method */ |
400 | if ( cff->version_major == 2 ) |
401 | { |
402 | FT_Library library = FT_FACE_LIBRARY( face ); |
403 | FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); |
404 | FT_Service_GlyphDict service = |
405 | (FT_Service_GlyphDict)ft_module_get_service( |
406 | sfnt_module, |
407 | FT_SERVICE_ID_GLYPH_DICT, |
408 | 0 ); |
409 | |
410 | |
411 | if ( service && service->name_index ) |
412 | return service->name_index( FT_FACE( face ), glyph_name ); |
413 | else |
414 | { |
415 | FT_ERROR(( "cff_get_name_index:" |
416 | " cannot get glyph index from a CFF2 font\n" |
417 | " " |
418 | " without the `psnames' module\n" )); |
419 | return 0; |
420 | } |
421 | } |
422 | |
423 | FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); |
424 | if ( !psnames ) |
425 | return 0; |
426 | |
427 | for ( i = 0; i < cff->num_glyphs; i++ ) |
428 | { |
429 | sid = charset->sids[i]; |
430 | |
431 | if ( sid > 390 ) |
432 | name = cff_index_get_string( cff, sid - 391 ); |
433 | else |
434 | name = (FT_String *)psnames->adobe_std_strings( sid ); |
435 | |
436 | if ( !name ) |
437 | continue; |
438 | |
439 | if ( !ft_strcmp( glyph_name, name ) ) |
440 | return i; |
441 | } |
442 | |
443 | return 0; |
444 | } |
445 | |
446 | |
447 | FT_DEFINE_SERVICE_GLYPHDICTREC( |
448 | cff_service_glyph_dict, |
449 | |
450 | (FT_GlyphDict_GetNameFunc) cff_get_glyph_name, /* get_name */ |
451 | (FT_GlyphDict_NameIndexFunc)cff_get_name_index /* name_index */ |
452 | ) |
453 | |
454 | |
455 | /* |
456 | * POSTSCRIPT INFO SERVICE |
457 | * |
458 | */ |
459 | |
460 | static FT_Int |
461 | cff_ps_has_glyph_names( FT_Face face ) |
462 | { |
463 | return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0; |
464 | } |
465 | |
466 | |
467 | static FT_Error |
468 | cff_ps_get_font_info( CFF_Face face, |
469 | PS_FontInfoRec* afont_info ) |
470 | { |
471 | CFF_Font cff = (CFF_Font)face->extra.data; |
472 | FT_Error error = FT_Err_Ok; |
473 | |
474 | |
475 | if ( cff && !cff->font_info ) |
476 | { |
477 | CFF_FontRecDict dict = &cff->top_font.font_dict; |
478 | PS_FontInfoRec *font_info = NULL; |
479 | FT_Memory memory = face->root.memory; |
480 | |
481 | |
482 | if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) ) |
483 | goto Fail; |
484 | |
485 | font_info->version = cff_index_get_sid_string( cff, |
486 | dict->version ); |
487 | font_info->notice = cff_index_get_sid_string( cff, |
488 | dict->notice ); |
489 | font_info->full_name = cff_index_get_sid_string( cff, |
490 | dict->full_name ); |
491 | font_info->family_name = cff_index_get_sid_string( cff, |
492 | dict->family_name ); |
493 | font_info->weight = cff_index_get_sid_string( cff, |
494 | dict->weight ); |
495 | font_info->italic_angle = dict->italic_angle; |
496 | font_info->is_fixed_pitch = dict->is_fixed_pitch; |
497 | font_info->underline_position = (FT_Short)dict->underline_position; |
498 | font_info->underline_thickness = (FT_UShort)dict->underline_thickness; |
499 | |
500 | cff->font_info = font_info; |
501 | } |
502 | |
503 | if ( cff ) |
504 | *afont_info = *cff->font_info; |
505 | |
506 | Fail: |
507 | return error; |
508 | } |
509 | |
510 | |
511 | static FT_Error |
512 | ( CFF_Face face, |
513 | PS_FontExtraRec* ) |
514 | { |
515 | CFF_Font cff = (CFF_Font)face->extra.data; |
516 | FT_Error error = FT_Err_Ok; |
517 | |
518 | |
519 | if ( cff && cff->font_extra == NULL ) |
520 | { |
521 | CFF_FontRecDict dict = &cff->top_font.font_dict; |
522 | PS_FontExtraRec* = NULL; |
523 | FT_Memory memory = face->root.memory; |
524 | FT_String* embedded_postscript; |
525 | |
526 | |
527 | if ( FT_ALLOC( font_extra, sizeof ( *font_extra ) ) ) |
528 | goto Fail; |
529 | |
530 | font_extra->fs_type = 0U; |
531 | |
532 | embedded_postscript = cff_index_get_sid_string( |
533 | cff, |
534 | dict->embedded_postscript ); |
535 | if ( embedded_postscript ) |
536 | { |
537 | FT_String* start_fstype; |
538 | FT_String* start_def; |
539 | |
540 | |
541 | /* Identify the XYZ integer in `/FSType XYZ def' substring. */ |
542 | if ( ( start_fstype = ft_strstr( embedded_postscript, |
543 | "/FSType" ) ) != NULL && |
544 | ( start_def = ft_strstr( start_fstype + |
545 | sizeof ( "/FSType" ) - 1, |
546 | "def" ) ) != NULL ) |
547 | { |
548 | FT_String* s; |
549 | |
550 | |
551 | for ( s = start_fstype + sizeof ( "/FSType" ) - 1; |
552 | s != start_def; |
553 | s++ ) |
554 | { |
555 | if ( *s >= '0' && *s <= '9' ) |
556 | { |
557 | if ( font_extra->fs_type >= ( FT_USHORT_MAX - 9 ) / 10 ) |
558 | { |
559 | /* Overflow - ignore the FSType value. */ |
560 | font_extra->fs_type = 0U; |
561 | break; |
562 | } |
563 | |
564 | font_extra->fs_type *= 10; |
565 | font_extra->fs_type += (FT_UShort)( *s - '0' ); |
566 | } |
567 | else if ( *s != ' ' && *s != '\n' && *s != '\r' ) |
568 | { |
569 | /* Non-whitespace character between `/FSType' and next `def' */ |
570 | /* - ignore the FSType value. */ |
571 | font_extra->fs_type = 0U; |
572 | break; |
573 | } |
574 | } |
575 | } |
576 | } |
577 | |
578 | cff->font_extra = font_extra; |
579 | } |
580 | |
581 | if ( cff ) |
582 | *afont_extra = *cff->font_extra; |
583 | |
584 | Fail: |
585 | return error; |
586 | } |
587 | |
588 | |
589 | FT_DEFINE_SERVICE_PSINFOREC( |
590 | cff_service_ps_info, |
591 | |
592 | (PS_GetFontInfoFunc) cff_ps_get_font_info, /* ps_get_font_info */ |
593 | (PS_GetFontExtraFunc) cff_ps_get_font_extra, /* ps_get_font_extra */ |
594 | (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names, /* ps_has_glyph_names */ |
595 | /* unsupported with CFF fonts */ |
596 | (PS_GetFontPrivateFunc)NULL, /* ps_get_font_private */ |
597 | /* not implemented */ |
598 | (PS_GetFontValueFunc) NULL /* ps_get_font_value */ |
599 | ) |
600 | |
601 | |
602 | /* |
603 | * POSTSCRIPT NAME SERVICE |
604 | * |
605 | */ |
606 | |
607 | static const char* |
608 | cff_get_ps_name( CFF_Face face ) |
609 | { |
610 | CFF_Font cff = (CFF_Font)face->extra.data; |
611 | SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
612 | |
613 | |
614 | /* following the OpenType specification 1.7, we return the name stored */ |
615 | /* in the `name' table for a CFF wrapped into an SFNT container */ |
616 | |
617 | if ( FT_IS_SFNT( FT_FACE( face ) ) && sfnt ) |
618 | { |
619 | FT_Library library = FT_FACE_LIBRARY( face ); |
620 | FT_Module sfnt_module = FT_Get_Module( library, "sfnt" ); |
621 | FT_Service_PsFontName service = |
622 | (FT_Service_PsFontName)ft_module_get_service( |
623 | sfnt_module, |
624 | FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, |
625 | 0 ); |
626 | |
627 | |
628 | if ( service && service->get_ps_font_name ) |
629 | return service->get_ps_font_name( FT_FACE( face ) ); |
630 | } |
631 | |
632 | return (const char*)cff->font_name; |
633 | } |
634 | |
635 | |
636 | FT_DEFINE_SERVICE_PSFONTNAMEREC( |
637 | cff_service_ps_name, |
638 | |
639 | (FT_PsName_GetFunc)cff_get_ps_name /* get_ps_font_name */ |
640 | ) |
641 | |
642 | |
643 | /* |
644 | * TT CMAP INFO |
645 | * |
646 | * If the charmap is a synthetic Unicode encoding cmap or |
647 | * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO |
648 | * service defined in SFNT module. |
649 | * |
650 | * Otherwise call the service function in the sfnt module. |
651 | * |
652 | */ |
653 | static FT_Error |
654 | cff_get_cmap_info( FT_CharMap charmap, |
655 | TT_CMapInfo *cmap_info ) |
656 | { |
657 | FT_CMap cmap = FT_CMAP( charmap ); |
658 | FT_Error error = FT_Err_Ok; |
659 | |
660 | FT_Face face = FT_CMAP_FACE( cmap ); |
661 | FT_Library library = FT_FACE_LIBRARY( face ); |
662 | |
663 | |
664 | if ( cmap->clazz != &cff_cmap_encoding_class_rec && |
665 | cmap->clazz != &cff_cmap_unicode_class_rec ) |
666 | { |
667 | FT_Module sfnt = FT_Get_Module( library, "sfnt" ); |
668 | FT_Service_TTCMaps service = |
669 | (FT_Service_TTCMaps)ft_module_get_service( sfnt, |
670 | FT_SERVICE_ID_TT_CMAP, |
671 | 0 ); |
672 | |
673 | |
674 | if ( service && service->get_cmap_info ) |
675 | error = service->get_cmap_info( charmap, cmap_info ); |
676 | } |
677 | else |
678 | error = FT_THROW( Invalid_CharMap_Format ); |
679 | |
680 | return error; |
681 | } |
682 | |
683 | |
684 | FT_DEFINE_SERVICE_TTCMAPSREC( |
685 | cff_service_get_cmap_info, |
686 | |
687 | (TT_CMap_Info_GetFunc)cff_get_cmap_info /* get_cmap_info */ |
688 | ) |
689 | |
690 | |
691 | /* |
692 | * CID INFO SERVICE |
693 | * |
694 | */ |
695 | static FT_Error |
696 | cff_get_ros( CFF_Face face, |
697 | const char* *registry, |
698 | const char* *ordering, |
699 | FT_Int *supplement ) |
700 | { |
701 | FT_Error error = FT_Err_Ok; |
702 | CFF_Font cff = (CFF_Font)face->extra.data; |
703 | |
704 | |
705 | if ( cff ) |
706 | { |
707 | CFF_FontRecDict dict = &cff->top_font.font_dict; |
708 | |
709 | |
710 | if ( dict->cid_registry == 0xFFFFU ) |
711 | { |
712 | error = FT_THROW( Invalid_Argument ); |
713 | goto Fail; |
714 | } |
715 | |
716 | if ( registry ) |
717 | { |
718 | if ( !cff->registry ) |
719 | cff->registry = cff_index_get_sid_string( cff, |
720 | dict->cid_registry ); |
721 | *registry = cff->registry; |
722 | } |
723 | |
724 | if ( ordering ) |
725 | { |
726 | if ( !cff->ordering ) |
727 | cff->ordering = cff_index_get_sid_string( cff, |
728 | dict->cid_ordering ); |
729 | *ordering = cff->ordering; |
730 | } |
731 | |
732 | /* |
733 | * XXX: According to Adobe TechNote #5176, the supplement in CFF |
734 | * can be a real number. We truncate it to fit public API |
735 | * since freetype-2.3.6. |
736 | */ |
737 | if ( supplement ) |
738 | { |
739 | if ( dict->cid_supplement < FT_INT_MIN || |
740 | dict->cid_supplement > FT_INT_MAX ) |
741 | FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n" , |
742 | dict->cid_supplement )); |
743 | *supplement = (FT_Int)dict->cid_supplement; |
744 | } |
745 | } |
746 | |
747 | Fail: |
748 | return error; |
749 | } |
750 | |
751 | |
752 | static FT_Error |
753 | cff_get_is_cid( CFF_Face face, |
754 | FT_Bool *is_cid ) |
755 | { |
756 | FT_Error error = FT_Err_Ok; |
757 | CFF_Font cff = (CFF_Font)face->extra.data; |
758 | |
759 | |
760 | *is_cid = 0; |
761 | |
762 | if ( cff ) |
763 | { |
764 | CFF_FontRecDict dict = &cff->top_font.font_dict; |
765 | |
766 | |
767 | if ( dict->cid_registry != 0xFFFFU ) |
768 | *is_cid = 1; |
769 | } |
770 | |
771 | return error; |
772 | } |
773 | |
774 | |
775 | static FT_Error |
776 | cff_get_cid_from_glyph_index( CFF_Face face, |
777 | FT_UInt glyph_index, |
778 | FT_UInt *cid ) |
779 | { |
780 | FT_Error error = FT_Err_Ok; |
781 | CFF_Font cff; |
782 | |
783 | |
784 | cff = (CFF_Font)face->extra.data; |
785 | |
786 | if ( cff ) |
787 | { |
788 | FT_UInt c; |
789 | CFF_FontRecDict dict = &cff->top_font.font_dict; |
790 | |
791 | |
792 | if ( dict->cid_registry == 0xFFFFU ) |
793 | { |
794 | error = FT_THROW( Invalid_Argument ); |
795 | goto Fail; |
796 | } |
797 | |
798 | if ( glyph_index >= cff->num_glyphs ) |
799 | { |
800 | error = FT_THROW( Invalid_Argument ); |
801 | goto Fail; |
802 | } |
803 | |
804 | c = cff->charset.sids[glyph_index]; |
805 | |
806 | if ( cid ) |
807 | *cid = c; |
808 | } |
809 | |
810 | Fail: |
811 | return error; |
812 | } |
813 | |
814 | |
815 | FT_DEFINE_SERVICE_CIDREC( |
816 | cff_service_cid_info, |
817 | |
818 | (FT_CID_GetRegistryOrderingSupplementFunc) |
819 | cff_get_ros, /* get_ros */ |
820 | (FT_CID_GetIsInternallyCIDKeyedFunc) |
821 | cff_get_is_cid, /* get_is_cid */ |
822 | (FT_CID_GetCIDFromGlyphIndexFunc) |
823 | cff_get_cid_from_glyph_index /* get_cid_from_glyph_index */ |
824 | ) |
825 | |
826 | |
827 | /* |
828 | * PROPERTY SERVICE |
829 | * |
830 | */ |
831 | |
832 | FT_DEFINE_SERVICE_PROPERTIESREC( |
833 | cff_service_properties, |
834 | |
835 | (FT_Properties_SetFunc)ps_property_set, /* set_property */ |
836 | (FT_Properties_GetFunc)ps_property_get ) /* get_property */ |
837 | |
838 | |
839 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
840 | |
841 | /* |
842 | * MULTIPLE MASTER SERVICE |
843 | * |
844 | */ |
845 | |
846 | static FT_Error |
847 | cff_set_mm_blend( CFF_Face face, |
848 | FT_UInt num_coords, |
849 | FT_Fixed* coords ) |
850 | { |
851 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
852 | |
853 | |
854 | return mm->set_mm_blend( FT_FACE( face ), num_coords, coords ); |
855 | } |
856 | |
857 | |
858 | static FT_Error |
859 | cff_get_mm_blend( CFF_Face face, |
860 | FT_UInt num_coords, |
861 | FT_Fixed* coords ) |
862 | { |
863 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
864 | |
865 | |
866 | return mm->get_mm_blend( FT_FACE( face ), num_coords, coords ); |
867 | } |
868 | |
869 | |
870 | static FT_Error |
871 | cff_set_mm_weightvector( CFF_Face face, |
872 | FT_UInt len, |
873 | FT_Fixed* weightvector ) |
874 | { |
875 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
876 | |
877 | |
878 | return mm->set_mm_weightvector( FT_FACE( face ), len, weightvector ); |
879 | } |
880 | |
881 | |
882 | static FT_Error |
883 | cff_get_mm_weightvector( CFF_Face face, |
884 | FT_UInt* len, |
885 | FT_Fixed* weightvector ) |
886 | { |
887 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
888 | |
889 | |
890 | return mm->get_mm_weightvector( FT_FACE( face ), len, weightvector ); |
891 | } |
892 | |
893 | |
894 | static FT_Error |
895 | cff_get_mm_var( CFF_Face face, |
896 | FT_MM_Var* *master ) |
897 | { |
898 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
899 | |
900 | |
901 | return mm->get_mm_var( FT_FACE( face ), master ); |
902 | } |
903 | |
904 | |
905 | static FT_Error |
906 | cff_set_var_design( CFF_Face face, |
907 | FT_UInt num_coords, |
908 | FT_Fixed* coords ) |
909 | { |
910 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
911 | |
912 | |
913 | return mm->set_var_design( FT_FACE( face ), num_coords, coords ); |
914 | } |
915 | |
916 | |
917 | static FT_Error |
918 | cff_get_var_design( CFF_Face face, |
919 | FT_UInt num_coords, |
920 | FT_Fixed* coords ) |
921 | { |
922 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
923 | |
924 | |
925 | return mm->get_var_design( FT_FACE( face ), num_coords, coords ); |
926 | } |
927 | |
928 | |
929 | static FT_Error |
930 | cff_set_instance( CFF_Face face, |
931 | FT_UInt instance_index ) |
932 | { |
933 | FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm; |
934 | |
935 | |
936 | return mm->set_instance( FT_FACE( face ), instance_index ); |
937 | } |
938 | |
939 | |
940 | FT_DEFINE_SERVICE_MULTIMASTERSREC( |
941 | cff_service_multi_masters, |
942 | |
943 | (FT_Get_MM_Func) NULL, /* get_mm */ |
944 | (FT_Set_MM_Design_Func) NULL, /* set_mm_design */ |
945 | (FT_Set_MM_Blend_Func) cff_set_mm_blend, /* set_mm_blend */ |
946 | (FT_Get_MM_Blend_Func) cff_get_mm_blend, /* get_mm_blend */ |
947 | (FT_Get_MM_Var_Func) cff_get_mm_var, /* get_mm_var */ |
948 | (FT_Set_Var_Design_Func) cff_set_var_design, /* set_var_design */ |
949 | (FT_Get_Var_Design_Func) cff_get_var_design, /* get_var_design */ |
950 | (FT_Set_Instance_Func) cff_set_instance, /* set_instance */ |
951 | (FT_Set_MM_WeightVector_Func)cff_set_mm_weightvector, /* set_mm_weightvector */ |
952 | (FT_Get_MM_WeightVector_Func)cff_get_mm_weightvector, /* get_mm_weightvector */ |
953 | |
954 | (FT_Get_Var_Blend_Func) cff_get_var_blend, /* get_var_blend */ |
955 | (FT_Done_Blend_Func) cff_done_blend /* done_blend */ |
956 | ) |
957 | |
958 | |
959 | /* |
960 | * METRICS VARIATIONS SERVICE |
961 | * |
962 | */ |
963 | |
964 | static FT_Error |
965 | cff_hadvance_adjust( CFF_Face face, |
966 | FT_UInt gindex, |
967 | FT_Int *avalue ) |
968 | { |
969 | FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; |
970 | |
971 | |
972 | return var->hadvance_adjust( FT_FACE( face ), gindex, avalue ); |
973 | } |
974 | |
975 | |
976 | static void |
977 | cff_metrics_adjust( CFF_Face face ) |
978 | { |
979 | FT_Service_MetricsVariations var = (FT_Service_MetricsVariations)face->var; |
980 | |
981 | |
982 | var->metrics_adjust( FT_FACE( face ) ); |
983 | } |
984 | |
985 | |
986 | FT_DEFINE_SERVICE_METRICSVARIATIONSREC( |
987 | cff_service_metrics_variations, |
988 | |
989 | (FT_HAdvance_Adjust_Func)cff_hadvance_adjust, /* hadvance_adjust */ |
990 | (FT_LSB_Adjust_Func) NULL, /* lsb_adjust */ |
991 | (FT_RSB_Adjust_Func) NULL, /* rsb_adjust */ |
992 | |
993 | (FT_VAdvance_Adjust_Func)NULL, /* vadvance_adjust */ |
994 | (FT_TSB_Adjust_Func) NULL, /* tsb_adjust */ |
995 | (FT_BSB_Adjust_Func) NULL, /* bsb_adjust */ |
996 | (FT_VOrg_Adjust_Func) NULL, /* vorg_adjust */ |
997 | |
998 | (FT_Metrics_Adjust_Func) cff_metrics_adjust /* metrics_adjust */ |
999 | ) |
1000 | #endif |
1001 | |
1002 | |
1003 | /* |
1004 | * CFFLOAD SERVICE |
1005 | * |
1006 | */ |
1007 | |
1008 | FT_DEFINE_SERVICE_CFFLOADREC( |
1009 | cff_service_cff_load, |
1010 | |
1011 | (FT_Get_Standard_Encoding_Func)cff_get_standard_encoding, |
1012 | (FT_Load_Private_Dict_Func) cff_load_private_dict, |
1013 | (FT_FD_Select_Get_Func) cff_fd_select_get, |
1014 | (FT_Blend_Check_Vector_Func) cff_blend_check_vector, |
1015 | (FT_Blend_Build_Vector_Func) cff_blend_build_vector |
1016 | ) |
1017 | |
1018 | |
1019 | /*************************************************************************/ |
1020 | /*************************************************************************/ |
1021 | /*************************************************************************/ |
1022 | /**** ****/ |
1023 | /**** ****/ |
1024 | /**** D R I V E R I N T E R F A C E ****/ |
1025 | /**** ****/ |
1026 | /**** ****/ |
1027 | /*************************************************************************/ |
1028 | /*************************************************************************/ |
1029 | /*************************************************************************/ |
1030 | |
1031 | #if !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES && \ |
1032 | defined TT_CONFIG_OPTION_GX_VAR_SUPPORT |
1033 | FT_DEFINE_SERVICEDESCREC10( |
1034 | cff_services, |
1035 | |
1036 | FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, |
1037 | FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters, |
1038 | FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_variations, |
1039 | FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, |
1040 | FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, |
1041 | FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict, |
1042 | FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, |
1043 | FT_SERVICE_ID_CID, &cff_service_cid_info, |
1044 | FT_SERVICE_ID_PROPERTIES, &cff_service_properties, |
1045 | FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load |
1046 | ) |
1047 | #elif !defined FT_CONFIG_OPTION_NO_GLYPH_NAMES |
1048 | FT_DEFINE_SERVICEDESCREC8( |
1049 | cff_services, |
1050 | |
1051 | FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, |
1052 | FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, |
1053 | FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, |
1054 | FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict, |
1055 | FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, |
1056 | FT_SERVICE_ID_CID, &cff_service_cid_info, |
1057 | FT_SERVICE_ID_PROPERTIES, &cff_service_properties, |
1058 | FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load |
1059 | ) |
1060 | #elif defined TT_CONFIG_OPTION_GX_VAR_SUPPORT |
1061 | FT_DEFINE_SERVICEDESCREC9( |
1062 | cff_services, |
1063 | |
1064 | FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, |
1065 | FT_SERVICE_ID_MULTI_MASTERS, &cff_service_multi_masters, |
1066 | FT_SERVICE_ID_METRICS_VARIATIONS, &cff_service_metrics_var, |
1067 | FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, |
1068 | FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, |
1069 | FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, |
1070 | FT_SERVICE_ID_CID, &cff_service_cid_info, |
1071 | FT_SERVICE_ID_PROPERTIES, &cff_service_properties, |
1072 | FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load |
1073 | ) |
1074 | #else |
1075 | FT_DEFINE_SERVICEDESCREC7( |
1076 | cff_services, |
1077 | |
1078 | FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_CFF, |
1079 | FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info, |
1080 | FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name, |
1081 | FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info, |
1082 | FT_SERVICE_ID_CID, &cff_service_cid_info, |
1083 | FT_SERVICE_ID_PROPERTIES, &cff_service_properties, |
1084 | FT_SERVICE_ID_CFF_LOAD, &cff_service_cff_load |
1085 | ) |
1086 | #endif |
1087 | |
1088 | |
1089 | FT_CALLBACK_DEF( FT_Module_Interface ) |
1090 | cff_get_interface( FT_Module driver, /* CFF_Driver */ |
1091 | const char* module_interface ) |
1092 | { |
1093 | FT_Library library; |
1094 | FT_Module sfnt; |
1095 | FT_Module_Interface result; |
1096 | |
1097 | |
1098 | result = ft_service_list_lookup( cff_services, module_interface ); |
1099 | if ( result ) |
1100 | return result; |
1101 | |
1102 | /* `driver' is not yet evaluated */ |
1103 | if ( !driver ) |
1104 | return NULL; |
1105 | library = driver->library; |
1106 | if ( !library ) |
1107 | return NULL; |
1108 | |
1109 | /* we pass our request to the `sfnt' module */ |
1110 | sfnt = FT_Get_Module( library, "sfnt" ); |
1111 | |
1112 | return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0; |
1113 | } |
1114 | |
1115 | |
1116 | /* The FT_DriverInterface structure is defined in ftdriver.h. */ |
1117 | |
1118 | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
1119 | #define CFF_SIZE_SELECT cff_size_select |
1120 | #else |
1121 | #define CFF_SIZE_SELECT 0 |
1122 | #endif |
1123 | |
1124 | FT_DEFINE_DRIVER( |
1125 | cff_driver_class, |
1126 | |
1127 | FT_MODULE_FONT_DRIVER | |
1128 | FT_MODULE_DRIVER_SCALABLE | |
1129 | FT_MODULE_DRIVER_HAS_HINTER | |
1130 | FT_MODULE_DRIVER_HINTS_LIGHTLY, |
1131 | |
1132 | sizeof ( PS_DriverRec ), |
1133 | "cff" , |
1134 | 0x10000L, |
1135 | 0x20000L, |
1136 | |
1137 | NULL, /* module-specific interface */ |
1138 | |
1139 | cff_driver_init, /* FT_Module_Constructor module_init */ |
1140 | cff_driver_done, /* FT_Module_Destructor module_done */ |
1141 | cff_get_interface, /* FT_Module_Requester get_interface */ |
1142 | |
1143 | sizeof ( TT_FaceRec ), |
1144 | sizeof ( CFF_SizeRec ), |
1145 | sizeof ( CFF_GlyphSlotRec ), |
1146 | |
1147 | cff_face_init, /* FT_Face_InitFunc init_face */ |
1148 | cff_face_done, /* FT_Face_DoneFunc done_face */ |
1149 | cff_size_init, /* FT_Size_InitFunc init_size */ |
1150 | cff_size_done, /* FT_Size_DoneFunc done_size */ |
1151 | cff_slot_init, /* FT_Slot_InitFunc init_slot */ |
1152 | cff_slot_done, /* FT_Slot_DoneFunc done_slot */ |
1153 | |
1154 | cff_glyph_load, /* FT_Slot_LoadFunc load_glyph */ |
1155 | |
1156 | cff_get_kerning, /* FT_Face_GetKerningFunc get_kerning */ |
1157 | NULL, /* FT_Face_AttachFunc attach_file */ |
1158 | cff_get_advances, /* FT_Face_GetAdvancesFunc get_advances */ |
1159 | |
1160 | cff_size_request, /* FT_Size_RequestFunc request_size */ |
1161 | CFF_SIZE_SELECT /* FT_Size_SelectFunc select_size */ |
1162 | ) |
1163 | |
1164 | |
1165 | /* END */ |
1166 | |