Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/freetype/src/psnames/psmodule.c
Line
Count
Source (jump to first uncovered line)
1
/****************************************************************************
2
 *
3
 * psmodule.c
4
 *
5
 *   psnames module implementation (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
#include <freetype/internal/ftdebug.h>
20
#include <freetype/internal/ftobjs.h>
21
#include <freetype/internal/services/svpscmap.h>
22
23
#include "psmodule.h"
24
25
  /*
26
   * The file `pstables.h' with its arrays and its function
27
   * `ft_get_adobe_glyph_index' is useful for other projects also (for
28
   * example, `pdfium' is using it).  However, if used as a C++ header,
29
   * including it in two different source files makes it necessary to use
30
   * `extern const' for the declaration of its arrays, otherwise the data
31
   * would be duplicated as mandated by the C++ standard.
32
   *
33
   * For this reason, we use `DEFINE_PS_TABLES' to guard the function
34
   * definitions, and `DEFINE_PS_TABLES_DATA' to provide both proper array
35
   * declarations and definitions.
36
   */
37
#include "pstables.h"
38
#define  DEFINE_PS_TABLES
39
#define  DEFINE_PS_TABLES_DATA
40
#include "pstables.h"
41
42
#include "psnamerr.h"
43
44
45
#ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
46
47
48
#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
49
50
51
7.32M
#define VARIANT_BIT         0x80000000UL
52
7.32M
#define BASE_GLYPH( code )  ( (FT_UInt32)( (code) & ~VARIANT_BIT ) )
53
54
55
  /* Return the Unicode value corresponding to a given glyph.  Note that */
56
  /* we do deal with glyph variants by detecting a non-initial dot in    */
57
  /* the name, as in `A.swash' or `e.final'; in this case, the           */
58
  /* VARIANT_BIT is set in the return value.                             */
59
  /*                                                                     */
60
  static FT_UInt32
61
  ps_unicode_value( const char*  glyph_name )
62
1.10M
  {
63
    /* If the name begins with `uni', then the glyph name may be a */
64
    /* hard-coded unicode character code.                          */
65
1.10M
    if ( glyph_name[0] == 'u' &&
66
248k
         glyph_name[1] == 'n' &&
67
243k
         glyph_name[2] == 'i' )
68
236k
    {
69
      /* determine whether the next four characters following are */
70
      /* hexadecimal.                                             */
71
72
      /* XXX: Add code to deal with ligatures, i.e. glyph names like */
73
      /*      `uniXXXXYYYYZZZZ'...                                   */
74
75
236k
      FT_Int       count;
76
236k
      FT_UInt32    value = 0;
77
236k
      const char*  p     = glyph_name + 3;
78
79
80
1.17M
      for ( count = 4; count > 0; count--, p++ )
81
939k
      {
82
939k
        char          c = *p;
83
939k
        unsigned int  d;
84
85
86
939k
        d = (unsigned char)c - '0';
87
939k
        if ( d >= 10 )
88
239k
        {
89
239k
          d = (unsigned char)c - 'A';
90
239k
          if ( d >= 6 )
91
4.15k
            d = 16;
92
235k
          else
93
235k
            d += 10;
94
239k
        }
95
96
        /* Exit if a non-uppercase hexadecimal character was found   */
97
        /* -- this also catches character codes below `0' since such */
98
        /* negative numbers cast to `unsigned int' are far too big.  */
99
939k
        if ( d >= 16 )
100
4.15k
          break;
101
102
934k
        value = ( value << 4 ) + d;
103
934k
      }
104
105
      /* there must be exactly four hex digits */
106
236k
      if ( count == 0 )
107
232k
      {
108
232k
        if ( *p == '\0' )
109
229k
          return value;
110
2.76k
        if ( *p == '.' )
111
0
          return (FT_UInt32)( value | VARIANT_BIT );
112
871k
      }
113
236k
    }
114
115
    /* If the name begins with `u', followed by four to six uppercase */
116
    /* hexadecimal digits, it is a hard-coded unicode character code. */
117
871k
    if ( glyph_name[0] == 'u' )
118
18.4k
    {
119
18.4k
      FT_Int       count;
120
18.4k
      FT_UInt32    value = 0;
121
18.4k
      const char*  p     = glyph_name + 1;
122
123
124
18.4k
      for ( count = 6; count > 0; count--, p++ )
125
18.4k
      {
126
18.4k
        char          c = *p;
127
18.4k
        unsigned int  d;
128
129
130
18.4k
        d = (unsigned char)c - '0';
131
18.4k
        if ( d >= 10 )
132
18.4k
        {
133
18.4k
          d = (unsigned char)c - 'A';
134
18.4k
          if ( d >= 6 )
135
18.4k
            d = 16;
136
7
          else
137
7
            d += 10;
138
18.4k
        }
139
140
18.4k
        if ( d >= 16 )
141
18.4k
          break;
142
143
34
        value = ( value << 4 ) + d;
144
34
      }
145
146
18.4k
      if ( count <= 2 )
147
1
      {
148
1
        if ( *p == '\0' )
149
1
          return value;
150
0
        if ( *p == '.' )
151
0
          return (FT_UInt32)( value | VARIANT_BIT );
152
871k
      }
153
18.4k
    }
154
155
    /* Look for a non-initial dot in the glyph name in order to */
156
    /* find variants like `A.swash', `e.final', etc.            */
157
871k
    {
158
871k
      FT_UInt32    value = 0;
159
871k
      const char*  p     = glyph_name;
160
161
162
3.64M
      for ( ; *p && *p != '.'; p++ )
163
2.77M
        ;
164
165
      /* now look up the glyph in the Adobe Glyph List;      */
166
      /* `.notdef', `.null' and the empty name are short cut */
167
871k
      if ( p > glyph_name )
168
250k
      {
169
250k
        value = (FT_UInt32)ft_get_adobe_glyph_index( glyph_name, p );
170
171
250k
        if ( *p == '.' )
172
259
          value |= (FT_UInt32)VARIANT_BIT;
173
250k
      }
174
175
871k
      return value;
176
871k
    }
177
871k
  }
178
179
180
  /* ft_qsort callback to sort the unicode map */
181
  FT_COMPARE_DEF( int )
182
  compare_uni_maps( const void*  a,
183
                    const void*  b )
184
3.10M
  {
185
3.10M
    PS_UniMap*  map1 = (PS_UniMap*)a;
186
3.10M
    PS_UniMap*  map2 = (PS_UniMap*)b;
187
3.10M
    FT_UInt32   unicode1 = BASE_GLYPH( map1->unicode );
188
3.10M
    FT_UInt32   unicode2 = BASE_GLYPH( map2->unicode );
189
190
191
    /* sort base glyphs before glyph variants */
192
3.10M
    if ( unicode1 == unicode2 )
193
620k
    {
194
620k
      if ( map1->unicode > map2->unicode )
195
0
        return 1;
196
620k
      else if ( map1->unicode < map2->unicode )
197
0
        return -1;
198
620k
      else
199
620k
        return 0;
200
2.48M
    }
201
2.48M
    else
202
2.48M
    {
203
2.48M
      if ( unicode1 > unicode2 )
204
1.14M
        return 1;
205
1.34M
      else if ( unicode1 < unicode2 )
206
1.34M
        return -1;
207
0
      else
208
0
        return 0;
209
2.48M
    }
210
3.10M
  }
211
212
213
  /* support for extra glyphs not handled (well) in AGL; */
214
  /* we add extra mappings for them if necessary         */
215
216
17.0M
#define EXTRA_GLYPH_LIST_SIZE  10
217
218
  static const FT_UInt32  ft_extra_glyph_unicodes[EXTRA_GLYPH_LIST_SIZE] =
219
  {
220
    /* WGL 4 */
221
    0x0394,
222
    0x03A9,
223
    0x2215,
224
    0x00AD,
225
    0x02C9,
226
    0x03BC,
227
    0x2219,
228
    0x00A0,
229
    /* Romanian */
230
    0x021A,
231
    0x021B
232
  };
233
234
  static const char  ft_extra_glyph_names[] =
235
  {
236
    'D','e','l','t','a',0,
237
    'O','m','e','g','a',0,
238
    'f','r','a','c','t','i','o','n',0,
239
    'h','y','p','h','e','n',0,
240
    'm','a','c','r','o','n',0,
241
    'm','u',0,
242
    'p','e','r','i','o','d','c','e','n','t','e','r','e','d',0,
243
    's','p','a','c','e',0,
244
    'T','c','o','m','m','a','a','c','c','e','n','t',0,
245
    't','c','o','m','m','a','a','c','c','e','n','t',0
246
  };
247
248
  static const FT_Int
249
  ft_extra_glyph_name_offsets[EXTRA_GLYPH_LIST_SIZE] =
250
  {
251
     0,
252
     6,
253
    12,
254
    21,
255
    28,
256
    35,
257
    38,
258
    53,
259
    59,
260
    72
261
  };
262
263
264
  static void
265
  ps_check_extra_glyph_name( const char*  gname,
266
                             FT_UInt      glyph,
267
                             FT_UInt*     extra_glyphs,
268
                             FT_UInt     *states )
269
1.10M
  {
270
1.10M
    FT_UInt  n;
271
272
273
11.9M
    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
274
10.9M
    {
275
10.9M
      if ( ft_strcmp( ft_extra_glyph_names +
276
10.9M
                        ft_extra_glyph_name_offsets[n], gname ) == 0 )
277
22.0k
      {
278
22.0k
        if ( states[n] == 0 )
279
1.86k
        {
280
          /* mark this extra glyph as a candidate for the cmap */
281
1.86k
          states[n]     = 1;
282
1.86k
          extra_glyphs[n] = glyph;
283
1.86k
        }
284
285
22.0k
        return;
286
22.0k
      }
287
10.9M
    }
288
1.10M
  }
289
290
291
  static void
292
  ps_check_extra_glyph_unicode( FT_UInt32  uni_char,
293
                                FT_UInt   *states )
294
460k
  {
295
460k
    FT_UInt  n;
296
297
298
5.06M
    for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
299
4.60M
    {
300
4.60M
      if ( uni_char == ft_extra_glyph_unicodes[n] )
301
11
      {
302
        /* disable this extra glyph from being added to the cmap */
303
11
        states[n] = 2;
304
305
11
        return;
306
11
      }
307
4.60M
    }
308
460k
  }
309
310
311
  /* Build a table that maps Unicode values to glyph indices. */
312
  static FT_Error
313
  ps_unicodes_init( FT_Memory             memory,
314
                    PS_Unicodes           table,
315
                    FT_UInt               num_glyphs,
316
                    PS_GetGlyphNameFunc   get_glyph_name,
317
                    PS_FreeGlyphNameFunc  free_glyph_name,
318
                    FT_Pointer            glyph_data )
319
1.37k
  {
320
1.37k
    FT_Error  error;
321
322
1.37k
    FT_UInt  extra_glyph_list_states[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
323
1.37k
    FT_UInt  extra_glyphs[EXTRA_GLYPH_LIST_SIZE];
324
325
326
    /* we first allocate the table */
327
1.37k
    table->num_maps = 0;
328
1.37k
    table->maps     = NULL;
329
330
1.37k
    if ( !FT_QNEW_ARRAY( table->maps, num_glyphs + EXTRA_GLYPH_LIST_SIZE ) )
331
1.37k
    {
332
1.37k
      FT_UInt     n;
333
1.37k
      FT_UInt     count;
334
1.37k
      PS_UniMap*  map;
335
1.37k
      FT_UInt32   uni_char;
336
337
338
1.37k
      map = table->maps;
339
340
2.53M
      for ( n = 0; n < num_glyphs; n++ )
341
2.53M
      {
342
2.53M
        const char*  gname = get_glyph_name( glyph_data, n );
343
344
345
2.53M
        if ( gname && *gname )
346
1.10M
        {
347
1.10M
          ps_check_extra_glyph_name( gname, n,
348
1.10M
                                     extra_glyphs, extra_glyph_list_states );
349
1.10M
          uni_char = ps_unicode_value( gname );
350
351
1.10M
          if ( BASE_GLYPH( uni_char ) != 0 )
352
460k
          {
353
460k
            ps_check_extra_glyph_unicode( uni_char,
354
460k
                                          extra_glyph_list_states );
355
460k
            map->unicode     = uni_char;
356
460k
            map->glyph_index = n;
357
460k
            map++;
358
460k
          }
359
360
1.10M
          if ( free_glyph_name )
361
0
            free_glyph_name( glyph_data, gname );
362
1.10M
        }
363
2.53M
      }
364
365
15.1k
      for ( n = 0; n < EXTRA_GLYPH_LIST_SIZE; n++ )
366
13.7k
      {
367
13.7k
        if ( extra_glyph_list_states[n] == 1 )
368
1.85k
        {
369
          /* This glyph name has an additional representation. */
370
          /* Add it to the cmap.                               */
371
372
1.85k
          map->unicode     = ft_extra_glyph_unicodes[n];
373
1.85k
          map->glyph_index = extra_glyphs[n];
374
1.85k
          map++;
375
1.85k
        }
376
13.7k
      }
377
378
      /* now compress the table a bit */
379
1.37k
      count = (FT_UInt)( map - table->maps );
380
381
1.37k
      if ( count == 0 )
382
51
      {
383
        /* No unicode chars here! */
384
51
        FT_FREE( table->maps );
385
51
        if ( !error )
386
51
          error = FT_THROW( No_Unicode_Glyph_Name );
387
51
      }
388
1.32k
      else
389
1.32k
      {
390
        /* Reallocate if the number of used entries is much smaller. */
391
1.32k
        if ( count < num_glyphs / 2 )
392
380
        {
393
380
          (void)FT_QRENEW_ARRAY( table->maps,
394
380
                                 num_glyphs + EXTRA_GLYPH_LIST_SIZE,
395
380
                                 count );
396
380
          error = FT_Err_Ok;
397
380
        }
398
399
        /* Sort the table in increasing order of unicode values, */
400
        /* taking care of glyph variants.                        */
401
1.32k
        ft_qsort( table->maps, count, sizeof ( PS_UniMap ),
402
1.32k
                  compare_uni_maps );
403
1.32k
      }
404
405
1.37k
      table->num_maps = count;
406
1.37k
    }
407
408
1.37k
    return error;
409
1.37k
  }
410
411
412
  static FT_UInt
413
  ps_unicodes_char_index( PS_Unicodes  table,
414
                          FT_UInt32    unicode )
415
0
  {
416
0
    PS_UniMap  *min, *max, *mid, *result = NULL;
417
418
419
    /* Perform a binary search on the table. */
420
421
0
    min = table->maps;
422
0
    max = min + table->num_maps - 1;
423
424
0
    while ( min <= max )
425
0
    {
426
0
      FT_UInt32  base_glyph;
427
428
429
0
      mid = min + ( ( max - min ) >> 1 );
430
431
0
      if ( mid->unicode == unicode )
432
0
      {
433
0
        result = mid;
434
0
        break;
435
0
      }
436
437
0
      base_glyph = BASE_GLYPH( mid->unicode );
438
439
0
      if ( base_glyph == unicode )
440
0
        result = mid; /* remember match but continue search for base glyph */
441
442
0
      if ( min == max )
443
0
        break;
444
445
0
      if ( base_glyph < unicode )
446
0
        min = mid + 1;
447
0
      else
448
0
        max = mid - 1;
449
0
    }
450
451
0
    if ( result )
452
0
      return result->glyph_index;
453
0
    else
454
0
      return 0;
455
0
  }
456
457
458
  static FT_UInt32
459
  ps_unicodes_char_next( PS_Unicodes  table,
460
                         FT_UInt32   *unicode )
461
0
  {
462
0
    FT_UInt    result    = 0;
463
0
    FT_UInt32  char_code = *unicode + 1;
464
465
466
0
    {
467
0
      FT_UInt     min = 0;
468
0
      FT_UInt     max = table->num_maps;
469
0
      FT_UInt     mid;
470
0
      PS_UniMap*  map;
471
0
      FT_UInt32   base_glyph;
472
473
474
0
      while ( min < max )
475
0
      {
476
0
        mid = min + ( ( max - min ) >> 1 );
477
0
        map = table->maps + mid;
478
479
0
        if ( map->unicode == char_code )
480
0
        {
481
0
          result = map->glyph_index;
482
0
          goto Exit;
483
0
        }
484
485
0
        base_glyph = BASE_GLYPH( map->unicode );
486
487
0
        if ( base_glyph == char_code )
488
0
          result = map->glyph_index;
489
490
0
        if ( base_glyph < char_code )
491
0
          min = mid + 1;
492
0
        else
493
0
          max = mid;
494
0
      }
495
496
0
      if ( result )
497
0
        goto Exit;               /* we have a variant glyph */
498
499
      /* we didn't find it; check whether we have a map just above it */
500
0
      char_code = 0;
501
502
0
      if ( min < table->num_maps )
503
0
      {
504
0
        map       = table->maps + min;
505
0
        result    = map->glyph_index;
506
0
        char_code = BASE_GLYPH( map->unicode );
507
0
      }
508
0
    }
509
510
0
  Exit:
511
0
    *unicode = char_code;
512
0
    return result;
513
0
  }
514
515
516
#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
517
518
519
  static const char*
520
  ps_get_macintosh_name( FT_UInt  name_index )
521
262k
  {
522
262k
    if ( name_index >= FT_NUM_MAC_NAMES )
523
0
      name_index = 0;
524
525
262k
    return ft_standard_glyph_names + ft_mac_names[name_index];
526
262k
  }
527
528
529
  static const char*
530
  ps_get_standard_strings( FT_UInt  sid )
531
593k
  {
532
593k
    if ( sid >= FT_NUM_SID_NAMES )
533
0
      return 0;
534
535
593k
    return ft_standard_glyph_names + ft_sid_names[sid];
536
593k
  }
537
538
539
#ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
540
541
  FT_DEFINE_SERVICE_PSCMAPSREC(
542
    pscmaps_interface,
543
544
    (PS_Unicode_ValueFunc)     ps_unicode_value,        /* unicode_value         */
545
    (PS_Unicodes_InitFunc)     ps_unicodes_init,        /* unicodes_init         */
546
    (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,  /* unicodes_char_index   */
547
    (PS_Unicodes_CharNextFunc) ps_unicodes_char_next,   /* unicodes_char_next    */
548
549
    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
550
    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
551
552
    t1_standard_encoding,                               /* adobe_std_encoding    */
553
    t1_expert_encoding                                  /* adobe_expert_encoding */
554
  )
555
556
#else
557
558
  FT_DEFINE_SERVICE_PSCMAPSREC(
559
    pscmaps_interface,
560
561
    NULL,                                               /* unicode_value         */
562
    NULL,                                               /* unicodes_init         */
563
    NULL,                                               /* unicodes_char_index   */
564
    NULL,                                               /* unicodes_char_next    */
565
566
    (PS_Macintosh_NameFunc)    ps_get_macintosh_name,   /* macintosh_name        */
567
    (PS_Adobe_Std_StringsFunc) ps_get_standard_strings, /* adobe_std_strings     */
568
569
    t1_standard_encoding,                               /* adobe_std_encoding    */
570
    t1_expert_encoding                                  /* adobe_expert_encoding */
571
  )
572
573
#endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
574
575
576
  FT_DEFINE_SERVICEDESCREC1(
577
    pscmaps_services,
578
579
    FT_SERVICE_ID_POSTSCRIPT_CMAPS, &pscmaps_interface )
580
581
582
  static FT_Pointer
583
  psnames_get_service( FT_Module    module,
584
                       const char*  service_id )
585
24.7k
  {
586
24.7k
    FT_UNUSED( module );
587
588
24.7k
    return ft_service_list_lookup( pscmaps_services, service_id );
589
24.7k
  }
590
591
#endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
592
593
594
#ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
595
#define PUT_PS_NAMES_SERVICE( a )  NULL
596
#else
597
#define PUT_PS_NAMES_SERVICE( a )  a
598
#endif
599
600
  FT_DEFINE_MODULE(
601
    psnames_module_class,
602
603
    0,  /* this is not a font driver, nor a renderer */
604
    sizeof ( FT_ModuleRec ),
605
606
    "psnames",  /* driver name                         */
607
    0x10000L,   /* driver version                      */
608
    0x20000L,   /* driver requires FreeType 2 or above */
609
610
    PUT_PS_NAMES_SERVICE(
611
      (void*)&pscmaps_interface ),   /* module specific interface */
612
613
    (FT_Module_Constructor)NULL,                                       /* module_init   */
614
    (FT_Module_Destructor) NULL,                                       /* module_done   */
615
    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) /* get_interface */
616
  )
617
618
619
/* END */