Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/freetype/src/cff/cffobjs.c
Line
Count
Source (jump to first uncovered line)
1
/****************************************************************************
2
 *
3
 * cffobjs.c
4
 *
5
 *   OpenType objects manager (body).
6
 *
7
 * Copyright (C) 1996-2021 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
20
#include <freetype/internal/ftdebug.h>
21
#include <freetype/internal/ftcalc.h>
22
#include <freetype/internal/ftstream.h>
23
#include <freetype/fterrors.h>
24
#include <freetype/ttnameid.h>
25
#include <freetype/tttags.h>
26
#include <freetype/internal/sfnt.h>
27
#include <freetype/ftdriver.h>
28
29
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
30
#include <freetype/ftmm.h>
31
#include <freetype/internal/services/svmm.h>
32
#include <freetype/internal/services/svmetric.h>
33
#endif
34
35
#include <freetype/internal/cffotypes.h>
36
#include "cffobjs.h"
37
#include "cffload.h"
38
#include "cffcmap.h"
39
40
#include "cfferrs.h"
41
42
#include <freetype/internal/psaux.h>
43
#include <freetype/internal/services/svcfftl.h>
44
45
46
  /**************************************************************************
47
   *
48
   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
49
   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
50
   * messages during execution.
51
   */
52
#undef  FT_COMPONENT
53
#define FT_COMPONENT  cffobjs
54
55
56
  /**************************************************************************
57
   *
58
   *                           SIZE FUNCTIONS
59
   *
60
   */
61
62
63
  static PSH_Globals_Funcs
64
  cff_size_get_globals_funcs( CFF_Size  size )
65
3.63k
  {
66
3.63k
    CFF_Face          face     = (CFF_Face)size->root.face;
67
3.63k
    CFF_Font          font     = (CFF_Font)face->extra.data;
68
3.63k
    PSHinter_Service  pshinter = font->pshinter;
69
3.63k
    FT_Module         module;
70
71
72
3.63k
    module = FT_Get_Module( size->root.face->driver->root.library,
73
3.63k
                            "pshinter" );
74
3.63k
    return ( module && pshinter && pshinter->get_globals_funcs )
75
3.63k
           ? pshinter->get_globals_funcs( module )
76
0
           : 0;
77
3.63k
  }
78
79
80
  FT_LOCAL_DEF( void )
81
  cff_size_done( FT_Size  cffsize )        /* CFF_Size */
82
1.81k
  {
83
1.81k
    FT_Memory     memory   = cffsize->face->memory;
84
1.81k
    CFF_Size      size     = (CFF_Size)cffsize;
85
1.81k
    CFF_Face      face     = (CFF_Face)size->root.face;
86
1.81k
    CFF_Font      font     = (CFF_Font)face->extra.data;
87
1.81k
    CFF_Internal  internal = (CFF_Internal)cffsize->internal->module_data;
88
89
90
1.81k
    if ( internal )
91
1.81k
    {
92
1.81k
      PSH_Globals_Funcs  funcs;
93
94
95
1.81k
      funcs = cff_size_get_globals_funcs( size );
96
1.81k
      if ( funcs )
97
1.81k
      {
98
1.81k
        FT_UInt  i;
99
100
101
1.81k
        funcs->destroy( internal->topfont );
102
103
1.81k
        for ( i = font->num_subfonts; i > 0; i-- )
104
0
          funcs->destroy( internal->subfonts[i - 1] );
105
1.81k
      }
106
107
1.81k
      FT_FREE( internal );
108
1.81k
    }
109
1.81k
  }
110
111
112
  /* CFF and Type 1 private dictionaries have slightly different      */
113
  /* structures; we need to synthesize a Type 1 dictionary on the fly */
114
115
  static void
116
  cff_make_private_dict( CFF_SubFont  subfont,
117
                         PS_Private   priv )
118
1.81k
  {
119
1.81k
    CFF_Private  cpriv = &subfont->private_dict;
120
1.81k
    FT_UInt      n, count;
121
122
123
1.81k
    FT_ZERO( priv );
124
125
1.81k
    count = priv->num_blue_values = cpriv->num_blue_values;
126
2.07k
    for ( n = 0; n < count; n++ )
127
258
      priv->blue_values[n] = (FT_Short)cpriv->blue_values[n];
128
129
1.81k
    count = priv->num_other_blues = cpriv->num_other_blues;
130
2.20k
    for ( n = 0; n < count; n++ )
131
388
      priv->other_blues[n] = (FT_Short)cpriv->other_blues[n];
132
133
1.81k
    count = priv->num_family_blues = cpriv->num_family_blues;
134
5.05k
    for ( n = 0; n < count; n++ )
135
3.24k
      priv->family_blues[n] = (FT_Short)cpriv->family_blues[n];
136
137
1.81k
    count = priv->num_family_other_blues = cpriv->num_family_other_blues;
138
2.08k
    for ( n = 0; n < count; n++ )
139
264
      priv->family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n];
140
141
1.81k
    priv->blue_scale = cpriv->blue_scale;
142
1.81k
    priv->blue_shift = (FT_Int)cpriv->blue_shift;
143
1.81k
    priv->blue_fuzz  = (FT_Int)cpriv->blue_fuzz;
144
145
1.81k
    priv->standard_width[0]  = (FT_UShort)cpriv->standard_width;
146
1.81k
    priv->standard_height[0] = (FT_UShort)cpriv->standard_height;
147
148
1.81k
    count = priv->num_snap_widths = cpriv->num_snap_widths;
149
1.81k
    for ( n = 0; n < count; n++ )
150
0
      priv->snap_widths[n] = (FT_Short)cpriv->snap_widths[n];
151
152
1.81k
    count = priv->num_snap_heights = cpriv->num_snap_heights;
153
1.81k
    for ( n = 0; n < count; n++ )
154
0
      priv->snap_heights[n] = (FT_Short)cpriv->snap_heights[n];
155
156
1.81k
    priv->force_bold     = cpriv->force_bold;
157
1.81k
    priv->language_group = cpriv->language_group;
158
1.81k
    priv->lenIV          = cpriv->lenIV;
159
1.81k
  }
160
161
162
  FT_LOCAL_DEF( FT_Error )
163
  cff_size_init( FT_Size  cffsize )         /* CFF_Size */
164
1.81k
  {
165
1.81k
    CFF_Size           size  = (CFF_Size)cffsize;
166
1.81k
    FT_Error           error = FT_Err_Ok;
167
1.81k
    PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
168
169
1.81k
    FT_Memory     memory   = cffsize->face->memory;
170
1.81k
    CFF_Internal  internal = NULL;
171
1.81k
    CFF_Face      face     = (CFF_Face)cffsize->face;
172
1.81k
    CFF_Font      font     = (CFF_Font)face->extra.data;
173
174
1.81k
    PS_PrivateRec priv;
175
176
1.81k
    FT_UInt       i;
177
178
1.81k
    if ( !funcs )
179
0
      goto Exit;
180
181
1.81k
    if ( FT_NEW( internal ) )
182
0
      goto Exit;
183
184
1.81k
    cff_make_private_dict( &font->top_font, &priv );
185
1.81k
    error = funcs->create( cffsize->face->memory, &priv,
186
1.81k
                             &internal->topfont );
187
1.81k
    if ( error )
188
0
      goto Exit;
189
190
1.81k
    for ( i = font->num_subfonts; i > 0; i-- )
191
0
    {
192
0
      CFF_SubFont  sub = font->subfonts[i - 1];
193
194
195
0
      cff_make_private_dict( sub, &priv );
196
0
      error = funcs->create( cffsize->face->memory, &priv,
197
0
                               &internal->subfonts[i - 1] );
198
0
      if ( error )
199
0
        goto Exit;
200
0
    }
201
202
1.81k
    cffsize->internal->module_data = internal;
203
204
1.81k
    size->strike_index = 0xFFFFFFFFUL;
205
206
1.81k
  Exit:
207
1.81k
    if ( error )
208
0
    {
209
0
      if ( internal )
210
0
      {
211
0
        for ( i = font->num_subfonts; i > 0; i-- )
212
0
          FT_FREE( internal->subfonts[i - 1] );
213
0
        FT_FREE( internal->topfont );
214
0
      }
215
216
0
      FT_FREE( internal );
217
0
    }
218
219
1.81k
    return error;
220
1.81k
  }
221
222
223
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
224
225
  FT_LOCAL_DEF( FT_Error )
226
  cff_size_select( FT_Size   size,
227
                   FT_ULong  strike_index )
228
0
  {
229
0
    CFF_Size           cffsize = (CFF_Size)size;
230
0
    PSH_Globals_Funcs  funcs;
231
232
233
0
    cffsize->strike_index = strike_index;
234
235
0
    FT_Select_Metrics( size->face, strike_index );
236
237
0
    funcs = cff_size_get_globals_funcs( cffsize );
238
239
0
    if ( funcs )
240
0
    {
241
0
      CFF_Face      face     = (CFF_Face)size->face;
242
0
      CFF_Font      font     = (CFF_Font)face->extra.data;
243
0
      CFF_Internal  internal = (CFF_Internal)size->internal->module_data;
244
245
0
      FT_Long  top_upm  = (FT_Long)font->top_font.font_dict.units_per_em;
246
0
      FT_UInt  i;
247
248
249
0
      funcs->set_scale( internal->topfont,
250
0
                        size->metrics.x_scale, size->metrics.y_scale,
251
0
                        0, 0 );
252
253
0
      for ( i = font->num_subfonts; i > 0; i-- )
254
0
      {
255
0
        CFF_SubFont  sub     = font->subfonts[i - 1];
256
0
        FT_Long      sub_upm = (FT_Long)sub->font_dict.units_per_em;
257
0
        FT_Pos       x_scale, y_scale;
258
259
260
0
        if ( top_upm != sub_upm )
261
0
        {
262
0
          x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
263
0
          y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
264
0
        }
265
0
        else
266
0
        {
267
0
          x_scale = size->metrics.x_scale;
268
0
          y_scale = size->metrics.y_scale;
269
0
        }
270
271
0
        funcs->set_scale( internal->subfonts[i - 1],
272
0
                          x_scale, y_scale, 0, 0 );
273
0
      }
274
0
    }
275
276
0
    return FT_Err_Ok;
277
0
  }
278
279
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
280
281
282
  FT_LOCAL_DEF( FT_Error )
283
  cff_size_request( FT_Size          size,
284
                    FT_Size_Request  req )
285
0
  {
286
0
    CFF_Size           cffsize = (CFF_Size)size;
287
0
    PSH_Globals_Funcs  funcs;
288
289
290
0
#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
291
292
0
    if ( FT_HAS_FIXED_SIZES( size->face ) )
293
0
    {
294
0
      CFF_Face      cffface = (CFF_Face)size->face;
295
0
      SFNT_Service  sfnt    = (SFNT_Service)cffface->sfnt;
296
0
      FT_ULong      strike_index;
297
298
299
0
      if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) )
300
0
        cffsize->strike_index = 0xFFFFFFFFUL;
301
0
      else
302
0
        return cff_size_select( size, strike_index );
303
0
    }
304
305
0
#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
306
307
0
    FT_Request_Metrics( size->face, req );
308
309
0
    funcs = cff_size_get_globals_funcs( cffsize );
310
311
0
    if ( funcs )
312
0
    {
313
0
      CFF_Face      cffface  = (CFF_Face)size->face;
314
0
      CFF_Font      font     = (CFF_Font)cffface->extra.data;
315
0
      CFF_Internal  internal = (CFF_Internal)size->internal->module_data;
316
317
0
      FT_Long  top_upm  = (FT_Long)font->top_font.font_dict.units_per_em;
318
0
      FT_UInt  i;
319
320
321
0
      funcs->set_scale( internal->topfont,
322
0
                        size->metrics.x_scale, size->metrics.y_scale,
323
0
                        0, 0 );
324
325
0
      for ( i = font->num_subfonts; i > 0; i-- )
326
0
      {
327
0
        CFF_SubFont  sub     = font->subfonts[i - 1];
328
0
        FT_Long      sub_upm = (FT_Long)sub->font_dict.units_per_em;
329
0
        FT_Pos       x_scale, y_scale;
330
331
332
0
        if ( top_upm != sub_upm )
333
0
        {
334
0
          x_scale = FT_MulDiv( size->metrics.x_scale, top_upm, sub_upm );
335
0
          y_scale = FT_MulDiv( size->metrics.y_scale, top_upm, sub_upm );
336
0
        }
337
0
        else
338
0
        {
339
0
          x_scale = size->metrics.x_scale;
340
0
          y_scale = size->metrics.y_scale;
341
0
        }
342
343
0
        funcs->set_scale( internal->subfonts[i - 1],
344
0
                          x_scale, y_scale, 0, 0 );
345
0
      }
346
0
    }
347
348
0
    return FT_Err_Ok;
349
0
  }
350
351
352
  /**************************************************************************
353
   *
354
   *                           SLOT  FUNCTIONS
355
   *
356
   */
357
358
  FT_LOCAL_DEF( void )
359
  cff_slot_done( FT_GlyphSlot  slot )
360
1.81k
  {
361
1.81k
    if ( slot->internal )
362
1.81k
      slot->internal->glyph_hints = NULL;
363
1.81k
  }
364
365
366
  FT_LOCAL_DEF( FT_Error )
367
  cff_slot_init( FT_GlyphSlot  slot )
368
1.81k
  {
369
1.81k
    CFF_Face          face     = (CFF_Face)slot->face;
370
1.81k
    CFF_Font          font     = (CFF_Font)face->extra.data;
371
1.81k
    PSHinter_Service  pshinter = font->pshinter;
372
373
374
1.81k
    if ( pshinter )
375
1.81k
    {
376
1.81k
      FT_Module  module;
377
378
379
1.81k
      module = FT_Get_Module( slot->face->driver->root.library,
380
1.81k
                              "pshinter" );
381
1.81k
      if ( module )
382
1.81k
      {
383
1.81k
        T2_Hints_Funcs  funcs;
384
385
386
1.81k
        funcs = pshinter->get_t2_funcs( module );
387
1.81k
        slot->internal->glyph_hints = (void*)funcs;
388
1.81k
      }
389
1.81k
    }
390
391
1.81k
    return FT_Err_Ok;
392
1.81k
  }
393
394
395
  /**************************************************************************
396
   *
397
   *                          FACE  FUNCTIONS
398
   *
399
   */
400
401
  static FT_String*
402
  cff_strcpy( FT_Memory         memory,
403
              const FT_String*  source )
404
554
  {
405
554
    FT_Error    error;
406
554
    FT_String*  result;
407
408
409
554
    (void)FT_STRDUP( result, source );
410
411
554
    FT_UNUSED( error );
412
413
554
    return result;
414
554
  }
415
416
417
  /* Strip all subset prefixes of the form `ABCDEF+'.  Usually, there */
418
  /* is only one, but font names like `APCOOG+JFABTD+FuturaBQ-Bold'   */
419
  /* have been seen in the wild.                                      */
420
421
  static void
422
  remove_subset_prefix( FT_String*  name )
423
0
  {
424
0
    FT_Int32  idx             = 0;
425
0
    FT_Int32  length          = (FT_Int32)ft_strlen( name ) + 1;
426
0
    FT_Bool   continue_search = 1;
427
428
429
0
    while ( continue_search )
430
0
    {
431
0
      if ( length >= 7 && name[6] == '+' )
432
0
      {
433
0
        for ( idx = 0; idx < 6; idx++ )
434
0
        {
435
          /* ASCII uppercase letters */
436
0
          if ( !( 'A' <= name[idx] && name[idx] <= 'Z' ) )
437
0
            continue_search = 0;
438
0
        }
439
440
0
        if ( continue_search )
441
0
        {
442
0
          for ( idx = 7; idx < length; idx++ )
443
0
            name[idx - 7] = name[idx];
444
0
          length -= 7;
445
0
        }
446
0
      }
447
0
      else
448
0
        continue_search = 0;
449
0
    }
450
0
  }
451
452
453
  /* Remove the style part from the family name (if present). */
454
455
  static void
456
  remove_style( FT_String*        family_name,
457
                const FT_String*  style_name )
458
178
  {
459
178
    FT_Int32  family_name_length, style_name_length;
460
461
462
178
    family_name_length = (FT_Int32)ft_strlen( family_name );
463
178
    style_name_length  = (FT_Int32)ft_strlen( style_name );
464
465
178
    if ( family_name_length > style_name_length )
466
145
    {
467
145
      FT_Int  idx;
468
469
470
145
      for ( idx = 1; idx <= style_name_length; idx++ )
471
145
      {
472
145
        if ( family_name[family_name_length - idx] !=
473
145
             style_name[style_name_length - idx] )
474
145
          break;
475
145
      }
476
477
145
      if ( idx > style_name_length )
478
0
      {
479
        /* family_name ends with style_name; remove it */
480
0
        idx = family_name_length - style_name_length - 1;
481
482
        /* also remove special characters     */
483
        /* between real family name and style */
484
0
        while ( idx > 0                     &&
485
0
                ( family_name[idx] == '-' ||
486
0
                  family_name[idx] == ' ' ||
487
0
                  family_name[idx] == '_' ||
488
0
                  family_name[idx] == '+' ) )
489
0
          idx--;
490
491
0
        if ( idx > 0 )
492
0
          family_name[idx + 1] = '\0';
493
0
      }
494
145
    }
495
178
  }
496
497
498
  FT_LOCAL_DEF( FT_Error )
499
  cff_face_init( FT_Stream      stream,
500
                 FT_Face        cffface,        /* CFF_Face */
501
                 FT_Int         face_index,
502
                 FT_Int         num_params,
503
                 FT_Parameter*  params )
504
5.86k
  {
505
5.86k
    CFF_Face            face        = (CFF_Face)cffface;
506
5.86k
    FT_Error            error;
507
5.86k
    SFNT_Service        sfnt;
508
5.86k
    FT_Service_PsCMaps  psnames;
509
5.86k
    PSHinter_Service    pshinter;
510
5.86k
    PSAux_Service       psaux;
511
5.86k
    FT_Service_CFFLoad  cffload;
512
5.86k
    FT_Bool             pure_cff    = 1;
513
5.86k
    FT_Bool             cff2        = 0;
514
5.86k
    FT_Bool             sfnt_format = 0;
515
5.86k
    FT_Library          library     = cffface->driver->root.library;
516
517
518
5.86k
    sfnt = (SFNT_Service)FT_Get_Module_Interface( library,
519
5.86k
                                                  "sfnt" );
520
5.86k
    if ( !sfnt )
521
0
    {
522
0
      FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" ));
523
0
      error = FT_THROW( Missing_Module );
524
0
      goto Exit;
525
0
    }
526
527
5.86k
    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
528
529
5.86k
    pshinter = (PSHinter_Service)FT_Get_Module_Interface( library,
530
5.86k
                                                          "pshinter" );
531
532
5.86k
    psaux = (PSAux_Service)FT_Get_Module_Interface( library,
533
5.86k
                                                    "psaux" );
534
5.86k
    if ( !psaux )
535
0
    {
536
0
      FT_ERROR(( "cff_face_init: cannot access `psaux' module\n" ));
537
0
      error = FT_THROW( Missing_Module );
538
0
      goto Exit;
539
0
    }
540
5.86k
    face->psaux = psaux;
541
542
5.86k
    FT_FACE_FIND_GLOBAL_SERVICE( face, cffload, CFF_LOAD );
543
544
5.86k
    FT_TRACE2(( "CFF driver\n" ));
545
546
    /* create input stream from resource */
547
5.86k
    if ( FT_STREAM_SEEK( 0 ) )
548
0
      goto Exit;
549
550
    /* check whether we have a valid OpenType file */
551
5.86k
    FT_TRACE2(( "  " ));
552
5.86k
    error = sfnt->init_face( stream, face, face_index, num_params, params );
553
5.86k
    if ( !error )
554
3.87k
    {
555
3.87k
      if ( face->format_tag != TTAG_OTTO )  /* `OTTO'; OpenType/CFF font */
556
0
      {
557
0
        FT_TRACE2(( "  not an OpenType/CFF font\n" ));
558
0
        error = FT_THROW( Unknown_File_Format );
559
0
        goto Exit;
560
0
      }
561
562
      /* if we are performing a simple font format check, exit immediately */
563
3.87k
      if ( face_index < 0 )
564
0
        return FT_Err_Ok;
565
566
3.87k
      sfnt_format = 1;
567
568
      /* now, the font can be either an OpenType/CFF font, or an SVG CEF */
569
      /* font; in the latter case it doesn't have a `head' table         */
570
3.87k
      error = face->goto_table( face, TTAG_head, stream, 0 );
571
3.87k
      if ( !error )
572
3.37k
      {
573
3.37k
        pure_cff = 0;
574
575
        /* load font directory */
576
3.37k
        error = sfnt->load_face( stream, face, face_index,
577
3.37k
                                 num_params, params );
578
3.37k
        if ( error )
579
815
          goto Exit;
580
496
      }
581
496
      else
582
496
      {
583
        /* load the `cmap' table explicitly */
584
496
        error = sfnt->load_cmap( face, stream );
585
496
        if ( error )
586
104
          goto Exit;
587
2.95k
      }
588
589
      /* now load the CFF part of the file; */
590
      /* give priority to CFF2              */
591
2.95k
      error = face->goto_table( face, TTAG_CFF2, stream, 0 );
592
2.95k
      if ( !error )
593
0
      {
594
0
        cff2          = 1;
595
0
        face->is_cff2 = cff2;
596
0
      }
597
598
2.95k
      if ( FT_ERR_EQ( error, Table_Missing ) )
599
2.95k
        error = face->goto_table( face, TTAG_CFF, stream, 0 );
600
601
2.95k
      if ( error )
602
19
        goto Exit;
603
1.99k
    }
604
1.99k
    else
605
1.99k
    {
606
      /* rewind to start of file; we are going to load a pure-CFF font */
607
1.99k
      if ( FT_STREAM_SEEK( 0 ) )
608
0
        goto Exit;
609
1.99k
      error = FT_Err_Ok;
610
1.99k
    }
611
612
    /* now load and parse the CFF table in the file */
613
4.93k
    {
614
4.93k
      CFF_Font         cff = NULL;
615
4.93k
      CFF_FontRecDict  dict;
616
4.93k
      FT_Memory        memory = cffface->memory;
617
4.93k
      FT_Int32         flags;
618
4.93k
      FT_UInt          i;
619
620
621
4.93k
      if ( FT_NEW( cff ) )
622
0
        goto Exit;
623
624
4.93k
      face->extra.data = cff;
625
4.93k
      error = cff_font_load( library,
626
4.93k
                             stream,
627
4.93k
                             face_index,
628
4.93k
                             cff,
629
4.93k
                             face,
630
4.93k
                             pure_cff,
631
4.93k
                             cff2 );
632
4.93k
      if ( error )
633
3.11k
        goto Exit;
634
635
      /* if we are performing a simple font format check, exit immediately */
636
      /* (this is here for pure CFF)                                       */
637
1.81k
      if ( face_index < 0 )
638
0
      {
639
0
        cffface->num_faces = (FT_Long)cff->num_faces;
640
0
        return FT_Err_Ok;
641
0
      }
642
643
1.81k
      cff->pshinter = pshinter;
644
1.81k
      cff->psnames  = psnames;
645
1.81k
      cff->cffload  = cffload;
646
647
1.81k
      cffface->face_index = face_index & 0xFFFF;
648
649
      /* Complement the root flags with some interesting information. */
650
      /* Note that this is only necessary for pure CFF and CEF fonts; */
651
      /* SFNT based fonts use the `name' table instead.               */
652
653
1.81k
      cffface->num_glyphs = (FT_Long)cff->num_glyphs;
654
655
1.81k
      dict = &cff->top_font.font_dict;
656
657
      /* we need the `psnames' module for CFF and CEF formats */
658
      /* which aren't CID-keyed                               */
659
1.81k
      if ( dict->cid_registry == 0xFFFFU && !psnames )
660
0
      {
661
0
        FT_ERROR(( "cff_face_init:"
662
0
                   " cannot open CFF & CEF fonts\n" ));
663
0
        FT_ERROR(( "              "
664
0
                   " without the `psnames' module\n" ));
665
0
        error = FT_THROW( Missing_Module );
666
0
        goto Exit;
667
0
      }
668
669
#ifdef FT_DEBUG_LEVEL_TRACE
670
      {
671
        FT_UInt     idx;
672
        FT_String*  s;
673
674
675
        FT_TRACE4(( "SIDs\n" ));
676
677
        /* dump string index, including default strings for convenience */
678
        for ( idx = 0; idx <= 390; idx++ )
679
        {
680
          s = cff_index_get_sid_string( cff, idx );
681
          if ( s )
682
            FT_TRACE4(( "  %5d %s\n", idx, s ));
683
        }
684
685
        /* In Multiple Master CFFs, two SIDs hold the Normalize Design  */
686
        /* Vector (NDV) and Convert Design Vector (CDV) charstrings,    */
687
        /* which may contain NULL bytes in the middle of the data, too. */
688
        /* We thus access `cff->strings' directly.                      */
689
        for ( idx = 1; idx < cff->num_strings; idx++ )
690
        {
691
          FT_Byte*    s1    = cff->strings[idx - 1];
692
          FT_Byte*    s2    = cff->strings[idx];
693
          FT_PtrDist  s1len = s2 - s1 - 1; /* without the final NULL byte */
694
          FT_PtrDist  l;
695
696
697
          FT_TRACE4(( "  %5d ", idx + 390 ));
698
          for ( l = 0; l < s1len; l++ )
699
            FT_TRACE4(( "%c", s1[l] ));
700
          FT_TRACE4(( "\n" ));
701
        }
702
703
        /* print last element */
704
        if ( cff->num_strings )
705
        {
706
          FT_Byte*    s1    = cff->strings[cff->num_strings - 1];
707
          FT_Byte*    s2    = cff->string_pool + cff->string_pool_size;
708
          FT_PtrDist  s1len = s2 - s1 - 1;
709
          FT_PtrDist  l;
710
711
712
          FT_TRACE4(( "  %5d ", cff->num_strings + 390 ));
713
          for ( l = 0; l < s1len; l++ )
714
            FT_TRACE4(( "%c", s1[l] ));
715
          FT_TRACE4(( "\n" ));
716
        }
717
      }
718
#endif /* FT_DEBUG_LEVEL_TRACE */
719
720
1.81k
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
721
1.81k
      {
722
1.81k
        FT_Service_MultiMasters       mm  = (FT_Service_MultiMasters)face->mm;
723
1.81k
        FT_Service_MetricsVariations  var = (FT_Service_MetricsVariations)face->var;
724
725
1.81k
        FT_UInt  instance_index = (FT_UInt)face_index >> 16;
726
727
728
1.81k
        if ( FT_HAS_MULTIPLE_MASTERS( cffface ) &&
729
0
             mm                                 &&
730
0
             instance_index > 0                 )
731
0
        {
732
0
          error = mm->set_instance( cffface, instance_index );
733
0
          if ( error )
734
0
            goto Exit;
735
736
0
          if ( var )
737
0
            var->metrics_adjust( cffface );
738
0
        }
739
1.81k
      }
740
1.81k
#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
741
742
1.81k
      if ( !dict->has_font_matrix )
743
22
        dict->units_per_em = pure_cff ? 1000 : face->root.units_per_EM;
744
745
      /* Normalize the font matrix so that `matrix->yy' is 1; if  */
746
      /* it is zero, we use `matrix->yx' instead.  The scaling is */
747
      /* done with `units_per_em' then (at this point, it already */
748
      /* contains the scaling factor, but without normalization   */
749
      /* of the matrix).                                          */
750
      /*                                                          */
751
      /* Note that the offsets must be expressed in integer font  */
752
      /* units.                                                   */
753
754
1.81k
      {
755
1.81k
        FT_Matrix*  matrix = &dict->font_matrix;
756
1.81k
        FT_Vector*  offset = &dict->font_offset;
757
1.81k
        FT_ULong*   upm    = &dict->units_per_em;
758
1.81k
        FT_Fixed    temp;
759
760
761
1.81k
        temp = matrix->yy ? FT_ABS( matrix->yy )
762
1.81k
                          : FT_ABS( matrix->yx );
763
764
1.81k
        if ( temp != 0x10000L )
765
1.71k
        {
766
1.71k
          *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
767
768
1.71k
          matrix->xx = FT_DivFix( matrix->xx, temp );
769
1.71k
          matrix->yx = FT_DivFix( matrix->yx, temp );
770
1.71k
          matrix->xy = FT_DivFix( matrix->xy, temp );
771
1.71k
          matrix->yy = FT_DivFix( matrix->yy, temp );
772
1.71k
          offset->x  = FT_DivFix( offset->x,  temp );
773
1.71k
          offset->y  = FT_DivFix( offset->y,  temp );
774
1.71k
        }
775
776
1.81k
        offset->x >>= 16;
777
1.81k
        offset->y >>= 16;
778
1.81k
      }
779
780
1.81k
      for ( i = cff->num_subfonts; i > 0; i-- )
781
0
      {
782
0
        CFF_FontRecDict  sub = &cff->subfonts[i - 1]->font_dict;
783
0
        CFF_FontRecDict  top = &cff->top_font.font_dict;
784
785
0
        FT_Matrix*  matrix;
786
0
        FT_Vector*  offset;
787
0
        FT_ULong*   upm;
788
0
        FT_Fixed    temp;
789
790
791
0
        if ( sub->has_font_matrix )
792
0
        {
793
0
          FT_Long  scaling;
794
795
796
          /* if we have a top-level matrix, */
797
          /* concatenate the subfont matrix */
798
799
0
          if ( top->has_font_matrix )
800
0
          {
801
0
            if ( top->units_per_em > 1 && sub->units_per_em > 1 )
802
0
              scaling = (FT_Long)FT_MIN( top->units_per_em,
803
0
                                         sub->units_per_em );
804
0
            else
805
0
              scaling = 1;
806
807
0
            FT_Matrix_Multiply_Scaled( &top->font_matrix,
808
0
                                       &sub->font_matrix,
809
0
                                       scaling );
810
0
            FT_Vector_Transform_Scaled( &sub->font_offset,
811
0
                                        &top->font_matrix,
812
0
                                        scaling );
813
814
0
            sub->units_per_em = (FT_ULong)
815
0
                                  FT_MulDiv( (FT_Long)sub->units_per_em,
816
0
                                             (FT_Long)top->units_per_em,
817
0
                                             scaling );
818
0
          }
819
0
        }
820
0
        else
821
0
        {
822
0
          sub->font_matrix = top->font_matrix;
823
0
          sub->font_offset = top->font_offset;
824
825
0
          sub->units_per_em = top->units_per_em;
826
0
        }
827
828
0
        matrix = &sub->font_matrix;
829
0
        offset = &sub->font_offset;
830
0
        upm    = &sub->units_per_em;
831
832
0
        temp = matrix->yy ? FT_ABS( matrix->yy )
833
0
                          : FT_ABS( matrix->yx );
834
835
836
0
        if ( temp != 0x10000L )
837
0
        {
838
0
          *upm = (FT_ULong)FT_DivFix( (FT_Long)*upm, temp );
839
840
0
          matrix->xx = FT_DivFix( matrix->xx, temp );
841
0
          matrix->yx = FT_DivFix( matrix->yx, temp );
842
0
          matrix->xy = FT_DivFix( matrix->xy, temp );
843
0
          matrix->yy = FT_DivFix( matrix->yy, temp );
844
0
          offset->x  = FT_DivFix( offset->x,  temp );
845
0
          offset->y  = FT_DivFix( offset->y,  temp );
846
0
        }
847
848
0
        offset->x >>= 16;
849
0
        offset->y >>= 16;
850
0
      }
851
852
1.81k
      if ( pure_cff )
853
277
      {
854
277
        char*  style_name = NULL;
855
856
857
        /* set up num_faces */
858
277
        cffface->num_faces = (FT_Long)cff->num_faces;
859
860
        /* compute number of glyphs */
861
277
        if ( dict->cid_registry != 0xFFFFU )
862
0
          cffface->num_glyphs = (FT_Long)( cff->charset.max_cid + 1 );
863
277
        else
864
277
          cffface->num_glyphs = (FT_Long)cff->charstrings_index.count;
865
866
        /* set global bbox, as well as EM size */
867
277
        cffface->bbox.xMin =   dict->font_bbox.xMin            >> 16;
868
277
        cffface->bbox.yMin =   dict->font_bbox.yMin            >> 16;
869
        /* no `U' suffix here to 0xFFFF! */
870
277
        cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFF ) >> 16;
871
277
        cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFF ) >> 16;
872
873
277
        cffface->units_per_EM = (FT_UShort)( dict->units_per_em );
874
875
277
        cffface->ascender  = (FT_Short)( cffface->bbox.yMax );
876
277
        cffface->descender = (FT_Short)( cffface->bbox.yMin );
877
878
277
        cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 );
879
277
        if ( cffface->height < cffface->ascender - cffface->descender )
880
6
          cffface->height = (FT_Short)( cffface->ascender -
881
6
                                        cffface->descender );
882
883
277
        cffface->underline_position  =
884
277
          (FT_Short)( dict->underline_position >> 16 );
885
277
        cffface->underline_thickness =
886
277
          (FT_Short)( dict->underline_thickness >> 16 );
887
888
        /* retrieve font family & style name */
889
277
        if ( dict->family_name )
890
277
        {
891
277
          char*  family_name;
892
893
894
277
          family_name = cff_index_get_sid_string( cff, dict->family_name );
895
277
          if ( family_name )
896
277
            cffface->family_name = cff_strcpy( memory, family_name );
897
277
        }
898
899
277
        if ( !cffface->family_name )
900
0
        {
901
0
          cffface->family_name = cff_index_get_name(
902
0
                                   cff,
903
0
                                   (FT_UInt)( face_index & 0xFFFF ) );
904
0
          if ( cffface->family_name )
905
0
            remove_subset_prefix( cffface->family_name );
906
0
        }
907
908
277
        if ( cffface->family_name )
909
277
        {
910
277
          char*  full   = cff_index_get_sid_string( cff,
911
277
                                                    dict->full_name );
912
277
          char*  fullp  = full;
913
277
          char*  family = cffface->family_name;
914
915
916
          /* We try to extract the style name from the full name.   */
917
          /* We need to ignore spaces and dashes during the search. */
918
277
          if ( full && family )
919
277
          {
920
1.88k
            while ( *fullp )
921
1.80k
            {
922
              /* skip common characters at the start of both strings */
923
1.80k
              if ( *fullp == *family )
924
1.46k
              {
925
1.46k
                family++;
926
1.46k
                fullp++;
927
1.46k
                continue;
928
1.46k
              }
929
930
              /* ignore spaces and dashes in full name during comparison */
931
347
              if ( *fullp == ' ' || *fullp == '-' )
932
147
              {
933
147
                fullp++;
934
147
                continue;
935
147
              }
936
937
              /* ignore spaces and dashes in family name during comparison */
938
200
              if ( *family == ' ' || *family == '-' )
939
3
              {
940
3
                family++;
941
3
                continue;
942
3
              }
943
944
197
              if ( !*family && *fullp )
945
178
              {
946
                /* The full name begins with the same characters as the  */
947
                /* family name, with spaces and dashes removed.  In this */
948
                /* case, the remaining string in `fullp' will be used as */
949
                /* the style name.                                       */
950
178
                style_name = cff_strcpy( memory, fullp );
951
952
                /* remove the style part from the family name (if present) */
953
178
                if ( style_name )
954
178
                  remove_style( cffface->family_name, style_name );
955
178
              }
956
197
              break;
957
197
            }
958
277
          }
959
277
        }
960
0
        else
961
0
        {
962
0
          char  *cid_font_name =
963
0
                   cff_index_get_sid_string( cff,
964
0
                                             dict->cid_font_name );
965
966
967
          /* do we have a `/FontName' for a CID-keyed font? */
968
0
          if ( cid_font_name )
969
0
            cffface->family_name = cff_strcpy( memory, cid_font_name );
970
0
        }
971
972
277
        if ( style_name )
973
178
          cffface->style_name = style_name;
974
99
        else
975
          /* assume "Regular" style if we don't know better */
976
99
          cffface->style_name = cff_strcpy( memory, "Regular" );
977
978
        /********************************************************************
979
         *
980
         * Compute face flags.
981
         */
982
277
        flags = FT_FACE_FLAG_SCALABLE   | /* scalable outlines */
983
277
                FT_FACE_FLAG_HORIZONTAL | /* horizontal data   */
984
277
                FT_FACE_FLAG_HINTER;      /* has native hinter */
985
986
277
        if ( sfnt_format )
987
277
          flags |= FT_FACE_FLAG_SFNT;
988
989
        /* fixed width font? */
990
277
        if ( dict->is_fixed_pitch )
991
0
          flags |= FT_FACE_FLAG_FIXED_WIDTH;
992
993
  /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */
994
#if 0
995
        /* kerning available? */
996
        if ( face->kern_pairs )
997
          flags |= FT_FACE_FLAG_KERNING;
998
#endif
999
1000
277
        cffface->face_flags |= flags;
1001
1002
        /********************************************************************
1003
         *
1004
         * Compute style flags.
1005
         */
1006
277
        flags = 0;
1007
1008
277
        if ( dict->italic_angle )
1009
0
          flags |= FT_STYLE_FLAG_ITALIC;
1010
1011
277
        {
1012
277
          char  *weight = cff_index_get_sid_string( cff,
1013
277
                                                    dict->weight );
1014
1015
1016
277
          if ( weight )
1017
271
            if ( !ft_strcmp( weight, "Bold"  ) ||
1018
271
                 !ft_strcmp( weight, "Black" ) )
1019
0
              flags |= FT_STYLE_FLAG_BOLD;
1020
277
        }
1021
1022
        /* double check */
1023
277
        if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name )
1024
277
          if ( !ft_strncmp( cffface->style_name, "Bold", 4 )  ||
1025
277
               !ft_strncmp( cffface->style_name, "Black", 5 ) )
1026
0
            flags |= FT_STYLE_FLAG_BOLD;
1027
1028
277
        cffface->style_flags = flags;
1029
277
      }
1030
1031
1.81k
#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
1032
      /* CID-keyed CFF or CFF2 fonts don't have glyph names -- the SFNT */
1033
      /* loader has unset this flag because of the 3.0 `post' table.    */
1034
1.81k
      if ( dict->cid_registry == 0xFFFFU && !cff2 )
1035
1.81k
        cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES;
1036
1.81k
#endif
1037
1038
1.81k
      if ( dict->cid_registry != 0xFFFFU && pure_cff )
1039
0
        cffface->face_flags |= FT_FACE_FLAG_CID_KEYED;
1040
1041
      /********************************************************************
1042
       *
1043
       * Compute char maps.
1044
       */
1045
1046
      /* Try to synthesize a Unicode charmap if there is none available */
1047
      /* already.  If an OpenType font contains a Unicode "cmap", we    */
1048
      /* will use it, whatever be in the CFF part of the file.          */
1049
1.81k
      {
1050
1.81k
        FT_CharMapRec  cmaprec;
1051
1.81k
        FT_CharMap     cmap;
1052
1.81k
        FT_UInt        nn;
1053
1.81k
        CFF_Encoding   encoding = &cff->encoding;
1054
1055
1056
1.88k
        for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ )
1057
123
        {
1058
123
          cmap = cffface->charmaps[nn];
1059
1060
          /* Windows Unicode? */
1061
123
          if ( cmap->platform_id == TT_PLATFORM_MICROSOFT &&
1062
13
               cmap->encoding_id == TT_MS_ID_UNICODE_CS   )
1063
13
            goto Skip_Unicode;
1064
1065
          /* Apple Unicode platform id? */
1066
110
          if ( cmap->platform_id == TT_PLATFORM_APPLE_UNICODE )
1067
40
            goto Skip_Unicode; /* Apple Unicode */
1068
110
        }
1069
1070
        /* since CID-keyed fonts don't contain glyph names, we can't */
1071
        /* construct a cmap                                          */
1072
1.76k
        if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU )
1073
0
          goto Exit;
1074
1075
        /* we didn't find a Unicode charmap -- synthesize one */
1076
1.76k
        cmaprec.face        = cffface;
1077
1.76k
        cmaprec.platform_id = TT_PLATFORM_MICROSOFT;
1078
1.76k
        cmaprec.encoding_id = TT_MS_ID_UNICODE_CS;
1079
1.76k
        cmaprec.encoding    = FT_ENCODING_UNICODE;
1080
1081
1.76k
        nn = (FT_UInt)cffface->num_charmaps;
1082
1083
1.76k
        error = FT_CMap_New( &cff_cmap_unicode_class_rec, NULL,
1084
1.76k
                             &cmaprec, NULL );
1085
1.76k
        if ( error                                      &&
1086
1.76k
             FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) &&
1087
1.76k
             FT_ERR_NEQ( error, Unimplemented_Feature ) )
1088
0
          goto Exit;
1089
1.76k
        error = FT_Err_Ok;
1090
1091
        /* if no Unicode charmap was previously selected, select this one */
1092
1.76k
        if ( !cffface->charmap && nn != (FT_UInt)cffface->num_charmaps )
1093
1.30k
          cffface->charmap = cffface->charmaps[nn];
1094
1095
1.81k
      Skip_Unicode:
1096
1.81k
        if ( encoding->count > 0 )
1097
1.27k
        {
1098
1.27k
          FT_CMap_Class  clazz;
1099
1100
1101
1.27k
          cmaprec.face        = cffface;
1102
1.27k
          cmaprec.platform_id = TT_PLATFORM_ADOBE;  /* Adobe platform id */
1103
1104
1.27k
          if ( encoding->offset == 0 )
1105
1.27k
          {
1106
1.27k
            cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
1107
1.27k
            cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
1108
1.27k
            clazz               = &cff_cmap_encoding_class_rec;
1109
1.27k
          }
1110
0
          else if ( encoding->offset == 1 )
1111
0
          {
1112
0
            cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
1113
0
            cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
1114
0
            clazz               = &cff_cmap_encoding_class_rec;
1115
0
          }
1116
0
          else
1117
0
          {
1118
0
            cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
1119
0
            cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
1120
0
            clazz               = &cff_cmap_encoding_class_rec;
1121
0
          }
1122
1123
1.27k
          error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );
1124
1.27k
        }
1125
1.81k
      }
1126
1.81k
    }
1127
1128
5.86k
  Exit:
1129
5.86k
    return error;
1130
1.81k
  }
1131
1132
1133
  FT_LOCAL_DEF( void )
1134
  cff_face_done( FT_Face  cffface )         /* CFF_Face */
1135
5.86k
  {
1136
5.86k
    CFF_Face      face = (CFF_Face)cffface;
1137
5.86k
    FT_Memory     memory;
1138
5.86k
    SFNT_Service  sfnt;
1139
1140
1141
5.86k
    if ( !face )
1142
0
      return;
1143
1144
5.86k
    memory = cffface->memory;
1145
5.86k
    sfnt   = (SFNT_Service)face->sfnt;
1146
1147
5.86k
    if ( sfnt )
1148
5.86k
      sfnt->done_face( face );
1149
1150
5.86k
    {
1151
5.86k
      CFF_Font  cff = (CFF_Font)face->extra.data;
1152
1153
1154
5.86k
      if ( cff )
1155
4.93k
      {
1156
4.93k
        cff_font_done( cff );
1157
4.93k
        FT_FREE( face->extra.data );
1158
4.93k
      }
1159
5.86k
    }
1160
1161
5.86k
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1162
5.86k
    cff_done_blend( face );
1163
5.86k
    face->blend = NULL;
1164
5.86k
#endif
1165
5.86k
  }
1166
1167
1168
  FT_LOCAL_DEF( FT_Error )
1169
  cff_driver_init( FT_Module  module )        /* CFF_Driver */
1170
5
  {
1171
5
    PS_Driver  driver = (PS_Driver)module;
1172
1173
5
    FT_UInt32  seed;
1174
1175
1176
    /* set default property values, cf. `ftcffdrv.h' */
1177
5
    driver->hinting_engine = FT_HINTING_ADOBE;
1178
1179
5
    driver->no_stem_darkening = TRUE;
1180
1181
5
    driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1;
1182
5
    driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1;
1183
5
    driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2;
1184
5
    driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2;
1185
5
    driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3;
1186
5
    driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3;
1187
5
    driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4;
1188
5
    driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4;
1189
1190
    /* compute random seed from some memory addresses */
1191
5
    seed = (FT_UInt32)( (FT_Offset)(char*)&seed          ^
1192
5
                        (FT_Offset)(char*)&module        ^
1193
5
                        (FT_Offset)(char*)module->memory );
1194
5
    seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 );
1195
1196
5
    driver->random_seed = (FT_Int32)seed;
1197
5
    if ( driver->random_seed < 0 )
1198
0
      driver->random_seed = -driver->random_seed;
1199
5
    else if ( driver->random_seed == 0 )
1200
0
      driver->random_seed = 123456789;
1201
1202
5
    return FT_Err_Ok;
1203
5
  }
1204
1205
1206
  FT_LOCAL_DEF( void )
1207
  cff_driver_done( FT_Module  module )        /* CFF_Driver */
1208
5
  {
1209
5
    FT_UNUSED( module );
1210
5
  }
1211
1212
1213
/* END */