1/***************************************************************************/
2/*                                                                         */
3/*  cf2ft.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 "cf2ft.h"
40#include FT_INTERNAL_DEBUG_H
41
42#include "cf2font.h"
43#include "cf2error.h"
44
45
46#define CF2_MAX_SIZE  cf2_intToFixed( 2000 )    /* max ppem */
47
48
49  /*
50   * This check should avoid most internal overflow cases.  Clients should
51   * generally respond to `Glyph_Too_Big' by getting a glyph outline
52   * at EM size, scaling it and filling it as a graphics operation.
53   *
54   */
55  static FT_Error
56  cf2_checkTransform( const CF2_Matrix*  transform,
57                      CF2_Int            unitsPerEm )
58  {
59    CF2_Fixed  maxScale;
60
61
62    FT_ASSERT( unitsPerEm > 0 );
63
64    if ( transform->a <= 0 || transform->d <= 0 )
65      return FT_THROW( Invalid_Size_Handle );
66
67    FT_ASSERT( transform->b == 0 && transform->c == 0 );
68    FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
69
70    if ( unitsPerEm > 0x7FFF )
71      return FT_THROW( Glyph_Too_Big );
72
73    maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
74
75    if ( transform->a > maxScale || transform->d > maxScale )
76      return FT_THROW( Glyph_Too_Big );
77
78    return FT_Err_Ok;
79  }
80
81
82  static void
83  cf2_setGlyphWidth( CF2_Outline  outline,
84                     CF2_Fixed    width )
85  {
86    CFF_Decoder*  decoder = outline->decoder;
87
88
89    FT_ASSERT( decoder );
90
91    decoder->glyph_width = cf2_fixedToInt( width );
92  }
93
94
95  /* Clean up font instance. */
96  static void
97  cf2_free_instance( void*  ptr )
98  {
99    CF2_Font  font = (CF2_Font)ptr;
100
101
102    if ( font )
103    {
104      FT_Memory  memory = font->memory;
105
106
107      (void)memory;
108    }
109  }
110
111
112  /********************************************/
113  /*                                          */
114  /* functions for handling client outline;   */
115  /* FreeType uses coordinates in 26.6 format */
116  /*                                          */
117  /********************************************/
118
119  static void
120  cf2_builder_moveTo( CF2_OutlineCallbacks      callbacks,
121                      const CF2_CallbackParams  params )
122  {
123    /* downcast the object pointer */
124    CF2_Outline   outline = (CF2_Outline)callbacks;
125    CFF_Builder*  builder;
126
127    (void)params;        /* only used in debug mode */
128
129
130    FT_ASSERT( outline && outline->decoder );
131    FT_ASSERT( params->op == CF2_PathOpMoveTo );
132
133    builder = &outline->decoder->builder;
134
135    /* note: two successive moves simply close the contour twice */
136    cff_builder_close_contour( builder );
137    builder->path_begun = 0;
138  }
139
140
141  static void
142  cf2_builder_lineTo( CF2_OutlineCallbacks      callbacks,
143                      const CF2_CallbackParams  params )
144  {
145    FT_Error  error;
146
147    /* downcast the object pointer */
148    CF2_Outline   outline = (CF2_Outline)callbacks;
149    CFF_Builder*  builder;
150
151
152    FT_ASSERT( outline && outline->decoder );
153    FT_ASSERT( params->op == CF2_PathOpLineTo );
154
155    builder = &outline->decoder->builder;
156
157    if ( !builder->path_begun )
158    {
159      /* record the move before the line; also check points and set */
160      /* `path_begun'                                               */
161      error = cff_builder_start_point( builder,
162                                       params->pt0.x,
163                                       params->pt0.y );
164      if ( error )
165      {
166        if ( !*callbacks->error )
167          *callbacks->error =  error;
168        return;
169      }
170    }
171
172    /* `cff_builder_add_point1' includes a check_points call for one point */
173    error = cff_builder_add_point1( builder,
174                                    params->pt1.x,
175                                    params->pt1.y );
176    if ( error )
177    {
178      if ( !*callbacks->error )
179        *callbacks->error =  error;
180      return;
181    }
182  }
183
184
185  static void
186  cf2_builder_cubeTo( CF2_OutlineCallbacks      callbacks,
187                      const CF2_CallbackParams  params )
188  {
189    FT_Error  error;
190
191    /* downcast the object pointer */
192    CF2_Outline   outline = (CF2_Outline)callbacks;
193    CFF_Builder*  builder;
194
195
196    FT_ASSERT( outline && outline->decoder );
197    FT_ASSERT( params->op == CF2_PathOpCubeTo );
198
199    builder = &outline->decoder->builder;
200
201    if ( !builder->path_begun )
202    {
203      /* record the move before the line; also check points and set */
204      /* `path_begun'                                               */
205      error = cff_builder_start_point( builder,
206                                       params->pt0.x,
207                                       params->pt0.y );
208      if ( error )
209      {
210        if ( !*callbacks->error )
211          *callbacks->error =  error;
212        return;
213      }
214    }
215
216    /* prepare room for 3 points: 2 off-curve, 1 on-curve */
217    error = cff_check_points( builder, 3 );
218    if ( error )
219    {
220      if ( !*callbacks->error )
221        *callbacks->error =  error;
222      return;
223    }
224
225    cff_builder_add_point( builder,
226                           params->pt1.x,
227                           params->pt1.y, 0 );
228    cff_builder_add_point( builder,
229                           params->pt2.x,
230                           params->pt2.y, 0 );
231    cff_builder_add_point( builder,
232                           params->pt3.x,
233                           params->pt3.y, 1 );
234  }
235
236
237  static void
238  cf2_outline_init( CF2_Outline  outline,
239                    FT_Memory    memory,
240                    FT_Error*    error )
241  {
242    FT_MEM_ZERO( outline, sizeof ( CF2_OutlineRec ) );
243
244    outline->root.memory = memory;
245    outline->root.error  = error;
246
247    outline->root.moveTo = cf2_builder_moveTo;
248    outline->root.lineTo = cf2_builder_lineTo;
249    outline->root.cubeTo = cf2_builder_cubeTo;
250  }
251
252
253  /* get scaling and hint flag from GlyphSlot */
254  static void
255  cf2_getScaleAndHintFlag( CFF_Decoder*  decoder,
256                           CF2_Fixed*    x_scale,
257                           CF2_Fixed*    y_scale,
258                           FT_Bool*      hinted,
259                           FT_Bool*      scaled )
260  {
261    FT_ASSERT( decoder && decoder->builder.glyph );
262
263    /* note: FreeType scale includes a factor of 64 */
264    *hinted = decoder->builder.glyph->hint;
265    *scaled = decoder->builder.glyph->scaled;
266
267    if ( *hinted )
268    {
269      *x_scale = ( decoder->builder.glyph->x_scale + 32 ) / 64;
270      *y_scale = ( decoder->builder.glyph->y_scale + 32 ) / 64;
271    }
272    else
273    {
274      /* for unhinted outlines, `cff_slot_load' does the scaling, */
275      /* thus render at `unity' scale                             */
276
277      *x_scale = 0x0400;   /* 1/64 as 16.16 */
278      *y_scale = 0x0400;
279    }
280  }
281
282
283  /* get units per em from `FT_Face' */
284  /* TODO: should handle font matrix concatenation? */
285  static FT_UShort
286  cf2_getUnitsPerEm( CFF_Decoder*  decoder )
287  {
288    FT_ASSERT( decoder && decoder->builder.face );
289    FT_ASSERT( decoder->builder.face->root.units_per_EM );
290
291    return decoder->builder.face->root.units_per_EM;
292  }
293
294
295  /* Main entry point: Render one glyph. */
296  FT_LOCAL_DEF( FT_Error )
297  cf2_decoder_parse_charstrings( CFF_Decoder*  decoder,
298                                 FT_Byte*      charstring_base,
299                                 FT_ULong      charstring_len )
300  {
301    FT_Memory  memory;
302    FT_Error   error = FT_Err_Ok;
303    CF2_Font   font;
304
305
306    FT_ASSERT( decoder && decoder->cff );
307
308    memory = decoder->builder.memory;
309
310    /* CF2 data is saved here across glyphs */
311    font = (CF2_Font)decoder->cff->cf2_instance.data;
312
313    /* on first glyph, allocate instance structure */
314    if ( decoder->cff->cf2_instance.data == NULL )
315    {
316      decoder->cff->cf2_instance.finalizer =
317        (FT_Generic_Finalizer)cf2_free_instance;
318
319      if ( FT_ALLOC( decoder->cff->cf2_instance.data,
320                     sizeof ( CF2_FontRec ) ) )
321        return FT_THROW( Out_Of_Memory );
322
323      font = (CF2_Font)decoder->cff->cf2_instance.data;
324
325      font->memory = memory;
326
327      /* initialize a client outline, to be shared by each glyph rendered */
328      cf2_outline_init( &font->outline, font->memory, &font->error );
329    }
330
331    /* save decoder; it is a stack variable and will be different on each */
332    /* call                                                               */
333    font->decoder         = decoder;
334    font->outline.decoder = decoder;
335
336    {
337      /* build parameters for Adobe engine */
338
339      CFF_Builder*  builder = &decoder->builder;
340      CFF_Driver    driver  = (CFF_Driver)FT_FACE_DRIVER( builder->face );
341
342      /* local error */
343      FT_Error       error2 = FT_Err_Ok;
344      CF2_BufferRec  buf;
345      CF2_Matrix     transform;
346      CF2_F16Dot16   glyphWidth;
347
348      FT_Bool  hinted;
349      FT_Bool  scaled;
350
351
352      /* FreeType has already looked up the GID; convert to         */
353      /* `RegionBuffer', assuming that the input has been validated */
354      FT_ASSERT( charstring_base + charstring_len >= charstring_base );
355
356      FT_ZERO( &buf );
357      buf.start =
358      buf.ptr   = charstring_base;
359      buf.end   = charstring_base + charstring_len;
360
361      FT_ZERO( &transform );
362
363      cf2_getScaleAndHintFlag( decoder,
364                               &transform.a,
365                               &transform.d,
366                               &hinted,
367                               &scaled );
368
369      font->renderingFlags = 0;
370      if ( hinted )
371        font->renderingFlags |= CF2_FlagsHinted;
372      if ( scaled && !driver->no_stem_darkening )
373        font->renderingFlags |= CF2_FlagsDarkened;
374
375      font->darkenParams[0] = driver->darken_params[0];
376      font->darkenParams[1] = driver->darken_params[1];
377      font->darkenParams[2] = driver->darken_params[2];
378      font->darkenParams[3] = driver->darken_params[3];
379      font->darkenParams[4] = driver->darken_params[4];
380      font->darkenParams[5] = driver->darken_params[5];
381      font->darkenParams[6] = driver->darken_params[6];
382      font->darkenParams[7] = driver->darken_params[7];
383
384      /* now get an outline for this glyph;      */
385      /* also get units per em to validate scale */
386      font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
387
388      if ( scaled )
389      {
390        error2 = cf2_checkTransform( &transform, font->unitsPerEm );
391        if ( error2 )
392          return error2;
393      }
394
395      error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
396      if ( error2 )
397        return FT_ERR( Invalid_File_Format );
398
399      cf2_setGlyphWidth( &font->outline, glyphWidth );
400
401      return FT_Err_Ok;
402    }
403  }
404
405
406  /* get pointer to current FreeType subfont (based on current glyphID) */
407  FT_LOCAL_DEF( CFF_SubFont )
408  cf2_getSubfont( CFF_Decoder*  decoder )
409  {
410    FT_ASSERT( decoder && decoder->current_subfont );
411
412    return decoder->current_subfont;
413  }
414
415
416  /* get `y_ppem' from `CFF_Size' */
417  FT_LOCAL_DEF( CF2_Fixed )
418  cf2_getPpemY( CFF_Decoder*  decoder )
419  {
420    FT_ASSERT( decoder                          &&
421               decoder->builder.face            &&
422               decoder->builder.face->root.size );
423
424    /*
425     * Note that `y_ppem' can be zero if there wasn't a call to
426     * `FT_Set_Char_Size' or something similar.  However, this isn't a
427     * problem since we come to this place in the code only if
428     * FT_LOAD_NO_SCALE is set (the other case gets caught by
429     * `cf2_checkTransform').  The ppem value is needed to compute the stem
430     * darkening, which is disabled for getting the unscaled outline.
431     *
432     */
433    return cf2_intToFixed(
434             decoder->builder.face->root.size->metrics.y_ppem );
435  }
436
437
438  /* get standard stem widths for the current subfont; */
439  /* FreeType stores these as integer font units       */
440  /* (note: variable names seem swapped)               */
441  FT_LOCAL_DEF( CF2_Fixed )
442  cf2_getStdVW( CFF_Decoder*  decoder )
443  {
444    FT_ASSERT( decoder && decoder->current_subfont );
445
446    return cf2_intToFixed(
447             decoder->current_subfont->private_dict.standard_height );
448  }
449
450
451  FT_LOCAL_DEF( CF2_Fixed )
452  cf2_getStdHW( CFF_Decoder*  decoder )
453  {
454    FT_ASSERT( decoder && decoder->current_subfont );
455
456    return cf2_intToFixed(
457             decoder->current_subfont->private_dict.standard_width );
458  }
459
460
461  /* note: FreeType stores 1000 times the actual value for `BlueScale' */
462  FT_LOCAL_DEF( void )
463  cf2_getBlueMetrics( CFF_Decoder*  decoder,
464                      CF2_Fixed*    blueScale,
465                      CF2_Fixed*    blueShift,
466                      CF2_Fixed*    blueFuzz )
467  {
468    FT_ASSERT( decoder && decoder->current_subfont );
469
470    *blueScale = FT_DivFix(
471                   decoder->current_subfont->private_dict.blue_scale,
472                   cf2_intToFixed( 1000 ) );
473    *blueShift = cf2_intToFixed(
474                   decoder->current_subfont->private_dict.blue_shift );
475    *blueFuzz  = cf2_intToFixed(
476                   decoder->current_subfont->private_dict.blue_fuzz );
477  }
478
479
480  /* get blue values counts and arrays; the FreeType parser has validated */
481  /* the counts and verified that each is an even number                  */
482  FT_LOCAL_DEF( void )
483  cf2_getBlueValues( CFF_Decoder*  decoder,
484                     size_t*       count,
485                     FT_Pos*      *data )
486  {
487    FT_ASSERT( decoder && decoder->current_subfont );
488
489    *count = decoder->current_subfont->private_dict.num_blue_values;
490    *data  = (FT_Pos*)
491               &decoder->current_subfont->private_dict.blue_values;
492  }
493
494
495  FT_LOCAL_DEF( void )
496  cf2_getOtherBlues( CFF_Decoder*  decoder,
497                     size_t*       count,
498                     FT_Pos*      *data )
499  {
500    FT_ASSERT( decoder && decoder->current_subfont );
501
502    *count = decoder->current_subfont->private_dict.num_other_blues;
503    *data  = (FT_Pos*)
504               &decoder->current_subfont->private_dict.other_blues;
505  }
506
507
508  FT_LOCAL_DEF( void )
509  cf2_getFamilyBlues( CFF_Decoder*  decoder,
510                      size_t*       count,
511                      FT_Pos*      *data )
512  {
513    FT_ASSERT( decoder && decoder->current_subfont );
514
515    *count = decoder->current_subfont->private_dict.num_family_blues;
516    *data  = (FT_Pos*)
517               &decoder->current_subfont->private_dict.family_blues;
518  }
519
520
521  FT_LOCAL_DEF( void )
522  cf2_getFamilyOtherBlues( CFF_Decoder*  decoder,
523                           size_t*       count,
524                           FT_Pos*      *data )
525  {
526    FT_ASSERT( decoder && decoder->current_subfont );
527
528    *count = decoder->current_subfont->private_dict.num_family_other_blues;
529    *data  = (FT_Pos*)
530               &decoder->current_subfont->private_dict.family_other_blues;
531  }
532
533
534  FT_LOCAL_DEF( CF2_Int )
535  cf2_getLanguageGroup( CFF_Decoder*  decoder )
536  {
537    FT_ASSERT( decoder && decoder->current_subfont );
538
539    return decoder->current_subfont->private_dict.language_group;
540  }
541
542
543  /* convert unbiased subroutine index to `CF2_Buffer' and */
544  /* return 0 on success                                   */
545  FT_LOCAL_DEF( CF2_Int )
546  cf2_initGlobalRegionBuffer( CFF_Decoder*  decoder,
547                              CF2_UInt      idx,
548                              CF2_Buffer    buf )
549  {
550    FT_ASSERT( decoder );
551
552    FT_ZERO( buf );
553
554    idx += (CF2_UInt)decoder->globals_bias;
555    if ( idx >= decoder->num_globals )
556      return TRUE;     /* error */
557
558    FT_ASSERT( decoder->globals );
559
560    buf->start =
561    buf->ptr   = decoder->globals[idx];
562    buf->end   = decoder->globals[idx + 1];
563
564    return FALSE;      /* success */
565  }
566
567
568  /* convert AdobeStandardEncoding code to CF2_Buffer; */
569  /* used for seac component                           */
570  FT_LOCAL_DEF( FT_Error )
571  cf2_getSeacComponent( CFF_Decoder*  decoder,
572                        CF2_Int       code,
573                        CF2_Buffer    buf )
574  {
575    CF2_Int   gid;
576    FT_Byte*  charstring;
577    FT_ULong  len;
578    FT_Error  error;
579
580
581    FT_ASSERT( decoder );
582
583    FT_ZERO( buf );
584
585#ifdef FT_CONFIG_OPTION_INCREMENTAL
586    /* Incremental fonts don't necessarily have valid charsets.        */
587    /* They use the character code, not the glyph index, in this case. */
588    if ( decoder->builder.face->root.internal->incremental_interface )
589      gid = code;
590    else
591#endif /* FT_CONFIG_OPTION_INCREMENTAL */
592    {
593      gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
594      if ( gid < 0 )
595        return FT_THROW( Invalid_Glyph_Format );
596    }
597
598    error = cff_get_glyph_data( decoder->builder.face,
599                                (CF2_UInt)gid,
600                                &charstring,
601                                &len );
602    /* TODO: for now, just pass the FreeType error through */
603    if ( error )
604      return error;
605
606    /* assume input has been validated */
607    FT_ASSERT( charstring + len >= charstring );
608
609    buf->start = charstring;
610    buf->end   = charstring + len;
611    buf->ptr   = buf->start;
612
613    return FT_Err_Ok;
614  }
615
616
617  FT_LOCAL_DEF( void )
618  cf2_freeSeacComponent( CFF_Decoder*  decoder,
619                         CF2_Buffer    buf )
620  {
621    FT_ASSERT( decoder );
622
623    cff_free_glyph_data( decoder->builder.face,
624                         (FT_Byte**)&buf->start,
625                         (FT_ULong)( buf->end - buf->start ) );
626  }
627
628
629  FT_LOCAL_DEF( CF2_Int )
630  cf2_initLocalRegionBuffer( CFF_Decoder*  decoder,
631                             CF2_UInt      idx,
632                             CF2_Buffer    buf )
633  {
634    FT_ASSERT( decoder );
635
636    FT_ZERO( buf );
637
638    idx += (CF2_UInt)decoder->locals_bias;
639    if ( idx >= decoder->num_locals )
640      return TRUE;     /* error */
641
642    FT_ASSERT( decoder->locals );
643
644    buf->start =
645    buf->ptr   = decoder->locals[idx];
646    buf->end   = decoder->locals[idx + 1];
647
648    return FALSE;      /* success */
649  }
650
651
652  FT_LOCAL_DEF( CF2_Fixed )
653  cf2_getDefaultWidthX( CFF_Decoder*  decoder )
654  {
655    FT_ASSERT( decoder && decoder->current_subfont );
656
657    return cf2_intToFixed(
658             decoder->current_subfont->private_dict.default_width );
659  }
660
661
662  FT_LOCAL_DEF( CF2_Fixed )
663  cf2_getNominalWidthX( CFF_Decoder*  decoder )
664  {
665    FT_ASSERT( decoder && decoder->current_subfont );
666
667    return cf2_intToFixed(
668             decoder->current_subfont->private_dict.nominal_width );
669  }
670
671
672  FT_LOCAL_DEF( void )
673  cf2_outline_reset( CF2_Outline  outline )
674  {
675    CFF_Decoder*  decoder = outline->decoder;
676
677
678    FT_ASSERT( decoder );
679
680    outline->root.windingMomentum = 0;
681
682    FT_GlyphLoader_Rewind( decoder->builder.loader );
683  }
684
685
686  FT_LOCAL_DEF( void )
687  cf2_outline_close( CF2_Outline  outline )
688  {
689    CFF_Decoder*  decoder = outline->decoder;
690
691
692    FT_ASSERT( decoder );
693
694    cff_builder_close_contour( &decoder->builder );
695
696    FT_GlyphLoader_Add( decoder->builder.loader );
697  }
698
699
700/* END */
701