[FREETYPE] Update to v2.5.5. CORE-8888
[reactos.git] / reactos / lib / 3rdparty / freetype / src / sfnt / sfdriver.c
1 /***************************************************************************/
2 /* */
3 /* sfdriver.c */
4 /* */
5 /* High-level SFNT driver interface (body). */
6 /* */
7 /* Copyright 1996-2007, 2009-2014 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 FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_SFNT_H
22 #include FT_INTERNAL_OBJECTS_H
23
24 #include "sfdriver.h"
25 #include "ttload.h"
26 #include "sfobjs.h"
27 #include "sfntpic.h"
28
29 #include "sferrors.h"
30
31 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
32 #include "ttsbit.h"
33 #endif
34
35 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
36 #include "ttpost.h"
37 #endif
38
39 #ifdef TT_CONFIG_OPTION_BDF
40 #include "ttbdf.h"
41 #include FT_SERVICE_BDF_H
42 #endif
43
44 #include "ttcmap.h"
45 #include "ttkern.h"
46 #include "ttmtx.h"
47
48 #include FT_SERVICE_GLYPH_DICT_H
49 #include FT_SERVICE_POSTSCRIPT_NAME_H
50 #include FT_SERVICE_SFNT_H
51 #include FT_SERVICE_TT_CMAP_H
52
53
54 /*************************************************************************/
55 /* */
56 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
57 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
58 /* messages during execution. */
59 /* */
60 #undef FT_COMPONENT
61 #define FT_COMPONENT trace_sfdriver
62
63
64 /*
65 * SFNT TABLE SERVICE
66 *
67 */
68
69 static void*
70 get_sfnt_table( TT_Face face,
71 FT_Sfnt_Tag tag )
72 {
73 void* table;
74
75
76 switch ( tag )
77 {
78 case FT_SFNT_HEAD:
79 table = &face->header;
80 break;
81
82 case FT_SFNT_HHEA:
83 table = &face->horizontal;
84 break;
85
86 case FT_SFNT_VHEA:
87 table = face->vertical_info ? &face->vertical : NULL;
88 break;
89
90 case FT_SFNT_OS2:
91 table = face->os2.version == 0xFFFFU ? NULL : &face->os2;
92 break;
93
94 case FT_SFNT_POST:
95 table = &face->postscript;
96 break;
97
98 case FT_SFNT_MAXP:
99 table = &face->max_profile;
100 break;
101
102 case FT_SFNT_PCLT:
103 table = face->pclt.Version ? &face->pclt : NULL;
104 break;
105
106 default:
107 table = NULL;
108 }
109
110 return table;
111 }
112
113
114 static FT_Error
115 sfnt_table_info( TT_Face face,
116 FT_UInt idx,
117 FT_ULong *tag,
118 FT_ULong *offset,
119 FT_ULong *length )
120 {
121 if ( !offset || !length )
122 return FT_THROW( Invalid_Argument );
123
124 if ( !tag )
125 *length = face->num_tables;
126 else
127 {
128 if ( idx >= face->num_tables )
129 return FT_THROW( Table_Missing );
130
131 *tag = face->dir_tables[idx].Tag;
132 *offset = face->dir_tables[idx].Offset;
133 *length = face->dir_tables[idx].Length;
134 }
135
136 return FT_Err_Ok;
137 }
138
139
140 FT_DEFINE_SERVICE_SFNT_TABLEREC(
141 sfnt_service_sfnt_table,
142 (FT_SFNT_TableLoadFunc)tt_face_load_any,
143 (FT_SFNT_TableGetFunc) get_sfnt_table,
144 (FT_SFNT_TableInfoFunc)sfnt_table_info )
145
146
147 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
148
149 /*
150 * GLYPH DICT SERVICE
151 *
152 */
153
154 static FT_Error
155 sfnt_get_glyph_name( TT_Face face,
156 FT_UInt glyph_index,
157 FT_Pointer buffer,
158 FT_UInt buffer_max )
159 {
160 FT_String* gname;
161 FT_Error error;
162
163
164 error = tt_face_get_ps_name( face, glyph_index, &gname );
165 if ( !error )
166 FT_STRCPYN( buffer, gname, buffer_max );
167
168 return error;
169 }
170
171
172 static FT_UInt
173 sfnt_get_name_index( TT_Face face,
174 FT_String* glyph_name )
175 {
176 FT_Face root = &face->root;
177
178 FT_UInt i, max_gid = FT_UINT_MAX;
179
180
181 if ( root->num_glyphs < 0 )
182 return 0;
183 else if ( (FT_ULong)root->num_glyphs < FT_UINT_MAX )
184 max_gid = (FT_UInt)root->num_glyphs;
185 else
186 FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
187 FT_UINT_MAX, root->num_glyphs ));
188
189 for ( i = 0; i < max_gid; i++ )
190 {
191 FT_String* gname;
192 FT_Error error = tt_face_get_ps_name( face, i, &gname );
193
194
195 if ( error )
196 continue;
197
198 if ( !ft_strcmp( glyph_name, gname ) )
199 return i;
200 }
201
202 return 0;
203 }
204
205
206 FT_DEFINE_SERVICE_GLYPHDICTREC(
207 sfnt_service_glyph_dict,
208 (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name,
209 (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )
210
211
212 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
213
214
215 /*
216 * POSTSCRIPT NAME SERVICE
217 *
218 */
219
220 static const char*
221 sfnt_get_ps_name( TT_Face face )
222 {
223 FT_Int n, found_win, found_apple;
224 const char* result = NULL;
225
226
227 /* shouldn't happen, but just in case to avoid memory leaks */
228 if ( face->postscript_name )
229 return face->postscript_name;
230
231 /* scan the name table to see whether we have a Postscript name here, */
232 /* either in Macintosh or Windows platform encodings */
233 found_win = -1;
234 found_apple = -1;
235
236 for ( n = 0; n < face->num_names; n++ )
237 {
238 TT_NameEntryRec* name = face->name_table.names + n;
239
240
241 if ( name->nameID == 6 && name->stringLength > 0 )
242 {
243 if ( name->platformID == 3 &&
244 name->encodingID == 1 &&
245 name->languageID == 0x409 )
246 found_win = n;
247
248 if ( name->platformID == 1 &&
249 name->encodingID == 0 &&
250 name->languageID == 0 )
251 found_apple = n;
252 }
253 }
254
255 if ( found_win != -1 )
256 {
257 FT_Memory memory = face->root.memory;
258 TT_NameEntryRec* name = face->name_table.names + found_win;
259 FT_UInt len = name->stringLength / 2;
260 FT_Error error = FT_Err_Ok;
261
262 FT_UNUSED( error );
263
264
265 if ( !FT_ALLOC( result, name->stringLength + 1 ) )
266 {
267 FT_Stream stream = face->name_table.stream;
268 FT_String* r = (FT_String*)result;
269 FT_Byte* p;
270
271
272 if ( FT_STREAM_SEEK( name->stringOffset ) ||
273 FT_FRAME_ENTER( name->stringLength ) )
274 {
275 FT_FREE( result );
276 name->stringLength = 0;
277 name->stringOffset = 0;
278 FT_FREE( name->string );
279
280 goto Exit;
281 }
282
283 p = (FT_Byte*)stream->cursor;
284
285 for ( ; len > 0; len--, p += 2 )
286 {
287 if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )
288 *r++ = p[1];
289 }
290 *r = '\0';
291
292 FT_FRAME_EXIT();
293 }
294 goto Exit;
295 }
296
297 if ( found_apple != -1 )
298 {
299 FT_Memory memory = face->root.memory;
300 TT_NameEntryRec* name = face->name_table.names + found_apple;
301 FT_UInt len = name->stringLength;
302 FT_Error error = FT_Err_Ok;
303
304 FT_UNUSED( error );
305
306
307 if ( !FT_ALLOC( result, len + 1 ) )
308 {
309 FT_Stream stream = face->name_table.stream;
310
311
312 if ( FT_STREAM_SEEK( name->stringOffset ) ||
313 FT_STREAM_READ( result, len ) )
314 {
315 name->stringOffset = 0;
316 name->stringLength = 0;
317 FT_FREE( name->string );
318 FT_FREE( result );
319 goto Exit;
320 }
321 ((char*)result)[len] = '\0';
322 }
323 }
324
325 Exit:
326 face->postscript_name = result;
327 return result;
328 }
329
330
331 FT_DEFINE_SERVICE_PSFONTNAMEREC(
332 sfnt_service_ps_name,
333 (FT_PsName_GetFunc)sfnt_get_ps_name )
334
335
336 /*
337 * TT CMAP INFO
338 */
339 FT_DEFINE_SERVICE_TTCMAPSREC(
340 tt_service_get_cmap_info,
341 (TT_CMap_Info_GetFunc)tt_get_cmap_info )
342
343
344 #ifdef TT_CONFIG_OPTION_BDF
345
346 static FT_Error
347 sfnt_get_charset_id( TT_Face face,
348 const char* *acharset_encoding,
349 const char* *acharset_registry )
350 {
351 BDF_PropertyRec encoding, registry;
352 FT_Error error;
353
354
355 /* XXX: I don't know whether this is correct, since
356 * tt_face_find_bdf_prop only returns something correct if we have
357 * previously selected a size that is listed in the BDF table.
358 * Should we change the BDF table format to include single offsets
359 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
360 */
361 error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
362 if ( !error )
363 {
364 error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
365 if ( !error )
366 {
367 if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
368 encoding.type == BDF_PROPERTY_TYPE_ATOM )
369 {
370 *acharset_encoding = encoding.u.atom;
371 *acharset_registry = registry.u.atom;
372 }
373 else
374 error = FT_THROW( Invalid_Argument );
375 }
376 }
377
378 return error;
379 }
380
381
382 FT_DEFINE_SERVICE_BDFRec(
383 sfnt_service_bdf,
384 (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,
385 (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )
386
387
388 #endif /* TT_CONFIG_OPTION_BDF */
389
390
391 /*
392 * SERVICE LIST
393 */
394
395 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
396 FT_DEFINE_SERVICEDESCREC5(
397 sfnt_services,
398 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
399 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
400 FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET,
401 FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET,
402 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
403 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
404 FT_DEFINE_SERVICEDESCREC4(
405 sfnt_services,
406 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
407 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
408 FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET,
409 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
410 #elif defined TT_CONFIG_OPTION_BDF
411 FT_DEFINE_SERVICEDESCREC4(
412 sfnt_services,
413 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
414 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
415 FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET,
416 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
417 #else
418 FT_DEFINE_SERVICEDESCREC3(
419 sfnt_services,
420 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
421 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
422 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
423 #endif
424
425
426 FT_CALLBACK_DEF( FT_Module_Interface )
427 sfnt_get_interface( FT_Module module,
428 const char* module_interface )
429 {
430 /* SFNT_SERVICES_GET dereferences `library' in PIC mode */
431 #ifdef FT_CONFIG_OPTION_PIC
432 FT_Library library;
433
434
435 if ( !module )
436 return NULL;
437 library = module->library;
438 if ( !library )
439 return NULL;
440 #else
441 FT_UNUSED( module );
442 #endif
443
444 return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface );
445 }
446
447
448 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
449 #define PUT_EMBEDDED_BITMAPS( a ) a
450 #else
451 #define PUT_EMBEDDED_BITMAPS( a ) NULL
452 #endif
453
454 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
455 #define PUT_PS_NAMES( a ) a
456 #else
457 #define PUT_PS_NAMES( a ) NULL
458 #endif
459
460 FT_DEFINE_SFNT_INTERFACE(
461 sfnt_interface,
462 tt_face_goto_table,
463
464 sfnt_init_face,
465 sfnt_load_face,
466 sfnt_done_face,
467 sfnt_get_interface,
468
469 tt_face_load_any,
470
471 tt_face_load_head,
472 tt_face_load_hhea,
473 tt_face_load_cmap,
474 tt_face_load_maxp,
475 tt_face_load_os2,
476 tt_face_load_post,
477
478 tt_face_load_name,
479 tt_face_free_name,
480
481 tt_face_load_kern,
482 tt_face_load_gasp,
483 tt_face_load_pclt,
484
485 /* see `ttload.h' */
486 PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
487
488 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
489
490 /* see `ttpost.h' */
491 PUT_PS_NAMES( tt_face_get_ps_name ),
492 PUT_PS_NAMES( tt_face_free_ps_names ),
493
494 /* since version 2.1.8 */
495 tt_face_get_kerning,
496
497 /* since version 2.2 */
498 tt_face_load_font_dir,
499 tt_face_load_hmtx,
500
501 /* see `ttsbit.h' and `sfnt.h' */
502 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
503 PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
504
505 PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ),
506 PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
507
508 tt_face_get_metrics
509 )
510
511
512 FT_DEFINE_MODULE(
513 sfnt_module_class,
514
515 0, /* not a font driver or renderer */
516 sizeof ( FT_ModuleRec ),
517
518 "sfnt", /* driver name */
519 0x10000L, /* driver version 1.0 */
520 0x20000L, /* driver requires FreeType 2.0 or higher */
521
522 (const void*)&SFNT_INTERFACE_GET, /* module specific interface */
523
524 (FT_Module_Constructor)0,
525 (FT_Module_Destructor) 0,
526 (FT_Module_Requester) sfnt_get_interface )
527
528
529 /* END */