1 /***************************************************************************/
5 /* FreeType Glue Component to Adobe's Interpreter (body). */
7 /* Copyright 2013 Adobe Systems Incorporated. */
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. */
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. */
36 /***************************************************************************/
40 #include FT_INTERNAL_DEBUG_H
46 #define CF2_MAX_SIZE cf2_intToFixed( 2000 ) /* max ppem */
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.
56 cf2_checkTransform( const CF2_Matrix
* transform
,
62 FT_ASSERT( unitsPerEm
> 0 );
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 );
68 if ( unitsPerEm
> 0x7FFF )
69 return FT_THROW( Glyph_Too_Big
);
71 maxScale
= FT_DivFix( CF2_MAX_SIZE
, cf2_intToFixed( unitsPerEm
) );
73 if ( transform
->a
> maxScale
|| transform
->d
> maxScale
)
74 return FT_THROW( Glyph_Too_Big
);
81 cf2_setGlyphWidth( CF2_Outline outline
,
84 CFF_Decoder
* decoder
= outline
->decoder
;
89 decoder
->glyph_width
= cf2_fixedToInt( width
);
93 /* Clean up font instance. */
95 cf2_free_instance( void* ptr
)
97 CF2_Font font
= (CF2_Font
)ptr
;
102 FT_Memory memory
= font
->memory
;
110 /********************************************/
112 /* functions for handling client outline; */
113 /* FreeType uses coordinates in 26.6 format */
115 /********************************************/
118 cf2_builder_moveTo( CF2_OutlineCallbacks callbacks
,
119 const CF2_CallbackParams params
)
121 /* downcast the object pointer */
122 CF2_Outline outline
= (CF2_Outline
)callbacks
;
123 CFF_Builder
* builder
;
125 (void)params
; /* only used in debug mode */
128 FT_ASSERT( outline
&& outline
->decoder
);
129 FT_ASSERT( params
->op
== CF2_PathOpMoveTo
);
131 builder
= &outline
->decoder
->builder
;
133 /* note: two successive moves simply close the contour twice */
134 cff_builder_close_contour( builder
);
135 builder
->path_begun
= 0;
140 cf2_builder_lineTo( CF2_OutlineCallbacks callbacks
,
141 const CF2_CallbackParams params
)
143 /* downcast the object pointer */
144 CF2_Outline outline
= (CF2_Outline
)callbacks
;
145 CFF_Builder
* builder
;
148 FT_ASSERT( outline
&& outline
->decoder
);
149 FT_ASSERT( params
->op
== CF2_PathOpLineTo
);
151 builder
= &outline
->decoder
->builder
;
153 if ( !builder
->path_begun
)
155 /* record the move before the line; also check points and set */
157 cff_builder_start_point( builder
,
162 /* `cff_builder_add_point1' includes a check_points call for one point */
163 cff_builder_add_point1( builder
,
170 cf2_builder_cubeTo( CF2_OutlineCallbacks callbacks
,
171 const CF2_CallbackParams params
)
173 /* downcast the object pointer */
174 CF2_Outline outline
= (CF2_Outline
)callbacks
;
175 CFF_Builder
* builder
;
178 FT_ASSERT( outline
&& outline
->decoder
);
179 FT_ASSERT( params
->op
== CF2_PathOpCubeTo
);
181 builder
= &outline
->decoder
->builder
;
183 if ( !builder
->path_begun
)
185 /* record the move before the line; also check points and set */
187 cff_builder_start_point( builder
,
192 /* prepare room for 3 points: 2 off-curve, 1 on-curve */
193 cff_check_points( builder
, 3 );
195 cff_builder_add_point( builder
,
198 cff_builder_add_point( builder
,
201 cff_builder_add_point( builder
,
208 cf2_outline_init( CF2_Outline outline
,
212 FT_MEM_ZERO( outline
, sizeof ( CF2_OutlineRec
) );
214 outline
->root
.memory
= memory
;
215 outline
->root
.error
= error
;
217 outline
->root
.moveTo
= cf2_builder_moveTo
;
218 outline
->root
.lineTo
= cf2_builder_lineTo
;
219 outline
->root
.cubeTo
= cf2_builder_cubeTo
;
223 /* get scaling and hint flag from GlyphSlot */
225 cf2_getScaleAndHintFlag( CFF_Decoder
* decoder
,
231 FT_ASSERT( decoder
&& decoder
->builder
.glyph
);
233 /* note: FreeType scale includes a factor of 64 */
234 *hinted
= decoder
->builder
.glyph
->hint
;
235 *scaled
= decoder
->builder
.glyph
->scaled
;
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 ) );
246 /* for unhinted outlines, `cff_slot_load' does the scaling, */
247 /* thus render at `unity' scale */
249 *x_scale
= 0x0400; /* 1/64 as 16.16 */
255 /* get units per em from `FT_Face' */
256 /* TODO: should handle font matrix concatenation? */
258 cf2_getUnitsPerEm( CFF_Decoder
* decoder
)
260 FT_ASSERT( decoder
&& decoder
->builder
.face
);
261 FT_ASSERT( decoder
->builder
.face
->root
.units_per_EM
);
263 return decoder
->builder
.face
->root
.units_per_EM
;
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
)
274 FT_Error error
= FT_Err_Ok
;
278 FT_ASSERT( decoder
&& decoder
->cff
);
280 memory
= decoder
->builder
.memory
;
282 /* CF2 data is saved here across glyphs */
283 font
= (CF2_Font
)decoder
->cff
->cf2_instance
.data
;
285 /* on first glyph, allocate instance structure */
286 if ( decoder
->cff
->cf2_instance
.data
== NULL
)
288 decoder
->cff
->cf2_instance
.finalizer
=
289 (FT_Generic_Finalizer
)cf2_free_instance
;
291 if ( FT_ALLOC( decoder
->cff
->cf2_instance
.data
,
292 sizeof ( CF2_FontRec
) ) )
293 return FT_THROW( Out_Of_Memory
);
295 font
= (CF2_Font
)decoder
->cff
->cf2_instance
.data
;
297 font
->memory
= memory
;
299 /* initialize a client outline, to be shared by each glyph rendered */
300 cf2_outline_init( &font
->outline
, font
->memory
, &font
->error
);
303 /* save decoder; it is a stack variable and will be different on each */
305 font
->decoder
= decoder
;
306 font
->outline
.decoder
= decoder
;
309 /* build parameters for Adobe engine */
311 CFF_Builder
* builder
= &decoder
->builder
;
312 CFF_Driver driver
= (CFF_Driver
)FT_FACE_DRIVER( builder
->face
);
315 FT_Error error2
= FT_Err_Ok
;
317 CF2_Matrix transform
;
318 CF2_F16Dot16 glyphWidth
;
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
);
330 buf
.ptr
= charstring_base
;
331 buf
.end
= charstring_base
+ charstring_len
;
333 FT_ZERO( &transform
);
335 cf2_getScaleAndHintFlag( decoder
,
341 font
->renderingFlags
= 0;
343 font
->renderingFlags
|= CF2_FlagsHinted
;
344 if ( scaled
&& !driver
->no_stem_darkening
)
345 font
->renderingFlags
|= CF2_FlagsDarkened
;
347 font
->darkenParams
[0] = driver
->darken_params
[0];
348 font
->darkenParams
[1] = driver
->darken_params
[1];
349 font
->darkenParams
[2] = driver
->darken_params
[2];
350 font
->darkenParams
[3] = driver
->darken_params
[3];
351 font
->darkenParams
[4] = driver
->darken_params
[4];
352 font
->darkenParams
[5] = driver
->darken_params
[5];
353 font
->darkenParams
[6] = driver
->darken_params
[6];
354 font
->darkenParams
[7] = driver
->darken_params
[7];
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
);
360 error2
= cf2_checkTransform( &transform
, font
->unitsPerEm
);
364 error2
= cf2_getGlyphOutline( font
, &buf
, &transform
, &glyphWidth
);
366 return FT_ERR( Invalid_File_Format
);
368 cf2_setGlyphWidth( &font
->outline
, glyphWidth
);
375 /* get pointer to current FreeType subfont (based on current glyphID) */
376 FT_LOCAL_DEF( CFF_SubFont
)
377 cf2_getSubfont( CFF_Decoder
* decoder
)
379 FT_ASSERT( decoder
&& decoder
->current_subfont
);
381 return decoder
->current_subfont
;
385 /* get `y_ppem' from `CFF_Size' */
386 FT_LOCAL_DEF( CF2_Fixed
)
387 cf2_getPpemY( CFF_Decoder
* decoder
)
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
);
394 return cf2_intToFixed(
395 decoder
->builder
.face
->root
.size
->metrics
.y_ppem
);
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
)
405 FT_ASSERT( decoder
&& decoder
->current_subfont
);
407 return cf2_intToFixed(
408 decoder
->current_subfont
->private_dict
.standard_height
);
412 FT_LOCAL_DEF( CF2_Fixed
)
413 cf2_getStdHW( CFF_Decoder
* decoder
)
415 FT_ASSERT( decoder
&& decoder
->current_subfont
);
417 return cf2_intToFixed(
418 decoder
->current_subfont
->private_dict
.standard_width
);
422 /* note: FreeType stores 1000 times the actual value for `BlueScale' */
424 cf2_getBlueMetrics( CFF_Decoder
* decoder
,
425 CF2_Fixed
* blueScale
,
426 CF2_Fixed
* blueShift
,
427 CF2_Fixed
* blueFuzz
)
429 FT_ASSERT( decoder
&& decoder
->current_subfont
);
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
);
441 /* get blue values counts and arrays; the FreeType parser has validated */
442 /* the counts and verified that each is an even number */
444 cf2_getBlueValues( CFF_Decoder
* decoder
,
448 FT_ASSERT( decoder
&& decoder
->current_subfont
);
450 *count
= decoder
->current_subfont
->private_dict
.num_blue_values
;
452 &decoder
->current_subfont
->private_dict
.blue_values
;
457 cf2_getOtherBlues( CFF_Decoder
* decoder
,
461 FT_ASSERT( decoder
&& decoder
->current_subfont
);
463 *count
= decoder
->current_subfont
->private_dict
.num_other_blues
;
465 &decoder
->current_subfont
->private_dict
.other_blues
;
470 cf2_getFamilyBlues( CFF_Decoder
* decoder
,
474 FT_ASSERT( decoder
&& decoder
->current_subfont
);
476 *count
= decoder
->current_subfont
->private_dict
.num_family_blues
;
478 &decoder
->current_subfont
->private_dict
.family_blues
;
483 cf2_getFamilyOtherBlues( CFF_Decoder
* decoder
,
487 FT_ASSERT( decoder
&& decoder
->current_subfont
);
489 *count
= decoder
->current_subfont
->private_dict
.num_family_other_blues
;
491 &decoder
->current_subfont
->private_dict
.family_other_blues
;
495 FT_LOCAL_DEF( CF2_Int
)
496 cf2_getLanguageGroup( CFF_Decoder
* decoder
)
498 FT_ASSERT( decoder
&& decoder
->current_subfont
);
500 return decoder
->current_subfont
->private_dict
.language_group
;
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
,
511 FT_ASSERT( decoder
&& decoder
->globals
);
515 idx
+= decoder
->globals_bias
;
516 if ( idx
>= decoder
->num_globals
)
517 return TRUE
; /* error */
520 buf
->ptr
= decoder
->globals
[idx
];
521 buf
->end
= decoder
->globals
[idx
+ 1];
523 return FALSE
; /* success */
527 /* convert AdobeStandardEncoding code to CF2_Buffer; */
528 /* used for seac component */
529 FT_LOCAL_DEF( FT_Error
)
530 cf2_getSeacComponent( CFF_Decoder
* decoder
,
540 FT_ASSERT( decoder
);
544 gid
= cff_lookup_glyph_by_stdcharcode( decoder
->cff
, code
);
546 return FT_THROW( Invalid_Glyph_Format
);
548 error
= cff_get_glyph_data( decoder
->builder
.face
,
552 /* TODO: for now, just pass the FreeType error through */
556 /* assume input has been validated */
557 FT_ASSERT( charstring
+ len
>= charstring
);
559 buf
->start
= charstring
;
560 buf
->end
= charstring
+ len
;
561 buf
->ptr
= buf
->start
;
568 cf2_freeSeacComponent( CFF_Decoder
* decoder
,
571 FT_ASSERT( decoder
);
573 cff_free_glyph_data( decoder
->builder
.face
,
574 (FT_Byte
**)&buf
->start
,
575 (FT_ULong
)( buf
->end
- buf
->start
) );
579 FT_LOCAL_DEF( CF2_Int
)
580 cf2_initLocalRegionBuffer( CFF_Decoder
* decoder
,
584 FT_ASSERT( decoder
&& decoder
->locals
);
588 idx
+= decoder
->locals_bias
;
589 if ( idx
>= decoder
->num_locals
)
590 return TRUE
; /* error */
593 buf
->ptr
= decoder
->locals
[idx
];
594 buf
->end
= decoder
->locals
[idx
+ 1];
596 return FALSE
; /* success */
600 FT_LOCAL_DEF( CF2_Fixed
)
601 cf2_getDefaultWidthX( CFF_Decoder
* decoder
)
603 FT_ASSERT( decoder
&& decoder
->current_subfont
);
605 return cf2_intToFixed(
606 decoder
->current_subfont
->private_dict
.default_width
);
610 FT_LOCAL_DEF( CF2_Fixed
)
611 cf2_getNominalWidthX( CFF_Decoder
* decoder
)
613 FT_ASSERT( decoder
&& decoder
->current_subfont
);
615 return cf2_intToFixed(
616 decoder
->current_subfont
->private_dict
.nominal_width
);
621 cf2_outline_reset( CF2_Outline outline
)
623 CFF_Decoder
* decoder
= outline
->decoder
;
626 FT_ASSERT( decoder
);
628 outline
->root
.windingMomentum
= 0;
630 FT_GlyphLoader_Rewind( decoder
->builder
.loader
);
635 cf2_outline_close( CF2_Outline outline
)
637 CFF_Decoder
* decoder
= outline
->decoder
;
640 FT_ASSERT( decoder
);
642 cff_builder_close_contour( &decoder
->builder
);
644 FT_GlyphLoader_Add( decoder
->builder
.loader
);