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