1 /***************************************************************************/
2 /*                                                                         */
3 /*  cidobjs.c                                                              */
4 /*                                                                         */
5 /*    CID objects manager (body).                                          */
6 /*                                                                         */
7 /*  Copyright 1996-2017 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_STREAM_H
22 
23 #include "cidgload.h"
24 #include "cidload.h"
25 
26 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
27 #include FT_INTERNAL_POSTSCRIPT_AUX_H
28 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
29 
30 #include "ciderrs.h"
31 
32 
33   /*************************************************************************/
34   /*                                                                       */
35   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
36   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
37   /* messages during execution.                                            */
38   /*                                                                       */
39 #undef  FT_COMPONENT
40 #define FT_COMPONENT  trace_cidobjs
41 
42 
43   /*************************************************************************/
44   /*                                                                       */
45   /*                            SLOT  FUNCTIONS                            */
46   /*                                                                       */
47   /*************************************************************************/
48 
49   FT_LOCAL_DEF( void )
cid_slot_done(FT_GlyphSlot slot)50   cid_slot_done( FT_GlyphSlot  slot )
51   {
52     slot->internal->glyph_hints = NULL;
53   }
54 
55 
56   FT_LOCAL_DEF( FT_Error )
cid_slot_init(FT_GlyphSlot slot)57   cid_slot_init( FT_GlyphSlot  slot )
58   {
59     CID_Face          face;
60     PSHinter_Service  pshinter;
61 
62 
63     face     = (CID_Face)slot->face;
64     pshinter = (PSHinter_Service)face->pshinter;
65 
66     if ( pshinter )
67     {
68       FT_Module  module;
69 
70 
71       module = FT_Get_Module( slot->face->driver->root.library,
72                               "pshinter" );
73       if ( module )
74       {
75         T1_Hints_Funcs  funcs;
76 
77 
78         funcs = pshinter->get_t1_funcs( module );
79         slot->internal->glyph_hints = (void*)funcs;
80       }
81     }
82 
83     return 0;
84   }
85 
86 
87   /*************************************************************************/
88   /*                                                                       */
89   /*                           SIZE  FUNCTIONS                             */
90   /*                                                                       */
91   /*************************************************************************/
92 
93 
94   static PSH_Globals_Funcs
cid_size_get_globals_funcs(CID_Size size)95   cid_size_get_globals_funcs( CID_Size  size )
96   {
97     CID_Face          face     = (CID_Face)size->root.face;
98     PSHinter_Service  pshinter = (PSHinter_Service)face->pshinter;
99     FT_Module         module;
100 
101 
102     module = FT_Get_Module( size->root.face->driver->root.library,
103                             "pshinter" );
104     return ( module && pshinter && pshinter->get_globals_funcs )
105            ? pshinter->get_globals_funcs( module )
106            : 0;
107   }
108 
109 
110   FT_LOCAL_DEF( void )
cid_size_done(FT_Size cidsize)111   cid_size_done( FT_Size  cidsize )         /* CID_Size */
112   {
113     CID_Size  size = (CID_Size)cidsize;
114 
115 
116     if ( cidsize->internal->module_data )
117     {
118       PSH_Globals_Funcs  funcs;
119 
120 
121       funcs = cid_size_get_globals_funcs( size );
122       if ( funcs )
123         funcs->destroy( (PSH_Globals)cidsize->internal->module_data );
124 
125       cidsize->internal->module_data = NULL;
126     }
127   }
128 
129 
130   FT_LOCAL_DEF( FT_Error )
cid_size_init(FT_Size cidsize)131   cid_size_init( FT_Size  cidsize )     /* CID_Size */
132   {
133     CID_Size           size  = (CID_Size)cidsize;
134     FT_Error           error = FT_Err_Ok;
135     PSH_Globals_Funcs  funcs = cid_size_get_globals_funcs( size );
136 
137 
138     if ( funcs )
139     {
140       PSH_Globals   globals;
141       CID_Face      face = (CID_Face)cidsize->face;
142       CID_FaceDict  dict = face->cid.font_dicts + face->root.face_index;
143       PS_Private    priv = &dict->private_dict;
144 
145 
146       error = funcs->create( cidsize->face->memory, priv, &globals );
147       if ( !error )
148         cidsize->internal->module_data = globals;
149     }
150 
151     return error;
152   }
153 
154 
155   FT_LOCAL( FT_Error )
cid_size_request(FT_Size size,FT_Size_Request req)156   cid_size_request( FT_Size          size,
157                     FT_Size_Request  req )
158   {
159     PSH_Globals_Funcs  funcs;
160 
161 
162     FT_Request_Metrics( size->face, req );
163 
164     funcs = cid_size_get_globals_funcs( (CID_Size)size );
165 
166     if ( funcs )
167       funcs->set_scale( (PSH_Globals)size->internal->module_data,
168                         size->metrics.x_scale,
169                         size->metrics.y_scale,
170                         0, 0 );
171 
172     return FT_Err_Ok;
173   }
174 
175 
176   /*************************************************************************/
177   /*                                                                       */
178   /*                           FACE  FUNCTIONS                             */
179   /*                                                                       */
180   /*************************************************************************/
181 
182   /*************************************************************************/
183   /*                                                                       */
184   /* <Function>                                                            */
185   /*    cid_face_done                                                      */
186   /*                                                                       */
187   /* <Description>                                                         */
188   /*    Finalizes a given face object.                                     */
189   /*                                                                       */
190   /* <Input>                                                               */
191   /*    face :: A pointer to the face object to destroy.                   */
192   /*                                                                       */
193   FT_LOCAL_DEF( void )
cid_face_done(FT_Face cidface)194   cid_face_done( FT_Face  cidface )         /* CID_Face */
195   {
196     CID_Face      face = (CID_Face)cidface;
197     FT_Memory     memory;
198     CID_FaceInfo  cid;
199     PS_FontInfo   info;
200 
201 
202     if ( !face )
203       return;
204 
205     cid    = &face->cid;
206     info   = &cid->font_info;
207     memory = cidface->memory;
208 
209     /* release subrs */
210     if ( face->subrs )
211     {
212       FT_Int  n;
213 
214 
215       for ( n = 0; n < cid->num_dicts; n++ )
216       {
217         CID_Subrs  subr = face->subrs + n;
218 
219 
220         if ( subr->code )
221         {
222           FT_FREE( subr->code[0] );
223           FT_FREE( subr->code );
224         }
225       }
226 
227       FT_FREE( face->subrs );
228     }
229 
230     /* release FontInfo strings */
231     FT_FREE( info->version );
232     FT_FREE( info->notice );
233     FT_FREE( info->full_name );
234     FT_FREE( info->family_name );
235     FT_FREE( info->weight );
236 
237     /* release font dictionaries */
238     FT_FREE( cid->font_dicts );
239     cid->num_dicts = 0;
240 
241     /* release other strings */
242     FT_FREE( cid->cid_font_name );
243     FT_FREE( cid->registry );
244     FT_FREE( cid->ordering );
245 
246     cidface->family_name = NULL;
247     cidface->style_name  = NULL;
248 
249     FT_FREE( face->binary_data );
250     FT_FREE( face->cid_stream );
251   }
252 
253 
254   /*************************************************************************/
255   /*                                                                       */
256   /* <Function>                                                            */
257   /*    cid_face_init                                                      */
258   /*                                                                       */
259   /* <Description>                                                         */
260   /*    Initializes a given CID face object.                               */
261   /*                                                                       */
262   /* <Input>                                                               */
263   /*    stream     :: The source font stream.                              */
264   /*                                                                       */
265   /*    face_index :: The index of the font face in the resource.          */
266   /*                                                                       */
267   /*    num_params :: Number of additional generic parameters.  Ignored.   */
268   /*                                                                       */
269   /*    params     :: Additional generic parameters.  Ignored.             */
270   /*                                                                       */
271   /* <InOut>                                                               */
272   /*    face       :: The newly built face object.                         */
273   /*                                                                       */
274   /* <Return>                                                              */
275   /*    FreeType error code.  0 means success.                             */
276   /*                                                                       */
277   FT_LOCAL_DEF( FT_Error )
cid_face_init(FT_Stream stream,FT_Face cidface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)278   cid_face_init( FT_Stream      stream,
279                  FT_Face        cidface,        /* CID_Face */
280                  FT_Int         face_index,
281                  FT_Int         num_params,
282                  FT_Parameter*  params )
283   {
284     CID_Face          face = (CID_Face)cidface;
285     FT_Error          error;
286     PSAux_Service     psaux;
287     PSHinter_Service  pshinter;
288 
289     FT_UNUSED( num_params );
290     FT_UNUSED( params );
291     FT_UNUSED( stream );
292 
293 
294     cidface->num_faces = 1;
295 
296     psaux = (PSAux_Service)face->psaux;
297     if ( !psaux )
298     {
299       psaux = (PSAux_Service)FT_Get_Module_Interface(
300                 FT_FACE_LIBRARY( face ), "psaux" );
301 
302       if ( !psaux )
303       {
304         FT_ERROR(( "cid_face_init: cannot access `psaux' module\n" ));
305         error = FT_THROW( Missing_Module );
306         goto Exit;
307       }
308 
309       face->psaux = psaux;
310     }
311 
312     pshinter = (PSHinter_Service)face->pshinter;
313     if ( !pshinter )
314     {
315       pshinter = (PSHinter_Service)FT_Get_Module_Interface(
316                    FT_FACE_LIBRARY( face ), "pshinter" );
317 
318       face->pshinter = pshinter;
319     }
320 
321     FT_TRACE2(( "CID driver\n" ));
322 
323     /* open the tokenizer; this will also check the font format */
324     if ( FT_STREAM_SEEK( 0 ) )
325       goto Exit;
326 
327     error = cid_face_open( face, face_index );
328     if ( error )
329       goto Exit;
330 
331     /* if we just wanted to check the format, leave successfully now */
332     if ( face_index < 0 )
333       goto Exit;
334 
335     /* check the face index */
336     /* XXX: handle CID fonts with more than a single face */
337     if ( ( face_index & 0xFFFF ) != 0 )
338     {
339       FT_ERROR(( "cid_face_init: invalid face index\n" ));
340       error = FT_THROW( Invalid_Argument );
341       goto Exit;
342     }
343 
344     /* now load the font program into the face object */
345 
346     /* initialize the face object fields */
347 
348     /* set up root face fields */
349     {
350       CID_FaceInfo  cid  = &face->cid;
351       PS_FontInfo   info = &cid->font_info;
352 
353 
354       cidface->num_glyphs   = (FT_Long)cid->cid_count;
355       cidface->num_charmaps = 0;
356 
357       cidface->face_index = face_index & 0xFFFF;
358 
359       cidface->face_flags |= FT_FACE_FLAG_SCALABLE   | /* scalable outlines */
360                              FT_FACE_FLAG_HORIZONTAL | /* horizontal data   */
361                              FT_FACE_FLAG_HINTER;      /* has native hinter */
362 
363       if ( info->is_fixed_pitch )
364         cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
365 
366       /* XXX: TODO: add kerning with .afm support */
367 
368       /* get style name -- be careful, some broken fonts only */
369       /* have a /FontName dictionary entry!                   */
370       cidface->family_name = info->family_name;
371       /* assume "Regular" style if we don't know better */
372       cidface->style_name = (char *)"Regular";
373       if ( cidface->family_name )
374       {
375         char*  full   = info->full_name;
376         char*  family = cidface->family_name;
377 
378 
379         if ( full )
380         {
381           while ( *full )
382           {
383             if ( *full == *family )
384             {
385               family++;
386               full++;
387             }
388             else
389             {
390               if ( *full == ' ' || *full == '-' )
391                 full++;
392               else if ( *family == ' ' || *family == '-' )
393                 family++;
394               else
395               {
396                 if ( !*family )
397                   cidface->style_name = full;
398                 break;
399               }
400             }
401           }
402         }
403       }
404       else
405       {
406         /* do we have a `/FontName'? */
407         if ( cid->cid_font_name )
408           cidface->family_name = cid->cid_font_name;
409       }
410 
411       /* compute style flags */
412       cidface->style_flags = 0;
413       if ( info->italic_angle )
414         cidface->style_flags |= FT_STYLE_FLAG_ITALIC;
415       if ( info->weight )
416       {
417         if ( !ft_strcmp( info->weight, "Bold"  ) ||
418              !ft_strcmp( info->weight, "Black" ) )
419           cidface->style_flags |= FT_STYLE_FLAG_BOLD;
420       }
421 
422       /* no embedded bitmap support */
423       cidface->num_fixed_sizes = 0;
424       cidface->available_sizes = NULL;
425 
426       cidface->bbox.xMin =   cid->font_bbox.xMin            >> 16;
427       cidface->bbox.yMin =   cid->font_bbox.yMin            >> 16;
428       /* no `U' suffix here to 0xFFFF! */
429       cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFF ) >> 16;
430       cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFF ) >> 16;
431 
432       if ( !cidface->units_per_EM )
433         cidface->units_per_EM = 1000;
434 
435       cidface->ascender  = (FT_Short)( cidface->bbox.yMax );
436       cidface->descender = (FT_Short)( cidface->bbox.yMin );
437 
438       cidface->height = (FT_Short)( ( cidface->units_per_EM * 12 ) / 10 );
439       if ( cidface->height < cidface->ascender - cidface->descender )
440         cidface->height = (FT_Short)( cidface->ascender - cidface->descender );
441 
442       cidface->underline_position  = (FT_Short)info->underline_position;
443       cidface->underline_thickness = (FT_Short)info->underline_thickness;
444     }
445 
446   Exit:
447     return error;
448   }
449 
450 
451   /*************************************************************************/
452   /*                                                                       */
453   /* <Function>                                                            */
454   /*    cid_driver_init                                                    */
455   /*                                                                       */
456   /* <Description>                                                         */
457   /*    Initializes a given CID driver object.                             */
458   /*                                                                       */
459   /* <Input>                                                               */
460   /*    driver :: A handle to the target driver object.                    */
461   /*                                                                       */
462   /* <Return>                                                              */
463   /*    FreeType error code.  0 means success.                             */
464   /*                                                                       */
465   FT_LOCAL_DEF( FT_Error )
cid_driver_init(FT_Module driver)466   cid_driver_init( FT_Module  driver )
467   {
468     FT_UNUSED( driver );
469 
470     return FT_Err_Ok;
471   }
472 
473 
474   /*************************************************************************/
475   /*                                                                       */
476   /* <Function>                                                            */
477   /*    cid_driver_done                                                    */
478   /*                                                                       */
479   /* <Description>                                                         */
480   /*    Finalizes a given CID driver.                                      */
481   /*                                                                       */
482   /* <Input>                                                               */
483   /*    driver :: A handle to the target CID driver.                       */
484   /*                                                                       */
485   FT_LOCAL_DEF( void )
cid_driver_done(FT_Module driver)486   cid_driver_done( FT_Module  driver )
487   {
488     FT_UNUSED( driver );
489   }
490 
491 
492 /* END */
493