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