1 | /**************************************************************************** |
2 | * |
3 | * ttdriver.c |
4 | * |
5 | * TrueType font driver implementation (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 <freetype/internal/ftdebug.h> |
20 | #include <freetype/internal/ftstream.h> |
21 | #include <freetype/internal/sfnt.h> |
22 | #include <freetype/internal/services/svfntfmt.h> |
23 | |
24 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
25 | #include <freetype/ftmm.h> |
26 | #include <freetype/internal/services/svmm.h> |
27 | #include <freetype/internal/services/svmetric.h> |
28 | #endif |
29 | |
30 | #include <freetype/internal/services/svtteng.h> |
31 | #include <freetype/internal/services/svttglyf.h> |
32 | #include <freetype/internal/services/svprop.h> |
33 | #include <freetype/ftdriver.h> |
34 | |
35 | #include "ttdriver.h" |
36 | #include "ttgload.h" |
37 | #include "ttpload.h" |
38 | |
39 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
40 | #include "ttgxvar.h" |
41 | #endif |
42 | |
43 | #include "tterrors.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 ttdriver |
54 | |
55 | |
56 | /* |
57 | * PROPERTY SERVICE |
58 | * |
59 | */ |
60 | FT_CALLBACK_DEF( FT_Error ) |
61 | tt_property_set( FT_Module module, /* TT_Driver */ |
62 | const char* property_name, |
63 | const void* value, |
64 | FT_Bool value_is_string ) |
65 | { |
66 | FT_Error error = FT_Err_Ok; |
67 | TT_Driver driver = (TT_Driver)module; |
68 | |
69 | #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES |
70 | FT_UNUSED( value_is_string ); |
71 | #endif |
72 | |
73 | |
74 | if ( !ft_strcmp( property_name, "interpreter-version" ) ) |
75 | { |
76 | FT_UInt interpreter_version; |
77 | |
78 | |
79 | #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES |
80 | if ( value_is_string ) |
81 | { |
82 | const char* s = (const char*)value; |
83 | |
84 | |
85 | interpreter_version = (FT_UInt)ft_strtol( s, NULL, 10 ); |
86 | } |
87 | else |
88 | #endif |
89 | { |
90 | FT_UInt* iv = (FT_UInt*)value; |
91 | |
92 | |
93 | interpreter_version = *iv; |
94 | } |
95 | |
96 | switch ( interpreter_version ) |
97 | { |
98 | case TT_INTERPRETER_VERSION_35: |
99 | driver->interpreter_version = TT_INTERPRETER_VERSION_35; |
100 | break; |
101 | |
102 | case TT_INTERPRETER_VERSION_38: |
103 | case TT_INTERPRETER_VERSION_40: |
104 | #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL |
105 | driver->interpreter_version = TT_INTERPRETER_VERSION_40; |
106 | break; |
107 | #endif |
108 | |
109 | default: |
110 | error = FT_ERR( Unimplemented_Feature ); |
111 | } |
112 | |
113 | return error; |
114 | } |
115 | |
116 | FT_TRACE2(( "tt_property_set: missing property `%s'\n" , |
117 | property_name )); |
118 | return FT_THROW( Missing_Property ); |
119 | } |
120 | |
121 | |
122 | FT_CALLBACK_DEF( FT_Error ) |
123 | tt_property_get( FT_Module module, /* TT_Driver */ |
124 | const char* property_name, |
125 | void* value ) |
126 | { |
127 | FT_Error error = FT_Err_Ok; |
128 | TT_Driver driver = (TT_Driver)module; |
129 | |
130 | FT_UInt interpreter_version = driver->interpreter_version; |
131 | |
132 | |
133 | if ( !ft_strcmp( property_name, "interpreter-version" ) ) |
134 | { |
135 | FT_UInt* val = (FT_UInt*)value; |
136 | |
137 | |
138 | *val = interpreter_version; |
139 | |
140 | return error; |
141 | } |
142 | |
143 | FT_TRACE2(( "tt_property_get: missing property `%s'\n" , |
144 | property_name )); |
145 | return FT_THROW( Missing_Property ); |
146 | } |
147 | |
148 | |
149 | FT_DEFINE_SERVICE_PROPERTIESREC( |
150 | tt_service_properties, |
151 | |
152 | tt_property_set, /* FT_Properties_SetFunc set_property */ |
153 | tt_property_get /* FT_Properties_GetFunc get_property */ |
154 | ) |
155 | |
156 | |
157 | /*************************************************************************/ |
158 | /*************************************************************************/ |
159 | /*************************************************************************/ |
160 | /**** ****/ |
161 | /**** ****/ |
162 | /**** F A C E S ****/ |
163 | /**** ****/ |
164 | /**** ****/ |
165 | /*************************************************************************/ |
166 | /*************************************************************************/ |
167 | /*************************************************************************/ |
168 | |
169 | |
170 | /************************************************************************** |
171 | * |
172 | * @Function: |
173 | * tt_get_kerning |
174 | * |
175 | * @Description: |
176 | * A driver method used to return the kerning vector between two |
177 | * glyphs of the same face. |
178 | * |
179 | * @Input: |
180 | * face :: |
181 | * A handle to the source face object. |
182 | * |
183 | * left_glyph :: |
184 | * The index of the left glyph in the kern pair. |
185 | * |
186 | * right_glyph :: |
187 | * The index of the right glyph in the kern pair. |
188 | * |
189 | * @Output: |
190 | * kerning :: |
191 | * The kerning vector. This is in font units for |
192 | * scalable formats, and in pixels for fixed-sizes |
193 | * formats. |
194 | * |
195 | * @Return: |
196 | * FreeType error code. 0 means success. |
197 | * |
198 | * @Note: |
199 | * Only horizontal layouts (left-to-right & right-to-left) are |
200 | * supported by this function. Other layouts, or more sophisticated |
201 | * kernings, are out of scope of this method (the basic driver |
202 | * interface is meant to be simple). |
203 | * |
204 | * They can be implemented by format-specific interfaces. |
205 | */ |
206 | FT_CALLBACK_DEF( FT_Error ) |
207 | tt_get_kerning( FT_Face face, /* TT_Face */ |
208 | FT_UInt left_glyph, |
209 | FT_UInt right_glyph, |
210 | FT_Vector* kerning ) |
211 | { |
212 | TT_Face ttface = (TT_Face)face; |
213 | SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; |
214 | |
215 | |
216 | kerning->x = 0; |
217 | kerning->y = 0; |
218 | |
219 | if ( sfnt ) |
220 | kerning->x = sfnt->get_kerning( ttface, left_glyph, right_glyph ); |
221 | |
222 | return 0; |
223 | } |
224 | |
225 | |
226 | FT_CALLBACK_DEF( FT_Error ) |
227 | tt_get_advances( FT_Face face, /* TT_Face */ |
228 | FT_UInt start, |
229 | FT_UInt count, |
230 | FT_Int32 flags, |
231 | FT_Fixed *advances ) |
232 | { |
233 | FT_UInt nn; |
234 | TT_Face ttface = (TT_Face)face; |
235 | |
236 | |
237 | /* XXX: TODO: check for sbits */ |
238 | |
239 | if ( flags & FT_LOAD_VERTICAL_LAYOUT ) |
240 | { |
241 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
242 | /* no fast retrieval for blended MM fonts without VVAR table */ |
243 | if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && |
244 | !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) |
245 | return FT_THROW( Unimplemented_Feature ); |
246 | #endif |
247 | |
248 | for ( nn = 0; nn < count; nn++ ) |
249 | { |
250 | FT_Short tsb; |
251 | FT_UShort ah; |
252 | |
253 | |
254 | /* since we don't need `tsb', we use zero for `yMax' parameter */ |
255 | TT_Get_VMetrics( ttface, start + nn, 0, &tsb, &ah ); |
256 | advances[nn] = ah; |
257 | } |
258 | } |
259 | else |
260 | { |
261 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
262 | /* no fast retrieval for blended MM fonts without HVAR table */ |
263 | if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) && |
264 | !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) |
265 | return FT_THROW( Unimplemented_Feature ); |
266 | #endif |
267 | |
268 | for ( nn = 0; nn < count; nn++ ) |
269 | { |
270 | FT_Short lsb; |
271 | FT_UShort aw; |
272 | |
273 | |
274 | TT_Get_HMetrics( ttface, start + nn, &lsb, &aw ); |
275 | advances[nn] = aw; |
276 | } |
277 | } |
278 | |
279 | return FT_Err_Ok; |
280 | } |
281 | |
282 | |
283 | /*************************************************************************/ |
284 | /*************************************************************************/ |
285 | /*************************************************************************/ |
286 | /**** ****/ |
287 | /**** ****/ |
288 | /**** S I Z E S ****/ |
289 | /**** ****/ |
290 | /**** ****/ |
291 | /*************************************************************************/ |
292 | /*************************************************************************/ |
293 | /*************************************************************************/ |
294 | |
295 | |
296 | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
297 | |
298 | FT_CALLBACK_DEF( FT_Error ) |
299 | tt_size_select( FT_Size size, |
300 | FT_ULong strike_index ) |
301 | { |
302 | TT_Face ttface = (TT_Face)size->face; |
303 | TT_Size ttsize = (TT_Size)size; |
304 | FT_Error error = FT_Err_Ok; |
305 | |
306 | |
307 | ttsize->strike_index = strike_index; |
308 | |
309 | if ( FT_IS_SCALABLE( size->face ) ) |
310 | { |
311 | /* use the scaled metrics, even when tt_size_reset fails */ |
312 | FT_Select_Metrics( size->face, strike_index ); |
313 | |
314 | tt_size_reset( ttsize ); /* ignore return value */ |
315 | } |
316 | else |
317 | { |
318 | SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; |
319 | FT_Size_Metrics* size_metrics = &size->metrics; |
320 | |
321 | |
322 | error = sfnt->load_strike_metrics( ttface, |
323 | strike_index, |
324 | size_metrics ); |
325 | if ( error ) |
326 | ttsize->strike_index = 0xFFFFFFFFUL; |
327 | } |
328 | |
329 | return error; |
330 | } |
331 | |
332 | #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
333 | |
334 | |
335 | FT_CALLBACK_DEF( FT_Error ) |
336 | tt_size_request( FT_Size size, |
337 | FT_Size_Request req ) |
338 | { |
339 | TT_Size ttsize = (TT_Size)size; |
340 | FT_Error error = FT_Err_Ok; |
341 | |
342 | |
343 | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
344 | |
345 | if ( FT_HAS_FIXED_SIZES( size->face ) ) |
346 | { |
347 | TT_Face ttface = (TT_Face)size->face; |
348 | SFNT_Service sfnt = (SFNT_Service)ttface->sfnt; |
349 | FT_ULong strike_index; |
350 | |
351 | |
352 | error = sfnt->set_sbit_strike( ttface, req, &strike_index ); |
353 | |
354 | if ( error ) |
355 | ttsize->strike_index = 0xFFFFFFFFUL; |
356 | else |
357 | return tt_size_select( size, strike_index ); |
358 | } |
359 | |
360 | #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ |
361 | |
362 | { |
363 | FT_Error err = FT_Request_Metrics( size->face, req ); |
364 | |
365 | |
366 | if ( err ) |
367 | { |
368 | error = err; |
369 | goto Exit; |
370 | } |
371 | } |
372 | |
373 | if ( FT_IS_SCALABLE( size->face ) ) |
374 | { |
375 | error = tt_size_reset( ttsize ); |
376 | |
377 | #ifdef TT_USE_BYTECODE_INTERPRETER |
378 | /* for the `MPS' bytecode instruction we need the point size */ |
379 | if ( !error ) |
380 | { |
381 | FT_UInt resolution = |
382 | ttsize->metrics->x_ppem > ttsize->metrics->y_ppem |
383 | ? req->horiResolution |
384 | : req->vertResolution; |
385 | |
386 | |
387 | /* if we don't have a resolution value, assume 72dpi */ |
388 | if ( req->type == FT_SIZE_REQUEST_TYPE_SCALES || |
389 | !resolution ) |
390 | resolution = 72; |
391 | |
392 | ttsize->point_size = FT_MulDiv( ttsize->ttmetrics.ppem, |
393 | 64 * 72, |
394 | resolution ); |
395 | } |
396 | #endif |
397 | } |
398 | |
399 | Exit: |
400 | return error; |
401 | } |
402 | |
403 | |
404 | /************************************************************************** |
405 | * |
406 | * @Function: |
407 | * tt_glyph_load |
408 | * |
409 | * @Description: |
410 | * A driver method used to load a glyph within a given glyph slot. |
411 | * |
412 | * @Input: |
413 | * slot :: |
414 | * A handle to the target slot object where the glyph |
415 | * will be loaded. |
416 | * |
417 | * size :: |
418 | * A handle to the source face size at which the glyph |
419 | * must be scaled, loaded, etc. |
420 | * |
421 | * glyph_index :: |
422 | * The index of the glyph in the font file. |
423 | * |
424 | * load_flags :: |
425 | * A flag indicating what to load for this glyph. The |
426 | * FT_LOAD_XXX constants can be used to control the |
427 | * glyph loading process (e.g., whether the outline |
428 | * should be scaled, whether to load bitmaps or not, |
429 | * whether to hint the outline, etc). |
430 | * |
431 | * @Return: |
432 | * FreeType error code. 0 means success. |
433 | */ |
434 | FT_CALLBACK_DEF( FT_Error ) |
435 | tt_glyph_load( FT_GlyphSlot slot, /* TT_GlyphSlot */ |
436 | FT_Size size, /* TT_Size */ |
437 | FT_UInt glyph_index, |
438 | FT_Int32 load_flags ) |
439 | { |
440 | TT_GlyphSlot ttslot = (TT_GlyphSlot)slot; |
441 | TT_Size ttsize = (TT_Size)size; |
442 | FT_Face face = ttslot->face; |
443 | FT_Error error; |
444 | |
445 | |
446 | if ( !slot ) |
447 | return FT_THROW( Invalid_Slot_Handle ); |
448 | |
449 | if ( !size ) |
450 | return FT_THROW( Invalid_Size_Handle ); |
451 | |
452 | if ( !face ) |
453 | return FT_THROW( Invalid_Face_Handle ); |
454 | |
455 | #ifdef FT_CONFIG_OPTION_INCREMENTAL |
456 | if ( glyph_index >= (FT_UInt)face->num_glyphs && |
457 | !face->internal->incremental_interface ) |
458 | #else |
459 | if ( glyph_index >= (FT_UInt)face->num_glyphs ) |
460 | #endif |
461 | return FT_THROW( Invalid_Argument ); |
462 | |
463 | if ( load_flags & FT_LOAD_NO_HINTING ) |
464 | { |
465 | /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT */ |
466 | /* are necessary to disable hinting for tricky fonts */ |
467 | |
468 | if ( FT_IS_TRICKY( face ) ) |
469 | load_flags &= ~FT_LOAD_NO_HINTING; |
470 | |
471 | if ( load_flags & FT_LOAD_NO_AUTOHINT ) |
472 | load_flags |= FT_LOAD_NO_HINTING; |
473 | } |
474 | |
475 | if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) ) |
476 | { |
477 | load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE; |
478 | |
479 | if ( !FT_IS_TRICKY( face ) ) |
480 | load_flags |= FT_LOAD_NO_HINTING; |
481 | } |
482 | |
483 | /* use hinted metrics only if we load a glyph with hinting */ |
484 | ttsize->metrics = ( load_flags & FT_LOAD_NO_HINTING ) |
485 | ? &size->metrics |
486 | : &ttsize->hinted_metrics; |
487 | |
488 | /* now fill in the glyph slot with outline/bitmap/layered */ |
489 | error = TT_Load_Glyph( ttsize, ttslot, glyph_index, load_flags ); |
490 | |
491 | /* force drop-out mode to 2 - irrelevant now */ |
492 | /* slot->outline.dropout_mode = 2; */ |
493 | |
494 | return error; |
495 | } |
496 | |
497 | |
498 | /*************************************************************************/ |
499 | /*************************************************************************/ |
500 | /*************************************************************************/ |
501 | /**** ****/ |
502 | /**** ****/ |
503 | /**** D R I V E R I N T E R F A C E ****/ |
504 | /**** ****/ |
505 | /**** ****/ |
506 | /*************************************************************************/ |
507 | /*************************************************************************/ |
508 | /*************************************************************************/ |
509 | |
510 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
511 | |
512 | FT_DEFINE_SERVICE_MULTIMASTERSREC( |
513 | tt_service_gx_multi_masters, |
514 | |
515 | NULL, /* FT_Get_MM_Func get_mm */ |
516 | NULL, /* FT_Set_MM_Design_Func set_mm_design */ |
517 | TT_Set_MM_Blend, /* FT_Set_MM_Blend_Func set_mm_blend */ |
518 | TT_Get_MM_Blend, /* FT_Get_MM_Blend_Func get_mm_blend */ |
519 | TT_Get_MM_Var, /* FT_Get_MM_Var_Func get_mm_var */ |
520 | TT_Set_Var_Design, /* FT_Set_Var_Design_Func set_var_design */ |
521 | TT_Get_Var_Design, /* FT_Get_Var_Design_Func get_var_design */ |
522 | TT_Set_Named_Instance, /* FT_Set_Named_Instance_Func set_named_instance */ |
523 | TT_Get_Default_Named_Instance, |
524 | /* FT_Get_Default_Named_Instance_Func get_default_named_instance */ |
525 | NULL, /* FT_Set_MM_WeightVector_Func set_mm_weightvector */ |
526 | NULL, /* FT_Get_MM_WeightVector_Func get_mm_weightvector */ |
527 | |
528 | tt_construct_ps_name, /* FT_Construct_PS_Name_Func construct_ps_name */ |
529 | tt_var_load_delta_set_index_mapping, |
530 | /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map */ |
531 | tt_var_load_item_variation_store, |
532 | /* FT_Var_Load_Item_Var_Store_Func load_item_variation_store */ |
533 | tt_var_get_item_delta, /* FT_Var_Get_Item_Delta_Func get_item_delta */ |
534 | tt_var_done_item_variation_store, |
535 | /* FT_Var_Done_Item_Var_Store_Func done_item_variation_store */ |
536 | tt_var_done_delta_set_index_map, |
537 | /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map */ |
538 | tt_get_var_blend, /* FT_Get_Var_Blend_Func get_var_blend */ |
539 | tt_done_blend /* FT_Done_Blend_Func done_blend */ |
540 | ) |
541 | |
542 | FT_DEFINE_SERVICE_METRICSVARIATIONSREC( |
543 | tt_service_metrics_variations, |
544 | |
545 | tt_hadvance_adjust, /* FT_HAdvance_Adjust_Func hadvance_adjust */ |
546 | NULL, /* FT_LSB_Adjust_Func lsb_adjust */ |
547 | NULL, /* FT_RSB_Adjust_Func rsb_adjust */ |
548 | |
549 | tt_vadvance_adjust, /* FT_VAdvance_Adjust_Func vadvance_adjust */ |
550 | NULL, /* FT_TSB_Adjust_Func tsb_adjust */ |
551 | NULL, /* FT_BSB_Adjust_Func bsb_adjust */ |
552 | NULL, /* FT_VOrg_Adjust_Func vorg_adjust */ |
553 | |
554 | tt_apply_mvar, /* FT_Metrics_Adjust_Func metrics_adjust */ |
555 | tt_size_reset_height /* FT_Size_Reset_Func size_reset */ |
556 | ) |
557 | |
558 | #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ |
559 | |
560 | |
561 | static const FT_Service_TrueTypeEngineRec tt_service_truetype_engine = |
562 | { |
563 | #ifdef TT_USE_BYTECODE_INTERPRETER |
564 | |
565 | FT_TRUETYPE_ENGINE_TYPE_PATENTED |
566 | |
567 | #else /* !TT_USE_BYTECODE_INTERPRETER */ |
568 | |
569 | FT_TRUETYPE_ENGINE_TYPE_NONE |
570 | |
571 | #endif /* TT_USE_BYTECODE_INTERPRETER */ |
572 | }; |
573 | |
574 | |
575 | FT_DEFINE_SERVICE_TTGLYFREC( |
576 | tt_service_truetype_glyf, |
577 | |
578 | (TT_Glyf_GetLocationFunc)tt_face_get_location /* get_location */ |
579 | ) |
580 | |
581 | |
582 | #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT |
583 | FT_DEFINE_SERVICEDESCREC6( |
584 | tt_services, |
585 | |
586 | FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE, |
587 | FT_SERVICE_ID_MULTI_MASTERS, &tt_service_gx_multi_masters, |
588 | FT_SERVICE_ID_METRICS_VARIATIONS, &tt_service_metrics_variations, |
589 | FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, |
590 | FT_SERVICE_ID_TT_GLYF, &tt_service_truetype_glyf, |
591 | FT_SERVICE_ID_PROPERTIES, &tt_service_properties ) |
592 | #else |
593 | FT_DEFINE_SERVICEDESCREC4( |
594 | tt_services, |
595 | |
596 | FT_SERVICE_ID_FONT_FORMAT, FT_FONT_FORMAT_TRUETYPE, |
597 | FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine, |
598 | FT_SERVICE_ID_TT_GLYF, &tt_service_truetype_glyf, |
599 | FT_SERVICE_ID_PROPERTIES, &tt_service_properties ) |
600 | #endif |
601 | |
602 | |
603 | FT_CALLBACK_DEF( FT_Module_Interface ) |
604 | tt_get_interface( FT_Module driver, /* TT_Driver */ |
605 | const char* tt_interface ) |
606 | { |
607 | FT_Library library; |
608 | FT_Module_Interface result; |
609 | FT_Module sfntd; |
610 | SFNT_Service sfnt; |
611 | |
612 | |
613 | result = ft_service_list_lookup( tt_services, tt_interface ); |
614 | if ( result ) |
615 | return result; |
616 | |
617 | if ( !driver ) |
618 | return NULL; |
619 | library = driver->library; |
620 | if ( !library ) |
621 | return NULL; |
622 | |
623 | /* only return the default interface from the SFNT module */ |
624 | sfntd = FT_Get_Module( library, "sfnt" ); |
625 | if ( sfntd ) |
626 | { |
627 | sfnt = (SFNT_Service)( sfntd->clazz->module_interface ); |
628 | if ( sfnt ) |
629 | return sfnt->get_interface( driver, tt_interface ); |
630 | } |
631 | |
632 | return 0; |
633 | } |
634 | |
635 | |
636 | /* The FT_DriverInterface structure is defined in ftdriver.h. */ |
637 | |
638 | #ifdef TT_USE_BYTECODE_INTERPRETER |
639 | #define TT_HINTER_FLAG FT_MODULE_DRIVER_HAS_HINTER |
640 | #else |
641 | #define TT_HINTER_FLAG 0 |
642 | #endif |
643 | |
644 | #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS |
645 | #define TT_SIZE_SELECT tt_size_select |
646 | #else |
647 | #define TT_SIZE_SELECT 0 |
648 | #endif |
649 | |
650 | FT_DEFINE_DRIVER( |
651 | tt_driver_class, |
652 | |
653 | FT_MODULE_FONT_DRIVER | |
654 | FT_MODULE_DRIVER_SCALABLE | |
655 | TT_HINTER_FLAG, |
656 | |
657 | sizeof ( TT_DriverRec ), |
658 | |
659 | "truetype" , /* driver name */ |
660 | 0x10000L, /* driver version == 1.0 */ |
661 | 0x20000L, /* driver requires FreeType 2.0 or above */ |
662 | |
663 | NULL, /* module-specific interface */ |
664 | |
665 | tt_driver_init, /* FT_Module_Constructor module_init */ |
666 | tt_driver_done, /* FT_Module_Destructor module_done */ |
667 | tt_get_interface, /* FT_Module_Requester get_interface */ |
668 | |
669 | sizeof ( TT_FaceRec ), |
670 | sizeof ( TT_SizeRec ), |
671 | sizeof ( FT_GlyphSlotRec ), |
672 | |
673 | tt_face_init, /* FT_Face_InitFunc init_face */ |
674 | tt_face_done, /* FT_Face_DoneFunc done_face */ |
675 | tt_size_init, /* FT_Size_InitFunc init_size */ |
676 | tt_size_done, /* FT_Size_DoneFunc done_size */ |
677 | tt_slot_init, /* FT_Slot_InitFunc init_slot */ |
678 | NULL, /* FT_Slot_DoneFunc done_slot */ |
679 | |
680 | tt_glyph_load, /* FT_Slot_LoadFunc load_glyph */ |
681 | |
682 | tt_get_kerning, /* FT_Face_GetKerningFunc get_kerning */ |
683 | NULL, /* FT_Face_AttachFunc attach_file */ |
684 | tt_get_advances, /* FT_Face_GetAdvancesFunc get_advances */ |
685 | |
686 | tt_size_request, /* FT_Size_RequestFunc request_size */ |
687 | TT_SIZE_SELECT /* FT_Size_SelectFunc select_size */ |
688 | ) |
689 | |
690 | |
691 | /* END */ |
692 | |