[FREETYPE] Update to v2.6.2. CORE-10614
[reactos.git] / reactos / lib / 3rdparty / 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_Int subrNum,
548 CF2_Buffer buf )
549 {
550 CF2_UInt idx;
551
552
553 FT_ASSERT( decoder );
554
555 FT_ZERO( buf );
556
557 idx = (CF2_UInt)( subrNum + decoder->globals_bias );
558 if ( idx >= decoder->num_globals )
559 return TRUE; /* error */
560
561 FT_ASSERT( decoder->globals );
562
563 buf->start =
564 buf->ptr = decoder->globals[idx];
565 buf->end = decoder->globals[idx + 1];
566
567 return FALSE; /* success */
568 }
569
570
571 /* convert AdobeStandardEncoding code to CF2_Buffer; */
572 /* used for seac component */
573 FT_LOCAL_DEF( FT_Error )
574 cf2_getSeacComponent( CFF_Decoder* decoder,
575 CF2_Int code,
576 CF2_Buffer buf )
577 {
578 CF2_Int gid;
579 FT_Byte* charstring;
580 FT_ULong len;
581 FT_Error error;
582
583
584 FT_ASSERT( decoder );
585
586 FT_ZERO( buf );
587
588 #ifdef FT_CONFIG_OPTION_INCREMENTAL
589 /* Incremental fonts don't necessarily have valid charsets. */
590 /* They use the character code, not the glyph index, in this case. */
591 if ( decoder->builder.face->root.internal->incremental_interface )
592 gid = code;
593 else
594 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
595 {
596 gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
597 if ( gid < 0 )
598 return FT_THROW( Invalid_Glyph_Format );
599 }
600
601 error = cff_get_glyph_data( decoder->builder.face,
602 (CF2_UInt)gid,
603 &charstring,
604 &len );
605 /* TODO: for now, just pass the FreeType error through */
606 if ( error )
607 return error;
608
609 /* assume input has been validated */
610 FT_ASSERT( charstring + len >= charstring );
611
612 buf->start = charstring;
613 buf->end = charstring + len;
614 buf->ptr = buf->start;
615
616 return FT_Err_Ok;
617 }
618
619
620 FT_LOCAL_DEF( void )
621 cf2_freeSeacComponent( CFF_Decoder* decoder,
622 CF2_Buffer buf )
623 {
624 FT_ASSERT( decoder );
625
626 cff_free_glyph_data( decoder->builder.face,
627 (FT_Byte**)&buf->start,
628 (FT_ULong)( buf->end - buf->start ) );
629 }
630
631
632 FT_LOCAL_DEF( CF2_Int )
633 cf2_initLocalRegionBuffer( CFF_Decoder* decoder,
634 CF2_Int subrNum,
635 CF2_Buffer buf )
636 {
637 CF2_UInt idx;
638
639
640 FT_ASSERT( decoder );
641
642 FT_ZERO( buf );
643
644 idx = (CF2_UInt)( subrNum + decoder->locals_bias );
645 if ( idx >= decoder->num_locals )
646 return TRUE; /* error */
647
648 FT_ASSERT( decoder->locals );
649
650 buf->start =
651 buf->ptr = decoder->locals[idx];
652 buf->end = decoder->locals[idx + 1];
653
654 return FALSE; /* success */
655 }
656
657
658 FT_LOCAL_DEF( CF2_Fixed )
659 cf2_getDefaultWidthX( CFF_Decoder* decoder )
660 {
661 FT_ASSERT( decoder && decoder->current_subfont );
662
663 return cf2_intToFixed(
664 decoder->current_subfont->private_dict.default_width );
665 }
666
667
668 FT_LOCAL_DEF( CF2_Fixed )
669 cf2_getNominalWidthX( CFF_Decoder* decoder )
670 {
671 FT_ASSERT( decoder && decoder->current_subfont );
672
673 return cf2_intToFixed(
674 decoder->current_subfont->private_dict.nominal_width );
675 }
676
677
678 FT_LOCAL_DEF( void )
679 cf2_outline_reset( CF2_Outline outline )
680 {
681 CFF_Decoder* decoder = outline->decoder;
682
683
684 FT_ASSERT( decoder );
685
686 outline->root.windingMomentum = 0;
687
688 FT_GlyphLoader_Rewind( decoder->builder.loader );
689 }
690
691
692 FT_LOCAL_DEF( void )
693 cf2_outline_close( CF2_Outline outline )
694 {
695 CFF_Decoder* decoder = outline->decoder;
696
697
698 FT_ASSERT( decoder );
699
700 cff_builder_close_contour( &decoder->builder );
701
702 FT_GlyphLoader_Add( decoder->builder.loader );
703 }
704
705
706 /* END */