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 | ( FT_Face face, /* CFF_Face */ |
515 | PS_FontExtraRec* ) |
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* = 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 | |