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