1 | /**************************************************************************** |
2 | * |
3 | * t1driver.c |
4 | * |
5 | * Type 1 driver interface (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 "t1driver.h" |
21 | #include "t1gload.h" |
22 | #include "t1load.h" |
23 | |
24 | #include "t1errors.h" |
25 | |
26 | #ifndef T1_CONFIG_OPTION_NO_AFM |
27 | #include "t1afm.h" |
28 | #endif |
29 | |
30 | #include FT_INTERNAL_DEBUG_H |
31 | #include FT_INTERNAL_STREAM_H |
32 | #include FT_INTERNAL_HASH_H |
33 | #include FT_INTERNAL_POSTSCRIPT_PROPS_H |
34 | #include FT_DRIVER_H |
35 | |
36 | #include FT_SERVICE_MULTIPLE_MASTERS_H |
37 | #include FT_SERVICE_GLYPH_DICT_H |
38 | #include FT_SERVICE_FONT_FORMAT_H |
39 | #include FT_SERVICE_POSTSCRIPT_NAME_H |
40 | #include FT_SERVICE_POSTSCRIPT_CMAPS_H |
41 | #include FT_SERVICE_POSTSCRIPT_INFO_H |
42 | #include FT_SERVICE_PROPERTIES_H |
43 | #include FT_SERVICE_KERNING_H |
44 | |
45 | |
46 | /************************************************************************** |
47 | * |
48 | * The macro FT_COMPONENT is used in trace mode. It is an implicit |
49 | * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log |
50 | * messages during execution. |
51 | */ |
52 | #undef FT_COMPONENT |
53 | #define FT_COMPONENT t1driver |
54 | |
55 | /* |
56 | * GLYPH DICT SERVICE |
57 | * |
58 | */ |
59 | |
60 | static FT_Error |
61 | t1_get_glyph_name( T1_Face face, |
62 | FT_UInt glyph_index, |
63 | FT_Pointer buffer, |
64 | FT_UInt buffer_max ) |
65 | { |
66 | FT_STRCPYN( buffer, face->type1.glyph_names[glyph_index], buffer_max ); |
67 | |
68 | return FT_Err_Ok; |
69 | } |
70 | |
71 | |
72 | static FT_UInt |
73 | t1_get_name_index( T1_Face face, |
74 | FT_String* glyph_name ) |
75 | { |
76 | FT_Int i; |
77 | |
78 | |
79 | for ( i = 0; i < face->type1.num_glyphs; i++ ) |
80 | { |
81 | FT_String* gname = face->type1.glyph_names[i]; |
82 | |
83 | |
84 | if ( !ft_strcmp( glyph_name, gname ) ) |
85 | return (FT_UInt)i; |
86 | } |
87 | |
88 | return 0; |
89 | } |
90 | |
91 | |
92 | static const FT_Service_GlyphDictRec t1_service_glyph_dict = |
93 | { |
94 | (FT_GlyphDict_GetNameFunc) t1_get_glyph_name, /* get_name */ |
95 | (FT_GlyphDict_NameIndexFunc)t1_get_name_index /* name_index */ |
96 | }; |
97 | |
98 | |
99 | /* |
100 | * POSTSCRIPT NAME SERVICE |
101 | * |
102 | */ |
103 | |
104 | static const char* |
105 | t1_get_ps_name( T1_Face face ) |
106 | { |
107 | return (const char*) face->type1.font_name; |
108 | } |
109 | |
110 | |
111 | static const FT_Service_PsFontNameRec t1_service_ps_name = |
112 | { |
113 | (FT_PsName_GetFunc)t1_get_ps_name /* get_ps_font_name */ |
114 | }; |
115 | |
116 | |
117 | /* |
118 | * MULTIPLE MASTERS SERVICE |
119 | * |
120 | */ |
121 | |
122 | #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
123 | static const FT_Service_MultiMastersRec t1_service_multi_masters = |
124 | { |
125 | (FT_Get_MM_Func) T1_Get_Multi_Master, /* get_mm */ |
126 | (FT_Set_MM_Design_Func) T1_Set_MM_Design, /* set_mm_design */ |
127 | (FT_Set_MM_Blend_Func) T1_Set_MM_Blend, /* set_mm_blend */ |
128 | (FT_Get_MM_Blend_Func) T1_Get_MM_Blend, /* get_mm_blend */ |
129 | (FT_Get_MM_Var_Func) T1_Get_MM_Var, /* get_mm_var */ |
130 | (FT_Set_Var_Design_Func) T1_Set_Var_Design, /* set_var_design */ |
131 | (FT_Get_Var_Design_Func) T1_Get_Var_Design, /* get_var_design */ |
132 | (FT_Set_Instance_Func) T1_Reset_MM_Blend, /* set_instance */ |
133 | (FT_Set_MM_WeightVector_Func)T1_Set_MM_WeightVector, /* set_mm_weightvector */ |
134 | (FT_Get_MM_WeightVector_Func)T1_Get_MM_WeightVector, /* get_mm_weightvector */ |
135 | |
136 | (FT_Get_Var_Blend_Func) NULL, /* get_var_blend */ |
137 | (FT_Done_Blend_Func) T1_Done_Blend /* done_blend */ |
138 | }; |
139 | #endif |
140 | |
141 | |
142 | /* |
143 | * POSTSCRIPT INFO SERVICE |
144 | * |
145 | */ |
146 | |
147 | static FT_Error |
148 | t1_ps_get_font_info( FT_Face face, |
149 | PS_FontInfoRec* afont_info ) |
150 | { |
151 | *afont_info = ((T1_Face)face)->type1.font_info; |
152 | |
153 | return FT_Err_Ok; |
154 | } |
155 | |
156 | |
157 | static FT_Error |
158 | ( FT_Face face, |
159 | PS_FontExtraRec* ) |
160 | { |
161 | *afont_extra = ((T1_Face)face)->type1.font_extra; |
162 | |
163 | return FT_Err_Ok; |
164 | } |
165 | |
166 | |
167 | static FT_Int |
168 | t1_ps_has_glyph_names( FT_Face face ) |
169 | { |
170 | FT_UNUSED( face ); |
171 | |
172 | return 1; |
173 | } |
174 | |
175 | |
176 | static FT_Error |
177 | t1_ps_get_font_private( FT_Face face, |
178 | PS_PrivateRec* afont_private ) |
179 | { |
180 | *afont_private = ((T1_Face)face)->type1.private_dict; |
181 | |
182 | return FT_Err_Ok; |
183 | } |
184 | |
185 | |
186 | static FT_Long |
187 | t1_ps_get_font_value( FT_Face face, |
188 | PS_Dict_Keys key, |
189 | FT_UInt idx, |
190 | void *value, |
191 | FT_Long value_len_ ) |
192 | { |
193 | FT_ULong retval = 0; /* always >= 1 if valid */ |
194 | FT_ULong value_len = value_len_ < 0 ? 0 : (FT_ULong)value_len_; |
195 | |
196 | T1_Face t1face = (T1_Face)face; |
197 | T1_Font type1 = &t1face->type1; |
198 | |
199 | |
200 | switch ( key ) |
201 | { |
202 | case PS_DICT_FONT_TYPE: |
203 | retval = sizeof ( type1->font_type ); |
204 | if ( value && value_len >= retval ) |
205 | *((FT_Byte *)value) = type1->font_type; |
206 | break; |
207 | |
208 | case PS_DICT_FONT_MATRIX: |
209 | if ( idx < sizeof ( type1->font_matrix ) / |
210 | sizeof ( type1->font_matrix.xx ) ) |
211 | { |
212 | FT_Fixed val = 0; |
213 | |
214 | |
215 | retval = sizeof ( val ); |
216 | if ( value && value_len >= retval ) |
217 | { |
218 | switch ( idx ) |
219 | { |
220 | case 0: |
221 | val = type1->font_matrix.xx; |
222 | break; |
223 | case 1: |
224 | val = type1->font_matrix.xy; |
225 | break; |
226 | case 2: |
227 | val = type1->font_matrix.yx; |
228 | break; |
229 | case 3: |
230 | val = type1->font_matrix.yy; |
231 | break; |
232 | } |
233 | *((FT_Fixed *)value) = val; |
234 | } |
235 | } |
236 | break; |
237 | |
238 | case PS_DICT_FONT_BBOX: |
239 | if ( idx < sizeof ( type1->font_bbox ) / |
240 | sizeof ( type1->font_bbox.xMin ) ) |
241 | { |
242 | FT_Fixed val = 0; |
243 | |
244 | |
245 | retval = sizeof ( val ); |
246 | if ( value && value_len >= retval ) |
247 | { |
248 | switch ( idx ) |
249 | { |
250 | case 0: |
251 | val = type1->font_bbox.xMin; |
252 | break; |
253 | case 1: |
254 | val = type1->font_bbox.yMin; |
255 | break; |
256 | case 2: |
257 | val = type1->font_bbox.xMax; |
258 | break; |
259 | case 3: |
260 | val = type1->font_bbox.yMax; |
261 | break; |
262 | } |
263 | *((FT_Fixed *)value) = val; |
264 | } |
265 | } |
266 | break; |
267 | |
268 | case PS_DICT_PAINT_TYPE: |
269 | retval = sizeof ( type1->paint_type ); |
270 | if ( value && value_len >= retval ) |
271 | *((FT_Byte *)value) = type1->paint_type; |
272 | break; |
273 | |
274 | case PS_DICT_FONT_NAME: |
275 | if ( type1->font_name ) |
276 | { |
277 | retval = ft_strlen( type1->font_name ) + 1; |
278 | if ( value && value_len >= retval ) |
279 | ft_memcpy( value, (void *)( type1->font_name ), retval ); |
280 | } |
281 | break; |
282 | |
283 | case PS_DICT_UNIQUE_ID: |
284 | retval = sizeof ( type1->private_dict.unique_id ); |
285 | if ( value && value_len >= retval ) |
286 | *((FT_Int *)value) = type1->private_dict.unique_id; |
287 | break; |
288 | |
289 | case PS_DICT_NUM_CHAR_STRINGS: |
290 | retval = sizeof ( type1->num_glyphs ); |
291 | if ( value && value_len >= retval ) |
292 | *((FT_Int *)value) = type1->num_glyphs; |
293 | break; |
294 | |
295 | case PS_DICT_CHAR_STRING_KEY: |
296 | if ( idx < (FT_UInt)type1->num_glyphs ) |
297 | { |
298 | retval = ft_strlen( type1->glyph_names[idx] ) + 1; |
299 | if ( value && value_len >= retval ) |
300 | { |
301 | ft_memcpy( value, (void *)( type1->glyph_names[idx] ), retval ); |
302 | ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; |
303 | } |
304 | } |
305 | break; |
306 | |
307 | case PS_DICT_CHAR_STRING: |
308 | if ( idx < (FT_UInt)type1->num_glyphs ) |
309 | { |
310 | retval = type1->charstrings_len[idx] + 1; |
311 | if ( value && value_len >= retval ) |
312 | { |
313 | ft_memcpy( value, (void *)( type1->charstrings[idx] ), |
314 | retval - 1 ); |
315 | ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; |
316 | } |
317 | } |
318 | break; |
319 | |
320 | case PS_DICT_ENCODING_TYPE: |
321 | retval = sizeof ( type1->encoding_type ); |
322 | if ( value && value_len >= retval ) |
323 | *((T1_EncodingType *)value) = type1->encoding_type; |
324 | break; |
325 | |
326 | case PS_DICT_ENCODING_ENTRY: |
327 | if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY && |
328 | idx < (FT_UInt)type1->encoding.num_chars ) |
329 | { |
330 | retval = ft_strlen( type1->encoding.char_name[idx] ) + 1; |
331 | if ( value && value_len >= retval ) |
332 | { |
333 | ft_memcpy( value, (void *)( type1->encoding.char_name[idx] ), |
334 | retval - 1 ); |
335 | ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; |
336 | } |
337 | } |
338 | break; |
339 | |
340 | case PS_DICT_NUM_SUBRS: |
341 | retval = sizeof ( type1->num_subrs ); |
342 | if ( value && value_len >= retval ) |
343 | *((FT_Int *)value) = type1->num_subrs; |
344 | break; |
345 | |
346 | case PS_DICT_SUBR: |
347 | { |
348 | FT_Bool ok = 0; |
349 | |
350 | |
351 | if ( type1->subrs_hash ) |
352 | { |
353 | /* convert subr index to array index */ |
354 | size_t* val = ft_hash_num_lookup( (FT_Int)idx, |
355 | type1->subrs_hash ); |
356 | |
357 | |
358 | if ( val ) |
359 | { |
360 | idx = *val; |
361 | ok = 1; |
362 | } |
363 | } |
364 | else |
365 | { |
366 | if ( idx < (FT_UInt)type1->num_subrs ) |
367 | ok = 1; |
368 | } |
369 | |
370 | if ( ok && type1->subrs ) |
371 | { |
372 | retval = type1->subrs_len[idx] + 1; |
373 | if ( value && value_len >= retval ) |
374 | { |
375 | ft_memcpy( value, (void *)( type1->subrs[idx] ), retval - 1 ); |
376 | ((FT_Char *)value)[retval - 1] = (FT_Char)'\0'; |
377 | } |
378 | } |
379 | } |
380 | break; |
381 | |
382 | case PS_DICT_STD_HW: |
383 | retval = sizeof ( type1->private_dict.standard_width[0] ); |
384 | if ( value && value_len >= retval ) |
385 | *((FT_UShort *)value) = type1->private_dict.standard_width[0]; |
386 | break; |
387 | |
388 | case PS_DICT_STD_VW: |
389 | retval = sizeof ( type1->private_dict.standard_height[0] ); |
390 | if ( value && value_len >= retval ) |
391 | *((FT_UShort *)value) = type1->private_dict.standard_height[0]; |
392 | break; |
393 | |
394 | case PS_DICT_NUM_BLUE_VALUES: |
395 | retval = sizeof ( type1->private_dict.num_blue_values ); |
396 | if ( value && value_len >= retval ) |
397 | *((FT_Byte *)value) = type1->private_dict.num_blue_values; |
398 | break; |
399 | |
400 | case PS_DICT_BLUE_VALUE: |
401 | if ( idx < type1->private_dict.num_blue_values ) |
402 | { |
403 | retval = sizeof ( type1->private_dict.blue_values[idx] ); |
404 | if ( value && value_len >= retval ) |
405 | *((FT_Short *)value) = type1->private_dict.blue_values[idx]; |
406 | } |
407 | break; |
408 | |
409 | case PS_DICT_BLUE_SCALE: |
410 | retval = sizeof ( type1->private_dict.blue_scale ); |
411 | if ( value && value_len >= retval ) |
412 | *((FT_Fixed *)value) = type1->private_dict.blue_scale; |
413 | break; |
414 | |
415 | case PS_DICT_BLUE_FUZZ: |
416 | retval = sizeof ( type1->private_dict.blue_fuzz ); |
417 | if ( value && value_len >= retval ) |
418 | *((FT_Int *)value) = type1->private_dict.blue_fuzz; |
419 | break; |
420 | |
421 | case PS_DICT_BLUE_SHIFT: |
422 | retval = sizeof ( type1->private_dict.blue_shift ); |
423 | if ( value && value_len >= retval ) |
424 | *((FT_Int *)value) = type1->private_dict.blue_shift; |
425 | break; |
426 | |
427 | case PS_DICT_NUM_OTHER_BLUES: |
428 | retval = sizeof ( type1->private_dict.num_other_blues ); |
429 | if ( value && value_len >= retval ) |
430 | *((FT_Byte *)value) = type1->private_dict.num_other_blues; |
431 | break; |
432 | |
433 | case PS_DICT_OTHER_BLUE: |
434 | if ( idx < type1->private_dict.num_other_blues ) |
435 | { |
436 | retval = sizeof ( type1->private_dict.other_blues[idx] ); |
437 | if ( value && value_len >= retval ) |
438 | *((FT_Short *)value) = type1->private_dict.other_blues[idx]; |
439 | } |
440 | break; |
441 | |
442 | case PS_DICT_NUM_FAMILY_BLUES: |
443 | retval = sizeof ( type1->private_dict.num_family_blues ); |
444 | if ( value && value_len >= retval ) |
445 | *((FT_Byte *)value) = type1->private_dict.num_family_blues; |
446 | break; |
447 | |
448 | case PS_DICT_FAMILY_BLUE: |
449 | if ( idx < type1->private_dict.num_family_blues ) |
450 | { |
451 | retval = sizeof ( type1->private_dict.family_blues[idx] ); |
452 | if ( value && value_len >= retval ) |
453 | *((FT_Short *)value) = type1->private_dict.family_blues[idx]; |
454 | } |
455 | break; |
456 | |
457 | case PS_DICT_NUM_FAMILY_OTHER_BLUES: |
458 | retval = sizeof ( type1->private_dict.num_family_other_blues ); |
459 | if ( value && value_len >= retval ) |
460 | *((FT_Byte *)value) = type1->private_dict.num_family_other_blues; |
461 | break; |
462 | |
463 | case PS_DICT_FAMILY_OTHER_BLUE: |
464 | if ( idx < type1->private_dict.num_family_other_blues ) |
465 | { |
466 | retval = sizeof ( type1->private_dict.family_other_blues[idx] ); |
467 | if ( value && value_len >= retval ) |
468 | *((FT_Short *)value) = type1->private_dict.family_other_blues[idx]; |
469 | } |
470 | break; |
471 | |
472 | case PS_DICT_NUM_STEM_SNAP_H: |
473 | retval = sizeof ( type1->private_dict.num_snap_widths ); |
474 | if ( value && value_len >= retval ) |
475 | *((FT_Byte *)value) = type1->private_dict.num_snap_widths; |
476 | break; |
477 | |
478 | case PS_DICT_STEM_SNAP_H: |
479 | if ( idx < type1->private_dict.num_snap_widths ) |
480 | { |
481 | retval = sizeof ( type1->private_dict.snap_widths[idx] ); |
482 | if ( value && value_len >= retval ) |
483 | *((FT_Short *)value) = type1->private_dict.snap_widths[idx]; |
484 | } |
485 | break; |
486 | |
487 | case PS_DICT_NUM_STEM_SNAP_V: |
488 | retval = sizeof ( type1->private_dict.num_snap_heights ); |
489 | if ( value && value_len >= retval ) |
490 | *((FT_Byte *)value) = type1->private_dict.num_snap_heights; |
491 | break; |
492 | |
493 | case PS_DICT_STEM_SNAP_V: |
494 | if ( idx < type1->private_dict.num_snap_heights ) |
495 | { |
496 | retval = sizeof ( type1->private_dict.snap_heights[idx] ); |
497 | if ( value && value_len >= retval ) |
498 | *((FT_Short *)value) = type1->private_dict.snap_heights[idx]; |
499 | } |
500 | break; |
501 | |
502 | case PS_DICT_RND_STEM_UP: |
503 | retval = sizeof ( type1->private_dict.round_stem_up ); |
504 | if ( value && value_len >= retval ) |
505 | *((FT_Bool *)value) = type1->private_dict.round_stem_up; |
506 | break; |
507 | |
508 | case PS_DICT_FORCE_BOLD: |
509 | retval = sizeof ( type1->private_dict.force_bold ); |
510 | if ( value && value_len >= retval ) |
511 | *((FT_Bool *)value) = type1->private_dict.force_bold; |
512 | break; |
513 | |
514 | case PS_DICT_MIN_FEATURE: |
515 | if ( idx < sizeof ( type1->private_dict.min_feature ) / |
516 | sizeof ( type1->private_dict.min_feature[0] ) ) |
517 | { |
518 | retval = sizeof ( type1->private_dict.min_feature[idx] ); |
519 | if ( value && value_len >= retval ) |
520 | *((FT_Short *)value) = type1->private_dict.min_feature[idx]; |
521 | } |
522 | break; |
523 | |
524 | case PS_DICT_LEN_IV: |
525 | retval = sizeof ( type1->private_dict.lenIV ); |
526 | if ( value && value_len >= retval ) |
527 | *((FT_Int *)value) = type1->private_dict.lenIV; |
528 | break; |
529 | |
530 | case PS_DICT_PASSWORD: |
531 | retval = sizeof ( type1->private_dict.password ); |
532 | if ( value && value_len >= retval ) |
533 | *((FT_Long *)value) = type1->private_dict.password; |
534 | break; |
535 | |
536 | case PS_DICT_LANGUAGE_GROUP: |
537 | retval = sizeof ( type1->private_dict.language_group ); |
538 | if ( value && value_len >= retval ) |
539 | *((FT_Long *)value) = type1->private_dict.language_group; |
540 | break; |
541 | |
542 | case PS_DICT_IS_FIXED_PITCH: |
543 | retval = sizeof ( type1->font_info.is_fixed_pitch ); |
544 | if ( value && value_len >= retval ) |
545 | *((FT_Bool *)value) = type1->font_info.is_fixed_pitch; |
546 | break; |
547 | |
548 | case PS_DICT_UNDERLINE_POSITION: |
549 | retval = sizeof ( type1->font_info.underline_position ); |
550 | if ( value && value_len >= retval ) |
551 | *((FT_Short *)value) = type1->font_info.underline_position; |
552 | break; |
553 | |
554 | case PS_DICT_UNDERLINE_THICKNESS: |
555 | retval = sizeof ( type1->font_info.underline_thickness ); |
556 | if ( value && value_len >= retval ) |
557 | *((FT_UShort *)value) = type1->font_info.underline_thickness; |
558 | break; |
559 | |
560 | case PS_DICT_FS_TYPE: |
561 | retval = sizeof ( type1->font_extra.fs_type ); |
562 | if ( value && value_len >= retval ) |
563 | *((FT_UShort *)value) = type1->font_extra.fs_type; |
564 | break; |
565 | |
566 | case PS_DICT_VERSION: |
567 | if ( type1->font_info.version ) |
568 | { |
569 | retval = ft_strlen( type1->font_info.version ) + 1; |
570 | if ( value && value_len >= retval ) |
571 | ft_memcpy( value, (void *)( type1->font_info.version ), retval ); |
572 | } |
573 | break; |
574 | |
575 | case PS_DICT_NOTICE: |
576 | if ( type1->font_info.notice ) |
577 | { |
578 | retval = ft_strlen( type1->font_info.notice ) + 1; |
579 | if ( value && value_len >= retval ) |
580 | ft_memcpy( value, (void *)( type1->font_info.notice ), retval ); |
581 | } |
582 | break; |
583 | |
584 | case PS_DICT_FULL_NAME: |
585 | if ( type1->font_info.full_name ) |
586 | { |
587 | retval = ft_strlen( type1->font_info.full_name ) + 1; |
588 | if ( value && value_len >= retval ) |
589 | ft_memcpy( value, (void *)( type1->font_info.full_name ), retval ); |
590 | } |
591 | break; |
592 | |
593 | case PS_DICT_FAMILY_NAME: |
594 | if ( type1->font_info.family_name ) |
595 | { |
596 | retval = ft_strlen( type1->font_info.family_name ) + 1; |
597 | if ( value && value_len >= retval ) |
598 | ft_memcpy( value, (void *)( type1->font_info.family_name ), |
599 | retval ); |
600 | } |
601 | break; |
602 | |
603 | case PS_DICT_WEIGHT: |
604 | if ( type1->font_info.weight ) |
605 | { |
606 | retval = ft_strlen( type1->font_info.weight ) + 1; |
607 | if ( value && value_len >= retval ) |
608 | ft_memcpy( value, (void *)( type1->font_info.weight ), retval ); |
609 | } |
610 | break; |
611 | |
612 | case PS_DICT_ITALIC_ANGLE: |
613 | retval = sizeof ( type1->font_info.italic_angle ); |
614 | if ( value && value_len >= retval ) |
615 | *((FT_Long *)value) = type1->font_info.italic_angle; |
616 | break; |
617 | } |
618 | |
619 | return retval == 0 ? -1 : (FT_Long)retval; |
620 | } |
621 | |
622 | |
623 | static const FT_Service_PsInfoRec t1_service_ps_info = |
624 | { |
625 | (PS_GetFontInfoFunc) t1_ps_get_font_info, /* ps_get_font_info */ |
626 | (PS_GetFontExtraFunc) t1_ps_get_font_extra, /* ps_get_font_extra */ |
627 | (PS_HasGlyphNamesFunc) t1_ps_has_glyph_names, /* ps_has_glyph_names */ |
628 | (PS_GetFontPrivateFunc)t1_ps_get_font_private, /* ps_get_font_private */ |
629 | (PS_GetFontValueFunc) t1_ps_get_font_value, /* ps_get_font_value */ |
630 | }; |
631 | |
632 | |
633 | #ifndef T1_CONFIG_OPTION_NO_AFM |
634 | static const FT_Service_KerningRec t1_service_kerning = |
635 | { |
636 | T1_Get_Track_Kerning, /* get_track */ |
637 | }; |
638 | #endif |
639 | |
640 | |
641 | /* |
642 | * PROPERTY SERVICE |
643 | * |
644 | */ |
645 | |
646 | FT_DEFINE_SERVICE_PROPERTIESREC( |
647 | t1_service_properties, |
648 | |
649 | (FT_Properties_SetFunc)ps_property_set, /* set_property */ |
650 | (FT_Properties_GetFunc)ps_property_get ) /* get_property */ |
651 | |
652 | |
653 | /* |
654 | * SERVICE LIST |
655 | * |
656 | */ |
657 | |
658 | static const FT_ServiceDescRec t1_services[] = |
659 | { |
660 | { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &t1_service_ps_name }, |
661 | { FT_SERVICE_ID_GLYPH_DICT, &t1_service_glyph_dict }, |
662 | { FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TYPE_1 }, |
663 | { FT_SERVICE_ID_POSTSCRIPT_INFO, &t1_service_ps_info }, |
664 | { FT_SERVICE_ID_PROPERTIES, &t1_service_properties }, |
665 | |
666 | #ifndef T1_CONFIG_OPTION_NO_AFM |
667 | { FT_SERVICE_ID_KERNING, &t1_service_kerning }, |
668 | #endif |
669 | |
670 | #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT |
671 | { FT_SERVICE_ID_MULTI_MASTERS, &t1_service_multi_masters }, |
672 | #endif |
673 | { NULL, NULL } |
674 | }; |
675 | |
676 | |
677 | FT_CALLBACK_DEF( FT_Module_Interface ) |
678 | Get_Interface( FT_Module module, |
679 | const FT_String* t1_interface ) |
680 | { |
681 | FT_UNUSED( module ); |
682 | |
683 | return ft_service_list_lookup( t1_services, t1_interface ); |
684 | } |
685 | |
686 | |
687 | #ifndef T1_CONFIG_OPTION_NO_AFM |
688 | |
689 | /************************************************************************** |
690 | * |
691 | * @Function: |
692 | * Get_Kerning |
693 | * |
694 | * @Description: |
695 | * A driver method used to return the kerning vector between two |
696 | * glyphs of the same face. |
697 | * |
698 | * @Input: |
699 | * face :: |
700 | * A handle to the source face object. |
701 | * |
702 | * left_glyph :: |
703 | * The index of the left glyph in the kern pair. |
704 | * |
705 | * right_glyph :: |
706 | * The index of the right glyph in the kern pair. |
707 | * |
708 | * @Output: |
709 | * kerning :: |
710 | * The kerning vector. This is in font units for |
711 | * scalable formats, and in pixels for fixed-sizes |
712 | * formats. |
713 | * |
714 | * @Return: |
715 | * FreeType error code. 0 means success. |
716 | * |
717 | * @Note: |
718 | * Only horizontal layouts (left-to-right & right-to-left) are |
719 | * supported by this function. Other layouts, or more sophisticated |
720 | * kernings are out of scope of this method (the basic driver |
721 | * interface is meant to be simple). |
722 | * |
723 | * They can be implemented by format-specific interfaces. |
724 | */ |
725 | static FT_Error |
726 | Get_Kerning( FT_Face t1face, /* T1_Face */ |
727 | FT_UInt left_glyph, |
728 | FT_UInt right_glyph, |
729 | FT_Vector* kerning ) |
730 | { |
731 | T1_Face face = (T1_Face)t1face; |
732 | |
733 | |
734 | kerning->x = 0; |
735 | kerning->y = 0; |
736 | |
737 | if ( face->afm_data ) |
738 | T1_Get_Kerning( (AFM_FontInfo)face->afm_data, |
739 | left_glyph, |
740 | right_glyph, |
741 | kerning ); |
742 | |
743 | return FT_Err_Ok; |
744 | } |
745 | |
746 | |
747 | #endif /* T1_CONFIG_OPTION_NO_AFM */ |
748 | |
749 | |
750 | FT_CALLBACK_TABLE_DEF |
751 | const FT_Driver_ClassRec t1_driver_class = |
752 | { |
753 | { |
754 | FT_MODULE_FONT_DRIVER | |
755 | FT_MODULE_DRIVER_SCALABLE | |
756 | FT_MODULE_DRIVER_HAS_HINTER, |
757 | |
758 | sizeof ( PS_DriverRec ), |
759 | |
760 | "type1" , |
761 | 0x10000L, |
762 | 0x20000L, |
763 | |
764 | NULL, /* module-specific interface */ |
765 | |
766 | T1_Driver_Init, /* FT_Module_Constructor module_init */ |
767 | T1_Driver_Done, /* FT_Module_Destructor module_done */ |
768 | Get_Interface, /* FT_Module_Requester get_interface */ |
769 | }, |
770 | |
771 | sizeof ( T1_FaceRec ), |
772 | sizeof ( T1_SizeRec ), |
773 | sizeof ( T1_GlyphSlotRec ), |
774 | |
775 | T1_Face_Init, /* FT_Face_InitFunc init_face */ |
776 | T1_Face_Done, /* FT_Face_DoneFunc done_face */ |
777 | T1_Size_Init, /* FT_Size_InitFunc init_size */ |
778 | T1_Size_Done, /* FT_Size_DoneFunc done_size */ |
779 | T1_GlyphSlot_Init, /* FT_Slot_InitFunc init_slot */ |
780 | T1_GlyphSlot_Done, /* FT_Slot_DoneFunc done_slot */ |
781 | |
782 | T1_Load_Glyph, /* FT_Slot_LoadFunc load_glyph */ |
783 | |
784 | #ifdef T1_CONFIG_OPTION_NO_AFM |
785 | NULL, /* FT_Face_GetKerningFunc get_kerning */ |
786 | NULL, /* FT_Face_AttachFunc attach_file */ |
787 | #else |
788 | Get_Kerning, /* FT_Face_GetKerningFunc get_kerning */ |
789 | T1_Read_Metrics, /* FT_Face_AttachFunc attach_file */ |
790 | #endif |
791 | T1_Get_Advances, /* FT_Face_GetAdvancesFunc get_advances */ |
792 | |
793 | T1_Size_Request, /* FT_Size_RequestFunc request_size */ |
794 | NULL /* FT_Size_SelectFunc select_size */ |
795 | }; |
796 | |
797 | |
798 | /* END */ |
799 | |