Create a branch for header work.
[reactos.git] / lib / 3rdparty / freetype / src / cff / cffdrivr.c
1 /***************************************************************************/
2 /* */
3 /* cffdrivr.c */
4 /* */
5 /* OpenType font driver implementation (body). */
6 /* */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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_FREETYPE_H
21 #include FT_INTERNAL_DEBUG_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_INTERNAL_SFNT_H
24 #include FT_TRUETYPE_IDS_H
25 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
26 #include FT_SERVICE_POSTSCRIPT_INFO_H
27 #include FT_SERVICE_TT_CMAP_H
28
29 #include "cffdrivr.h"
30 #include "cffgload.h"
31 #include "cffload.h"
32 #include "cffcmap.h"
33
34 #include "cfferrs.h"
35
36 #include FT_SERVICE_XFREE86_NAME_H
37 #include FT_SERVICE_GLYPH_DICT_H
38
39 /*************************************************************************/
40 /* */
41 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
42 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
43 /* messages during execution. */
44 /* */
45 #undef FT_COMPONENT
46 #define FT_COMPONENT trace_cffdriver
47
48
49 /*************************************************************************/
50 /*************************************************************************/
51 /*************************************************************************/
52 /**** ****/
53 /**** ****/
54 /**** F A C E S ****/
55 /**** ****/
56 /**** ****/
57 /*************************************************************************/
58 /*************************************************************************/
59 /*************************************************************************/
60
61
62 #undef PAIR_TAG
63 #define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \
64 (FT_ULong)right )
65
66
67 /*************************************************************************/
68 /* */
69 /* <Function> */
70 /* cff_get_kerning */
71 /* */
72 /* <Description> */
73 /* A driver method used to return the kerning vector between two */
74 /* glyphs of the same face. */
75 /* */
76 /* <Input> */
77 /* face :: A handle to the source face object. */
78 /* */
79 /* left_glyph :: The index of the left glyph in the kern pair. */
80 /* */
81 /* right_glyph :: The index of the right glyph in the kern pair. */
82 /* */
83 /* <Output> */
84 /* kerning :: The kerning vector. This is in font units for */
85 /* scalable formats, and in pixels for fixed-sizes */
86 /* formats. */
87 /* */
88 /* <Return> */
89 /* FreeType error code. 0 means success. */
90 /* */
91 /* <Note> */
92 /* Only horizontal layouts (left-to-right & right-to-left) are */
93 /* supported by this function. Other layouts, or more sophisticated */
94 /* kernings, are out of scope of this method (the basic driver */
95 /* interface is meant to be simple). */
96 /* */
97 /* They can be implemented by format-specific interfaces. */
98 /* */
99 FT_CALLBACK_DEF( FT_Error )
100 cff_get_kerning( FT_Face ttface, /* TT_Face */
101 FT_UInt left_glyph,
102 FT_UInt right_glyph,
103 FT_Vector* kerning )
104 {
105 TT_Face face = (TT_Face)ttface;
106 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
107
108
109 kerning->x = 0;
110 kerning->y = 0;
111
112 if ( sfnt )
113 kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
114
115 return CFF_Err_Ok;
116 }
117
118
119 #undef PAIR_TAG
120
121
122 /*************************************************************************/
123 /* */
124 /* <Function> */
125 /* Load_Glyph */
126 /* */
127 /* <Description> */
128 /* A driver method used to load a glyph within a given glyph slot. */
129 /* */
130 /* <Input> */
131 /* slot :: A handle to the target slot object where the glyph */
132 /* will be loaded. */
133 /* */
134 /* size :: A handle to the source face size at which the glyph */
135 /* must be scaled, loaded, etc. */
136 /* */
137 /* glyph_index :: The index of the glyph in the font file. */
138 /* */
139 /* load_flags :: A flag indicating what to load for this glyph. The */
140 /* FT_LOAD_??? constants can be used to control the */
141 /* glyph loading process (e.g., whether the outline */
142 /* should be scaled, whether to load bitmaps or not, */
143 /* whether to hint the outline, etc). */
144 /* */
145 /* <Return> */
146 /* FreeType error code. 0 means success. */
147 /* */
148 FT_CALLBACK_DEF( FT_Error )
149 Load_Glyph( FT_GlyphSlot cffslot, /* CFF_GlyphSlot */
150 FT_Size cffsize, /* CFF_Size */
151 FT_UInt glyph_index,
152 FT_Int32 load_flags )
153 {
154 FT_Error error;
155 CFF_GlyphSlot slot = (CFF_GlyphSlot)cffslot;
156 CFF_Size size = (CFF_Size)cffsize;
157
158
159 if ( !slot )
160 return CFF_Err_Invalid_Slot_Handle;
161
162 /* check whether we want a scaled outline or bitmap */
163 if ( !size )
164 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
165
166 if ( load_flags & FT_LOAD_NO_SCALE )
167 size = NULL;
168
169 /* reset the size object if necessary */
170 if ( size )
171 {
172 /* these two objects must have the same parent */
173 if ( cffsize->face != cffslot->face )
174 return CFF_Err_Invalid_Face_Handle;
175 }
176
177 /* now load the glyph outline if necessary */
178 error = cff_slot_load( slot, size, glyph_index, load_flags );
179
180 /* force drop-out mode to 2 - irrelevant now */
181 /* slot->outline.dropout_mode = 2; */
182
183 return error;
184 }
185
186
187 /*
188 * GLYPH DICT SERVICE
189 *
190 */
191
192 static FT_Error
193 cff_get_glyph_name( CFF_Face face,
194 FT_UInt glyph_index,
195 FT_Pointer buffer,
196 FT_UInt buffer_max )
197 {
198 CFF_Font font = (CFF_Font)face->extra.data;
199 FT_Memory memory = FT_FACE_MEMORY( face );
200 FT_String* gname;
201 FT_UShort sid;
202 FT_Service_PsCMaps psnames;
203 FT_Error error;
204
205
206 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
207 if ( !psnames )
208 {
209 FT_ERROR(( "cff_get_glyph_name:" ));
210 FT_ERROR(( " cannot get glyph name from CFF & CEF fonts\n" ));
211 FT_ERROR(( " " ));
212 FT_ERROR(( " without the `PSNames' module\n" ));
213 error = CFF_Err_Unknown_File_Format;
214 goto Exit;
215 }
216
217 /* first, locate the sid in the charset table */
218 sid = font->charset.sids[glyph_index];
219
220 /* now, lookup the name itself */
221 gname = cff_index_get_sid_string( &font->string_index, sid, psnames );
222
223 if ( gname )
224 FT_STRCPYN( buffer, gname, buffer_max );
225
226 FT_FREE( gname );
227 error = CFF_Err_Ok;
228
229 Exit:
230 return error;
231 }
232
233
234 static FT_UInt
235 cff_get_name_index( CFF_Face face,
236 FT_String* glyph_name )
237 {
238 CFF_Font cff;
239 CFF_Charset charset;
240 FT_Service_PsCMaps psnames;
241 FT_Memory memory = FT_FACE_MEMORY( face );
242 FT_String* name;
243 FT_UShort sid;
244 FT_UInt i;
245 FT_Int result;
246
247
248 cff = (CFF_FontRec *)face->extra.data;
249 charset = &cff->charset;
250
251 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
252 if ( !psnames )
253 return 0;
254
255 for ( i = 0; i < cff->num_glyphs; i++ )
256 {
257 sid = charset->sids[i];
258
259 if ( sid > 390 )
260 name = cff_index_get_name( &cff->string_index, sid - 391 );
261 else
262 name = (FT_String *)psnames->adobe_std_strings( sid );
263
264 if ( !name )
265 continue;
266
267 result = ft_strcmp( glyph_name, name );
268
269 if ( sid > 390 )
270 FT_FREE( name );
271
272 if ( !result )
273 return i;
274 }
275
276 return 0;
277 }
278
279
280 static const FT_Service_GlyphDictRec cff_service_glyph_dict =
281 {
282 (FT_GlyphDict_GetNameFunc) cff_get_glyph_name,
283 (FT_GlyphDict_NameIndexFunc)cff_get_name_index,
284 };
285
286
287 /*
288 * POSTSCRIPT INFO SERVICE
289 *
290 */
291
292 static FT_Int
293 cff_ps_has_glyph_names( FT_Face face )
294 {
295 return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
296 }
297
298
299 static FT_Error
300 cff_ps_get_font_info( CFF_Face face,
301 PS_FontInfoRec* afont_info )
302 {
303 CFF_Font cff = (CFF_Font)face->extra.data;
304 FT_Error error = FT_Err_Ok;
305
306
307 if ( cff && cff->font_info == NULL )
308 {
309 CFF_FontRecDict dict = &cff->top_font.font_dict;
310 PS_FontInfoRec *font_info;
311 FT_Memory memory = face->root.memory;
312
313
314 if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
315 goto Fail;
316
317 font_info->version = cff_index_get_sid_string( &cff->string_index,
318 dict->version,
319 cff->psnames );
320 font_info->notice = cff_index_get_sid_string( &cff->string_index,
321 dict->notice,
322 cff->psnames );
323 font_info->full_name = cff_index_get_sid_string( &cff->string_index,
324 dict->full_name,
325 cff->psnames );
326 font_info->family_name = cff_index_get_sid_string( &cff->string_index,
327 dict->family_name,
328 cff->psnames );
329 font_info->weight = cff_index_get_sid_string( &cff->string_index,
330 dict->weight,
331 cff->psnames );
332 font_info->italic_angle = dict->italic_angle;
333 font_info->is_fixed_pitch = dict->is_fixed_pitch;
334 font_info->underline_position = (FT_Short)dict->underline_position;
335 font_info->underline_thickness = (FT_Short)dict->underline_thickness;
336
337 cff->font_info = font_info;
338 }
339
340 *afont_info = *cff->font_info;
341
342 Fail:
343 return error;
344 }
345
346
347 static const FT_Service_PsInfoRec cff_service_ps_info =
348 {
349 (PS_GetFontInfoFunc) cff_ps_get_font_info,
350 (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
351 (PS_GetFontPrivateFunc)NULL /* unsupported with CFF fonts */
352 };
353
354
355 /*
356 * TT CMAP INFO
357 *
358 * If the charmap is a synthetic Unicode encoding cmap or
359 * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
360 * service defined in SFNT module.
361 *
362 * Otherwise call the service function in the sfnt module.
363 *
364 */
365 static FT_Error
366 cff_get_cmap_info( FT_CharMap charmap,
367 TT_CMapInfo *cmap_info )
368 {
369 FT_CMap cmap = FT_CMAP( charmap );
370 FT_Error error = CFF_Err_Ok;
371
372
373 cmap_info->language = 0;
374
375 if ( cmap->clazz != &cff_cmap_encoding_class_rec &&
376 cmap->clazz != &cff_cmap_unicode_class_rec )
377 {
378 FT_Face face = FT_CMAP_FACE( cmap );
379 FT_Library library = FT_FACE_LIBRARY( face );
380 FT_Module sfnt = FT_Get_Module( library, "sfnt" );
381 FT_Service_TTCMaps service =
382 (FT_Service_TTCMaps)ft_module_get_service( sfnt,
383 FT_SERVICE_ID_TT_CMAP );
384
385
386 if ( service && service->get_cmap_info )
387 error = service->get_cmap_info( charmap, cmap_info );
388 }
389
390 return error;
391 }
392
393
394 static const FT_Service_TTCMapsRec cff_service_get_cmap_info =
395 {
396 (TT_CMap_Info_GetFunc)cff_get_cmap_info
397 };
398
399
400 /*************************************************************************/
401 /*************************************************************************/
402 /*************************************************************************/
403 /**** ****/
404 /**** ****/
405 /**** D R I V E R I N T E R F A C E ****/
406 /**** ****/
407 /**** ****/
408 /*************************************************************************/
409 /*************************************************************************/
410 /*************************************************************************/
411
412 static const FT_ServiceDescRec cff_services[] =
413 {
414 { FT_SERVICE_ID_XF86_NAME, FT_XF86_FORMAT_CFF },
415 { FT_SERVICE_ID_POSTSCRIPT_INFO, &cff_service_ps_info },
416 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
417 { FT_SERVICE_ID_GLYPH_DICT, &cff_service_glyph_dict },
418 #endif
419 { FT_SERVICE_ID_TT_CMAP, &cff_service_get_cmap_info },
420 { NULL, NULL }
421 };
422
423
424 FT_CALLBACK_DEF( FT_Module_Interface )
425 cff_get_interface( FT_Module driver, /* CFF_Driver */
426 const char* module_interface )
427 {
428 FT_Module sfnt;
429 FT_Module_Interface result;
430
431
432 result = ft_service_list_lookup( cff_services, module_interface );
433 if ( result != NULL )
434 return result;
435
436 /* we pass our request to the `sfnt' module */
437 sfnt = FT_Get_Module( driver->library, "sfnt" );
438
439 return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
440 }
441
442
443 /* The FT_DriverInterface structure is defined in ftdriver.h. */
444
445 FT_CALLBACK_TABLE_DEF
446 const FT_Driver_ClassRec cff_driver_class =
447 {
448 /* begin with the FT_Module_Class fields */
449 {
450 FT_MODULE_FONT_DRIVER |
451 FT_MODULE_DRIVER_SCALABLE |
452 FT_MODULE_DRIVER_HAS_HINTER,
453
454 sizeof( CFF_DriverRec ),
455 "cff",
456 0x10000L,
457 0x20000L,
458
459 0, /* module-specific interface */
460
461 cff_driver_init,
462 cff_driver_done,
463 cff_get_interface,
464 },
465
466 /* now the specific driver fields */
467 sizeof( TT_FaceRec ),
468 sizeof( CFF_SizeRec ),
469 sizeof( CFF_GlyphSlotRec ),
470
471 cff_face_init,
472 cff_face_done,
473 cff_size_init,
474 cff_size_done,
475 cff_slot_init,
476 cff_slot_done,
477
478 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
479 ft_stub_set_char_sizes,
480 ft_stub_set_pixel_sizes,
481 #endif
482
483 Load_Glyph,
484
485 cff_get_kerning,
486 0, /* FT_Face_AttachFunc */
487 0, /* FT_Face_GetAdvancesFunc */
488
489 cff_size_request,
490
491 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
492 cff_size_select
493 #else
494 0 /* FT_Size_SelectFunc */
495 #endif
496 };
497
498
499 /* END */