update for HEAD-2003050101
[reactos.git] / lib / freetype / src / cff / cffobjs.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffobjs.c                                                              */
4 /*                                                                         */
5 /*    OpenType objects manager (body).                                     */
6 /*                                                                         */
7 /*  Copyright 1996-2001, 2002 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_CALC_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_ERRORS_H
24 #include FT_TRUETYPE_IDS_H
25 #include FT_TRUETYPE_TAGS_H
26 #include FT_INTERNAL_SFNT_H
27 #include FT_INTERNAL_POSTSCRIPT_NAMES_H
28 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
29 #include "cffobjs.h"
30 #include "cffload.h"
31 #include "cffcmap.h"
32 #include "cfferrs.h"
33
34
35   /*************************************************************************/
36   /*                                                                       */
37   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
38   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
39   /* messages during execution.                                            */
40   /*                                                                       */
41 #undef  FT_COMPONENT
42 #define FT_COMPONENT  trace_cffobjs
43
44
45   /*************************************************************************/
46   /*                                                                       */
47   /*                            SIZE FUNCTIONS                             */
48   /*                                                                       */
49   /*  Note that we store the global hints in the size's "internal" root    */
50   /*  field.                                                               */
51   /*                                                                       */
52   /*************************************************************************/
53
54
55   static PSH_Globals_Funcs
56   cff_size_get_globals_funcs( CFF_Size  size )
57   {
58     CFF_Face          face     = (CFF_Face)size->face;
59     CFF_Font          font     = (CFF_FontRec *)face->extra.data;
60     PSHinter_Service  pshinter = (PSHinter_Service)font->pshinter;
61     FT_Module         module;
62
63
64     module = FT_Get_Module( size->face->driver->root.library,
65                             "pshinter" );
66     return ( module && pshinter && pshinter->get_globals_funcs )
67            ? pshinter->get_globals_funcs( module )
68            : 0;
69   }
70
71
72   FT_LOCAL_DEF( void )
73   cff_size_done( CFF_Size  size )
74   {
75     if ( size->internal )
76     {
77       PSH_Globals_Funcs  funcs;
78
79
80       funcs = cff_size_get_globals_funcs( size );
81       if ( funcs )
82         funcs->destroy( (PSH_Globals)size->internal );
83
84       size->internal = 0;
85     }
86   }
87
88
89   FT_LOCAL_DEF( FT_Error )
90   cff_size_init( CFF_Size  size )
91   {
92     FT_Error           error = 0;
93     PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
94
95
96     if ( funcs )
97     {
98       PSH_Globals    globals;
99       CFF_Face       face    = (CFF_Face)size->face;
100       CFF_Font       font    = (CFF_FontRec *)face->extra.data;
101       CFF_SubFont    subfont = &font->top_font;
102
103       CFF_Private    cpriv   = &subfont->private_dict;
104       PS_PrivateRec  priv;
105
106
107       /* IMPORTANT: The CFF and Type1 private dictionaries have    */
108       /*            slightly different structures; we need to      */
109       /*            synthetize a type1 dictionary on the fly here. */
110
111       {
112         FT_UInt  n, count;
113
114
115         FT_MEM_ZERO( &priv, sizeof ( priv ) );
116
117         count = priv.num_blue_values = cpriv->num_blue_values;
118         for ( n = 0; n < count; n++ )
119           priv.blue_values[n] = (FT_Short)cpriv->blue_values[n];
120
121         count = priv.num_other_blues = cpriv->num_other_blues;
122         for ( n = 0; n < count; n++ )
123           priv.other_blues[n] = (FT_Short)cpriv->other_blues[n];
124
125         count = priv.num_family_blues = cpriv->num_family_blues;
126         for ( n = 0; n < count; n++ )
127           priv.family_blues[n] = (FT_Short)cpriv->family_blues[n];
128
129         count = priv.num_family_other_blues = cpriv->num_family_other_blues;
130         for ( n = 0; n < count; n++ )
131           priv.family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
132
133         priv.blue_scale = cpriv->blue_scale;
134         priv.blue_shift = (FT_Int)cpriv->blue_shift;
135         priv.blue_fuzz  = (FT_Int)cpriv->blue_fuzz;
136
137         priv.standard_width[0]  = (FT_UShort)cpriv->standard_width;
138         priv.standard_height[0] = (FT_UShort)cpriv->standard_height;
139
140         count = priv.num_snap_widths = cpriv->num_snap_widths;
141         for ( n = 0; n < count; n++ )
142           priv.snap_widths[n] = (FT_Short)cpriv->snap_widths[n];
143
144         count = priv.num_snap_heights = cpriv->num_snap_heights;
145         for ( n = 0; n < count; n++ )
146           priv.snap_heights[n] = (FT_Short)cpriv->snap_heights[n];
147
148         priv.force_bold     = cpriv->force_bold;
149         priv.language_group = cpriv->language_group;
150         priv.lenIV          = cpriv->lenIV;
151       }
152
153       error = funcs->create( size->face->memory, &priv, &globals );
154       if ( !error )
155         size->internal = (FT_Size_Internal)(void*)globals;
156     }
157
158     return error;
159   }
160
161
162   FT_LOCAL_DEF( FT_Error )
163   cff_size_reset( CFF_Size  size )
164   {
165     PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
166     FT_Error           error = 0;
167
168
169     if ( funcs )
170       error = funcs->set_scale( (PSH_Globals)size->internal,
171                                  size->metrics.x_scale,
172                                  size->metrics.y_scale,
173                                  0, 0 );
174     return error;
175   }
176
177
178   /*************************************************************************/
179   /*                                                                       */
180   /*                            SLOT  FUNCTIONS                            */
181   /*                                                                       */
182   /*************************************************************************/
183
184   FT_LOCAL_DEF( void )
185   cff_slot_done( CFF_GlyphSlot  slot )
186   {
187     slot->root.internal->glyph_hints = 0;
188   }
189
190
191   FT_LOCAL_DEF( FT_Error )
192   cff_slot_init( CFF_GlyphSlot  slot )
193   {
194     CFF_Face          face     = (CFF_Face)slot->root.face;
195     CFF_Font          font     = (CFF_FontRec *)face->extra.data;
196     PSHinter_Service  pshinter = (PSHinter_Service)font->pshinter;
197
198
199     if ( pshinter )
200     {
201       FT_Module  module;
202
203
204       module = FT_Get_Module( slot->root.face->driver->root.library,
205                               "pshinter" );
206       if ( module )
207       {
208         T2_Hints_Funcs  funcs;
209
210
211         funcs = pshinter->get_t2_funcs( module );
212         slot->root.internal->glyph_hints = (void*)funcs;
213       }
214     }
215
216     return 0;
217   }
218
219
220   /*************************************************************************/
221   /*                                                                       */
222   /*                           FACE  FUNCTIONS                             */
223   /*                                                                       */
224   /*************************************************************************/
225
226   static FT_String*
227   cff_strcpy( FT_Memory         memory,
228               const FT_String*  source )
229   {
230     FT_Error    error;
231     FT_String*  result = 0;
232     FT_Int      len = (FT_Int)ft_strlen( source );
233
234
235     if ( !FT_ALLOC( result, len + 1 ) )
236     {
237       FT_MEM_COPY( result, source, len );
238       result[len] = 0;
239     }
240
241     FT_UNUSED( error );
242
243     return result;
244   }
245
246
247
248
249   FT_LOCAL_DEF( FT_Error )
250   cff_face_init( FT_Stream      stream,
251                  CFF_Face       face,
252                  FT_Int         face_index,
253                  FT_Int         num_params,
254                  FT_Parameter*  params )
255   {
256     FT_Error          error;
257     SFNT_Service      sfnt;
258     PSNames_Service   psnames;
259     PSHinter_Service  pshinter;
260     FT_Bool           pure_cff    = 1;
261     FT_Bool           sfnt_format = 0;
262
263
264     sfnt = (SFNT_Service)FT_Get_Module_Interface(
265              face->root.driver->root.library, "sfnt" );
266     if ( !sfnt )
267       goto Bad_Format;
268
269     psnames = (PSNames_Service)FT_Get_Module_Interface(
270                 face->root.driver->root.library, "psnames" );
271
272     pshinter = (PSHinter_Service)FT_Get_Module_Interface(
273                  face->root.driver->root.library, "pshinter" );
274
275     /* create input stream from resource */
276     if ( FT_STREAM_SEEK( 0 ) )
277       goto Exit;
278
279     /* check that we have a valid OpenType file */
280     error = sfnt->init_face( stream, face, face_index, num_params, params );
281     if ( !error )
282     {
283       if ( face->format_tag != 0x4F54544FL )  /* `OTTO'; OpenType/CFF font */
284       {
285         FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
286         goto Bad_Format;
287       }
288
289       /* if we are performing a simple font format check, exit immediately */
290       if ( face_index < 0 )
291         return CFF_Err_Ok;
292
293       sfnt_format = 1;
294
295       /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
296       /* font in the later case; it doesn't have a `head' table          */
297       error = face->goto_table( face, TTAG_head, stream, 0 );
298       if ( !error )
299       {
300         pure_cff = 0;
301
302         /* load font directory */
303         error = sfnt->load_face( stream, face,
304                                  face_index, num_params, params );
305         if ( error )
306           goto Exit;
307       }
308       else
309       {
310         /* load the `cmap' table by hand */
311         error = sfnt->load_charmaps( face, stream );
312         if ( error )
313           goto Exit;
314
315         /* XXX: we don't load the GPOS table, as OpenType Layout     */
316         /* support will be added later to a layout library on top of */
317         /* FreeType 2                                                */
318       }
319
320       /* now, load the CFF part of the file */
321       error = face->goto_table( face, TTAG_CFF, stream, 0 );
322       if ( error )
323         goto Exit;
324     }
325     else
326     {
327       /* rewind to start of file; we are going to load a pure-CFF font */
328       if ( FT_STREAM_SEEK( 0 ) )
329         goto Exit;
330       error = CFF_Err_Ok;
331     }
332
333     /* now load and parse the CFF table in the file */
334     {
335       CFF_Font   cff;
336       FT_Memory  memory = face->root.memory;
337       FT_Face    root;
338       FT_Int32   flags;
339
340
341       if ( FT_NEW( cff ) )
342         goto Exit;
343
344       face->extra.data = cff;
345       error = cff_font_load( stream, face_index, cff );
346       if ( error )
347         goto Exit;
348
349       cff->pshinter = pshinter;
350       cff->psnames  = psnames;
351
352       /* Complement the root flags with some interesting information. */
353       /* Note that this is only necessary for pure CFF and CEF fonts. */
354
355       root             = &face->root;
356       root->num_glyphs = cff->num_glyphs;
357
358       if ( pure_cff )
359       {
360         CFF_FontRecDict  dict = &cff->top_font.font_dict;
361
362
363         /* we need the `PSNames' module for pure-CFF and CEF formats */
364         if ( !psnames )
365         {
366           FT_ERROR(( "cff_face_init:" ));
367           FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
368           FT_ERROR(( "              " ));
369           FT_ERROR(( " without the `PSNames' module\n" ));
370           goto Bad_Format;
371         }
372
373         /* Set up num_faces. */
374         root->num_faces = cff->num_faces;
375
376         /* compute number of glyphs */
377         if ( dict->cid_registry )
378           root->num_glyphs = dict->cid_count;
379         else
380           root->num_glyphs = cff->charstrings_index.count;
381
382         /* set global bbox, as well as EM size */
383         root->bbox.xMin =   dict->font_bbox.xMin             >> 16;
384         root->bbox.yMin =   dict->font_bbox.yMin             >> 16;
385         root->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16;
386         root->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16;
387
388
389         root->ascender  = (FT_Short)( root->bbox.yMax );
390         root->descender = (FT_Short)( root->bbox.yMin );
391         root->height    = (FT_Short)(
392           ( ( root->ascender - root->descender ) * 12 ) / 10 );
393
394         if ( dict->units_per_em )
395           root->units_per_EM = dict->units_per_em;
396         else
397           root->units_per_EM = 1000;
398
399         /* retrieve font family & style name */
400         root->family_name  = cff_index_get_name( &cff->name_index, face_index );
401         if ( dict->cid_registry )
402           root->style_name = cff_strcpy( memory, "Regular" );  /* XXXX */
403         else
404           root->style_name = cff_index_get_sid_string( &cff->string_index,
405                                                        dict->weight,
406                                                        psnames );
407
408         /*******************************************************************/
409         /*                                                                 */
410         /* Compute face flags.                                             */
411         /*                                                                 */
412         flags = FT_FACE_FLAG_SCALABLE  |    /* scalable outlines */
413                 FT_FACE_FLAG_HORIZONTAL;    /* horizontal data   */
414
415         if ( sfnt_format )
416           flags |= FT_FACE_FLAG_SFNT;
417
418         /* fixed width font? */
419         if ( dict->is_fixed_pitch )
420           flags |= FT_FACE_FLAG_FIXED_WIDTH;
421
422   /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
423 #if 0
424         /* kerning available? */
425         if ( face->kern_pairs )
426           flags |= FT_FACE_FLAG_KERNING;
427 #endif
428
429 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
430         flags |= FT_FACE_FLAG_GLYPH_NAMES;
431 #endif
432
433         root->face_flags = flags;
434
435         /*******************************************************************/
436         /*                                                                 */
437         /* Compute style flags.                                            */
438         /*                                                                 */
439         flags = 0;
440
441         if ( dict->italic_angle )
442           flags |= FT_STYLE_FLAG_ITALIC;
443
444         /* XXX: may not be correct */
445         if ( cff->top_font.private_dict.force_bold )
446           flags |= FT_STYLE_FLAG_BOLD;
447
448         root->style_flags = flags;
449       }
450
451       /*******************************************************************/
452       /*                                                                 */
453       /* Compute char maps.                                              */
454       /*                                                                 */
455
456       /* Try to synthetize a Unicode charmap if there is none available */
457       /* already.  If an OpenType font contains a Unicode "cmap", we    */
458       /* will use it, whatever be in the CFF part of the file.          */
459       {
460         FT_CharMapRec  cmaprec;
461         FT_CharMap     cmap;
462         FT_UInt        nn;
463         CFF_Encoding   encoding = &cff->encoding;
464
465
466         for ( nn = 0; nn < (FT_UInt) root->num_charmaps; nn++ )
467         {
468           cmap = root->charmaps[nn];
469
470           /* Windows Unicode (3,1)? */
471           if ( cmap->platform_id == 3 && cmap->encoding_id == 1 )
472             goto Skip_Unicode;
473
474           /* Deprecated Unicode platform id? */
475           if ( cmap->platform_id == 0 )
476             goto Skip_Unicode; /* Standard Unicode (deprecated) */
477         }
478
479         /* we didn't find a Unicode charmap, synthetize one */
480         cmaprec.face        = root;
481         cmaprec.platform_id = 3;
482         cmaprec.encoding_id = 1;
483         cmaprec.encoding    = FT_ENCODING_UNICODE;
484
485         nn = (FT_UInt) root->num_charmaps;
486
487         FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL );
488
489         /* if no Unicode charmap was previously selected, select this one */
490         if ( root->charmap == NULL && nn != (FT_UInt) root->num_charmaps )
491           root->charmap = root->charmaps[nn];
492
493       Skip_Unicode:
494         if ( encoding->count > 0 )
495         {
496           FT_CMap_Class  clazz;
497
498
499           cmaprec.face        = root;
500           cmaprec.platform_id = 7;  /* Adobe platform id */
501
502           if ( encoding->offset == 0 )
503           {
504             cmaprec.encoding_id = 0;
505             cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
506             clazz               = &cff_cmap_encoding_class_rec;
507           }
508           else if ( encoding->offset == 1 )
509           {
510             cmaprec.encoding_id = 1;
511             cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
512             clazz               = &cff_cmap_encoding_class_rec;
513           }
514           else
515           {
516             cmaprec.encoding_id = 3;
517             cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
518             clazz               = &cff_cmap_encoding_class_rec;
519           }
520
521           FT_CMap_New( clazz, NULL, &cmaprec, NULL );
522         }
523
524       }
525     }
526
527   Exit:
528     return error;
529
530   Bad_Format:
531     error = CFF_Err_Unknown_File_Format;
532     goto Exit;
533   }
534
535
536   FT_LOCAL_DEF( void )
537   cff_face_done( CFF_Face  face )
538   {
539     FT_Memory     memory = face->root.memory;
540     SFNT_Service  sfnt   = (SFNT_Service)face->sfnt;
541
542
543     if ( sfnt )
544       sfnt->done_face( face );
545
546     {
547       CFF_Font  cff = (CFF_Font)face->extra.data;
548
549
550       if ( cff )
551       {
552         cff_font_done( cff );
553         FT_FREE( face->extra.data );
554       }
555     }
556   }
557
558
559   FT_LOCAL_DEF( FT_Error )
560   cff_driver_init( CFF_Driver  driver )
561   {
562     FT_UNUSED( driver );
563
564     return CFF_Err_Ok;
565   }
566
567
568   FT_LOCAL_DEF( void )
569   cff_driver_done( CFF_Driver  driver )
570   {
571     FT_UNUSED( driver );
572   }
573
574
575 /* END */