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