XFA: merge patch from CL 815103002
[pdfium.git] / third_party / freetype / src / cff / cf2ft.c
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 += 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_UInt      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     gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
586     if ( gid < 0 )
587       return FT_THROW( Invalid_Glyph_Format );
588
589     error = cff_get_glyph_data( decoder->builder.face,
590                                 gid,
591                                 &charstring,
592                                 &len );
593     /* TODO: for now, just pass the FreeType error through */
594     if ( error )
595       return error;
596
597     /* assume input has been validated */
598     FT_ASSERT( charstring + len >= charstring );
599
600     buf->start = charstring;
601     buf->end   = charstring + len;
602     buf->ptr   = buf->start;
603
604     return FT_Err_Ok;
605   }
606
607
608   FT_LOCAL_DEF( void )
609   cf2_freeSeacComponent( CFF_Decoder*  decoder,
610                          CF2_Buffer    buf )
611   {
612     FT_ASSERT( decoder );
613
614     cff_free_glyph_data( decoder->builder.face,
615                          (FT_Byte**)&buf->start,
616                          (FT_ULong)( buf->end - buf->start ) );
617   }
618
619
620   FT_LOCAL_DEF( CF2_Int )
621   cf2_initLocalRegionBuffer( CFF_Decoder*  decoder,
622                              CF2_UInt      idx,
623                              CF2_Buffer    buf )
624   {
625     FT_ASSERT( decoder );
626
627     FT_ZERO( buf );
628
629     idx += decoder->locals_bias;
630     if ( idx >= decoder->num_locals )
631       return TRUE;     /* error */
632
633     FT_ASSERT( decoder->locals );
634
635     buf->start =
636     buf->ptr   = decoder->locals[idx];
637     buf->end   = decoder->locals[idx + 1];
638
639     return FALSE;      /* success */
640   }
641
642
643   FT_LOCAL_DEF( CF2_Fixed )
644   cf2_getDefaultWidthX( CFF_Decoder*  decoder )
645   {
646     FT_ASSERT( decoder && decoder->current_subfont );
647
648     return cf2_intToFixed(
649              decoder->current_subfont->private_dict.default_width );
650   }
651
652
653   FT_LOCAL_DEF( CF2_Fixed )
654   cf2_getNominalWidthX( CFF_Decoder*  decoder )
655   {
656     FT_ASSERT( decoder && decoder->current_subfont );
657
658     return cf2_intToFixed(
659              decoder->current_subfont->private_dict.nominal_width );
660   }
661
662
663   FT_LOCAL_DEF( void )
664   cf2_outline_reset( CF2_Outline  outline )
665   {
666     CFF_Decoder*  decoder = outline->decoder;
667
668
669     FT_ASSERT( decoder );
670
671     outline->root.windingMomentum = 0;
672
673     FT_GlyphLoader_Rewind( decoder->builder.loader );
674   }
675
676
677   FT_LOCAL_DEF( void )
678   cf2_outline_close( CF2_Outline  outline )
679   {
680     CFF_Decoder*  decoder = outline->decoder;
681
682
683     FT_ASSERT( decoder );
684
685     cff_builder_close_contour( &decoder->builder );
686
687     FT_GlyphLoader_Add( decoder->builder.loader );
688   }
689
690
691 /* END */