The BIG graph update
[rrdtool.git] / libraries / freetype-2.0.5 / cffobjs.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  cffobjs.c                                                              */
4 /*                                                                         */
5 /*    OpenType objects manager (body).                                     */
6 /*                                                                         */
7 /*  Copyright 1996-2001 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 "cffobjs.h"
29 #include "cffload.h"
30
31 #include "cfferrs.h"
32
33 #include <string.h>         /* for strlen() */
34
35
36   /*************************************************************************/
37   /*                                                                       */
38   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
39   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
40   /* messages during execution.                                            */
41   /*                                                                       */
42 #undef  FT_COMPONENT
43 #define FT_COMPONENT  trace_cffobjs
44
45
46   /*************************************************************************/
47   /*                                                                       */
48   /*                           FACE  FUNCTIONS                             */
49   /*                                                                       */
50   /*************************************************************************/
51
52   static FT_String*
53   CFF_StrCopy( FT_Memory         memory,
54                const FT_String*  source )
55   {
56     FT_Error    error;
57     FT_String*  result = 0;
58     FT_Int      len = (FT_Int)strlen( source );
59
60
61     if ( !ALLOC( result, len + 1 ) )
62     {
63       MEM_Copy( result, source, len );
64       result[len] = 0;
65     }
66     return result;
67   }
68
69
70 #if 0
71
72   /* this function is used to build a Unicode charmap from the glyph names */
73   /* in a file                                                             */
74   static FT_Error
75   CFF_Build_Unicode_Charmap( CFF_Face            face,
76                              FT_ULong            base_offset,
77                              PSNames_Interface*  psnames )
78   {
79     CFF_Font*       font = (CFF_Font*)face->extra.data;
80     FT_Memory       memory = FT_FACE_MEMORY(face);
81     FT_UInt         n, num_glyphs = face->root.num_glyphs;
82     const char**    glyph_names;
83     FT_Error        error;
84     CFF_Font_Dict*  dict = &font->top_font.font_dict;
85     FT_ULong        charset_offset;
86     FT_Byte         format;
87     FT_Stream       stream = face->root.stream;
88
89
90     charset_offset = dict->charset_offset;
91     if ( !charset_offset )
92     {
93       FT_ERROR(( "CFF_Build_Unicode_Charmap: charset table is missing\n" ));
94       error = CFF_Err_Invalid_File_Format;
95       goto Exit;
96     }
97
98     /* allocate the charmap */
99     if ( ALLOC( face->charmap, ...
100
101     /* seek to charset table and allocate glyph names table */
102     if ( FILE_Seek( base_offset + charset_offset )           ||
103          ALLOC_ARRAY( glyph_names, num_glyphs, const char* ) )
104       goto Exit;
105
106     /* now, read each glyph name and store it in the glyph name table */
107     if ( READ_Byte( format ) )
108       goto Fail;
109
110     switch ( format )
111     {
112     case 0:  /* format 0 - one SID per glyph */
113       {
114         const char**  gname = glyph_names;
115         const char**  limit = gname + num_glyphs;
116
117
118         if ( ACCESS_Frame( num_glyphs * 2 ) )
119           goto Fail;
120
121         for ( ; gname < limit; gname++ )
122           gname[0] = CFF_Get_String( &font->string_index,
123                                      GET_UShort(),
124                                      psnames );
125         FORGET_Frame();
126         break;
127       }
128
129     case 1:  /* format 1 - sequential ranges                    */
130     case 2:  /* format 2 - sequential ranges with 16-bit counts */
131       {
132         const char**  gname = glyph_names;
133         const char**  limit = gname + num_glyphs;
134         FT_UInt       len = 3;
135
136
137         if ( format == 2 )
138           len++;
139
140         while ( gname < limit )
141         {
142           FT_UInt  first;
143           FT_UInt  count;
144
145
146           if ( ACCESS_Frame( len ) )
147             goto Fail;
148
149           first = GET_UShort();
150           if ( format == 3 )
151             count = GET_UShort();
152           else
153             count = GET_Byte();
154
155           FORGET_Frame();
156
157           for ( ; count > 0; count-- )
158           {
159             gname[0] = CFF_Get_String( &font->string_index,
160                                        first,
161                                        psnames );
162             gname++;
163             first++;
164           }
165         }
166         break;
167       }
168
169     default:   /* unknown charset format! */
170       FT_ERROR(( "CFF_Build_Unicode_Charmap: unknown charset format!\n" ));
171       error = CFF_Err_Invalid_File_Format;
172       goto Fail;
173     }
174
175     /* all right, the glyph names were loaded; we now need to create */
176     /* the corresponding unicode charmap                             */
177
178   Fail:
179     for ( n = 0; n < num_glyphs; n++ )
180       FREE( glyph_names[n] );
181
182     FREE( glyph_names );
183
184   Exit:
185     return error;
186   }
187
188 #endif /* 0 */
189
190
191   static FT_Encoding
192   find_encoding( int  platform_id,
193                  int  encoding_id )
194   {
195     typedef struct  TEncoding
196     {
197       int          platform_id;
198       int          encoding_id;
199       FT_Encoding  encoding;
200
201     } TEncoding;
202
203     static
204     const TEncoding  tt_encodings[] =
205     {
206       { TT_PLATFORM_ISO,           -1,                  ft_encoding_unicode },
207
208       { TT_PLATFORM_APPLE_UNICODE, -1,                  ft_encoding_unicode },
209
210       { TT_PLATFORM_MACINTOSH,     TT_MAC_ID_ROMAN,     ft_encoding_apple_roman },
211
212       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_UNICODE_CS, ft_encoding_unicode },
213       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_SJIS,       ft_encoding_sjis },
214       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_GB2312,     ft_encoding_gb2312 },
215       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_BIG_5,      ft_encoding_big5 },
216       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_WANSUNG,    ft_encoding_wansung },
217       { TT_PLATFORM_MICROSOFT,     TT_MS_ID_JOHAB,      ft_encoding_johab }
218     };
219
220     const TEncoding  *cur, *limit;
221
222
223     cur   = tt_encodings;
224     limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] );
225
226     for ( ; cur < limit; cur++ )
227     {
228       if ( cur->platform_id == platform_id )
229       {
230         if ( cur->encoding_id == encoding_id ||
231              cur->encoding_id == -1          )
232           return cur->encoding;
233       }
234     }
235
236     return ft_encoding_none;
237   }
238
239
240   /*************************************************************************/
241   /*                                                                       */
242   /* <Function>                                                            */
243   /*    CFF_Init_Face                                                      */
244   /*                                                                       */
245   /* <Description>                                                         */
246   /*    Initializes a given OpenType face object.                          */
247   /*                                                                       */
248   /* <Input>                                                               */
249   /*    stream     :: The source font stream.                              */
250   /*                                                                       */
251   /*    face_index :: The index of the font face in the resource.          */
252   /*                                                                       */
253   /*    num_params :: Number of additional generic parameters.  Ignored.   */
254   /*                                                                       */
255   /*    params     :: Additional generic parameters.  Ignored.             */
256   /*                                                                       */
257   /* <InOut>                                                               */
258   /*    face       :: The newly built face object.                         */
259   /*                                                                       */
260   /* <Return>                                                              */
261   /*    FreeType error code.  0 means success.                             */
262   /*                                                                       */
263   FT_LOCAL_DEF FT_Error
264   CFF_Init_Face( FT_Stream      stream,
265                  CFF_Face       face,
266                  FT_Int         face_index,
267                  FT_Int         num_params,
268                  FT_Parameter*  params )
269   {
270     FT_Error            error;
271     SFNT_Interface*     sfnt;
272     PSNames_Interface*  psnames;
273     FT_Bool             pure_cff    = 1;
274     FT_Bool             sfnt_format = 0;
275
276
277     sfnt = (SFNT_Interface*)FT_Get_Module_Interface(
278              face->root.driver->root.library, "sfnt" );
279     if ( !sfnt )
280       goto Bad_Format;
281
282     psnames = (PSNames_Interface*)FT_Get_Module_Interface(
283                 face->root.driver->root.library, "psnames" );
284
285     /* create input stream from resource */
286     if ( FILE_Seek( 0 ) )
287       goto Exit;
288
289     /* check that we have a valid OpenType file */
290     error = sfnt->init_face( stream, face, face_index, num_params, params );
291     if ( !error )
292     {
293       if ( face->format_tag != 0x4F54544FL )  /* `OTTO'; OpenType/CFF font */
294       {
295         FT_TRACE2(( "[not a valid OpenType/CFF font]\n" ));
296         goto Bad_Format;
297       }
298
299       /* if we are performing a simple font format check, exit immediately */
300       if ( face_index < 0 )
301         return CFF_Err_Ok;
302
303       sfnt_format = 1;
304
305       /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
306       /* font in the later case; it doesn't have a `head' table          */
307       error = face->goto_table( face, TTAG_head, stream, 0 );
308       if ( !error )
309       {
310         pure_cff = 0;
311
312         /* load font directory */
313         error = sfnt->load_face( stream, face,
314                                  face_index, num_params, params );
315         if ( error )
316           goto Exit;
317       }
318       else
319       {
320         /* load the `cmap' table by hand */
321         error = sfnt->load_charmaps( face, stream );
322         if ( error )
323           goto Exit;
324
325         /* XXX: we don't load the GPOS table, as OpenType Layout     */
326         /* support will be added later to a layout library on top of */
327         /* FreeType 2                                                */
328       }
329
330       /* now, load the CFF part of the file */
331       error = face->goto_table( face, TTAG_CFF, stream, 0 );
332       if ( error )
333         goto Exit;
334     }
335     else
336     {
337       /* rewind to start of file; we are going to load a pure-CFF font */
338       if ( FILE_Seek( 0 ) )
339         goto Exit;
340       error = CFF_Err_Ok;
341     }
342
343     /* now load and parse the CFF table in the file */
344     {
345       CFF_Font*  cff;
346       FT_Memory  memory = face->root.memory;
347       FT_Face    root;
348       FT_UInt    flags;
349
350
351       if ( ALLOC( cff, sizeof ( *cff ) ) )
352         goto Exit;
353
354       face->extra.data = cff;
355       error = CFF_Load_Font( stream, face_index, cff );
356       if ( error )
357         goto Exit;
358
359       /* Complement the root flags with some interesting information. */
360       /* Note that this is only necessary for pure CFF and CEF fonts. */
361
362       root = &face->root;
363       if ( pure_cff )
364       {
365         CFF_Font_Dict*  dict = &cff->top_font.font_dict;
366
367
368         /* we need the `PSNames' module for pure-CFF and CEF formats */
369         if ( !psnames )
370         {
371           FT_ERROR(( "CFF_Init_Face:" ));
372           FT_ERROR(( " cannot open CFF & CEF fonts\n" ));
373           FT_ERROR(( "             " ));
374           FT_ERROR(( " without the `PSNames' module\n" ));
375           goto Bad_Format;
376         }
377
378         /* Set up num_faces. */
379         root->num_faces = cff->num_faces;
380
381         /* compute number of glyphs */
382         if ( dict->cid_registry )
383           root->num_glyphs = dict->cid_count;
384         else
385           root->num_glyphs = cff->charstrings_index.count;
386
387         /* set global bbox, as well as EM size */
388         root->bbox      = dict->font_bbox;
389         root->ascender  = (FT_Short)( root->bbox.yMax >> 16 );
390         root->descender = (FT_Short)( root->bbox.yMin >> 16 );
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_Get_Name( &cff->name_index, face_index );
401         if ( dict->cid_registry )
402           root->style_name = CFF_StrCopy( memory, "Regular" );  /* XXXX */
403         else
404           root->style_name = CFF_Get_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         /* set the charmaps if any */
451         if ( sfnt_format )
452         {
453           /*****************************************************************/
454           /*                                                               */
455           /* Polish the charmaps.                                          */
456           /*                                                               */
457           /*   Try to set the charmap encoding according to the platform & */
458           /*   encoding ID of each charmap.                                */
459           /*                                                               */
460           TT_CharMap  charmap;
461           FT_Int      n;
462
463
464           charmap            = face->charmaps;
465           root->num_charmaps = face->num_charmaps;
466
467           /* allocate table of pointers */
468           if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) )
469             goto Exit;
470
471           for ( n = 0; n < root->num_charmaps; n++, charmap++ )
472           {
473             FT_Int  platform = charmap->cmap.platformID;
474             FT_Int  encoding = charmap->cmap.platformEncodingID;
475
476
477             charmap->root.face        = (FT_Face)face;
478             charmap->root.platform_id = (FT_UShort)platform;
479             charmap->root.encoding_id = (FT_UShort)encoding;
480             charmap->root.encoding    = find_encoding( platform, encoding );
481
482             /* now, set root->charmap with a unicode charmap */
483             /* wherever available                            */
484             if ( !root->charmap                                &&
485                  charmap->root.encoding == ft_encoding_unicode )
486               root->charmap = (FT_CharMap)charmap;
487
488             root->charmaps[n] = (FT_CharMap)charmap;
489           }
490         }
491       }
492     }
493
494   Exit:
495     return error;
496
497   Bad_Format:
498     error = CFF_Err_Unknown_File_Format;
499     goto Exit;
500   }
501
502
503   /*************************************************************************/
504   /*                                                                       */
505   /* <Function>                                                            */
506   /*    CFF_Done_Face                                                      */
507   /*                                                                       */
508   /* <Description>                                                         */
509   /*    Finalizes a given face object.                                     */
510   /*                                                                       */
511   /* <Input>                                                               */
512   /*    face :: A pointer to the face object to destroy.                   */
513   /*                                                                       */
514   FT_LOCAL_DEF void
515   CFF_Done_Face( CFF_Face  face )
516   {
517     FT_Memory        memory = face->root.memory;
518     SFNT_Interface*  sfnt   = (SFNT_Interface*)face->sfnt;
519
520
521     if ( sfnt )
522       sfnt->done_face( face );
523
524     {
525       CFF_Font*  cff = (CFF_Font*)face->extra.data;
526
527
528       if ( cff )
529       {
530         CFF_Done_Font( cff );
531         FREE( face->extra.data );
532       }
533     }
534   }
535
536
537   /*************************************************************************/
538   /*                                                                       */
539   /* <Function>                                                            */
540   /*    CFF_Init_Driver                                                    */
541   /*                                                                       */
542   /* <Description>                                                         */
543   /*    Initializes a given OpenType driver object.                        */
544   /*                                                                       */
545   /* <Input>                                                               */
546   /*    driver :: A handle to the target driver object.                    */
547   /*                                                                       */
548   /* <Return>                                                              */
549   /*    FreeType error code.  0 means success.                             */
550   /*                                                                       */
551   FT_LOCAL_DEF FT_Error
552   CFF_Init_Driver( CFF_Driver  driver )
553   {
554     /* init extension registry if needed */
555
556 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
557
558     return TT_Init_Extensions( driver );
559
560 #else
561
562     FT_UNUSED( driver );
563
564     return CFF_Err_Ok;
565
566 #endif
567   }
568
569
570   /*************************************************************************/
571   /*                                                                       */
572   /* <Function>                                                            */
573   /*    CFF_Done_Driver                                                    */
574   /*                                                                       */
575   /* <Description>                                                         */
576   /*    Finalizes a given OpenType driver.                                 */
577   /*                                                                       */
578   /* <Input>                                                               */
579   /*    driver :: A handle to the target OpenType driver.                  */
580   /*                                                                       */
581   FT_LOCAL_DEF void
582   CFF_Done_Driver( CFF_Driver  driver )
583   {
584     /* destroy extensions registry if needed */
585
586 #ifdef TT_CONFIG_OPTION_EXTEND_ENGINE
587
588     TT_Done_Extensions( driver );
589
590 #else
591
592     FT_UNUSED( driver );
593
594 #endif
595   }
596
597
598 /* END */