Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/freetype/src/psaux/psft.c
Line
Count
Source (jump to first uncovered line)
1
/****************************************************************************
2
 *
3
 * psft.c
4
 *
5
 *   FreeType Glue Component to Adobe's Interpreter (body).
6
 *
7
 * Copyright 2013-2014 Adobe Systems Incorporated.
8
 *
9
 * This software, and all works of authorship, whether in source or
10
 * object code form as indicated by the copyright notice(s) included
11
 * herein (collectively, the "Work") is made available, and may only be
12
 * used, modified, and distributed under the FreeType Project License,
13
 * LICENSE.TXT.  Additionally, subject to the terms and conditions of the
14
 * FreeType Project License, each contributor to the Work hereby grants
15
 * to any individual or legal entity exercising permissions granted by
16
 * the FreeType Project License and this section (hereafter, "You" or
17
 * "Your") a perpetual, worldwide, non-exclusive, no-charge,
18
 * royalty-free, irrevocable (except as stated in this section) patent
19
 * license to make, have made, use, offer to sell, sell, import, and
20
 * otherwise transfer the Work, where such license applies only to those
21
 * patent claims licensable by such contributor that are necessarily
22
 * infringed by their contribution(s) alone or by combination of their
23
 * contribution(s) with the Work to which such contribution(s) was
24
 * submitted.  If You institute patent litigation against any entity
25
 * (including a cross-claim or counterclaim in a lawsuit) alleging that
26
 * the Work or a contribution incorporated within the Work constitutes
27
 * direct or contributory patent infringement, then any patent licenses
28
 * granted to You under this License for that Work shall terminate as of
29
 * the date such litigation is filed.
30
 *
31
 * By using, modifying, or distributing the Work you indicate that you
32
 * have read and understood the terms and conditions of the
33
 * FreeType Project License as well as those provided in this section,
34
 * and you accept them fully.
35
 *
36
 */
37
38
39
#include "psft.h"
40
#include <freetype/internal/ftdebug.h>
41
42
#include "psfont.h"
43
#include "pserror.h"
44
#include "psobjs.h"
45
#include "cffdecode.h"
46
47
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
48
#include <freetype/ftmm.h>
49
#include <freetype/internal/services/svmm.h>
50
#endif
51
52
#include <freetype/internal/services/svcfftl.h>
53
54
55
0
#define CF2_MAX_SIZE  cf2_intToFixed( 2000 )    /* max ppem */
56
57
58
  /*
59
   * This check should avoid most internal overflow cases.  Clients should
60
   * generally respond to `Glyph_Too_Big' by getting a glyph outline
61
   * at EM size, scaling it and filling it as a graphics operation.
62
   *
63
   */
64
  static FT_Error
65
  cf2_checkTransform( const CF2_Matrix*  transform,
66
                      CF2_Int            unitsPerEm )
67
0
  {
68
0
    CF2_Fixed  maxScale;
69
70
71
0
    FT_ASSERT( unitsPerEm > 0 );
72
73
0
    if ( transform->a <= 0 || transform->d <= 0 )
74
0
      return FT_THROW( Invalid_Size_Handle );
75
76
0
    FT_ASSERT( transform->b == 0 && transform->c == 0 );
77
0
    FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
78
79
0
    if ( unitsPerEm > 0x7FFF )
80
0
      return FT_THROW( Glyph_Too_Big );
81
82
0
    maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
83
84
0
    if ( transform->a > maxScale || transform->d > maxScale )
85
0
      return FT_THROW( Glyph_Too_Big );
86
87
0
    return FT_Err_Ok;
88
0
  }
89
90
91
  static void
92
  cf2_setGlyphWidth( CF2_Outline  outline,
93
                     CF2_Fixed    width )
94
0
  {
95
0
    PS_Decoder*  decoder = outline->decoder;
96
97
98
0
    FT_ASSERT( decoder );
99
100
0
    if ( !decoder->builder.is_t1 )
101
0
      *decoder->glyph_width = cf2_fixedToInt( width );
102
0
  }
103
104
105
  /* Clean up font instance. */
106
  static void
107
  cf2_free_instance( void*  ptr )
108
0
  {
109
0
    CF2_Font  font = (CF2_Font)ptr;
110
111
112
0
    if ( font )
113
0
    {
114
0
      FT_Memory  memory = font->memory;
115
116
117
0
      FT_FREE( font->blend.lastNDV );
118
0
      FT_FREE( font->blend.BV );
119
0
    }
120
0
  }
121
122
123
  /*********************************************
124
   *
125
   * functions for handling client outline;
126
   * FreeType uses coordinates in 26.6 format
127
   *
128
   */
129
130
  static void
131
  cf2_builder_moveTo( CF2_OutlineCallbacks      callbacks,
132
                      const CF2_CallbackParams  params )
133
0
  {
134
    /* downcast the object pointer */
135
0
    CF2_Outline  outline = (CF2_Outline)callbacks;
136
0
    PS_Builder*  builder;
137
138
0
    (void)params;        /* only used in debug mode */
139
140
141
0
    FT_ASSERT( outline && outline->decoder );
142
0
    FT_ASSERT( params->op == CF2_PathOpMoveTo );
143
144
0
    builder = &outline->decoder->builder;
145
146
    /* note: two successive moves simply close the contour twice */
147
0
    ps_builder_close_contour( builder );
148
0
    builder->path_begun = 0;
149
0
  }
150
151
152
  static void
153
  cf2_builder_lineTo( CF2_OutlineCallbacks      callbacks,
154
                      const CF2_CallbackParams  params )
155
0
  {
156
0
    FT_Error  error;
157
158
    /* downcast the object pointer */
159
0
    CF2_Outline  outline = (CF2_Outline)callbacks;
160
0
    PS_Builder*  builder;
161
162
163
0
    FT_ASSERT( outline && outline->decoder );
164
0
    FT_ASSERT( params->op == CF2_PathOpLineTo );
165
166
0
    builder = &outline->decoder->builder;
167
168
0
    if ( !builder->path_begun )
169
0
    {
170
      /* record the move before the line; also check points and set */
171
      /* `path_begun'                                               */
172
0
      error = ps_builder_start_point( builder,
173
0
                                      params->pt0.x,
174
0
                                      params->pt0.y );
175
0
      if ( error )
176
0
      {
177
0
        if ( !*callbacks->error )
178
0
          *callbacks->error =  error;
179
0
        return;
180
0
      }
181
0
    }
182
183
    /* `ps_builder_add_point1' includes a check_points call for one point */
184
0
    error = ps_builder_add_point1( builder,
185
0
                                   params->pt1.x,
186
0
                                   params->pt1.y );
187
0
    if ( error )
188
0
    {
189
0
      if ( !*callbacks->error )
190
0
        *callbacks->error =  error;
191
0
      return;
192
0
    }
193
0
  }
194
195
196
  static void
197
  cf2_builder_cubeTo( CF2_OutlineCallbacks      callbacks,
198
                      const CF2_CallbackParams  params )
199
0
  {
200
0
    FT_Error  error;
201
202
    /* downcast the object pointer */
203
0
    CF2_Outline  outline = (CF2_Outline)callbacks;
204
0
    PS_Builder*  builder;
205
206
207
0
    FT_ASSERT( outline && outline->decoder );
208
0
    FT_ASSERT( params->op == CF2_PathOpCubeTo );
209
210
0
    builder = &outline->decoder->builder;
211
212
0
    if ( !builder->path_begun )
213
0
    {
214
      /* record the move before the line; also check points and set */
215
      /* `path_begun'                                               */
216
0
      error = ps_builder_start_point( builder,
217
0
                                      params->pt0.x,
218
0
                                      params->pt0.y );
219
0
      if ( error )
220
0
      {
221
0
        if ( !*callbacks->error )
222
0
          *callbacks->error =  error;
223
0
        return;
224
0
      }
225
0
    }
226
227
    /* prepare room for 3 points: 2 off-curve, 1 on-curve */
228
0
    error = ps_builder_check_points( builder, 3 );
229
0
    if ( error )
230
0
    {
231
0
      if ( !*callbacks->error )
232
0
        *callbacks->error =  error;
233
0
      return;
234
0
    }
235
236
0
    ps_builder_add_point( builder,
237
0
                          params->pt1.x,
238
0
                          params->pt1.y, 0 );
239
0
    ps_builder_add_point( builder,
240
0
                          params->pt2.x,
241
0
                          params->pt2.y, 0 );
242
0
    ps_builder_add_point( builder,
243
0
                          params->pt3.x,
244
0
                          params->pt3.y, 1 );
245
0
  }
246
247
248
  static void
249
  cf2_outline_init( CF2_Outline  outline,
250
                    FT_Memory    memory,
251
                    FT_Error*    error )
252
0
  {
253
0
    FT_ZERO( outline );
254
255
0
    outline->root.memory = memory;
256
0
    outline->root.error  = error;
257
258
0
    outline->root.moveTo = cf2_builder_moveTo;
259
0
    outline->root.lineTo = cf2_builder_lineTo;
260
0
    outline->root.cubeTo = cf2_builder_cubeTo;
261
0
  }
262
263
264
  /* get scaling and hint flag from GlyphSlot */
265
  static void
266
  cf2_getScaleAndHintFlag( PS_Decoder*  decoder,
267
                           CF2_Fixed*   x_scale,
268
                           CF2_Fixed*   y_scale,
269
                           FT_Bool*     hinted,
270
                           FT_Bool*     scaled )
271
0
  {
272
0
    FT_ASSERT( decoder && decoder->builder.glyph );
273
274
    /* note: FreeType scale includes a factor of 64 */
275
0
    *hinted = decoder->builder.glyph->hint;
276
0
    *scaled = decoder->builder.glyph->scaled;
277
278
0
    if ( *hinted )
279
0
    {
280
0
      *x_scale = ADD_INT32( decoder->builder.glyph->x_scale, 32 ) / 64;
281
0
      *y_scale = ADD_INT32( decoder->builder.glyph->y_scale, 32 ) / 64;
282
0
    }
283
0
    else
284
0
    {
285
      /* for unhinted outlines, `cff_slot_load' does the scaling, */
286
      /* thus render at `unity' scale                             */
287
288
0
      *x_scale = 0x0400;   /* 1/64 as 16.16 */
289
0
      *y_scale = 0x0400;
290
0
    }
291
0
  }
292
293
294
  /* get units per em from `FT_Face' */
295
  /* TODO: should handle font matrix concatenation? */
296
  static FT_UShort
297
  cf2_getUnitsPerEm( PS_Decoder*  decoder )
298
0
  {
299
0
    FT_ASSERT( decoder && decoder->builder.face );
300
0
    FT_ASSERT( decoder->builder.face->units_per_EM );
301
302
0
    return decoder->builder.face->units_per_EM;
303
0
  }
304
305
306
  /* Main entry point: Render one glyph. */
307
  FT_LOCAL_DEF( FT_Error )
308
  cf2_decoder_parse_charstrings( PS_Decoder*  decoder,
309
                                 FT_Byte*     charstring_base,
310
                                 FT_ULong     charstring_len )
311
0
  {
312
0
    FT_Memory  memory;
313
0
    FT_Error   error = FT_Err_Ok;
314
0
    CF2_Font   font;
315
316
0
    FT_Bool  is_t1 = decoder->builder.is_t1;
317
318
319
0
    FT_ASSERT( decoder &&
320
0
               ( is_t1 || decoder->cff ) );
321
322
0
    if ( is_t1 && !decoder->current_subfont )
323
0
    {
324
0
      FT_ERROR(( "cf2_decoder_parse_charstrings (Type 1): "
325
0
                 "SubFont missing. Use `t1_make_subfont' first\n" ));
326
0
      return FT_THROW( Invalid_Table );
327
0
    }
328
329
0
    memory = decoder->builder.memory;
330
331
    /* CF2 data is saved here across glyphs */
332
0
    font = (CF2_Font)decoder->cf2_instance->data;
333
334
    /* on first glyph, allocate instance structure */
335
0
    if ( !decoder->cf2_instance->data )
336
0
    {
337
0
      decoder->cf2_instance->finalizer =
338
0
        (FT_Generic_Finalizer)cf2_free_instance;
339
340
0
      if ( FT_ALLOC( decoder->cf2_instance->data,
341
0
                     sizeof ( CF2_FontRec ) ) )
342
0
        return FT_THROW( Out_Of_Memory );
343
344
0
      font = (CF2_Font)decoder->cf2_instance->data;
345
346
0
      font->memory = memory;
347
348
0
      if ( !is_t1 )
349
0
        font->cffload = (FT_Service_CFFLoad)decoder->cff->cffload;
350
351
      /* initialize a client outline, to be shared by each glyph rendered */
352
0
      cf2_outline_init( &font->outline, font->memory, &font->error );
353
0
    }
354
355
    /* save decoder; it is a stack variable and will be different on each */
356
    /* call                                                               */
357
0
    font->decoder         = decoder;
358
0
    font->outline.decoder = decoder;
359
360
0
    {
361
      /* build parameters for Adobe engine */
362
363
0
      PS_Builder*  builder = &decoder->builder;
364
0
      PS_Driver    driver  = (PS_Driver)FT_FACE_DRIVER( builder->face );
365
366
0
      FT_Bool  no_stem_darkening_driver =
367
0
                 driver->no_stem_darkening;
368
0
      FT_Char  no_stem_darkening_font =
369
0
                 builder->face->internal->no_stem_darkening;
370
371
      /* local error */
372
0
      FT_Error       error2 = FT_Err_Ok;
373
0
      CF2_BufferRec  buf;
374
0
      CF2_Matrix     transform;
375
0
      CF2_F16Dot16   glyphWidth;
376
377
0
      FT_Bool  hinted;
378
0
      FT_Bool  scaled;
379
380
381
      /* FreeType has already looked up the GID; convert to         */
382
      /* `RegionBuffer', assuming that the input has been validated */
383
0
      FT_ASSERT( charstring_base + charstring_len >= charstring_base );
384
385
0
      FT_ZERO( &buf );
386
0
      buf.start =
387
0
      buf.ptr   = charstring_base;
388
0
      buf.end   = FT_OFFSET( charstring_base, charstring_len );
389
390
0
      FT_ZERO( &transform );
391
392
0
      cf2_getScaleAndHintFlag( decoder,
393
0
                               &transform.a,
394
0
                               &transform.d,
395
0
                               &hinted,
396
0
                               &scaled );
397
398
0
      if ( is_t1 )
399
0
        font->isCFF2 = FALSE;
400
0
      else
401
0
      {
402
        /* copy isCFF2 boolean from TT_Face to CF2_Font */
403
0
        font->isCFF2 = ((TT_Face)builder->face)->is_cff2;
404
0
      }
405
0
      font->isT1 = is_t1;
406
407
0
      font->renderingFlags = 0;
408
0
      if ( hinted )
409
0
        font->renderingFlags |= CF2_FlagsHinted;
410
0
      if ( scaled && ( !no_stem_darkening_font        ||
411
0
                       ( no_stem_darkening_font < 0 &&
412
0
                         !no_stem_darkening_driver  ) ) )
413
0
        font->renderingFlags |= CF2_FlagsDarkened;
414
415
0
      font->darkenParams[0] = driver->darken_params[0];
416
0
      font->darkenParams[1] = driver->darken_params[1];
417
0
      font->darkenParams[2] = driver->darken_params[2];
418
0
      font->darkenParams[3] = driver->darken_params[3];
419
0
      font->darkenParams[4] = driver->darken_params[4];
420
0
      font->darkenParams[5] = driver->darken_params[5];
421
0
      font->darkenParams[6] = driver->darken_params[6];
422
0
      font->darkenParams[7] = driver->darken_params[7];
423
424
      /* now get an outline for this glyph;      */
425
      /* also get units per em to validate scale */
426
0
      font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
427
428
0
      if ( scaled )
429
0
      {
430
0
        error2 = cf2_checkTransform( &transform, font->unitsPerEm );
431
0
        if ( error2 )
432
0
          return error2;
433
0
      }
434
435
0
      error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
436
0
      if ( error2 )
437
0
        return FT_ERR( Invalid_File_Format );
438
439
0
      cf2_setGlyphWidth( &font->outline, glyphWidth );
440
441
0
      return FT_Err_Ok;
442
0
    }
443
0
  }
444
445
446
  /* get pointer to current FreeType subfont (based on current glyphID) */
447
  FT_LOCAL_DEF( CFF_SubFont )
448
  cf2_getSubfont( PS_Decoder*  decoder )
449
0
  {
450
0
    FT_ASSERT( decoder && decoder->current_subfont );
451
452
0
    return decoder->current_subfont;
453
0
  }
454
455
456
  /* get pointer to VStore structure */
457
  FT_LOCAL_DEF( CFF_VStore )
458
  cf2_getVStore( PS_Decoder*  decoder )
459
0
  {
460
0
    FT_ASSERT( decoder && decoder->cff );
461
462
0
    return &decoder->cff->vstore;
463
0
  }
464
465
466
  /* get maxstack value from CFF2 Top DICT */
467
  FT_LOCAL_DEF( FT_UInt )
468
  cf2_getMaxstack( PS_Decoder*  decoder )
469
0
  {
470
0
    FT_ASSERT( decoder && decoder->cff );
471
472
0
    return decoder->cff->top_font.font_dict.maxstack;
473
0
  }
474
475
476
#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
477
  /* Get normalized design vector for current render request; */
478
  /* return pointer and length.                               */
479
  /*                                                          */
480
  /* Note: Uses FT_Fixed not CF2_Fixed for the vector.        */
481
  FT_LOCAL_DEF( FT_Error )
482
  cf2_getNormalizedVector( PS_Decoder*  decoder,
483
                           CF2_UInt     *len,
484
                           FT_Fixed*    *vec )
485
0
  {
486
0
    TT_Face                  face;
487
0
    FT_Service_MultiMasters  mm;
488
489
490
0
    FT_ASSERT( decoder && decoder->builder.face );
491
0
    FT_ASSERT( vec && len );
492
0
    FT_ASSERT( !decoder->builder.is_t1 );
493
494
0
    face = (TT_Face)decoder->builder.face;
495
0
    mm   = (FT_Service_MultiMasters)face->mm;
496
497
0
    return mm->get_var_blend( FT_FACE( face ), len, NULL, vec, NULL );
498
0
  }
499
#endif
500
501
502
  /* get `y_ppem' from `CFF_Size' */
503
  FT_LOCAL_DEF( CF2_Fixed )
504
  cf2_getPpemY( PS_Decoder*  decoder )
505
0
  {
506
0
    FT_ASSERT( decoder                     &&
507
0
               decoder->builder.face       &&
508
0
               decoder->builder.face->size );
509
510
    /*
511
     * Note that `y_ppem' can be zero if there wasn't a call to
512
     * `FT_Set_Char_Size' or something similar.  However, this isn't a
513
     * problem since we come to this place in the code only if
514
     * FT_LOAD_NO_SCALE is set (the other case gets caught by
515
     * `cf2_checkTransform').  The ppem value is needed to compute the stem
516
     * darkening, which is disabled for getting the unscaled outline.
517
     *
518
     */
519
0
    return cf2_intToFixed(
520
0
             decoder->builder.face->size->metrics.y_ppem );
521
0
  }
522
523
524
  /* get standard stem widths for the current subfont; */
525
  /* FreeType stores these as integer font units       */
526
  /* (note: variable names seem swapped)               */
527
  FT_LOCAL_DEF( CF2_Fixed )
528
  cf2_getStdVW( PS_Decoder*  decoder )
529
0
  {
530
0
    FT_ASSERT( decoder && decoder->current_subfont );
531
532
0
    return cf2_intToFixed(
533
0
             decoder->current_subfont->private_dict.standard_height );
534
0
  }
535
536
537
  FT_LOCAL_DEF( CF2_Fixed )
538
  cf2_getStdHW( PS_Decoder*  decoder )
539
0
  {
540
0
    FT_ASSERT( decoder && decoder->current_subfont );
541
542
0
    return cf2_intToFixed(
543
0
             decoder->current_subfont->private_dict.standard_width );
544
0
  }
545
546
547
  /* note: FreeType stores 1000 times the actual value for `BlueScale' */
548
  FT_LOCAL_DEF( void )
549
  cf2_getBlueMetrics( PS_Decoder*  decoder,
550
                      CF2_Fixed*   blueScale,
551
                      CF2_Fixed*   blueShift,
552
                      CF2_Fixed*   blueFuzz )
553
0
  {
554
0
    FT_ASSERT( decoder && decoder->current_subfont );
555
556
0
    *blueScale = FT_DivFix(
557
0
                   decoder->current_subfont->private_dict.blue_scale,
558
0
                   cf2_intToFixed( 1000 ) );
559
0
    *blueShift = cf2_intToFixed(
560
0
                   decoder->current_subfont->private_dict.blue_shift );
561
0
    *blueFuzz  = cf2_intToFixed(
562
0
                   decoder->current_subfont->private_dict.blue_fuzz );
563
0
  }
564
565
566
  /* get blue values counts and arrays; the FreeType parser has validated */
567
  /* the counts and verified that each is an even number                  */
568
  FT_LOCAL_DEF( void )
569
  cf2_getBlueValues( PS_Decoder*  decoder,
570
                     size_t*      count,
571
                     FT_Pos*     *data )
572
0
  {
573
0
    FT_ASSERT( decoder && decoder->current_subfont );
574
575
0
    *count = decoder->current_subfont->private_dict.num_blue_values;
576
0
    *data  = (FT_Pos*)
577
0
               &decoder->current_subfont->private_dict.blue_values;
578
0
  }
579
580
581
  FT_LOCAL_DEF( void )
582
  cf2_getOtherBlues( PS_Decoder*  decoder,
583
                     size_t*      count,
584
                     FT_Pos*     *data )
585
0
  {
586
0
    FT_ASSERT( decoder && decoder->current_subfont );
587
588
0
    *count = decoder->current_subfont->private_dict.num_other_blues;
589
0
    *data  = (FT_Pos*)
590
0
               &decoder->current_subfont->private_dict.other_blues;
591
0
  }
592
593
594
  FT_LOCAL_DEF( void )
595
  cf2_getFamilyBlues( PS_Decoder*  decoder,
596
                      size_t*      count,
597
                      FT_Pos*     *data )
598
0
  {
599
0
    FT_ASSERT( decoder && decoder->current_subfont );
600
601
0
    *count = decoder->current_subfont->private_dict.num_family_blues;
602
0
    *data  = (FT_Pos*)
603
0
               &decoder->current_subfont->private_dict.family_blues;
604
0
  }
605
606
607
  FT_LOCAL_DEF( void )
608
  cf2_getFamilyOtherBlues( PS_Decoder*  decoder,
609
                           size_t*      count,
610
                           FT_Pos*     *data )
611
0
  {
612
0
    FT_ASSERT( decoder && decoder->current_subfont );
613
614
0
    *count = decoder->current_subfont->private_dict.num_family_other_blues;
615
0
    *data  = (FT_Pos*)
616
0
               &decoder->current_subfont->private_dict.family_other_blues;
617
0
  }
618
619
620
  FT_LOCAL_DEF( CF2_Int )
621
  cf2_getLanguageGroup( PS_Decoder*  decoder )
622
0
  {
623
0
    FT_ASSERT( decoder && decoder->current_subfont );
624
625
0
    return decoder->current_subfont->private_dict.language_group;
626
0
  }
627
628
629
  /* convert unbiased subroutine index to `CF2_Buffer' and */
630
  /* return 0 on success                                   */
631
  FT_LOCAL_DEF( CF2_Int )
632
  cf2_initGlobalRegionBuffer( PS_Decoder*  decoder,
633
                              CF2_Int      subrNum,
634
                              CF2_Buffer   buf )
635
0
  {
636
0
    CF2_UInt  idx;
637
638
639
0
    FT_ASSERT( decoder );
640
641
0
    FT_ZERO( buf );
642
643
0
    idx = (CF2_UInt)( subrNum + decoder->globals_bias );
644
0
    if ( idx >= decoder->num_globals )
645
0
      return TRUE;     /* error */
646
647
0
    FT_ASSERT( decoder->globals );
648
649
0
    buf->start =
650
0
    buf->ptr   = decoder->globals[idx];
651
0
    buf->end   = decoder->globals[idx + 1];
652
653
0
    return FALSE;      /* success */
654
0
  }
655
656
657
  /* convert AdobeStandardEncoding code to CF2_Buffer; */
658
  /* used for seac component                           */
659
  FT_LOCAL_DEF( FT_Error )
660
  cf2_getSeacComponent( PS_Decoder*  decoder,
661
                        CF2_Int      code,
662
                        CF2_Buffer   buf )
663
0
  {
664
0
    CF2_Int   gid;
665
0
    FT_Byte*  charstring;
666
0
    FT_ULong  len;
667
0
    FT_Error  error;
668
669
670
0
    FT_ASSERT( decoder );
671
0
    FT_ASSERT( !decoder->builder.is_t1 );
672
673
0
    FT_ZERO( buf );
674
675
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
676
    /* Incremental fonts don't necessarily have valid charsets.        */
677
    /* They use the character code, not the glyph index, in this case. */
678
0
    if ( decoder->builder.face->internal->incremental_interface )
679
0
      gid = code;
680
0
    else
681
0
#endif /* FT_CONFIG_OPTION_INCREMENTAL */
682
0
    {
683
0
      gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
684
0
      if ( gid < 0 )
685
0
        return FT_THROW( Invalid_Glyph_Format );
686
0
    }
687
688
0
    error = decoder->get_glyph_callback( (TT_Face)decoder->builder.face,
689
0
                                         (CF2_UInt)gid,
690
0
                                         &charstring,
691
0
                                         &len );
692
    /* TODO: for now, just pass the FreeType error through */
693
0
    if ( error )
694
0
      return error;
695
696
    /* assume input has been validated */
697
0
    FT_ASSERT( charstring + len >= charstring );
698
699
0
    buf->start = charstring;
700
0
    buf->end   = FT_OFFSET( charstring, len );
701
0
    buf->ptr   = buf->start;
702
703
0
    return FT_Err_Ok;
704
0
  }
705
706
707
  FT_LOCAL_DEF( void )
708
  cf2_freeSeacComponent( PS_Decoder*  decoder,
709
                         CF2_Buffer   buf )
710
0
  {
711
0
    FT_ASSERT( decoder );
712
0
    FT_ASSERT( !decoder->builder.is_t1 );
713
714
0
    decoder->free_glyph_callback( (TT_Face)decoder->builder.face,
715
0
                                  (FT_Byte**)&buf->start,
716
0
                                  (FT_ULong)( buf->end - buf->start ) );
717
0
  }
718
719
720
  FT_LOCAL_DEF( FT_Error )
721
  cf2_getT1SeacComponent( PS_Decoder*  decoder,
722
                          FT_UInt      glyph_index,
723
                          CF2_Buffer   buf )
724
0
  {
725
0
    FT_Data   glyph_data;
726
0
    FT_Error  error = FT_Err_Ok;
727
0
    T1_Face   face  = (T1_Face)decoder->builder.face;
728
0
    T1_Font   type1 = &face->type1;
729
730
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
731
0
    FT_Incremental_InterfaceRec  *inc =
732
0
      face->root.internal->incremental_interface;
733
734
735
    /* For incremental fonts get the character data using the */
736
    /* callback function.                                     */
737
0
    if ( inc )
738
0
      error = inc->funcs->get_glyph_data( inc->object,
739
0
                                          glyph_index, &glyph_data );
740
0
    else
741
0
#endif
742
    /* For ordinary fonts get the character data stored in the face record. */
743
0
    {
744
0
      glyph_data.pointer = type1->charstrings[glyph_index];
745
0
      glyph_data.length  = (FT_Int)type1->charstrings_len[glyph_index];
746
0
    }
747
748
0
    if ( !error )
749
0
    {
750
0
      FT_Byte*  charstring_base = (FT_Byte*)glyph_data.pointer;
751
0
      FT_ULong  charstring_len  = (FT_ULong)glyph_data.length;
752
753
754
0
      FT_ASSERT( charstring_base + charstring_len >= charstring_base );
755
756
0
      FT_ZERO( buf );
757
0
      buf->start =
758
0
      buf->ptr   = charstring_base;
759
0
      buf->end   = charstring_base + charstring_len;
760
0
    }
761
762
0
    return error;
763
0
  }
764
765
766
  FT_LOCAL_DEF( void )
767
  cf2_freeT1SeacComponent( PS_Decoder*  decoder,
768
                           CF2_Buffer   buf )
769
0
  {
770
0
#ifdef FT_CONFIG_OPTION_INCREMENTAL
771
772
0
    T1_Face  face;
773
0
    FT_Data  data;
774
775
776
0
    FT_ASSERT( decoder );
777
778
0
    face = (T1_Face)decoder->builder.face;
779
780
0
    data.pointer = buf->start;
781
0
    data.length  = (FT_Int)( buf->end - buf->start );
782
783
0
    if ( face->root.internal->incremental_interface )
784
0
      face->root.internal->incremental_interface->funcs->free_glyph_data(
785
0
        face->root.internal->incremental_interface->object,
786
0
        &data );
787
788
#else /* !FT_CONFIG_OPTION_INCREMENTAL */
789
790
    FT_UNUSED( decoder );
791
    FT_UNUSED( buf );
792
793
#endif /* !FT_CONFIG_OPTION_INCREMENTAL */
794
0
  }
795
796
797
  FT_LOCAL_DEF( CF2_Int )
798
  cf2_initLocalRegionBuffer( PS_Decoder*  decoder,
799
                             CF2_Int      subrNum,
800
                             CF2_Buffer   buf )
801
0
  {
802
0
    CF2_UInt  idx;
803
804
805
0
    FT_ASSERT( decoder );
806
807
0
    FT_ZERO( buf );
808
809
0
    idx = (CF2_UInt)( subrNum + decoder->locals_bias );
810
0
    if ( idx >= decoder->num_locals )
811
0
      return TRUE;     /* error */
812
813
0
    FT_ASSERT( decoder->locals );
814
815
0
    buf->start = decoder->locals[idx];
816
817
0
    if ( decoder->builder.is_t1 )
818
0
    {
819
      /* The Type 1 driver stores subroutines without the seed bytes. */
820
      /* The CID driver stores subroutines with seed bytes.  This     */
821
      /* case is taken care of when decoder->subrs_len == 0.          */
822
0
      if ( decoder->locals_len )
823
0
        buf->end = FT_OFFSET( buf->start, decoder->locals_len[idx] );
824
0
      else
825
0
      {
826
        /* We are using subroutines from a CID font.  We must adjust */
827
        /* for the seed bytes.                                       */
828
0
        buf->start += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 );
829
0
        buf->end    = decoder->locals[idx + 1];
830
0
      }
831
832
0
      if ( !buf->start )
833
0
      {
834
0
        FT_ERROR(( "cf2_initLocalRegionBuffer (Type 1 mode):"
835
0
                   " invoking empty subrs\n" ));
836
0
      }
837
0
    }
838
0
    else
839
0
    {
840
0
      buf->end = decoder->locals[idx + 1];
841
0
    }
842
843
0
    buf->ptr = buf->start;
844
845
0
    return FALSE;      /* success */
846
0
  }
847
848
849
  FT_LOCAL_DEF( CF2_Fixed )
850
  cf2_getDefaultWidthX( PS_Decoder*  decoder )
851
0
  {
852
0
    FT_ASSERT( decoder && decoder->current_subfont );
853
854
0
    return cf2_intToFixed(
855
0
             decoder->current_subfont->private_dict.default_width );
856
0
  }
857
858
859
  FT_LOCAL_DEF( CF2_Fixed )
860
  cf2_getNominalWidthX( PS_Decoder*  decoder )
861
0
  {
862
0
    FT_ASSERT( decoder && decoder->current_subfont );
863
864
0
    return cf2_intToFixed(
865
0
             decoder->current_subfont->private_dict.nominal_width );
866
0
  }
867
868
869
  FT_LOCAL_DEF( void )
870
  cf2_outline_reset( CF2_Outline  outline )
871
0
  {
872
0
    PS_Decoder*  decoder = outline->decoder;
873
874
875
0
    FT_ASSERT( decoder );
876
877
0
    outline->root.windingMomentum = 0;
878
879
0
    FT_GlyphLoader_Rewind( decoder->builder.loader );
880
0
  }
881
882
883
  FT_LOCAL_DEF( void )
884
  cf2_outline_close( CF2_Outline  outline )
885
0
  {
886
0
    PS_Decoder*  decoder = outline->decoder;
887
888
889
0
    FT_ASSERT( decoder );
890
891
0
    ps_builder_close_contour( &decoder->builder );
892
893
0
    FT_GlyphLoader_Add( decoder->builder.loader );
894
0
  }
895
896
897
/* END */