1 /***************************************************************************/
2 /*                                                                         */
3 /*  t42objs.c                                                              */
4 /*                                                                         */
5 /*    Type 42 objects manager (body).                                      */
6 /*                                                                         */
7 /*  Copyright 2002-2009, 2011, 2013                                        */
8 /*  by Roberto Alameda.                                                    */
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 "t42objs.h"
20 #include "t42parse.h"
21 #include "t42error.h"
22 #include FT_INTERNAL_DEBUG_H
23 #include FT_LIST_H
24 #include FT_TRUETYPE_IDS_H
25 
26 
27 #undef  FT_COMPONENT
28 #define FT_COMPONENT  trace_t42
29 
30 
31   static FT_Error
T42_Open_Face(T42_Face face)32   T42_Open_Face( T42_Face  face )
33   {
34     T42_LoaderRec  loader;
35     T42_Parser     parser;
36     T1_Font        type1 = &face->type1;
37     FT_Memory      memory = face->root.memory;
38     FT_Error       error;
39 
40     PSAux_Service  psaux  = (PSAux_Service)face->psaux;
41 
42 
43     t42_loader_init( &loader, face );
44 
45     parser = &loader.parser;
46 
47     if ( FT_ALLOC( face->ttf_data, 12 ) )
48       goto Exit;
49 
50     error = t42_parser_init( parser,
51                              face->root.stream,
52                              memory,
53                              psaux);
54     if ( error )
55       goto Exit;
56 
57     error = t42_parse_dict( face, &loader,
58                             parser->base_dict, parser->base_len );
59     if ( error )
60       goto Exit;
61 
62     if ( type1->font_type != 42 )
63     {
64       FT_ERROR(( "T42_Open_Face: cannot handle FontType %d\n",
65                  type1->font_type ));
66       error = FT_THROW( Unknown_File_Format );
67       goto Exit;
68     }
69 
70     /* now, propagate the charstrings and glyphnames tables */
71     /* to the Type1 data                                    */
72     type1->num_glyphs = loader.num_glyphs;
73 
74     if ( !loader.charstrings.init )
75     {
76       FT_ERROR(( "T42_Open_Face: no charstrings array in face\n" ));
77       error = FT_THROW( Invalid_File_Format );
78     }
79 
80     loader.charstrings.init  = 0;
81     type1->charstrings_block = loader.charstrings.block;
82     type1->charstrings       = loader.charstrings.elements;
83     type1->charstrings_len   = loader.charstrings.lengths;
84 
85     /* we copy the glyph names `block' and `elements' fields; */
86     /* the `lengths' field must be released later             */
87     type1->glyph_names_block    = loader.glyph_names.block;
88     type1->glyph_names          = (FT_String**)loader.glyph_names.elements;
89     loader.glyph_names.block    = 0;
90     loader.glyph_names.elements = 0;
91 
92     /* we must now build type1.encoding when we have a custom array */
93     if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY )
94     {
95       FT_Int    charcode, idx, min_char, max_char;
96       FT_Byte*  glyph_name;
97 
98 
99       /* OK, we do the following: for each element in the encoding   */
100       /* table, look up the index of the glyph having the same name  */
101       /* as defined in the CharStrings array.                        */
102       /* The index is then stored in type1.encoding.char_index, and  */
103       /* the name in type1.encoding.char_name                        */
104 
105       min_char = 0;
106       max_char = 0;
107 
108       charcode = 0;
109       for ( ; charcode < loader.encoding_table.max_elems; charcode++ )
110       {
111         FT_Byte*  char_name;
112 
113 
114         type1->encoding.char_index[charcode] = 0;
115         type1->encoding.char_name [charcode] = (char *)".notdef";
116 
117         char_name = loader.encoding_table.elements[charcode];
118         if ( char_name )
119           for ( idx = 0; idx < type1->num_glyphs; idx++ )
120           {
121             glyph_name = (FT_Byte*)type1->glyph_names[idx];
122             if ( ft_strcmp( (const char*)char_name,
123                             (const char*)glyph_name ) == 0 )
124             {
125               type1->encoding.char_index[charcode] = (FT_UShort)idx;
126               type1->encoding.char_name [charcode] = (char*)glyph_name;
127 
128               /* Change min/max encoded char only if glyph name is */
129               /* not /.notdef                                      */
130               if ( ft_strcmp( (const char*)".notdef",
131                               (const char*)glyph_name ) != 0 )
132               {
133                 if ( charcode < min_char )
134                   min_char = charcode;
135                 if ( charcode >= max_char )
136                   max_char = charcode + 1;
137               }
138               break;
139             }
140           }
141       }
142 
143       type1->encoding.code_first = min_char;
144       type1->encoding.code_last  = max_char;
145       type1->encoding.num_chars  = loader.num_chars;
146     }
147 
148   Exit:
149     t42_loader_done( &loader );
150     return error;
151   }
152 
153 
154   /***************** Driver Functions *************/
155 
156 
157   FT_LOCAL_DEF( FT_Error )
T42_Face_Init(FT_Stream stream,FT_Face t42face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)158   T42_Face_Init( FT_Stream      stream,
159                  FT_Face        t42face,       /* T42_Face */
160                  FT_Int         face_index,
161                  FT_Int         num_params,
162                  FT_Parameter*  params )
163   {
164     T42_Face            face  = (T42_Face)t42face;
165     FT_Error            error;
166     FT_Service_PsCMaps  psnames;
167     PSAux_Service       psaux;
168     FT_Face             root  = (FT_Face)&face->root;
169     T1_Font             type1 = &face->type1;
170     PS_FontInfo         info  = &type1->font_info;
171 
172     FT_UNUSED( num_params );
173     FT_UNUSED( params );
174     FT_UNUSED( stream );
175 
176 
177     face->ttf_face       = NULL;
178     face->root.num_faces = 1;
179 
180     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
181     face->psnames = psnames;
182 
183     face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
184                                            "psaux" );
185     psaux = (PSAux_Service)face->psaux;
186     if ( !psaux )
187     {
188       FT_ERROR(( "T42_Face_Init: cannot access `psaux' module\n" ));
189       error = FT_THROW( Missing_Module );
190       goto Exit;
191     }
192 
193     FT_TRACE2(( "Type 42 driver\n" ));
194 
195     /* open the tokenizer, this will also check the font format */
196     error = T42_Open_Face( face );
197     if ( error )
198       goto Exit;
199 
200     /* if we just wanted to check the format, leave successfully now */
201     if ( face_index < 0 )
202       goto Exit;
203 
204     /* check the face index */
205     if ( face_index > 0 )
206     {
207       FT_ERROR(( "T42_Face_Init: invalid face index\n" ));
208       error = FT_THROW( Invalid_Argument );
209       goto Exit;
210     }
211 
212     /* Now load the font program into the face object */
213 
214     /* Init the face object fields */
215     /* Now set up root face fields */
216 
217     root->num_glyphs   = type1->num_glyphs;
218     root->num_charmaps = 0;
219     root->face_index   = 0;
220 
221     root->face_flags |= FT_FACE_FLAG_SCALABLE    |
222                         FT_FACE_FLAG_HORIZONTAL  |
223                         FT_FACE_FLAG_GLYPH_NAMES;
224 
225     if ( info->is_fixed_pitch )
226       root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
227 
228     /* We only set this flag if we have the patented bytecode interpreter. */
229     /* There are no known `tricky' Type42 fonts that could be loaded with  */
230     /* the unpatented interpreter.                                         */
231 #ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
232     root->face_flags |= FT_FACE_FLAG_HINTER;
233 #endif
234 
235     /* XXX: TODO -- add kerning with .afm support */
236 
237     /* get style name -- be careful, some broken fonts only */
238     /* have a `/FontName' dictionary entry!                 */
239     root->family_name = info->family_name;
240     /* assume "Regular" style if we don't know better */
241     root->style_name = (char *)"Regular";
242     if ( root->family_name )
243     {
244       char*  full   = info->full_name;
245       char*  family = root->family_name;
246 
247 
248       if ( full )
249       {
250         while ( *full )
251         {
252           if ( *full == *family )
253           {
254             family++;
255             full++;
256           }
257           else
258           {
259             if ( *full == ' ' || *full == '-' )
260               full++;
261             else if ( *family == ' ' || *family == '-' )
262               family++;
263             else
264             {
265               if ( !*family )
266                 root->style_name = full;
267               break;
268             }
269           }
270         }
271       }
272     }
273     else
274     {
275       /* do we have a `/FontName'? */
276       if ( type1->font_name )
277         root->family_name = type1->font_name;
278     }
279 
280     /* no embedded bitmap support */
281     root->num_fixed_sizes = 0;
282     root->available_sizes = 0;
283 
284     /* Load the TTF font embedded in the T42 font */
285     {
286       FT_Open_Args  args;
287 
288 
289       args.flags       = FT_OPEN_MEMORY;
290       args.memory_base = face->ttf_data;
291       args.memory_size = face->ttf_size;
292 
293       if ( num_params )
294       {
295         args.flags     |= FT_OPEN_PARAMS;
296         args.num_params = num_params;
297         args.params     = params;
298       }
299 
300       error = FT_Open_Face( FT_FACE_LIBRARY( face ),
301                             &args, 0, &face->ttf_face );
302     }
303 
304     if ( error )
305       goto Exit;
306 
307     FT_Done_Size( face->ttf_face->size );
308 
309     /* Ignore info in FontInfo dictionary and use the info from the  */
310     /* loaded TTF font.  The PostScript interpreter also ignores it. */
311     root->bbox         = face->ttf_face->bbox;
312     root->units_per_EM = face->ttf_face->units_per_EM;
313 
314     root->ascender  = face->ttf_face->ascender;
315     root->descender = face->ttf_face->descender;
316     root->height    = face->ttf_face->height;
317 
318     root->max_advance_width  = face->ttf_face->max_advance_width;
319     root->max_advance_height = face->ttf_face->max_advance_height;
320 
321     root->underline_position  = (FT_Short)info->underline_position;
322     root->underline_thickness = (FT_Short)info->underline_thickness;
323 
324     /* compute style flags */
325     root->style_flags = 0;
326     if ( info->italic_angle )
327       root->style_flags |= FT_STYLE_FLAG_ITALIC;
328 
329     if ( face->ttf_face->style_flags & FT_STYLE_FLAG_BOLD )
330       root->style_flags |= FT_STYLE_FLAG_BOLD;
331 
332     if ( face->ttf_face->face_flags & FT_FACE_FLAG_VERTICAL )
333       root->face_flags |= FT_FACE_FLAG_VERTICAL;
334 
335     {
336       if ( psnames )
337       {
338         FT_CharMapRec    charmap;
339         T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
340         FT_CMap_Class    clazz;
341 
342 
343         charmap.face = root;
344 
345         /* first of all, try to synthesize a Unicode charmap */
346         charmap.platform_id = TT_PLATFORM_MICROSOFT;
347         charmap.encoding_id = TT_MS_ID_UNICODE_CS;
348         charmap.encoding    = FT_ENCODING_UNICODE;
349 
350         error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
351         if ( error                                      &&
352              FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
353           goto Exit;
354         error = FT_Err_Ok;
355 
356         /* now, generate an Adobe Standard encoding when appropriate */
357         charmap.platform_id = TT_PLATFORM_ADOBE;
358         clazz               = NULL;
359 
360         switch ( type1->encoding_type )
361         {
362         case T1_ENCODING_TYPE_STANDARD:
363           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
364           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
365           clazz               = cmap_classes->standard;
366           break;
367 
368         case T1_ENCODING_TYPE_EXPERT:
369           charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
370           charmap.encoding_id = TT_ADOBE_ID_EXPERT;
371           clazz               = cmap_classes->expert;
372           break;
373 
374         case T1_ENCODING_TYPE_ARRAY:
375           charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
376           charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
377           clazz               = cmap_classes->custom;
378           break;
379 
380         case T1_ENCODING_TYPE_ISOLATIN1:
381           charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
382           charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
383           clazz               = cmap_classes->unicode;
384           break;
385 
386         default:
387           ;
388         }
389 
390         if ( clazz )
391           error = FT_CMap_New( clazz, NULL, &charmap, NULL );
392 
393 #if 0
394         /* Select default charmap */
395         if ( root->num_charmaps )
396           root->charmap = root->charmaps[0];
397 #endif
398       }
399     }
400   Exit:
401     return error;
402   }
403 
404 
405   FT_LOCAL_DEF( void )
T42_Face_Done(FT_Face t42face)406   T42_Face_Done( FT_Face  t42face )
407   {
408     T42_Face     face = (T42_Face)t42face;
409     T1_Font      type1;
410     PS_FontInfo  info;
411     FT_Memory    memory;
412 
413 
414     if ( !face )
415       return;
416 
417     type1  = &face->type1;
418     info   = &type1->font_info;
419     memory = face->root.memory;
420 
421     /* delete internal ttf face prior to freeing face->ttf_data */
422     if ( face->ttf_face )
423       FT_Done_Face( face->ttf_face );
424 
425     /* release font info strings */
426     FT_FREE( info->version );
427     FT_FREE( info->notice );
428     FT_FREE( info->full_name );
429     FT_FREE( info->family_name );
430     FT_FREE( info->weight );
431 
432     /* release top dictionary */
433     FT_FREE( type1->charstrings_len );
434     FT_FREE( type1->charstrings );
435     FT_FREE( type1->glyph_names );
436 
437     FT_FREE( type1->charstrings_block );
438     FT_FREE( type1->glyph_names_block );
439 
440     FT_FREE( type1->encoding.char_index );
441     FT_FREE( type1->encoding.char_name );
442     FT_FREE( type1->font_name );
443 
444     FT_FREE( face->ttf_data );
445 
446 #if 0
447     /* release afm data if present */
448     if ( face->afm_data )
449       T1_Done_AFM( memory, (T1_AFM*)face->afm_data );
450 #endif
451 
452     /* release unicode map, if any */
453     FT_FREE( face->unicode_map.maps );
454     face->unicode_map.num_maps = 0;
455 
456     face->root.family_name = 0;
457     face->root.style_name  = 0;
458   }
459 
460 
461   /*************************************************************************/
462   /*                                                                       */
463   /* <Function>                                                            */
464   /*    T42_Driver_Init                                                    */
465   /*                                                                       */
466   /* <Description>                                                         */
467   /*    Initializes a given Type 42 driver object.                         */
468   /*                                                                       */
469   /* <Input>                                                               */
470   /*    driver :: A handle to the target driver object.                    */
471   /*                                                                       */
472   /* <Return>                                                              */
473   /*    FreeType error code.  0 means success.                             */
474   /*                                                                       */
475   FT_LOCAL_DEF( FT_Error )
T42_Driver_Init(FT_Module module)476   T42_Driver_Init( FT_Module  module )        /* T42_Driver */
477   {
478     T42_Driver  driver = (T42_Driver)module;
479     FT_Module   ttmodule;
480 
481 
482     ttmodule = FT_Get_Module( module->library, "truetype" );
483     if ( !ttmodule )
484     {
485       FT_ERROR(( "T42_Driver_Init: cannot access `truetype' module\n" ));
486       return FT_THROW( Missing_Module );
487     }
488 
489     driver->ttclazz = (FT_Driver_Class)ttmodule->clazz;
490 
491     return FT_Err_Ok;
492   }
493 
494 
495   FT_LOCAL_DEF( void )
T42_Driver_Done(FT_Module module)496   T42_Driver_Done( FT_Module  module )
497   {
498     FT_UNUSED( module );
499   }
500 
501 
502   FT_LOCAL_DEF( FT_Error )
T42_Size_Init(FT_Size size)503   T42_Size_Init( FT_Size  size )         /* T42_Size */
504   {
505     T42_Size  t42size = (T42_Size)size;
506     FT_Face   face    = size->face;
507     T42_Face  t42face = (T42_Face)face;
508     FT_Size   ttsize;
509     FT_Error  error;
510 
511 
512     error = FT_New_Size( t42face->ttf_face, &ttsize );
513     t42size->ttsize = ttsize;
514 
515     FT_Activate_Size( ttsize );
516 
517     return error;
518   }
519 
520 
521   FT_LOCAL_DEF( FT_Error )
T42_Size_Request(FT_Size t42size,FT_Size_Request req)522   T42_Size_Request( FT_Size          t42size,      /* T42_Size */
523                     FT_Size_Request  req )
524   {
525     T42_Size  size = (T42_Size)t42size;
526     T42_Face  face = (T42_Face)t42size->face;
527     FT_Error  error;
528 
529 
530     FT_Activate_Size( size->ttsize );
531 
532     error = FT_Request_Size( face->ttf_face, req );
533     if ( !error )
534       t42size->metrics = face->ttf_face->size->metrics;
535 
536     return error;
537   }
538 
539 
540   FT_LOCAL_DEF( FT_Error )
T42_Size_Select(FT_Size t42size,FT_ULong strike_index)541   T42_Size_Select( FT_Size   t42size,         /* T42_Size */
542                    FT_ULong  strike_index )
543   {
544     T42_Size  size = (T42_Size)t42size;
545     T42_Face  face = (T42_Face)t42size->face;
546     FT_Error  error;
547 
548 
549     FT_Activate_Size( size->ttsize );
550 
551     error = FT_Select_Size( face->ttf_face, (FT_Int)strike_index );
552     if ( !error )
553       t42size->metrics = face->ttf_face->size->metrics;
554 
555     return error;
556 
557   }
558 
559 
560   FT_LOCAL_DEF( void )
T42_Size_Done(FT_Size t42size)561   T42_Size_Done( FT_Size  t42size )             /* T42_Size */
562   {
563     T42_Size     size    = (T42_Size)t42size;
564     FT_Face      face    = t42size->face;
565     T42_Face     t42face = (T42_Face)face;
566     FT_ListNode  node;
567 
568 
569     node = FT_List_Find( &t42face->ttf_face->sizes_list, size->ttsize );
570     if ( node )
571     {
572       FT_Done_Size( size->ttsize );
573       size->ttsize = NULL;
574     }
575   }
576 
577 
578   FT_LOCAL_DEF( FT_Error )
T42_GlyphSlot_Init(FT_GlyphSlot t42slot)579   T42_GlyphSlot_Init( FT_GlyphSlot  t42slot )        /* T42_GlyphSlot */
580   {
581     T42_GlyphSlot  slot    = (T42_GlyphSlot)t42slot;
582     FT_Face        face    = t42slot->face;
583     T42_Face       t42face = (T42_Face)face;
584     FT_GlyphSlot   ttslot;
585     FT_Error       error   = FT_Err_Ok;
586 
587 
588     if ( face->glyph == NULL )
589     {
590       /* First glyph slot for this face */
591       slot->ttslot = t42face->ttf_face->glyph;
592     }
593     else
594     {
595       error = FT_New_GlyphSlot( t42face->ttf_face, &ttslot );
596       slot->ttslot = ttslot;
597     }
598 
599     return error;
600   }
601 
602 
603   FT_LOCAL_DEF( void )
T42_GlyphSlot_Done(FT_GlyphSlot t42slot)604   T42_GlyphSlot_Done( FT_GlyphSlot  t42slot )       /* T42_GlyphSlot */
605   {
606     T42_GlyphSlot  slot = (T42_GlyphSlot)t42slot;
607 
608 
609     FT_Done_GlyphSlot( slot->ttslot );
610   }
611 
612 
613   static void
t42_glyphslot_clear(FT_GlyphSlot slot)614   t42_glyphslot_clear( FT_GlyphSlot  slot )
615   {
616     /* free bitmap if needed */
617     ft_glyphslot_free_bitmap( slot );
618 
619     /* clear all public fields in the glyph slot */
620     FT_ZERO( &slot->metrics );
621     FT_ZERO( &slot->outline );
622     FT_ZERO( &slot->bitmap );
623 
624     slot->bitmap_left   = 0;
625     slot->bitmap_top    = 0;
626     slot->num_subglyphs = 0;
627     slot->subglyphs     = 0;
628     slot->control_data  = 0;
629     slot->control_len   = 0;
630     slot->other         = 0;
631     slot->format        = FT_GLYPH_FORMAT_NONE;
632 
633     slot->linearHoriAdvance = 0;
634     slot->linearVertAdvance = 0;
635   }
636 
637 
638   FT_LOCAL_DEF( FT_Error )
T42_GlyphSlot_Load(FT_GlyphSlot glyph,FT_Size size,FT_UInt glyph_index,FT_Int32 load_flags)639   T42_GlyphSlot_Load( FT_GlyphSlot  glyph,
640                       FT_Size       size,
641                       FT_UInt       glyph_index,
642                       FT_Int32      load_flags )
643   {
644     FT_Error         error;
645     T42_GlyphSlot    t42slot = (T42_GlyphSlot)glyph;
646     T42_Size         t42size = (T42_Size)size;
647     FT_Driver_Class  ttclazz = ((T42_Driver)glyph->face->driver)->ttclazz;
648 
649 
650     FT_TRACE1(( "T42_GlyphSlot_Load: glyph index %d\n", glyph_index ));
651 
652     t42_glyphslot_clear( t42slot->ttslot );
653     error = ttclazz->load_glyph( t42slot->ttslot,
654                                  t42size->ttsize,
655                                  glyph_index,
656                                  load_flags | FT_LOAD_NO_BITMAP );
657 
658     if ( !error )
659     {
660       glyph->metrics = t42slot->ttslot->metrics;
661 
662       glyph->linearHoriAdvance = t42slot->ttslot->linearHoriAdvance;
663       glyph->linearVertAdvance = t42slot->ttslot->linearVertAdvance;
664 
665       glyph->format  = t42slot->ttslot->format;
666       glyph->outline = t42slot->ttslot->outline;
667 
668       glyph->bitmap      = t42slot->ttslot->bitmap;
669       glyph->bitmap_left = t42slot->ttslot->bitmap_left;
670       glyph->bitmap_top  = t42slot->ttslot->bitmap_top;
671 
672       glyph->num_subglyphs = t42slot->ttslot->num_subglyphs;
673       glyph->subglyphs     = t42slot->ttslot->subglyphs;
674 
675       glyph->control_data  = t42slot->ttslot->control_data;
676       glyph->control_len   = t42slot->ttslot->control_len;
677     }
678 
679     return error;
680   }
681 
682 
683 /* END */
684