1 /****************************************************************************
   2  *
   3  * t1objs.c
   4  *
   5  *   Type 1 objects manager (body).
   6  *
   7  * Copyright (C) 1996-2019 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_CALC_H
  21 #include FT_INTERNAL_DEBUG_H
  22 #include FT_INTERNAL_STREAM_H
  23 #include FT_TRUETYPE_IDS_H
  24 #include FT_DRIVER_H
  25 
  26 #include "t1gload.h"
  27 #include "t1load.h"
  28 
  29 #include "t1errors.h"
  30 
  31 #ifndef T1_CONFIG_OPTION_NO_AFM
  32 #include "t1afm.h"
  33 #endif
  34 
  35 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
  36 #include FT_INTERNAL_POSTSCRIPT_AUX_H
  37 
  38 
  39   /**************************************************************************
  40    *
  41    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
  42    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
  43    * messages during execution.
  44    */
  45 #undef  FT_COMPONENT
  46 #define FT_COMPONENT  t1objs
  47 
  48 
  49   /**************************************************************************
  50    *
  51    *                           SIZE FUNCTIONS
  52    *
  53    */
  54 
  55 
  56   static PSH_Globals_Funcs
  57   T1_Size_Get_Globals_Funcs( T1_Size  size )
  58   {
  59     T1_Face           face     = (T1_Face)size->root.face;
  60     PSHinter_Service  pshinter = (PSHinter_Service)face->pshinter;
  61     FT_Module         module;
  62 
  63 
  64     module = FT_Get_Module( size->root.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   T1_Size_Done( FT_Size  t1size )          /* T1_Size */
  74   {
  75     T1_Size  size = (T1_Size)t1size;
  76 
  77 
  78     if ( t1size->internal->module_data )
  79     {
  80       PSH_Globals_Funcs  funcs;
  81 
  82 
  83       funcs = T1_Size_Get_Globals_Funcs( size );
  84       if ( funcs )
  85         funcs->destroy( (PSH_Globals)t1size->internal->module_data );
  86 
  87       t1size->internal->module_data = NULL;
  88     }
  89   }
  90 
  91 
  92   FT_LOCAL_DEF( FT_Error )
  93   T1_Size_Init( FT_Size  t1size )      /* T1_Size */
  94   {
  95     T1_Size            size  = (T1_Size)t1size;
  96     FT_Error           error = FT_Err_Ok;
  97     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
  98 
  99 
 100     if ( funcs )
 101     {
 102       PSH_Globals  globals;
 103       T1_Face      face = (T1_Face)size->root.face;
 104 
 105 
 106       error = funcs->create( size->root.face->memory,
 107                              &face->type1.private_dict, &globals );
 108       if ( !error )
 109         t1size->internal->module_data = globals;
 110     }
 111 
 112     return error;
 113   }
 114 
 115 
 116   FT_LOCAL_DEF( FT_Error )
 117   T1_Size_Request( FT_Size          t1size,     /* T1_Size */
 118                    FT_Size_Request  req )
 119   {
 120     T1_Size            size  = (T1_Size)t1size;
 121     PSH_Globals_Funcs  funcs = T1_Size_Get_Globals_Funcs( size );
 122 
 123 
 124     FT_Request_Metrics( size->root.face, req );
 125 
 126     if ( funcs )
 127       funcs->set_scale( (PSH_Globals)t1size->internal->module_data,
 128                         size->root.metrics.x_scale,
 129                         size->root.metrics.y_scale,
 130                         0, 0 );
 131 
 132     return FT_Err_Ok;
 133   }
 134 
 135 
 136   /**************************************************************************
 137    *
 138    *                           SLOT  FUNCTIONS
 139    *
 140    */
 141 
 142   FT_LOCAL_DEF( void )
 143   T1_GlyphSlot_Done( FT_GlyphSlot  slot )
 144   {
 145     slot->internal->glyph_hints = NULL;
 146   }
 147 
 148 
 149   FT_LOCAL_DEF( FT_Error )
 150   T1_GlyphSlot_Init( FT_GlyphSlot  slot )
 151   {
 152     T1_Face           face;
 153     PSHinter_Service  pshinter;
 154 
 155 
 156     face     = (T1_Face)slot->face;
 157     pshinter = (PSHinter_Service)face->pshinter;
 158 
 159     if ( pshinter )
 160     {
 161       FT_Module  module;
 162 
 163 
 164       module = FT_Get_Module( slot->face->driver->root.library,
 165                               "pshinter" );
 166       if ( module )
 167       {
 168         T1_Hints_Funcs  funcs;
 169 
 170 
 171         funcs = pshinter->get_t1_funcs( module );
 172         slot->internal->glyph_hints = (void*)funcs;
 173       }
 174     }
 175 
 176     return 0;
 177   }
 178 
 179 
 180   /**************************************************************************
 181    *
 182    *                           FACE  FUNCTIONS
 183    *
 184    */
 185 
 186 
 187   /**************************************************************************
 188    *
 189    * @Function:
 190    *   T1_Face_Done
 191    *
 192    * @Description:
 193    *   The face object destructor.
 194    *
 195    * @Input:
 196    *   face ::
 197    *     A typeless pointer to the face object to destroy.
 198    */
 199   FT_LOCAL_DEF( void )
 200   T1_Face_Done( FT_Face  t1face )         /* T1_Face */
 201   {
 202     T1_Face    face = (T1_Face)t1face;
 203     FT_Memory  memory;
 204     T1_Font    type1;
 205 
 206 
 207     if ( !face )
 208       return;
 209 
 210     memory = face->root.memory;
 211     type1  = &face->type1;
 212 
 213 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT
 214     /* release multiple masters information */
 215     FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) );
 216 
 217     if ( face->buildchar )
 218     {
 219       FT_FREE( face->buildchar );
 220 
 221       face->buildchar     = NULL;
 222       face->len_buildchar = 0;
 223     }
 224 
 225     T1_Done_Blend( face );
 226     face->blend = NULL;
 227 #endif
 228 
 229     /* release font info strings */
 230     {
 231       PS_FontInfo  info = &type1->font_info;
 232 
 233 
 234       FT_FREE( info->version );
 235       FT_FREE( info->notice );
 236       FT_FREE( info->full_name );
 237       FT_FREE( info->family_name );
 238       FT_FREE( info->weight );
 239     }
 240 
 241     /* release top dictionary */
 242     FT_FREE( type1->charstrings_len );
 243     FT_FREE( type1->charstrings );
 244     FT_FREE( type1->glyph_names );
 245 
 246     FT_FREE( type1->subrs );
 247     FT_FREE( type1->subrs_len );
 248 
 249     ft_hash_num_free( type1->subrs_hash, memory );
 250     FT_FREE( type1->subrs_hash );
 251 
 252     FT_FREE( type1->subrs_block );
 253     FT_FREE( type1->charstrings_block );
 254     FT_FREE( type1->glyph_names_block );
 255 
 256     FT_FREE( type1->encoding.char_index );
 257     FT_FREE( type1->encoding.char_name );
 258     FT_FREE( type1->font_name );
 259 
 260 #ifndef T1_CONFIG_OPTION_NO_AFM
 261     /* release afm data if present */
 262     if ( face->afm_data )
 263       T1_Done_Metrics( memory, (AFM_FontInfo)face->afm_data );
 264 #endif
 265 
 266     /* release unicode map, if any */
 267 #if 0
 268     FT_FREE( face->unicode_map_rec.maps );
 269     face->unicode_map_rec.num_maps = 0;
 270     face->unicode_map              = NULL;
 271 #endif
 272 
 273     face->root.family_name = NULL;
 274     face->root.style_name  = NULL;
 275   }
 276 
 277 
 278   /**************************************************************************
 279    *
 280    * @Function:
 281    *   T1_Face_Init
 282    *
 283    * @Description:
 284    *   The face object constructor.
 285    *
 286    * @Input:
 287    *   stream ::
 288    *     input stream where to load font data.
 289    *
 290    *   face_index ::
 291    *     The index of the font face in the resource.
 292    *
 293    *   num_params ::
 294    *     Number of additional generic parameters.  Ignored.
 295    *
 296    *   params ::
 297    *     Additional generic parameters.  Ignored.
 298    *
 299    * @InOut:
 300    *   face ::
 301    *     The face record to build.
 302    *
 303    * @Return:
 304    *   FreeType error code.  0 means success.
 305    */
 306   FT_LOCAL_DEF( FT_Error )
 307   T1_Face_Init( FT_Stream      stream,
 308                 FT_Face        t1face,          /* T1_Face */
 309                 FT_Int         face_index,
 310                 FT_Int         num_params,
 311                 FT_Parameter*  params )
 312   {
 313     T1_Face             face = (T1_Face)t1face;
 314     FT_Error            error;
 315     FT_Service_PsCMaps  psnames;
 316     PSAux_Service       psaux;
 317     T1_Font             type1 = &face->type1;
 318     PS_FontInfo         info = &type1->font_info;
 319 
 320     FT_UNUSED( num_params );
 321     FT_UNUSED( params );
 322     FT_UNUSED( stream );
 323 
 324 
 325     face->root.num_faces = 1;
 326 
 327     FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
 328     face->psnames = psnames;
 329 
 330     face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
 331                                            "psaux" );
 332     psaux = (PSAux_Service)face->psaux;
 333     if ( !psaux )
 334     {
 335       FT_ERROR(( "T1_Face_Init: cannot access `psaux' module\n" ));
 336       error = FT_THROW( Missing_Module );
 337       goto Exit;
 338     }
 339 
 340     face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ),
 341                                               "pshinter" );
 342 
 343     FT_TRACE2(( "Type 1 driver\n" ));
 344 
 345     /* open the tokenizer; this will also check the font format */
 346     error = T1_Open_Face( face );
 347     if ( error )
 348       goto Exit;
 349 
 350     FT_TRACE2(( "T1_Face_Init: %08p (index %d)\n",
 351                 face,
 352                 face_index ));
 353 
 354     /* if we just wanted to check the format, leave successfully now */
 355     if ( face_index < 0 )
 356       goto Exit;
 357 
 358     /* check the face index */
 359     if ( ( face_index & 0xFFFF ) > 0 )
 360     {
 361       FT_ERROR(( "T1_Face_Init: invalid face index\n" ));
 362       error = FT_THROW( Invalid_Argument );
 363       goto Exit;
 364     }
 365 
 366     /* now load the font program into the face object */
 367 
 368     /* initialize the face object fields */
 369 
 370     /* set up root face fields */
 371     {
 372       FT_Face  root = (FT_Face)&face->root;
 373 
 374 
 375       root->num_glyphs = type1->num_glyphs;
 376       root->face_index = 0;
 377 
 378       root->face_flags |= FT_FACE_FLAG_SCALABLE    |
 379                           FT_FACE_FLAG_HORIZONTAL  |
 380                           FT_FACE_FLAG_GLYPH_NAMES |
 381                           FT_FACE_FLAG_HINTER;
 382 
 383       if ( info->is_fixed_pitch )
 384         root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH;
 385 
 386       if ( face->blend )
 387         root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS;
 388 
 389       /* The following code to extract the family and the style is very   */
 390       /* simplistic and might get some things wrong.  For a full-featured */
 391       /* algorithm you might have a look at the whitepaper given at       */
 392       /*                                                                  */
 393       /*   https://blogs.msdn.com/text/archive/2007/04/23/wpf-font-selection-model.aspx */
 394 
 395       /* get style name -- be careful, some broken fonts only */
 396       /* have a `/FontName' dictionary entry!                 */
 397       root->family_name = info->family_name;
 398       root->style_name  = NULL;
 399 
 400       if ( root->family_name )
 401       {
 402         char*  full   = info->full_name;
 403         char*  family = root->family_name;
 404 
 405 
 406         if ( full )
 407         {
 408           FT_Bool  the_same = TRUE;
 409 
 410 
 411           while ( *full )
 412           {
 413             if ( *full == *family )
 414             {
 415               family++;
 416               full++;
 417             }
 418             else
 419             {
 420               if ( *full == ' ' || *full == '-' )
 421                 full++;
 422               else if ( *family == ' ' || *family == '-' )
 423                 family++;
 424               else
 425               {
 426                 the_same = FALSE;
 427 
 428                 if ( !*family )
 429                   root->style_name = full;
 430                 break;
 431               }
 432             }
 433           }
 434 
 435           if ( the_same )
 436             root->style_name = (char *)"Regular";
 437         }
 438       }
 439       else
 440       {
 441         /* do we have a `/FontName'? */
 442         if ( type1->font_name )
 443           root->family_name = type1->font_name;
 444       }
 445 
 446       if ( !root->style_name )
 447       {
 448         if ( info->weight )
 449           root->style_name = info->weight;
 450         else
 451           /* assume `Regular' style because we don't know better */
 452           root->style_name = (char *)"Regular";
 453       }
 454 
 455       /* compute style flags */
 456       root->style_flags = 0;
 457       if ( info->italic_angle )
 458         root->style_flags |= FT_STYLE_FLAG_ITALIC;
 459       if ( info->weight )
 460       {
 461         if ( !ft_strcmp( info->weight, "Bold"  ) ||
 462              !ft_strcmp( info->weight, "Black" ) )
 463           root->style_flags |= FT_STYLE_FLAG_BOLD;
 464       }
 465 
 466       /* no embedded bitmap support */
 467       root->num_fixed_sizes = 0;
 468       root->available_sizes = NULL;
 469 
 470       root->bbox.xMin =   type1->font_bbox.xMin            >> 16;
 471       root->bbox.yMin =   type1->font_bbox.yMin            >> 16;
 472       /* no `U' suffix here to 0xFFFF! */
 473       root->bbox.xMax = ( type1->font_bbox.xMax + 0xFFFF ) >> 16;
 474       root->bbox.yMax = ( type1->font_bbox.yMax + 0xFFFF ) >> 16;
 475 
 476       /* Set units_per_EM if we didn't set it in t1_parse_font_matrix. */
 477       if ( !root->units_per_EM )
 478         root->units_per_EM = 1000;
 479 
 480       root->ascender  = (FT_Short)( root->bbox.yMax );
 481       root->descender = (FT_Short)( root->bbox.yMin );
 482 
 483       root->height = (FT_Short)( ( root->units_per_EM * 12 ) / 10 );
 484       if ( root->height < root->ascender - root->descender )
 485         root->height = (FT_Short)( root->ascender - root->descender );
 486 
 487       /* now compute the maximum advance width */
 488       root->max_advance_width =
 489         (FT_Short)( root->bbox.xMax );
 490       {
 491         FT_Pos  max_advance;
 492 
 493 
 494         error = T1_Compute_Max_Advance( face, &max_advance );
 495 
 496         /* in case of error, keep the standard width */
 497         if ( !error )
 498           root->max_advance_width = (FT_Short)FIXED_TO_INT( max_advance );
 499         else
 500           error = FT_Err_Ok;   /* clear error */
 501       }
 502 
 503       root->max_advance_height = root->height;
 504 
 505       root->underline_position  = (FT_Short)info->underline_position;
 506       root->underline_thickness = (FT_Short)info->underline_thickness;
 507     }
 508 
 509     {
 510       FT_Face  root = &face->root;
 511 
 512 
 513       if ( psnames )
 514       {
 515         FT_CharMapRec    charmap;
 516         T1_CMap_Classes  cmap_classes = psaux->t1_cmap_classes;
 517         FT_CMap_Class    clazz;
 518 
 519 
 520         charmap.face = root;
 521 
 522         /* first of all, try to synthesize a Unicode charmap */
 523         charmap.platform_id = TT_PLATFORM_MICROSOFT;
 524         charmap.encoding_id = TT_MS_ID_UNICODE_CS;
 525         charmap.encoding    = FT_ENCODING_UNICODE;
 526 
 527         error = FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL );
 528         if ( error                                      &&
 529              FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
 530              FT_ERR_NEQ( error, Unimplemented_Feature ) )
 531           goto Exit;
 532         error = FT_Err_Ok;
 533 
 534         /* now, generate an Adobe Standard encoding when appropriate */
 535         charmap.platform_id = TT_PLATFORM_ADOBE;
 536         clazz               = NULL;
 537 
 538         switch ( type1->encoding_type )
 539         {
 540         case T1_ENCODING_TYPE_STANDARD:
 541           charmap.encoding    = FT_ENCODING_ADOBE_STANDARD;
 542           charmap.encoding_id = TT_ADOBE_ID_STANDARD;
 543           clazz               = cmap_classes->standard;
 544           break;
 545 
 546         case T1_ENCODING_TYPE_EXPERT:
 547           charmap.encoding    = FT_ENCODING_ADOBE_EXPERT;
 548           charmap.encoding_id = TT_ADOBE_ID_EXPERT;
 549           clazz               = cmap_classes->expert;
 550           break;
 551 
 552         case T1_ENCODING_TYPE_ARRAY:
 553           charmap.encoding    = FT_ENCODING_ADOBE_CUSTOM;
 554           charmap.encoding_id = TT_ADOBE_ID_CUSTOM;
 555           clazz               = cmap_classes->custom;
 556           break;
 557 
 558         case T1_ENCODING_TYPE_ISOLATIN1:
 559           charmap.encoding    = FT_ENCODING_ADOBE_LATIN_1;
 560           charmap.encoding_id = TT_ADOBE_ID_LATIN_1;
 561           clazz               = cmap_classes->unicode;
 562           break;
 563 
 564         default:
 565           ;
 566         }
 567 
 568         if ( clazz )
 569           error = FT_CMap_New( clazz, NULL, &charmap, NULL );
 570       }
 571     }
 572 
 573   Exit:
 574     return error;
 575   }
 576 
 577 
 578   /**************************************************************************
 579    *
 580    * @Function:
 581    *   T1_Driver_Init
 582    *
 583    * @Description:
 584    *   Initializes a given Type 1 driver object.
 585    *
 586    * @Input:
 587    *   driver ::
 588    *     A handle to the target driver object.
 589    *
 590    * @Return:
 591    *   FreeType error code.  0 means success.
 592    */
 593   FT_LOCAL_DEF( FT_Error )
 594   T1_Driver_Init( FT_Module  module )
 595   {
 596     PS_Driver  driver = (PS_Driver)module;
 597 
 598     FT_UInt32  seed;
 599 
 600 
 601     /* set default property values, cf. `ftt1drv.h' */
 602 #ifdef T1_CONFIG_OPTION_OLD_ENGINE
 603     driver->hinting_engine = FT_HINTING_FREETYPE;
 604 #else
 605     driver->hinting_engine = FT_HINTING_ADOBE;
 606 #endif
 607 
 608     driver->no_stem_darkening = TRUE;
 609 
 610     driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
 611     driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
 612     driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
 613     driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
 614     driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
 615     driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
 616     driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
 617     driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
 618 
 619     /* compute random seed from some memory addresses */
 620     seed = (FT_UInt32)( (FT_Offset)(char*)&seed          ^
 621                         (FT_Offset)(char*)&module        ^
 622                         (FT_Offset)(char*)module->memory );
 623     seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
 624 
 625     driver->random_seed = (FT_Int32)seed;
 626     if ( driver->random_seed < 0 )
 627       driver->random_seed = -driver->random_seed;
 628     else if ( driver->random_seed == 0 )
 629       driver->random_seed = 123456789;
 630 
 631     return FT_Err_Ok;
 632   }
 633 
 634 
 635   /**************************************************************************
 636    *
 637    * @Function:
 638    *   T1_Driver_Done
 639    *
 640    * @Description:
 641    *   Finalizes a given Type 1 driver.
 642    *
 643    * @Input:
 644    *   driver ::
 645    *     A handle to the target Type 1 driver.
 646    */
 647   FT_LOCAL_DEF( void )
 648   T1_Driver_Done( FT_Module  driver )
 649   {
 650     FT_UNUSED( driver );
 651   }
 652 
 653 
 654 /* END */