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