20f3a2c28e9ab4c3c5524f106f27660f539db70b
[reactos.git] / sdk / lib / 3rdparty / freetype / src / cff / cffgload.c
1 /***************************************************************************/
2 /* */
3 /* cffgload.c */
4 /* */
5 /* OpenType Glyph Loader (body). */
6 /* */
7 /* Copyright 1996-2017 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
17
18
19 #include <ft2build.h>
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_STREAM_H
22 #include FT_INTERNAL_SFNT_H
23 #include FT_INTERNAL_CALC_H
24 #include FT_OUTLINE_H
25 #include FT_CFF_DRIVER_H
26
27 #include "cffobjs.h"
28 #include "cffload.h"
29 #include "cffgload.h"
30 #include "cf2ft.h" /* for cf2_decoder_parse_charstrings */
31
32 #include "cfferrs.h"
33
34
35 /*************************************************************************/
36 /* */
37 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
38 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
39 /* messages during execution. */
40 /* */
41 #undef FT_COMPONENT
42 #define FT_COMPONENT trace_cffgload
43
44
45 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
46
47 typedef enum CFF_Operator_
48 {
49 cff_op_unknown = 0,
50
51 cff_op_rmoveto,
52 cff_op_hmoveto,
53 cff_op_vmoveto,
54
55 cff_op_rlineto,
56 cff_op_hlineto,
57 cff_op_vlineto,
58
59 cff_op_rrcurveto,
60 cff_op_hhcurveto,
61 cff_op_hvcurveto,
62 cff_op_rcurveline,
63 cff_op_rlinecurve,
64 cff_op_vhcurveto,
65 cff_op_vvcurveto,
66
67 cff_op_flex,
68 cff_op_hflex,
69 cff_op_hflex1,
70 cff_op_flex1,
71
72 cff_op_endchar,
73
74 cff_op_hstem,
75 cff_op_vstem,
76 cff_op_hstemhm,
77 cff_op_vstemhm,
78
79 cff_op_hintmask,
80 cff_op_cntrmask,
81 cff_op_dotsection, /* deprecated, acts as no-op */
82
83 cff_op_abs,
84 cff_op_add,
85 cff_op_sub,
86 cff_op_div,
87 cff_op_neg,
88 cff_op_random,
89 cff_op_mul,
90 cff_op_sqrt,
91
92 cff_op_blend,
93
94 cff_op_drop,
95 cff_op_exch,
96 cff_op_index,
97 cff_op_roll,
98 cff_op_dup,
99
100 cff_op_put,
101 cff_op_get,
102 cff_op_store,
103 cff_op_load,
104
105 cff_op_and,
106 cff_op_or,
107 cff_op_not,
108 cff_op_eq,
109 cff_op_ifelse,
110
111 cff_op_callsubr,
112 cff_op_callgsubr,
113 cff_op_return,
114
115 /* Type 1 opcodes: invalid but seen in real life */
116 cff_op_hsbw,
117 cff_op_closepath,
118 cff_op_callothersubr,
119 cff_op_pop,
120 cff_op_seac,
121 cff_op_sbw,
122 cff_op_setcurrentpoint,
123
124 /* do not remove */
125 cff_op_max
126
127 } CFF_Operator;
128
129
130 #define CFF_COUNT_CHECK_WIDTH 0x80
131 #define CFF_COUNT_EXACT 0x40
132 #define CFF_COUNT_CLEAR_STACK 0x20
133
134 /* count values which have the `CFF_COUNT_CHECK_WIDTH' flag set are */
135 /* used for checking the width and requested numbers of arguments */
136 /* only; they are set to zero afterwards */
137
138 /* the other two flags are informative only and unused currently */
139
140 static const FT_Byte cff_argument_counts[] =
141 {
142 0, /* unknown */
143
144 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */
145 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
146 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT,
147
148 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */
149 0 | CFF_COUNT_CLEAR_STACK,
150 0 | CFF_COUNT_CLEAR_STACK,
151
152 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */
153 0 | CFF_COUNT_CLEAR_STACK,
154 0 | CFF_COUNT_CLEAR_STACK,
155 0 | CFF_COUNT_CLEAR_STACK,
156 0 | CFF_COUNT_CLEAR_STACK,
157 0 | CFF_COUNT_CLEAR_STACK,
158 0 | CFF_COUNT_CLEAR_STACK,
159
160 13, /* flex */
161 7,
162 9,
163 11,
164
165 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */
166
167 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */
168 2 | CFF_COUNT_CHECK_WIDTH,
169 2 | CFF_COUNT_CHECK_WIDTH,
170 2 | CFF_COUNT_CHECK_WIDTH,
171
172 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */
173 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */
174 0, /* dotsection */
175
176 1, /* abs */
177 2,
178 2,
179 2,
180 1,
181 0,
182 2,
183 1,
184
185 1, /* blend */
186
187 1, /* drop */
188 2,
189 1,
190 2,
191 1,
192
193 2, /* put */
194 1,
195 4,
196 3,
197
198 2, /* and */
199 2,
200 1,
201 2,
202 4,
203
204 1, /* callsubr */
205 1,
206 0,
207
208 2, /* hsbw */
209 0,
210 0,
211 0,
212 5, /* seac */
213 4, /* sbw */
214 2 /* setcurrentpoint */
215 };
216
217 #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
218
219
220 /*************************************************************************/
221 /*************************************************************************/
222 /*************************************************************************/
223 /********** *********/
224 /********** *********/
225 /********** GENERIC CHARSTRING PARSING *********/
226 /********** *********/
227 /********** *********/
228 /*************************************************************************/
229 /*************************************************************************/
230 /*************************************************************************/
231
232
233 /*************************************************************************/
234 /* */
235 /* <Function> */
236 /* cff_builder_init */
237 /* */
238 /* <Description> */
239 /* Initializes a given glyph builder. */
240 /* */
241 /* <InOut> */
242 /* builder :: A pointer to the glyph builder to initialize. */
243 /* */
244 /* <Input> */
245 /* face :: The current face object. */
246 /* */
247 /* size :: The current size object. */
248 /* */
249 /* glyph :: The current glyph object. */
250 /* */
251 /* hinting :: Whether hinting is active. */
252 /* */
253 static void
254 cff_builder_init( CFF_Builder* builder,
255 TT_Face face,
256 CFF_Size size,
257 CFF_GlyphSlot glyph,
258 FT_Bool hinting )
259 {
260 builder->path_begun = 0;
261 builder->load_points = 1;
262
263 builder->face = face;
264 builder->glyph = glyph;
265 builder->memory = face->root.memory;
266
267 if ( glyph )
268 {
269 FT_GlyphLoader loader = glyph->root.internal->loader;
270
271
272 builder->loader = loader;
273 builder->base = &loader->base.outline;
274 builder->current = &loader->current.outline;
275 FT_GlyphLoader_Rewind( loader );
276
277 builder->hints_globals = NULL;
278 builder->hints_funcs = NULL;
279
280 if ( hinting && size )
281 {
282 FT_Size ftsize = FT_SIZE( size );
283 CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
284
285
286 if ( internal )
287 {
288 builder->hints_globals = (void *)internal->topfont;
289 builder->hints_funcs = glyph->root.internal->glyph_hints;
290 }
291 }
292 }
293
294 builder->pos_x = 0;
295 builder->pos_y = 0;
296
297 builder->left_bearing.x = 0;
298 builder->left_bearing.y = 0;
299 builder->advance.x = 0;
300 builder->advance.y = 0;
301 }
302
303
304 /*************************************************************************/
305 /* */
306 /* <Function> */
307 /* cff_builder_done */
308 /* */
309 /* <Description> */
310 /* Finalizes a given glyph builder. Its contents can still be used */
311 /* after the call, but the function saves important information */
312 /* within the corresponding glyph slot. */
313 /* */
314 /* <Input> */
315 /* builder :: A pointer to the glyph builder to finalize. */
316 /* */
317 static void
318 cff_builder_done( CFF_Builder* builder )
319 {
320 CFF_GlyphSlot glyph = builder->glyph;
321
322
323 if ( glyph )
324 glyph->root.outline = *builder->base;
325 }
326
327
328 /*************************************************************************/
329 /* */
330 /* <Function> */
331 /* cff_compute_bias */
332 /* */
333 /* <Description> */
334 /* Computes the bias value in dependence of the number of glyph */
335 /* subroutines. */
336 /* */
337 /* <Input> */
338 /* in_charstring_type :: The `CharstringType' value of the top DICT */
339 /* dictionary. */
340 /* */
341 /* num_subrs :: The number of glyph subroutines. */
342 /* */
343 /* <Return> */
344 /* The bias value. */
345 static FT_Int
346 cff_compute_bias( FT_Int in_charstring_type,
347 FT_UInt num_subrs )
348 {
349 FT_Int result;
350
351
352 if ( in_charstring_type == 1 )
353 result = 0;
354 else if ( num_subrs < 1240 )
355 result = 107;
356 else if ( num_subrs < 33900U )
357 result = 1131;
358 else
359 result = 32768U;
360
361 return result;
362 }
363
364
365 /*************************************************************************/
366 /* */
367 /* <Function> */
368 /* cff_decoder_init */
369 /* */
370 /* <Description> */
371 /* Initializes a given glyph decoder. */
372 /* */
373 /* <InOut> */
374 /* decoder :: A pointer to the glyph builder to initialize. */
375 /* */
376 /* <Input> */
377 /* face :: The current face object. */
378 /* */
379 /* size :: The current size object. */
380 /* */
381 /* slot :: The current glyph object. */
382 /* */
383 /* hinting :: Whether hinting is active. */
384 /* */
385 /* hint_mode :: The hinting mode. */
386 /* */
387 FT_LOCAL_DEF( void )
388 cff_decoder_init( CFF_Decoder* decoder,
389 TT_Face face,
390 CFF_Size size,
391 CFF_GlyphSlot slot,
392 FT_Bool hinting,
393 FT_Render_Mode hint_mode )
394 {
395 CFF_Font cff = (CFF_Font)face->extra.data;
396
397
398 /* clear everything */
399 FT_ZERO( decoder );
400
401 /* initialize builder */
402 cff_builder_init( &decoder->builder, face, size, slot, hinting );
403
404 /* initialize Type2 decoder */
405 decoder->cff = cff;
406 decoder->num_globals = cff->global_subrs_index.count;
407 decoder->globals = cff->global_subrs;
408 decoder->globals_bias = cff_compute_bias(
409 cff->top_font.font_dict.charstring_type,
410 decoder->num_globals );
411
412 decoder->hint_mode = hint_mode;
413 }
414
415
416 /* this function is used to select the subfont */
417 /* and the locals subrs array */
418 FT_LOCAL_DEF( FT_Error )
419 cff_decoder_prepare( CFF_Decoder* decoder,
420 CFF_Size size,
421 FT_UInt glyph_index )
422 {
423 CFF_Builder *builder = &decoder->builder;
424 CFF_Font cff = (CFF_Font)builder->face->extra.data;
425 CFF_SubFont sub = &cff->top_font;
426 FT_Error error = FT_Err_Ok;
427
428
429 /* manage CID fonts */
430 if ( cff->num_subfonts )
431 {
432 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index );
433
434
435 if ( fd_index >= cff->num_subfonts )
436 {
437 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
438 error = FT_THROW( Invalid_File_Format );
439 goto Exit;
440 }
441
442 FT_TRACE3(( " in subfont %d:\n", fd_index ));
443
444 sub = cff->subfonts[fd_index];
445
446 if ( builder->hints_funcs && size )
447 {
448 FT_Size ftsize = FT_SIZE( size );
449 CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data;
450
451
452 /* for CFFs without subfonts, this value has already been set */
453 builder->hints_globals = (void *)internal->subfonts[fd_index];
454 }
455 }
456
457 decoder->num_locals = sub->local_subrs_index.count;
458 decoder->locals = sub->local_subrs;
459 decoder->locals_bias = cff_compute_bias(
460 decoder->cff->top_font.font_dict.charstring_type,
461 decoder->num_locals );
462
463 decoder->glyph_width = sub->private_dict.default_width;
464 decoder->nominal_width = sub->private_dict.nominal_width;
465
466 decoder->current_subfont = sub;
467
468 Exit:
469 return error;
470 }
471
472
473 /* check that there is enough space for `count' more points */
474 FT_LOCAL_DEF( FT_Error )
475 cff_check_points( CFF_Builder* builder,
476 FT_Int count )
477 {
478 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
479 }
480
481
482 /* add a new point, do not check space */
483 FT_LOCAL_DEF( void )
484 cff_builder_add_point( CFF_Builder* builder,
485 FT_Pos x,
486 FT_Pos y,
487 FT_Byte flag )
488 {
489 FT_Outline* outline = builder->current;
490
491
492 if ( builder->load_points )
493 {
494 FT_Vector* point = outline->points + outline->n_points;
495 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
496
497 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
498 CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( builder->face );
499
500
501 if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
502 {
503 point->x = x >> 16;
504 point->y = y >> 16;
505 }
506 else
507 #endif
508 {
509 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
510 point->x = x >> 10;
511 point->y = y >> 10;
512 }
513 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
514 }
515
516 outline->n_points++;
517 }
518
519
520 /* check space for a new on-curve point, then add it */
521 FT_LOCAL_DEF( FT_Error )
522 cff_builder_add_point1( CFF_Builder* builder,
523 FT_Pos x,
524 FT_Pos y )
525 {
526 FT_Error error;
527
528
529 error = cff_check_points( builder, 1 );
530 if ( !error )
531 cff_builder_add_point( builder, x, y, 1 );
532
533 return error;
534 }
535
536
537 /* check space for a new contour, then add it */
538 static FT_Error
539 cff_builder_add_contour( CFF_Builder* builder )
540 {
541 FT_Outline* outline = builder->current;
542 FT_Error error;
543
544
545 if ( !builder->load_points )
546 {
547 outline->n_contours++;
548 return FT_Err_Ok;
549 }
550
551 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
552 if ( !error )
553 {
554 if ( outline->n_contours > 0 )
555 outline->contours[outline->n_contours - 1] =
556 (short)( outline->n_points - 1 );
557
558 outline->n_contours++;
559 }
560
561 return error;
562 }
563
564
565 /* if a path was begun, add its first on-curve point */
566 FT_LOCAL_DEF( FT_Error )
567 cff_builder_start_point( CFF_Builder* builder,
568 FT_Pos x,
569 FT_Pos y )
570 {
571 FT_Error error = FT_Err_Ok;
572
573
574 /* test whether we are building a new contour */
575 if ( !builder->path_begun )
576 {
577 builder->path_begun = 1;
578 error = cff_builder_add_contour( builder );
579 if ( !error )
580 error = cff_builder_add_point1( builder, x, y );
581 }
582
583 return error;
584 }
585
586
587 /* close the current contour */
588 FT_LOCAL_DEF( void )
589 cff_builder_close_contour( CFF_Builder* builder )
590 {
591 FT_Outline* outline = builder->current;
592 FT_Int first;
593
594
595 if ( !outline )
596 return;
597
598 first = outline->n_contours <= 1
599 ? 0 : outline->contours[outline->n_contours - 2] + 1;
600
601 /* We must not include the last point in the path if it */
602 /* is located on the first point. */
603 if ( outline->n_points > 1 )
604 {
605 FT_Vector* p1 = outline->points + first;
606 FT_Vector* p2 = outline->points + outline->n_points - 1;
607 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1;
608
609
610 /* `delete' last point only if it coincides with the first */
611 /* point and if it is not a control point (which can happen). */
612 if ( p1->x == p2->x && p1->y == p2->y )
613 if ( *control == FT_CURVE_TAG_ON )
614 outline->n_points--;
615 }
616
617 if ( outline->n_contours > 0 )
618 {
619 /* Don't add contours only consisting of one point, i.e., */
620 /* check whether begin point and last point are the same. */
621 if ( first == outline->n_points - 1 )
622 {
623 outline->n_contours--;
624 outline->n_points--;
625 }
626 else
627 outline->contours[outline->n_contours - 1] =
628 (short)( outline->n_points - 1 );
629 }
630 }
631
632
633 FT_LOCAL_DEF( FT_Int )
634 cff_lookup_glyph_by_stdcharcode( CFF_Font cff,
635 FT_Int charcode )
636 {
637 FT_UInt n;
638 FT_UShort glyph_sid;
639
640
641 /* CID-keyed fonts don't have glyph names */
642 if ( !cff->charset.sids )
643 return -1;
644
645 /* check range of standard char code */
646 if ( charcode < 0 || charcode > 255 )
647 return -1;
648
649 /* Get code to SID mapping from `cff_standard_encoding'. */
650 glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode );
651
652 for ( n = 0; n < cff->num_glyphs; n++ )
653 {
654 if ( cff->charset.sids[n] == glyph_sid )
655 return (FT_Int)n;
656 }
657
658 return -1;
659 }
660
661
662 FT_LOCAL_DEF( FT_Error )
663 cff_get_glyph_data( TT_Face face,
664 FT_UInt glyph_index,
665 FT_Byte** pointer,
666 FT_ULong* length )
667 {
668 #ifdef FT_CONFIG_OPTION_INCREMENTAL
669 /* For incremental fonts get the character data using the */
670 /* callback function. */
671 if ( face->root.internal->incremental_interface )
672 {
673 FT_Data data;
674 FT_Error error =
675 face->root.internal->incremental_interface->funcs->get_glyph_data(
676 face->root.internal->incremental_interface->object,
677 glyph_index, &data );
678
679
680 *pointer = (FT_Byte*)data.pointer;
681 *length = (FT_ULong)data.length;
682
683 return error;
684 }
685 else
686 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
687
688 {
689 CFF_Font cff = (CFF_Font)(face->extra.data);
690
691
692 return cff_index_access_element( &cff->charstrings_index, glyph_index,
693 pointer, length );
694 }
695 }
696
697
698 FT_LOCAL_DEF( void )
699 cff_free_glyph_data( TT_Face face,
700 FT_Byte** pointer,
701 FT_ULong length )
702 {
703 #ifndef FT_CONFIG_OPTION_INCREMENTAL
704 FT_UNUSED( length );
705 #endif
706
707 #ifdef FT_CONFIG_OPTION_INCREMENTAL
708 /* For incremental fonts get the character data using the */
709 /* callback function. */
710 if ( face->root.internal->incremental_interface )
711 {
712 FT_Data data;
713
714
715 data.pointer = *pointer;
716 data.length = (FT_Int)length;
717
718 face->root.internal->incremental_interface->funcs->free_glyph_data(
719 face->root.internal->incremental_interface->object, &data );
720 }
721 else
722 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
723
724 {
725 CFF_Font cff = (CFF_Font)(face->extra.data);
726
727
728 cff_index_forget_element( &cff->charstrings_index, pointer );
729 }
730 }
731
732
733 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
734
735 static FT_Error
736 cff_operator_seac( CFF_Decoder* decoder,
737 FT_Pos asb,
738 FT_Pos adx,
739 FT_Pos ady,
740 FT_Int bchar,
741 FT_Int achar )
742 {
743 FT_Error error;
744 CFF_Builder* builder = &decoder->builder;
745 FT_Int bchar_index, achar_index;
746 TT_Face face = decoder->builder.face;
747 FT_Vector left_bearing, advance;
748 FT_Byte* charstring;
749 FT_ULong charstring_len;
750 FT_Pos glyph_width;
751
752
753 if ( decoder->seac )
754 {
755 FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
756 return FT_THROW( Syntax_Error );
757 }
758
759 adx += decoder->builder.left_bearing.x;
760 ady += decoder->builder.left_bearing.y;
761
762 #ifdef FT_CONFIG_OPTION_INCREMENTAL
763 /* Incremental fonts don't necessarily have valid charsets. */
764 /* They use the character code, not the glyph index, in this case. */
765 if ( face->root.internal->incremental_interface )
766 {
767 bchar_index = bchar;
768 achar_index = achar;
769 }
770 else
771 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
772 {
773 CFF_Font cff = (CFF_Font)(face->extra.data);
774
775
776 bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar );
777 achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar );
778 }
779
780 if ( bchar_index < 0 || achar_index < 0 )
781 {
782 FT_ERROR(( "cff_operator_seac:"
783 " invalid seac character code arguments\n" ));
784 return FT_THROW( Syntax_Error );
785 }
786
787 /* If we are trying to load a composite glyph, do not load the */
788 /* accent character and return the array of subglyphs. */
789 if ( builder->no_recurse )
790 {
791 FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph;
792 FT_GlyphLoader loader = glyph->internal->loader;
793 FT_SubGlyph subg;
794
795
796 /* reallocate subglyph array if necessary */
797 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 );
798 if ( error )
799 goto Exit;
800
801 subg = loader->current.subglyphs;
802
803 /* subglyph 0 = base character */
804 subg->index = bchar_index;
805 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
806 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
807 subg->arg1 = 0;
808 subg->arg2 = 0;
809 subg++;
810
811 /* subglyph 1 = accent character */
812 subg->index = achar_index;
813 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
814 subg->arg1 = (FT_Int)( adx >> 16 );
815 subg->arg2 = (FT_Int)( ady >> 16 );
816
817 /* set up remaining glyph fields */
818 glyph->num_subglyphs = 2;
819 glyph->subglyphs = loader->base.subglyphs;
820 glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
821
822 loader->current.num_subglyphs = 2;
823 }
824
825 FT_GlyphLoader_Prepare( builder->loader );
826
827 /* First load `bchar' in builder */
828 error = cff_get_glyph_data( face, (FT_UInt)bchar_index,
829 &charstring, &charstring_len );
830 if ( !error )
831 {
832 /* the seac operator must not be nested */
833 decoder->seac = TRUE;
834 error = cff_decoder_parse_charstrings( decoder, charstring,
835 charstring_len, 0 );
836 decoder->seac = FALSE;
837
838 cff_free_glyph_data( face, &charstring, charstring_len );
839
840 if ( error )
841 goto Exit;
842 }
843
844 /* Save the left bearing, advance and glyph width of the base */
845 /* character as they will be erased by the next load. */
846
847 left_bearing = builder->left_bearing;
848 advance = builder->advance;
849 glyph_width = decoder->glyph_width;
850
851 builder->left_bearing.x = 0;
852 builder->left_bearing.y = 0;
853
854 builder->pos_x = adx - asb;
855 builder->pos_y = ady;
856
857 /* Now load `achar' on top of the base outline. */
858 error = cff_get_glyph_data( face, (FT_UInt)achar_index,
859 &charstring, &charstring_len );
860 if ( !error )
861 {
862 /* the seac operator must not be nested */
863 decoder->seac = TRUE;
864 error = cff_decoder_parse_charstrings( decoder, charstring,
865 charstring_len, 0 );
866 decoder->seac = FALSE;
867
868 cff_free_glyph_data( face, &charstring, charstring_len );
869
870 if ( error )
871 goto Exit;
872 }
873
874 /* Restore the left side bearing, advance and glyph width */
875 /* of the base character. */
876 builder->left_bearing = left_bearing;
877 builder->advance = advance;
878 decoder->glyph_width = glyph_width;
879
880 builder->pos_x = 0;
881 builder->pos_y = 0;
882
883 Exit:
884 return error;
885 }
886
887
888 /*************************************************************************/
889 /* */
890 /* <Function> */
891 /* cff_decoder_parse_charstrings */
892 /* */
893 /* <Description> */
894 /* Parses a given Type 2 charstrings program. */
895 /* */
896 /* <InOut> */
897 /* decoder :: The current Type 1 decoder. */
898 /* */
899 /* <Input> */
900 /* charstring_base :: The base of the charstring stream. */
901 /* */
902 /* charstring_len :: The length in bytes of the charstring stream. */
903 /* */
904 /* in_dict :: Set to 1 if function is called from top or */
905 /* private DICT (needed for Multiple Master CFFs). */
906 /* */
907 /* <Return> */
908 /* FreeType error code. 0 means success. */
909 /* */
910 FT_LOCAL_DEF( FT_Error )
911 cff_decoder_parse_charstrings( CFF_Decoder* decoder,
912 FT_Byte* charstring_base,
913 FT_ULong charstring_len,
914 FT_Bool in_dict )
915 {
916 FT_Error error;
917 CFF_Decoder_Zone* zone;
918 FT_Byte* ip;
919 FT_Byte* limit;
920 CFF_Builder* builder = &decoder->builder;
921 FT_Pos x, y;
922 FT_Fixed* stack;
923 FT_Int charstring_type =
924 decoder->cff->top_font.font_dict.charstring_type;
925 FT_UShort num_designs =
926 decoder->cff->top_font.font_dict.num_designs;
927 FT_UShort num_axes =
928 decoder->cff->top_font.font_dict.num_axes;
929
930 T2_Hints_Funcs hinter;
931
932
933 /* set default width */
934 decoder->num_hints = 0;
935 decoder->read_width = 1;
936
937 /* initialize the decoder */
938 decoder->top = decoder->stack;
939 decoder->zone = decoder->zones;
940 zone = decoder->zones;
941 stack = decoder->top;
942
943 hinter = (T2_Hints_Funcs)builder->hints_funcs;
944
945 builder->path_begun = 0;
946
947 zone->base = charstring_base;
948 limit = zone->limit = charstring_base + charstring_len;
949 ip = zone->cursor = zone->base;
950
951 error = FT_Err_Ok;
952
953 x = builder->pos_x;
954 y = builder->pos_y;
955
956 /* begin hints recording session, if any */
957 if ( hinter )
958 hinter->open( hinter->hints );
959
960 /* now execute loop */
961 while ( ip < limit )
962 {
963 CFF_Operator op;
964 FT_Byte v;
965
966
967 /********************************************************************/
968 /* */
969 /* Decode operator or operand */
970 /* */
971 v = *ip++;
972 if ( v >= 32 || v == 28 )
973 {
974 FT_Int shift = 16;
975 FT_Int32 val;
976
977
978 /* this is an operand, push it on the stack */
979
980 /* if we use shifts, all computations are done with unsigned */
981 /* values; the conversion to a signed value is the last step */
982 if ( v == 28 )
983 {
984 if ( ip + 1 >= limit )
985 goto Syntax_Error;
986 val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] );
987 ip += 2;
988 }
989 else if ( v < 247 )
990 val = (FT_Int32)v - 139;
991 else if ( v < 251 )
992 {
993 if ( ip >= limit )
994 goto Syntax_Error;
995 val = ( (FT_Int32)v - 247 ) * 256 + *ip++ + 108;
996 }
997 else if ( v < 255 )
998 {
999 if ( ip >= limit )
1000 goto Syntax_Error;
1001 val = -( (FT_Int32)v - 251 ) * 256 - *ip++ - 108;
1002 }
1003 else
1004 {
1005 if ( ip + 3 >= limit )
1006 goto Syntax_Error;
1007 val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
1008 ( (FT_UInt32)ip[1] << 16 ) |
1009 ( (FT_UInt32)ip[2] << 8 ) |
1010 (FT_UInt32)ip[3] );
1011 ip += 4;
1012 if ( charstring_type == 2 )
1013 shift = 0;
1014 }
1015 if ( decoder->top - stack >= CFF_MAX_OPERANDS )
1016 goto Stack_Overflow;
1017
1018 val = (FT_Int32)( (FT_UInt32)val << shift );
1019 *decoder->top++ = val;
1020
1021 #ifdef FT_DEBUG_LEVEL_TRACE
1022 if ( !( val & 0xFFFFL ) )
1023 FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
1024 else
1025 FT_TRACE4(( " %.5f", val / 65536.0 ));
1026 #endif
1027
1028 }
1029 else
1030 {
1031 /* The specification says that normally arguments are to be taken */
1032 /* from the bottom of the stack. However, this seems not to be */
1033 /* correct, at least for Acroread 7.0.8 on GNU/Linux: It pops the */
1034 /* arguments similar to a PS interpreter. */
1035
1036 FT_Fixed* args = decoder->top;
1037 FT_Int num_args = (FT_Int)( args - decoder->stack );
1038 FT_Int req_args;
1039
1040
1041 /* find operator */
1042 op = cff_op_unknown;
1043
1044 switch ( v )
1045 {
1046 case 1:
1047 op = cff_op_hstem;
1048 break;
1049 case 3:
1050 op = cff_op_vstem;
1051 break;
1052 case 4:
1053 op = cff_op_vmoveto;
1054 break;
1055 case 5:
1056 op = cff_op_rlineto;
1057 break;
1058 case 6:
1059 op = cff_op_hlineto;
1060 break;
1061 case 7:
1062 op = cff_op_vlineto;
1063 break;
1064 case 8:
1065 op = cff_op_rrcurveto;
1066 break;
1067 case 9:
1068 op = cff_op_closepath;
1069 break;
1070 case 10:
1071 op = cff_op_callsubr;
1072 break;
1073 case 11:
1074 op = cff_op_return;
1075 break;
1076 case 12:
1077 {
1078 if ( ip >= limit )
1079 goto Syntax_Error;
1080 v = *ip++;
1081
1082 switch ( v )
1083 {
1084 case 0:
1085 op = cff_op_dotsection;
1086 break;
1087 case 1: /* this is actually the Type1 vstem3 operator */
1088 op = cff_op_vstem;
1089 break;
1090 case 2: /* this is actually the Type1 hstem3 operator */
1091 op = cff_op_hstem;
1092 break;
1093 case 3:
1094 op = cff_op_and;
1095 break;
1096 case 4:
1097 op = cff_op_or;
1098 break;
1099 case 5:
1100 op = cff_op_not;
1101 break;
1102 case 6:
1103 op = cff_op_seac;
1104 break;
1105 case 7:
1106 op = cff_op_sbw;
1107 break;
1108 case 8:
1109 op = cff_op_store;
1110 break;
1111 case 9:
1112 op = cff_op_abs;
1113 break;
1114 case 10:
1115 op = cff_op_add;
1116 break;
1117 case 11:
1118 op = cff_op_sub;
1119 break;
1120 case 12:
1121 op = cff_op_div;
1122 break;
1123 case 13:
1124 op = cff_op_load;
1125 break;
1126 case 14:
1127 op = cff_op_neg;
1128 break;
1129 case 15:
1130 op = cff_op_eq;
1131 break;
1132 case 16:
1133 op = cff_op_callothersubr;
1134 break;
1135 case 17:
1136 op = cff_op_pop;
1137 break;
1138 case 18:
1139 op = cff_op_drop;
1140 break;
1141 case 20:
1142 op = cff_op_put;
1143 break;
1144 case 21:
1145 op = cff_op_get;
1146 break;
1147 case 22:
1148 op = cff_op_ifelse;
1149 break;
1150 case 23:
1151 op = cff_op_random;
1152 break;
1153 case 24:
1154 op = cff_op_mul;
1155 break;
1156 case 26:
1157 op = cff_op_sqrt;
1158 break;
1159 case 27:
1160 op = cff_op_dup;
1161 break;
1162 case 28:
1163 op = cff_op_exch;
1164 break;
1165 case 29:
1166 op = cff_op_index;
1167 break;
1168 case 30:
1169 op = cff_op_roll;
1170 break;
1171 case 33:
1172 op = cff_op_setcurrentpoint;
1173 break;
1174 case 34:
1175 op = cff_op_hflex;
1176 break;
1177 case 35:
1178 op = cff_op_flex;
1179 break;
1180 case 36:
1181 op = cff_op_hflex1;
1182 break;
1183 case 37:
1184 op = cff_op_flex1;
1185 break;
1186 default:
1187 FT_TRACE4(( " unknown op (12, %d)\n", v ));
1188 break;
1189 }
1190 }
1191 break;
1192 case 13:
1193 op = cff_op_hsbw;
1194 break;
1195 case 14:
1196 op = cff_op_endchar;
1197 break;
1198 case 16:
1199 op = cff_op_blend;
1200 break;
1201 case 18:
1202 op = cff_op_hstemhm;
1203 break;
1204 case 19:
1205 op = cff_op_hintmask;
1206 break;
1207 case 20:
1208 op = cff_op_cntrmask;
1209 break;
1210 case 21:
1211 op = cff_op_rmoveto;
1212 break;
1213 case 22:
1214 op = cff_op_hmoveto;
1215 break;
1216 case 23:
1217 op = cff_op_vstemhm;
1218 break;
1219 case 24:
1220 op = cff_op_rcurveline;
1221 break;
1222 case 25:
1223 op = cff_op_rlinecurve;
1224 break;
1225 case 26:
1226 op = cff_op_vvcurveto;
1227 break;
1228 case 27:
1229 op = cff_op_hhcurveto;
1230 break;
1231 case 29:
1232 op = cff_op_callgsubr;
1233 break;
1234 case 30:
1235 op = cff_op_vhcurveto;
1236 break;
1237 case 31:
1238 op = cff_op_hvcurveto;
1239 break;
1240 default:
1241 FT_TRACE4(( " unknown op (%d)\n", v ));
1242 break;
1243 }
1244
1245 if ( op == cff_op_unknown )
1246 continue;
1247
1248 /* in Multiple Master CFFs, T2 charstrings can appear in */
1249 /* dictionaries, but some operators are prohibited */
1250 if ( in_dict )
1251 {
1252 switch ( op )
1253 {
1254 case cff_op_hstem:
1255 case cff_op_vstem:
1256 case cff_op_vmoveto:
1257 case cff_op_rlineto:
1258 case cff_op_hlineto:
1259 case cff_op_vlineto:
1260 case cff_op_rrcurveto:
1261 case cff_op_hstemhm:
1262 case cff_op_hintmask:
1263 case cff_op_cntrmask:
1264 case cff_op_rmoveto:
1265 case cff_op_hmoveto:
1266 case cff_op_vstemhm:
1267 case cff_op_rcurveline:
1268 case cff_op_rlinecurve:
1269 case cff_op_vvcurveto:
1270 case cff_op_hhcurveto:
1271 case cff_op_vhcurveto:
1272 case cff_op_hvcurveto:
1273 case cff_op_hflex:
1274 case cff_op_flex:
1275 case cff_op_hflex1:
1276 case cff_op_flex1:
1277 case cff_op_callsubr:
1278 case cff_op_callgsubr:
1279 goto MM_Error;
1280
1281 default:
1282 break;
1283 }
1284 }
1285
1286 /* check arguments */
1287 req_args = cff_argument_counts[op];
1288 if ( req_args & CFF_COUNT_CHECK_WIDTH )
1289 {
1290 if ( num_args > 0 && decoder->read_width )
1291 {
1292 /* If `nominal_width' is non-zero, the number is really a */
1293 /* difference against `nominal_width'. Else, the number here */
1294 /* is truly a width, not a difference against `nominal_width'. */
1295 /* If the font does not set `nominal_width', then */
1296 /* `nominal_width' defaults to zero, and so we can set */
1297 /* `glyph_width' to `nominal_width' plus number on the stack */
1298 /* -- for either case. */
1299
1300 FT_Int set_width_ok;
1301
1302
1303 switch ( op )
1304 {
1305 case cff_op_hmoveto:
1306 case cff_op_vmoveto:
1307 set_width_ok = num_args & 2;
1308 break;
1309
1310 case cff_op_hstem:
1311 case cff_op_vstem:
1312 case cff_op_hstemhm:
1313 case cff_op_vstemhm:
1314 case cff_op_rmoveto:
1315 case cff_op_hintmask:
1316 case cff_op_cntrmask:
1317 set_width_ok = num_args & 1;
1318 break;
1319
1320 case cff_op_endchar:
1321 /* If there is a width specified for endchar, we either have */
1322 /* 1 argument or 5 arguments. We like to argue. */
1323 set_width_ok = in_dict
1324 ? 0
1325 : ( ( num_args == 5 ) || ( num_args == 1 ) );
1326 break;
1327
1328 default:
1329 set_width_ok = 0;
1330 break;
1331 }
1332
1333 if ( set_width_ok )
1334 {
1335 decoder->glyph_width = decoder->nominal_width +
1336 ( stack[0] >> 16 );
1337
1338 if ( decoder->width_only )
1339 {
1340 /* we only want the advance width; stop here */
1341 break;
1342 }
1343
1344 /* Consumed an argument. */
1345 num_args--;
1346 }
1347 }
1348
1349 decoder->read_width = 0;
1350 req_args = 0;
1351 }
1352
1353 req_args &= 0x000F;
1354 if ( num_args < req_args )
1355 goto Stack_Underflow;
1356 args -= req_args;
1357 num_args -= req_args;
1358
1359 /* At this point, `args' points to the first argument of the */
1360 /* operand in case `req_args' isn't zero. Otherwise, we have */
1361 /* to adjust `args' manually. */
1362
1363 /* Note that we only pop arguments from the stack which we */
1364 /* really need and can digest so that we can continue in case */
1365 /* of superfluous stack elements. */
1366
1367 switch ( op )
1368 {
1369 case cff_op_hstem:
1370 case cff_op_vstem:
1371 case cff_op_hstemhm:
1372 case cff_op_vstemhm:
1373 /* the number of arguments is always even here */
1374 FT_TRACE4((
1375 op == cff_op_hstem ? " hstem\n" :
1376 ( op == cff_op_vstem ? " vstem\n" :
1377 ( op == cff_op_hstemhm ? " hstemhm\n" : " vstemhm\n" ) ) ));
1378
1379 if ( hinter )
1380 hinter->stems( hinter->hints,
1381 ( op == cff_op_hstem || op == cff_op_hstemhm ),
1382 num_args / 2,
1383 args - ( num_args & ~1 ) );
1384
1385 decoder->num_hints += num_args / 2;
1386 args = stack;
1387 break;
1388
1389 case cff_op_hintmask:
1390 case cff_op_cntrmask:
1391 FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
1392
1393 /* implement vstem when needed -- */
1394 /* the specification doesn't say it, but this also works */
1395 /* with the 'cntrmask' operator */
1396 /* */
1397 if ( num_args > 0 )
1398 {
1399 if ( hinter )
1400 hinter->stems( hinter->hints,
1401 0,
1402 num_args / 2,
1403 args - ( num_args & ~1 ) );
1404
1405 decoder->num_hints += num_args / 2;
1406 }
1407
1408 /* In a valid charstring there must be at least one byte */
1409 /* after `hintmask' or `cntrmask' (e.g., for a `return' */
1410 /* instruction). Additionally, there must be space for */
1411 /* `num_hints' bits. */
1412
1413 if ( ( ip + ( ( decoder->num_hints + 7 ) >> 3 ) ) >= limit )
1414 goto Syntax_Error;
1415
1416 if ( hinter )
1417 {
1418 if ( op == cff_op_hintmask )
1419 hinter->hintmask( hinter->hints,
1420 (FT_UInt)builder->current->n_points,
1421 (FT_UInt)decoder->num_hints,
1422 ip );
1423 else
1424 hinter->counter( hinter->hints,
1425 (FT_UInt)decoder->num_hints,
1426 ip );
1427 }
1428
1429 #ifdef FT_DEBUG_LEVEL_TRACE
1430 {
1431 FT_UInt maskbyte;
1432
1433
1434 FT_TRACE4(( " (maskbytes:" ));
1435
1436 for ( maskbyte = 0;
1437 maskbyte < (FT_UInt)( ( decoder->num_hints + 7 ) >> 3 );
1438 maskbyte++, ip++ )
1439 FT_TRACE4(( " 0x%02X", *ip ));
1440
1441 FT_TRACE4(( ")\n" ));
1442 }
1443 #else
1444 ip += ( decoder->num_hints + 7 ) >> 3;
1445 #endif
1446 args = stack;
1447 break;
1448
1449 case cff_op_rmoveto:
1450 FT_TRACE4(( " rmoveto\n" ));
1451
1452 cff_builder_close_contour( builder );
1453 builder->path_begun = 0;
1454 x = ADD_LONG( x, args[-2] );
1455 y = ADD_LONG( y, args[-1] );
1456 args = stack;
1457 break;
1458
1459 case cff_op_vmoveto:
1460 FT_TRACE4(( " vmoveto\n" ));
1461
1462 cff_builder_close_contour( builder );
1463 builder->path_begun = 0;
1464 y = ADD_LONG( y, args[-1] );
1465 args = stack;
1466 break;
1467
1468 case cff_op_hmoveto:
1469 FT_TRACE4(( " hmoveto\n" ));
1470
1471 cff_builder_close_contour( builder );
1472 builder->path_begun = 0;
1473 x = ADD_LONG( x, args[-1] );
1474 args = stack;
1475 break;
1476
1477 case cff_op_rlineto:
1478 FT_TRACE4(( " rlineto\n" ));
1479
1480 if ( cff_builder_start_point( builder, x, y ) ||
1481 cff_check_points( builder, num_args / 2 ) )
1482 goto Fail;
1483
1484 if ( num_args < 2 )
1485 goto Stack_Underflow;
1486
1487 args -= num_args & ~1;
1488 while ( args < decoder->top )
1489 {
1490 x = ADD_LONG( x, args[0] );
1491 y = ADD_LONG( y, args[1] );
1492 cff_builder_add_point( builder, x, y, 1 );
1493 args += 2;
1494 }
1495 args = stack;
1496 break;
1497
1498 case cff_op_hlineto:
1499 case cff_op_vlineto:
1500 {
1501 FT_Int phase = ( op == cff_op_hlineto );
1502
1503
1504 FT_TRACE4(( op == cff_op_hlineto ? " hlineto\n"
1505 : " vlineto\n" ));
1506
1507 if ( num_args < 0 )
1508 goto Stack_Underflow;
1509
1510 /* there exist subsetted fonts (found in PDFs) */
1511 /* which call `hlineto' without arguments */
1512 if ( num_args == 0 )
1513 break;
1514
1515 if ( cff_builder_start_point( builder, x, y ) ||
1516 cff_check_points( builder, num_args ) )
1517 goto Fail;
1518
1519 args = stack;
1520 while ( args < decoder->top )
1521 {
1522 if ( phase )
1523 x = ADD_LONG( x, args[0] );
1524 else
1525 y = ADD_LONG( y, args[0] );
1526
1527 if ( cff_builder_add_point1( builder, x, y ) )
1528 goto Fail;
1529
1530 args++;
1531 phase ^= 1;
1532 }
1533 args = stack;
1534 }
1535 break;
1536
1537 case cff_op_rrcurveto:
1538 {
1539 FT_Int nargs;
1540
1541
1542 FT_TRACE4(( " rrcurveto\n" ));
1543
1544 if ( num_args < 6 )
1545 goto Stack_Underflow;
1546
1547 nargs = num_args - num_args % 6;
1548
1549 if ( cff_builder_start_point( builder, x, y ) ||
1550 cff_check_points( builder, nargs / 2 ) )
1551 goto Fail;
1552
1553 args -= nargs;
1554 while ( args < decoder->top )
1555 {
1556 x = ADD_LONG( x, args[0] );
1557 y = ADD_LONG( y, args[1] );
1558 cff_builder_add_point( builder, x, y, 0 );
1559
1560 x = ADD_LONG( x, args[2] );
1561 y = ADD_LONG( y, args[3] );
1562 cff_builder_add_point( builder, x, y, 0 );
1563
1564 x = ADD_LONG( x, args[4] );
1565 y = ADD_LONG( y, args[5] );
1566 cff_builder_add_point( builder, x, y, 1 );
1567
1568 args += 6;
1569 }
1570 args = stack;
1571 }
1572 break;
1573
1574 case cff_op_vvcurveto:
1575 {
1576 FT_Int nargs;
1577
1578
1579 FT_TRACE4(( " vvcurveto\n" ));
1580
1581 if ( num_args < 4 )
1582 goto Stack_Underflow;
1583
1584 /* if num_args isn't of the form 4n or 4n+1, */
1585 /* we enforce it by clearing the second bit */
1586
1587 nargs = num_args & ~2;
1588
1589 if ( cff_builder_start_point( builder, x, y ) )
1590 goto Fail;
1591
1592 args -= nargs;
1593
1594 if ( nargs & 1 )
1595 {
1596 x = ADD_LONG( x, args[0] );
1597 args++;
1598 nargs--;
1599 }
1600
1601 if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
1602 goto Fail;
1603
1604 while ( args < decoder->top )
1605 {
1606 y = ADD_LONG( y, args[0] );
1607 cff_builder_add_point( builder, x, y, 0 );
1608
1609 x = ADD_LONG( x, args[1] );
1610 y = ADD_LONG( y, args[2] );
1611 cff_builder_add_point( builder, x, y, 0 );
1612
1613 y = ADD_LONG( y, args[3] );
1614 cff_builder_add_point( builder, x, y, 1 );
1615
1616 args += 4;
1617 }
1618 args = stack;
1619 }
1620 break;
1621
1622 case cff_op_hhcurveto:
1623 {
1624 FT_Int nargs;
1625
1626
1627 FT_TRACE4(( " hhcurveto\n" ));
1628
1629 if ( num_args < 4 )
1630 goto Stack_Underflow;
1631
1632 /* if num_args isn't of the form 4n or 4n+1, */
1633 /* we enforce it by clearing the second bit */
1634
1635 nargs = num_args & ~2;
1636
1637 if ( cff_builder_start_point( builder, x, y ) )
1638 goto Fail;
1639
1640 args -= nargs;
1641 if ( nargs & 1 )
1642 {
1643 y = ADD_LONG( y, args[0] );
1644 args++;
1645 nargs--;
1646 }
1647
1648 if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
1649 goto Fail;
1650
1651 while ( args < decoder->top )
1652 {
1653 x = ADD_LONG( x, args[0] );
1654 cff_builder_add_point( builder, x, y, 0 );
1655
1656 x = ADD_LONG( x, args[1] );
1657 y = ADD_LONG( y, args[2] );
1658 cff_builder_add_point( builder, x, y, 0 );
1659
1660 x = ADD_LONG( x, args[3] );
1661 cff_builder_add_point( builder, x, y, 1 );
1662
1663 args += 4;
1664 }
1665 args = stack;
1666 }
1667 break;
1668
1669 case cff_op_vhcurveto:
1670 case cff_op_hvcurveto:
1671 {
1672 FT_Int phase;
1673 FT_Int nargs;
1674
1675
1676 FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto\n"
1677 : " hvcurveto\n" ));
1678
1679 if ( cff_builder_start_point( builder, x, y ) )
1680 goto Fail;
1681
1682 if ( num_args < 4 )
1683 goto Stack_Underflow;
1684
1685 /* if num_args isn't of the form 8n, 8n+1, 8n+4, or 8n+5, */
1686 /* we enforce it by clearing the second bit */
1687
1688 nargs = num_args & ~2;
1689
1690 args -= nargs;
1691 if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) )
1692 goto Stack_Underflow;
1693
1694 phase = ( op == cff_op_hvcurveto );
1695
1696 while ( nargs >= 4 )
1697 {
1698 nargs -= 4;
1699 if ( phase )
1700 {
1701 x = ADD_LONG( x, args[0] );
1702 cff_builder_add_point( builder, x, y, 0 );
1703
1704 x = ADD_LONG( x, args[1] );
1705 y = ADD_LONG( y, args[2] );
1706 cff_builder_add_point( builder, x, y, 0 );
1707
1708 y = ADD_LONG( y, args[3] );
1709 if ( nargs == 1 )
1710 x = ADD_LONG( x, args[4] );
1711 cff_builder_add_point( builder, x, y, 1 );
1712 }
1713 else
1714 {
1715 y = ADD_LONG( y, args[0] );
1716 cff_builder_add_point( builder, x, y, 0 );
1717
1718 x = ADD_LONG( x, args[1] );
1719 y = ADD_LONG( y, args[2] );
1720 cff_builder_add_point( builder, x, y, 0 );
1721
1722 x = ADD_LONG( x, args[3] );
1723 if ( nargs == 1 )
1724 y = ADD_LONG( y, args[4] );
1725 cff_builder_add_point( builder, x, y, 1 );
1726 }
1727 args += 4;
1728 phase ^= 1;
1729 }
1730 args = stack;
1731 }
1732 break;
1733
1734 case cff_op_rlinecurve:
1735 {
1736 FT_Int num_lines;
1737 FT_Int nargs;
1738
1739
1740 FT_TRACE4(( " rlinecurve\n" ));
1741
1742 if ( num_args < 8 )
1743 goto Stack_Underflow;
1744
1745 nargs = num_args & ~1;
1746 num_lines = ( nargs - 6 ) / 2;
1747
1748 if ( cff_builder_start_point( builder, x, y ) ||
1749 cff_check_points( builder, num_lines + 3 ) )
1750 goto Fail;
1751
1752 args -= nargs;
1753
1754 /* first, add the line segments */
1755 while ( num_lines > 0 )
1756 {
1757 x = ADD_LONG( x, args[0] );
1758 y = ADD_LONG( y, args[1] );
1759 cff_builder_add_point( builder, x, y, 1 );
1760
1761 args += 2;
1762 num_lines--;
1763 }
1764
1765 /* then the curve */
1766 x = ADD_LONG( x, args[0] );
1767 y = ADD_LONG( y, args[1] );
1768 cff_builder_add_point( builder, x, y, 0 );
1769
1770 x = ADD_LONG( x, args[2] );
1771 y = ADD_LONG( y, args[3] );
1772 cff_builder_add_point( builder, x, y, 0 );
1773
1774 x = ADD_LONG( x, args[4] );
1775 y = ADD_LONG( y, args[5] );
1776 cff_builder_add_point( builder, x, y, 1 );
1777
1778 args = stack;
1779 }
1780 break;
1781
1782 case cff_op_rcurveline:
1783 {
1784 FT_Int num_curves;
1785 FT_Int nargs;
1786
1787
1788 FT_TRACE4(( " rcurveline\n" ));
1789
1790 if ( num_args < 8 )
1791 goto Stack_Underflow;
1792
1793 nargs = num_args - 2;
1794 nargs = nargs - nargs % 6 + 2;
1795 num_curves = ( nargs - 2 ) / 6;
1796
1797 if ( cff_builder_start_point( builder, x, y ) ||
1798 cff_check_points( builder, num_curves * 3 + 2 ) )
1799 goto Fail;
1800
1801 args -= nargs;
1802
1803 /* first, add the curves */
1804 while ( num_curves > 0 )
1805 {
1806 x = ADD_LONG( x, args[0] );
1807 y = ADD_LONG( y, args[1] );
1808 cff_builder_add_point( builder, x, y, 0 );
1809
1810 x = ADD_LONG( x, args[2] );
1811 y = ADD_LONG( y, args[3] );
1812 cff_builder_add_point( builder, x, y, 0 );
1813
1814 x = ADD_LONG( x, args[4] );
1815 y = ADD_LONG( y, args[5] );
1816 cff_builder_add_point( builder, x, y, 1 );
1817
1818 args += 6;
1819 num_curves--;
1820 }
1821
1822 /* then the final line */
1823 x = ADD_LONG( x, args[0] );
1824 y = ADD_LONG( y, args[1] );
1825 cff_builder_add_point( builder, x, y, 1 );
1826
1827 args = stack;
1828 }
1829 break;
1830
1831 case cff_op_hflex1:
1832 {
1833 FT_Pos start_y;
1834
1835
1836 FT_TRACE4(( " hflex1\n" ));
1837
1838 /* adding five more points: 4 control points, 1 on-curve point */
1839 /* -- make sure we have enough space for the start point if it */
1840 /* needs to be added */
1841 if ( cff_builder_start_point( builder, x, y ) ||
1842 cff_check_points( builder, 6 ) )
1843 goto Fail;
1844
1845 /* record the starting point's y position for later use */
1846 start_y = y;
1847
1848 /* first control point */
1849 x = ADD_LONG( x, args[0] );
1850 y = ADD_LONG( y, args[1] );
1851 cff_builder_add_point( builder, x, y, 0 );
1852
1853 /* second control point */
1854 x = ADD_LONG( x, args[2] );
1855 y = ADD_LONG( y, args[3] );
1856 cff_builder_add_point( builder, x, y, 0 );
1857
1858 /* join point; on curve, with y-value the same as the last */
1859 /* control point's y-value */
1860 x = ADD_LONG( x, args[4] );
1861 cff_builder_add_point( builder, x, y, 1 );
1862
1863 /* third control point, with y-value the same as the join */
1864 /* point's y-value */
1865 x = ADD_LONG( x, args[5] );
1866 cff_builder_add_point( builder, x, y, 0 );
1867
1868 /* fourth control point */
1869 x = ADD_LONG( x, args[6] );
1870 y = ADD_LONG( y, args[7] );
1871 cff_builder_add_point( builder, x, y, 0 );
1872
1873 /* ending point, with y-value the same as the start */
1874 x = ADD_LONG( x, args[8] );
1875 y = start_y;
1876 cff_builder_add_point( builder, x, y, 1 );
1877
1878 args = stack;
1879 break;
1880 }
1881
1882 case cff_op_hflex:
1883 {
1884 FT_Pos start_y;
1885
1886
1887 FT_TRACE4(( " hflex\n" ));
1888
1889 /* adding six more points; 4 control points, 2 on-curve points */
1890 if ( cff_builder_start_point( builder, x, y ) ||
1891 cff_check_points( builder, 6 ) )
1892 goto Fail;
1893
1894 /* record the starting point's y-position for later use */
1895 start_y = y;
1896
1897 /* first control point */
1898 x = ADD_LONG( x, args[0] );
1899 cff_builder_add_point( builder, x, y, 0 );
1900
1901 /* second control point */
1902 x = ADD_LONG( x, args[1] );
1903 y = ADD_LONG( y, args[2] );
1904 cff_builder_add_point( builder, x, y, 0 );
1905
1906 /* join point; on curve, with y-value the same as the last */
1907 /* control point's y-value */
1908 x = ADD_LONG( x, args[3] );
1909 cff_builder_add_point( builder, x, y, 1 );
1910
1911 /* third control point, with y-value the same as the join */
1912 /* point's y-value */
1913 x = ADD_LONG( x, args[4] );
1914 cff_builder_add_point( builder, x, y, 0 );
1915
1916 /* fourth control point */
1917 x = ADD_LONG( x, args[5] );
1918 y = start_y;
1919 cff_builder_add_point( builder, x, y, 0 );
1920
1921 /* ending point, with y-value the same as the start point's */
1922 /* y-value -- we don't add this point, though */
1923 x = ADD_LONG( x, args[6] );
1924 cff_builder_add_point( builder, x, y, 1 );
1925
1926 args = stack;
1927 break;
1928 }
1929
1930 case cff_op_flex1:
1931 {
1932 FT_Pos start_x, start_y; /* record start x, y values for */
1933 /* alter use */
1934 FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */
1935 /* algorithm below */
1936 FT_Int horizontal, count;
1937 FT_Fixed* temp;
1938
1939
1940 FT_TRACE4(( " flex1\n" ));
1941
1942 /* adding six more points; 4 control points, 2 on-curve points */
1943 if ( cff_builder_start_point( builder, x, y ) ||
1944 cff_check_points( builder, 6 ) )
1945 goto Fail;
1946
1947 /* record the starting point's x, y position for later use */
1948 start_x = x;
1949 start_y = y;
1950
1951 /* XXX: figure out whether this is supposed to be a horizontal */
1952 /* or vertical flex; the Type 2 specification is vague... */
1953
1954 temp = args;
1955
1956 /* grab up to the last argument */
1957 for ( count = 5; count > 0; count-- )
1958 {
1959 dx = ADD_LONG( dx, temp[0] );
1960 dy = ADD_LONG( dy, temp[1] );
1961 temp += 2;
1962 }
1963
1964 if ( dx < 0 )
1965 dx = -dx;
1966 if ( dy < 0 )
1967 dy = -dy;
1968
1969 /* strange test, but here it is... */
1970 horizontal = ( dx > dy );
1971
1972 for ( count = 5; count > 0; count-- )
1973 {
1974 x = ADD_LONG( x, args[0] );
1975 y = ADD_LONG( y, args[1] );
1976 cff_builder_add_point( builder, x, y,
1977 (FT_Bool)( count == 3 ) );
1978 args += 2;
1979 }
1980
1981 /* is last operand an x- or y-delta? */
1982 if ( horizontal )
1983 {
1984 x = ADD_LONG( x, args[0] );
1985 y = start_y;
1986 }
1987 else
1988 {
1989 x = start_x;
1990 y = ADD_LONG( y, args[0] );
1991 }
1992
1993 cff_builder_add_point( builder, x, y, 1 );
1994
1995 args = stack;
1996 break;
1997 }
1998
1999 case cff_op_flex:
2000 {
2001 FT_UInt count;
2002
2003
2004 FT_TRACE4(( " flex\n" ));
2005
2006 if ( cff_builder_start_point( builder, x, y ) ||
2007 cff_check_points( builder, 6 ) )
2008 goto Fail;
2009
2010 for ( count = 6; count > 0; count-- )
2011 {
2012 x = ADD_LONG( x, args[0] );
2013 y = ADD_LONG( y, args[1] );
2014 cff_builder_add_point( builder, x, y,
2015 (FT_Bool)( count == 4 || count == 1 ) );
2016 args += 2;
2017 }
2018
2019 args = stack;
2020 }
2021 break;
2022
2023 case cff_op_seac:
2024 FT_TRACE4(( " seac\n" ));
2025
2026 error = cff_operator_seac( decoder,
2027 args[0], args[1], args[2],
2028 (FT_Int)( args[3] >> 16 ),
2029 (FT_Int)( args[4] >> 16 ) );
2030
2031 /* add current outline to the glyph slot */
2032 FT_GlyphLoader_Add( builder->loader );
2033
2034 /* return now! */
2035 FT_TRACE4(( "\n" ));
2036 return error;
2037
2038 case cff_op_endchar:
2039 /* in dictionaries, `endchar' simply indicates end of data */
2040 if ( in_dict )
2041 return error;
2042
2043 FT_TRACE4(( " endchar\n" ));
2044
2045 /* We are going to emulate the seac operator. */
2046 if ( num_args >= 4 )
2047 {
2048 /* Save glyph width so that the subglyphs don't overwrite it. */
2049 FT_Pos glyph_width = decoder->glyph_width;
2050
2051
2052 error = cff_operator_seac( decoder,
2053 0L, args[-4], args[-3],
2054 (FT_Int)( args[-2] >> 16 ),
2055 (FT_Int)( args[-1] >> 16 ) );
2056
2057 decoder->glyph_width = glyph_width;
2058 }
2059 else
2060 {
2061 cff_builder_close_contour( builder );
2062
2063 /* close hints recording session */
2064 if ( hinter )
2065 {
2066 if ( hinter->close( hinter->hints,
2067 (FT_UInt)builder->current->n_points ) )
2068 goto Syntax_Error;
2069
2070 /* apply hints to the loaded glyph outline now */
2071 error = hinter->apply( hinter->hints,
2072 builder->current,
2073 (PSH_Globals)builder->hints_globals,
2074 decoder->hint_mode );
2075 if ( error )
2076 goto Fail;
2077 }
2078
2079 /* add current outline to the glyph slot */
2080 FT_GlyphLoader_Add( builder->loader );
2081 }
2082
2083 /* return now! */
2084 FT_TRACE4(( "\n" ));
2085 return error;
2086
2087 case cff_op_abs:
2088 FT_TRACE4(( " abs\n" ));
2089
2090 if ( args[0] < 0 )
2091 {
2092 if ( args[0] == FT_LONG_MIN )
2093 args[0] = FT_LONG_MAX;
2094 else
2095 args[0] = -args[0];
2096 }
2097 args++;
2098 break;
2099
2100 case cff_op_add:
2101 FT_TRACE4(( " add\n" ));
2102
2103 args[0] = ADD_LONG( args[0], args[1] );
2104 args++;
2105 break;
2106
2107 case cff_op_sub:
2108 FT_TRACE4(( " sub\n" ));
2109
2110 args[0] = SUB_LONG( args[0], args[1] );
2111 args++;
2112 break;
2113
2114 case cff_op_div:
2115 FT_TRACE4(( " div\n" ));
2116
2117 args[0] = FT_DivFix( args[0], args[1] );
2118 args++;
2119 break;
2120
2121 case cff_op_neg:
2122 FT_TRACE4(( " neg\n" ));
2123
2124 if ( args[0] == FT_LONG_MIN )
2125 args[0] = FT_LONG_MAX;
2126 args[0] = -args[0];
2127 args++;
2128 break;
2129
2130 case cff_op_random:
2131 FT_TRACE4(( " random\n" ));
2132
2133 /* only use the lower 16 bits of `random' */
2134 /* to generate a number in the range (0;1] */
2135 args[0] = (FT_Fixed)
2136 ( ( decoder->current_subfont->random & 0xFFFF ) + 1 );
2137 args++;
2138
2139 decoder->current_subfont->random =
2140 cff_random( decoder->current_subfont->random );
2141 break;
2142
2143 case cff_op_mul:
2144 FT_TRACE4(( " mul\n" ));
2145
2146 args[0] = FT_MulFix( args[0], args[1] );
2147 args++;
2148 break;
2149
2150 case cff_op_sqrt:
2151 FT_TRACE4(( " sqrt\n" ));
2152
2153 if ( args[0] > 0 )
2154 {
2155 FT_Fixed root = args[0];
2156 FT_Fixed new_root;
2157
2158
2159 for (;;)
2160 {
2161 new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1;
2162 if ( new_root == root )
2163 break;
2164 root = new_root;
2165 }
2166 args[0] = new_root;
2167 }
2168 else
2169 args[0] = 0;
2170 args++;
2171 break;
2172
2173 case cff_op_drop:
2174 /* nothing */
2175 FT_TRACE4(( " drop\n" ));
2176
2177 break;
2178
2179 case cff_op_exch:
2180 {
2181 FT_Fixed tmp;
2182
2183
2184 FT_TRACE4(( " exch\n" ));
2185
2186 tmp = args[0];
2187 args[0] = args[1];
2188 args[1] = tmp;
2189 args += 2;
2190 }
2191 break;
2192
2193 case cff_op_index:
2194 {
2195 FT_Int idx = (FT_Int)( args[0] >> 16 );
2196
2197
2198 FT_TRACE4(( " index\n" ));
2199
2200 if ( idx < 0 )
2201 idx = 0;
2202 else if ( idx > num_args - 2 )
2203 idx = num_args - 2;
2204 args[0] = args[-( idx + 1 )];
2205 args++;
2206 }
2207 break;
2208
2209 case cff_op_roll:
2210 {
2211 FT_Int count = (FT_Int)( args[0] >> 16 );
2212 FT_Int idx = (FT_Int)( args[1] >> 16 );
2213
2214
2215 FT_TRACE4(( " roll\n" ));
2216
2217 if ( count <= 0 )
2218 count = 1;
2219
2220 args -= count;
2221 if ( args < stack )
2222 goto Stack_Underflow;
2223
2224 if ( idx >= 0 )
2225 {
2226 while ( idx > 0 )
2227 {
2228 FT_Fixed tmp = args[count - 1];
2229 FT_Int i;
2230
2231
2232 for ( i = count - 2; i >= 0; i-- )
2233 args[i + 1] = args[i];
2234 args[0] = tmp;
2235 idx--;
2236 }
2237 }
2238 else
2239 {
2240 while ( idx < 0 )
2241 {
2242 FT_Fixed tmp = args[0];
2243 FT_Int i;
2244
2245
2246 for ( i = 0; i < count - 1; i++ )
2247 args[i] = args[i + 1];
2248 args[count - 1] = tmp;
2249 idx++;
2250 }
2251 }
2252 args += count;
2253 }
2254 break;
2255
2256 case cff_op_dup:
2257 FT_TRACE4(( " dup\n" ));
2258
2259 args[1] = args[0];
2260 args += 2;
2261 break;
2262
2263 case cff_op_put:
2264 {
2265 FT_Fixed val = args[0];
2266 FT_Int idx = (FT_Int)( args[1] >> 16 );
2267
2268
2269 FT_TRACE4(( " put\n" ));
2270
2271 /* the Type2 specification before version 16-March-2000 */
2272 /* didn't give a hard-coded size limit of the temporary */
2273 /* storage array; instead, an argument of the */
2274 /* `MultipleMaster' operator set the size */
2275 if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
2276 decoder->buildchar[idx] = val;
2277 }
2278 break;
2279
2280 case cff_op_get:
2281 {
2282 FT_Int idx = (FT_Int)( args[0] >> 16 );
2283 FT_Fixed val = 0;
2284
2285
2286 FT_TRACE4(( " get\n" ));
2287
2288 if ( idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS )
2289 val = decoder->buildchar[idx];
2290
2291 args[0] = val;
2292 args++;
2293 }
2294 break;
2295
2296 case cff_op_store:
2297 /* this operator was removed from the Type2 specification */
2298 /* in version 16-March-2000 */
2299
2300 /* since we currently don't handle interpolation of multiple */
2301 /* master fonts, this is a no-op */
2302 FT_TRACE4(( " store\n"));
2303 break;
2304
2305 case cff_op_load:
2306 /* this operator was removed from the Type2 specification */
2307 /* in version 16-March-2000 */
2308 {
2309 FT_Int reg_idx = (FT_Int)args[0];
2310 FT_Int idx = (FT_Int)args[1];
2311 FT_Int count = (FT_Int)args[2];
2312
2313
2314 FT_TRACE4(( " load\n" ));
2315
2316 /* since we currently don't handle interpolation of multiple */
2317 /* master fonts, we store a vector [1 0 0 ...] in the */
2318 /* temporary storage array regardless of the Registry index */
2319 if ( reg_idx >= 0 && reg_idx <= 2 &&
2320 idx >= 0 && idx < CFF_MAX_TRANS_ELEMENTS &&
2321 count >= 0 && count <= num_axes )
2322 {
2323 FT_Int end, i;
2324
2325
2326 end = FT_MIN( idx + count, CFF_MAX_TRANS_ELEMENTS );
2327
2328 if ( idx < end )
2329 decoder->buildchar[idx] = 1 << 16;
2330
2331 for ( i = idx + 1; i < end; i++ )
2332 decoder->buildchar[i] = 0;
2333 }
2334 }
2335 break;
2336
2337 case cff_op_blend:
2338 /* this operator was removed from the Type2 specification */
2339 /* in version 16-March-2000 */
2340 {
2341 FT_Int num_results = (FT_Int)( args[0] >> 16 );
2342
2343
2344 FT_TRACE4(( " blend\n" ));
2345
2346 if ( num_results < 0 )
2347 goto Syntax_Error;
2348
2349 if ( num_results * (FT_Int)num_designs > num_args )
2350 goto Stack_Underflow;
2351
2352 /* since we currently don't handle interpolation of multiple */
2353 /* master fonts, return the `num_results' values of the */
2354 /* first master */
2355 args -= num_results * ( num_designs - 1 );
2356 num_args -= num_results * ( num_designs - 1 );
2357 }
2358 break;
2359
2360 case cff_op_dotsection:
2361 /* this operator is deprecated and ignored by the parser */
2362 FT_TRACE4(( " dotsection\n" ));
2363 break;
2364
2365 case cff_op_closepath:
2366 /* this is an invalid Type 2 operator; however, there */
2367 /* exist fonts which are incorrectly converted from probably */
2368 /* Type 1 to CFF, and some parsers seem to accept it */
2369
2370 FT_TRACE4(( " closepath (invalid op)\n" ));
2371
2372 args = stack;
2373 break;
2374
2375 case cff_op_hsbw:
2376 /* this is an invalid Type 2 operator; however, there */
2377 /* exist fonts which are incorrectly converted from probably */
2378 /* Type 1 to CFF, and some parsers seem to accept it */
2379
2380 FT_TRACE4(( " hsbw (invalid op)\n" ));
2381
2382 decoder->glyph_width =
2383 ADD_LONG( decoder->nominal_width, ( args[1] >> 16 ) );
2384
2385 decoder->builder.left_bearing.x = args[0];
2386 decoder->builder.left_bearing.y = 0;
2387
2388 x = ADD_LONG( decoder->builder.pos_x, args[0] );
2389 y = decoder->builder.pos_y;
2390 args = stack;
2391 break;
2392
2393 case cff_op_sbw:
2394 /* this is an invalid Type 2 operator; however, there */
2395 /* exist fonts which are incorrectly converted from probably */
2396 /* Type 1 to CFF, and some parsers seem to accept it */
2397
2398 FT_TRACE4(( " sbw (invalid op)\n" ));
2399
2400 decoder->glyph_width =
2401 ADD_LONG( decoder->nominal_width, ( args[2] >> 16 ) );
2402
2403 decoder->builder.left_bearing.x = args[0];
2404 decoder->builder.left_bearing.y = args[1];
2405
2406 x = ADD_LONG( decoder->builder.pos_x, args[0] );
2407 y = ADD_LONG( decoder->builder.pos_y, args[1] );
2408 args = stack;
2409 break;
2410
2411 case cff_op_setcurrentpoint:
2412 /* this is an invalid Type 2 operator; however, there */
2413 /* exist fonts which are incorrectly converted from probably */
2414 /* Type 1 to CFF, and some parsers seem to accept it */
2415
2416 FT_TRACE4(( " setcurrentpoint (invalid op)\n" ));
2417
2418 x = ADD_LONG( decoder->builder.pos_x, args[0] );
2419 y = ADD_LONG( decoder->builder.pos_y, args[1] );
2420 args = stack;
2421 break;
2422
2423 case cff_op_callothersubr:
2424 /* this is an invalid Type 2 operator; however, there */
2425 /* exist fonts which are incorrectly converted from probably */
2426 /* Type 1 to CFF, and some parsers seem to accept it */
2427
2428 FT_TRACE4(( " callothersubr (invalid op)\n" ));
2429
2430 /* subsequent `pop' operands should add the arguments, */
2431 /* this is the implementation described for `unknown' other */
2432 /* subroutines in the Type1 spec. */
2433 /* */
2434 /* XXX Fix return arguments (see discussion below). */
2435 args -= 2 + ( args[-2] >> 16 );
2436 if ( args < stack )
2437 goto Stack_Underflow;
2438 break;
2439
2440 case cff_op_pop:
2441 /* this is an invalid Type 2 operator; however, there */
2442 /* exist fonts which are incorrectly converted from probably */
2443 /* Type 1 to CFF, and some parsers seem to accept it */
2444
2445 FT_TRACE4(( " pop (invalid op)\n" ));
2446
2447 /* XXX Increasing `args' is wrong: After a certain number of */
2448 /* `pop's we get a stack overflow. Reason for doing it is */
2449 /* code like this (actually found in a CFF font): */
2450 /* */
2451 /* 17 1 3 callothersubr */
2452 /* pop */
2453 /* callsubr */
2454 /* */
2455 /* Since we handle `callothersubr' as a no-op, and */
2456 /* `callsubr' needs at least one argument, `pop' can't be a */
2457 /* no-op too as it basically should be. */
2458 /* */
2459 /* The right solution would be to provide real support for */
2460 /* `callothersubr' as done in `t1decode.c', however, given */
2461 /* the fact that CFF fonts with `pop' are invalid, it is */
2462 /* questionable whether it is worth the time. */
2463 args++;
2464 break;
2465
2466 case cff_op_and:
2467 {
2468 FT_Fixed cond = ( args[0] && args[1] );
2469
2470
2471 FT_TRACE4(( " and\n" ));
2472
2473 args[0] = cond ? 0x10000L : 0;
2474 args++;
2475 }
2476 break;
2477
2478 case cff_op_or:
2479 {
2480 FT_Fixed cond = ( args[0] || args[1] );
2481
2482
2483 FT_TRACE4(( " or\n" ));
2484
2485 args[0] = cond ? 0x10000L : 0;
2486 args++;
2487 }
2488 break;
2489
2490 case cff_op_not:
2491 {
2492 FT_Fixed cond = !args[0];
2493
2494
2495 FT_TRACE4(( " not\n" ));
2496
2497 args[0] = cond ? 0x10000L : 0;
2498 args++;
2499 }
2500 break;
2501
2502 case cff_op_eq:
2503 {
2504 FT_Fixed cond = ( args[0] == args[1] );
2505
2506
2507 FT_TRACE4(( " eq\n" ));
2508
2509 args[0] = cond ? 0x10000L : 0;
2510 args++;
2511 }
2512 break;
2513
2514 case cff_op_ifelse:
2515 {
2516 FT_Fixed cond = ( args[2] <= args[3] );
2517
2518
2519 FT_TRACE4(( " ifelse\n" ));
2520
2521 if ( !cond )
2522 args[0] = args[1];
2523 args++;
2524 }
2525 break;
2526
2527 case cff_op_callsubr:
2528 {
2529 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
2530 decoder->locals_bias );
2531
2532
2533 FT_TRACE4(( " callsubr (idx %d, entering level %d)\n",
2534 idx,
2535 zone - decoder->zones + 1 ));
2536
2537 if ( idx >= decoder->num_locals )
2538 {
2539 FT_ERROR(( "cff_decoder_parse_charstrings:"
2540 " invalid local subr index\n" ));
2541 goto Syntax_Error;
2542 }
2543
2544 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2545 {
2546 FT_ERROR(( "cff_decoder_parse_charstrings:"
2547 " too many nested subrs\n" ));
2548 goto Syntax_Error;
2549 }
2550
2551 zone->cursor = ip; /* save current instruction pointer */
2552
2553 zone++;
2554 zone->base = decoder->locals[idx];
2555 zone->limit = decoder->locals[idx + 1];
2556 zone->cursor = zone->base;
2557
2558 if ( !zone->base || zone->limit == zone->base )
2559 {
2560 FT_ERROR(( "cff_decoder_parse_charstrings:"
2561 " invoking empty subrs\n" ));
2562 goto Syntax_Error;
2563 }
2564
2565 decoder->zone = zone;
2566 ip = zone->base;
2567 limit = zone->limit;
2568 }
2569 break;
2570
2571 case cff_op_callgsubr:
2572 {
2573 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) +
2574 decoder->globals_bias );
2575
2576
2577 FT_TRACE4(( " callgsubr (idx %d, entering level %d)\n",
2578 idx,
2579 zone - decoder->zones + 1 ));
2580
2581 if ( idx >= decoder->num_globals )
2582 {
2583 FT_ERROR(( "cff_decoder_parse_charstrings:"
2584 " invalid global subr index\n" ));
2585 goto Syntax_Error;
2586 }
2587
2588 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS )
2589 {
2590 FT_ERROR(( "cff_decoder_parse_charstrings:"
2591 " too many nested subrs\n" ));
2592 goto Syntax_Error;
2593 }
2594
2595 zone->cursor = ip; /* save current instruction pointer */
2596
2597 zone++;
2598 zone->base = decoder->globals[idx];
2599 zone->limit = decoder->globals[idx + 1];
2600 zone->cursor = zone->base;
2601
2602 if ( !zone->base || zone->limit == zone->base )
2603 {
2604 FT_ERROR(( "cff_decoder_parse_charstrings:"
2605 " invoking empty subrs\n" ));
2606 goto Syntax_Error;
2607 }
2608
2609 decoder->zone = zone;
2610 ip = zone->base;
2611 limit = zone->limit;
2612 }
2613 break;
2614
2615 case cff_op_return:
2616 FT_TRACE4(( " return (leaving level %d)\n",
2617 decoder->zone - decoder->zones ));
2618
2619 if ( decoder->zone <= decoder->zones )
2620 {
2621 FT_ERROR(( "cff_decoder_parse_charstrings:"
2622 " unexpected return\n" ));
2623 goto Syntax_Error;
2624 }
2625
2626 decoder->zone--;
2627 zone = decoder->zone;
2628 ip = zone->cursor;
2629 limit = zone->limit;
2630 break;
2631
2632 default:
2633 FT_ERROR(( "Unimplemented opcode: %d", ip[-1] ));
2634
2635 if ( ip[-1] == 12 )
2636 FT_ERROR(( " %d", ip[0] ));
2637 FT_ERROR(( "\n" ));
2638
2639 return FT_THROW( Unimplemented_Feature );
2640 }
2641
2642 decoder->top = args;
2643
2644 if ( decoder->top - stack >= CFF_MAX_OPERANDS )
2645 goto Stack_Overflow;
2646
2647 } /* general operator processing */
2648
2649 } /* while ip < limit */
2650
2651 FT_TRACE4(( "..end..\n\n" ));
2652
2653 Fail:
2654 return error;
2655
2656 MM_Error:
2657 FT_TRACE4(( "cff_decoder_parse_charstrings:"
2658 " invalid opcode found in top DICT charstring\n"));
2659 return FT_THROW( Invalid_File_Format );
2660
2661 Syntax_Error:
2662 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
2663 return FT_THROW( Invalid_File_Format );
2664
2665 Stack_Underflow:
2666 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
2667 return FT_THROW( Too_Few_Arguments );
2668
2669 Stack_Overflow:
2670 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
2671 return FT_THROW( Stack_Overflow );
2672 }
2673
2674 #endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
2675
2676
2677 /*************************************************************************/
2678 /*************************************************************************/
2679 /*************************************************************************/
2680 /********** *********/
2681 /********** *********/
2682 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
2683 /********** *********/
2684 /********** The following code is in charge of computing *********/
2685 /********** the maximum advance width of the font. It *********/
2686 /********** quickly processes each glyph charstring to *********/
2687 /********** extract the value from either a `sbw' or `seac' *********/
2688 /********** operator. *********/
2689 /********** *********/
2690 /*************************************************************************/
2691 /*************************************************************************/
2692 /*************************************************************************/
2693
2694
2695 #if 0 /* unused until we support pure CFF fonts */
2696
2697
2698 FT_LOCAL_DEF( FT_Error )
2699 cff_compute_max_advance( TT_Face face,
2700 FT_Int* max_advance )
2701 {
2702 FT_Error error = FT_Err_Ok;
2703 CFF_Decoder decoder;
2704 FT_Int glyph_index;
2705 CFF_Font cff = (CFF_Font)face->other;
2706
2707
2708 *max_advance = 0;
2709
2710 /* Initialize load decoder */
2711 cff_decoder_init( &decoder, face, 0, 0, 0, 0 );
2712
2713 decoder.builder.metrics_only = 1;
2714 decoder.builder.load_points = 0;
2715
2716 /* For each glyph, parse the glyph charstring and extract */
2717 /* the advance width. */
2718 for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
2719 glyph_index++ )
2720 {
2721 FT_Byte* charstring;
2722 FT_ULong charstring_len;
2723
2724
2725 /* now get load the unscaled outline */
2726 error = cff_get_glyph_data( face, glyph_index,
2727 &charstring, &charstring_len );
2728 if ( !error )
2729 {
2730 error = cff_decoder_prepare( &decoder, size, glyph_index );
2731 if ( !error )
2732 error = cff_decoder_parse_charstrings( &decoder,
2733 charstring,
2734 charstring_len,
2735 0 );
2736
2737 cff_free_glyph_data( face, &charstring, &charstring_len );
2738 }
2739
2740 /* ignore the error if one has occurred -- skip to next glyph */
2741 error = FT_Err_Ok;
2742 }
2743
2744 *max_advance = decoder.builder.advance.x;
2745
2746 return FT_Err_Ok;
2747 }
2748
2749
2750 #endif /* 0 */
2751
2752
2753 FT_LOCAL_DEF( FT_Error )
2754 cff_slot_load( CFF_GlyphSlot glyph,
2755 CFF_Size size,
2756 FT_UInt glyph_index,
2757 FT_Int32 load_flags )
2758 {
2759 FT_Error error;
2760 CFF_Decoder decoder;
2761 TT_Face face = (TT_Face)glyph->root.face;
2762 FT_Bool hinting, scaled, force_scaling;
2763 CFF_Font cff = (CFF_Font)face->extra.data;
2764
2765 FT_Matrix font_matrix;
2766 FT_Vector font_offset;
2767
2768
2769 force_scaling = FALSE;
2770
2771 /* in a CID-keyed font, consider `glyph_index' as a CID and map */
2772 /* it immediately to the real glyph_index -- if it isn't a */
2773 /* subsetted font, glyph_indices and CIDs are identical, though */
2774 if ( cff->top_font.font_dict.cid_registry != 0xFFFFU &&
2775 cff->charset.cids )
2776 {
2777 /* don't handle CID 0 (.notdef) which is directly mapped to GID 0 */
2778 if ( glyph_index != 0 )
2779 {
2780 glyph_index = cff_charset_cid_to_gindex( &cff->charset,
2781 glyph_index );
2782 if ( glyph_index == 0 )
2783 return FT_THROW( Invalid_Argument );
2784 }
2785 }
2786 else if ( glyph_index >= cff->num_glyphs )
2787 return FT_THROW( Invalid_Argument );
2788
2789 if ( load_flags & FT_LOAD_NO_RECURSE )
2790 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
2791
2792 glyph->x_scale = 0x10000L;
2793 glyph->y_scale = 0x10000L;
2794 if ( size )
2795 {
2796 glyph->x_scale = size->root.metrics.x_scale;
2797 glyph->y_scale = size->root.metrics.y_scale;
2798 }
2799
2800 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2801
2802 /* try to load embedded bitmap if any */
2803 /* */
2804 /* XXX: The convention should be emphasized in */
2805 /* the documents because it can be confusing. */
2806 if ( size )
2807 {
2808 CFF_Face cff_face = (CFF_Face)size->root.face;
2809 SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt;
2810 FT_Stream stream = cff_face->root.stream;
2811
2812
2813 if ( size->strike_index != 0xFFFFFFFFUL &&
2814 sfnt->load_eblc &&
2815 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
2816 {
2817 TT_SBit_MetricsRec metrics;
2818
2819
2820 error = sfnt->load_sbit_image( face,
2821 size->strike_index,
2822 glyph_index,
2823 (FT_UInt)load_flags,
2824 stream,
2825 &glyph->root.bitmap,
2826 &metrics );
2827
2828 if ( !error )
2829 {
2830 FT_Bool has_vertical_info;
2831 FT_UShort advance;
2832 FT_Short dummy;
2833
2834
2835 glyph->root.outline.n_points = 0;
2836 glyph->root.outline.n_contours = 0;
2837
2838 glyph->root.metrics.width = (FT_Pos)metrics.width << 6;
2839 glyph->root.metrics.height = (FT_Pos)metrics.height << 6;
2840
2841 glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
2842 glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
2843 glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
2844
2845 glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
2846 glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
2847 glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
2848
2849 glyph->root.format = FT_GLYPH_FORMAT_BITMAP;
2850
2851 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2852 {
2853 glyph->root.bitmap_left = metrics.vertBearingX;
2854 glyph->root.bitmap_top = metrics.vertBearingY;
2855 }
2856 else
2857 {
2858 glyph->root.bitmap_left = metrics.horiBearingX;
2859 glyph->root.bitmap_top = metrics.horiBearingY;
2860 }
2861
2862 /* compute linear advance widths */
2863
2864 (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
2865 glyph_index,
2866 &dummy,
2867 &advance );
2868 glyph->root.linearHoriAdvance = advance;
2869
2870 has_vertical_info = FT_BOOL(
2871 face->vertical_info &&
2872 face->vertical.number_Of_VMetrics > 0 );
2873
2874 /* get the vertical metrics from the vmtx table if we have one */
2875 if ( has_vertical_info )
2876 {
2877 (void)( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
2878 glyph_index,
2879 &dummy,
2880 &advance );
2881 glyph->root.linearVertAdvance = advance;
2882 }
2883 else
2884 {
2885 /* make up vertical ones */
2886 if ( face->os2.version != 0xFFFFU )
2887 glyph->root.linearVertAdvance = (FT_Pos)
2888 ( face->os2.sTypoAscender - face->os2.sTypoDescender );
2889 else
2890 glyph->root.linearVertAdvance = (FT_Pos)
2891 ( face->horizontal.Ascender - face->horizontal.Descender );
2892 }
2893
2894 return error;
2895 }
2896 }
2897 }
2898
2899 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2900
2901 /* return immediately if we only want the embedded bitmaps */
2902 if ( load_flags & FT_LOAD_SBITS_ONLY )
2903 return FT_THROW( Invalid_Argument );
2904
2905 /* if we have a CID subfont, use its matrix (which has already */
2906 /* been multiplied with the root matrix) */
2907
2908 /* this scaling is only relevant if the PS hinter isn't active */
2909 if ( cff->num_subfonts )
2910 {
2911 FT_Long top_upm, sub_upm;
2912 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select,
2913 glyph_index );
2914
2915
2916 if ( fd_index >= cff->num_subfonts )
2917 fd_index = (FT_Byte)( cff->num_subfonts - 1 );
2918
2919 top_upm = (FT_Long)cff->top_font.font_dict.units_per_em;
2920 sub_upm = (FT_Long)cff->subfonts[fd_index]->font_dict.units_per_em;
2921
2922
2923 font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix;
2924 font_offset = cff->subfonts[fd_index]->font_dict.font_offset;
2925
2926 if ( top_upm != sub_upm )
2927 {
2928 glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm );
2929 glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm );
2930
2931 force_scaling = TRUE;
2932 }
2933 }
2934 else
2935 {
2936 font_matrix = cff->top_font.font_dict.font_matrix;
2937 font_offset = cff->top_font.font_dict.font_offset;
2938 }
2939
2940 glyph->root.outline.n_points = 0;
2941 glyph->root.outline.n_contours = 0;
2942
2943 /* top-level code ensures that FT_LOAD_NO_HINTING is set */
2944 /* if FT_LOAD_NO_SCALE is active */
2945 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
2946 scaled = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 );
2947
2948 glyph->hint = hinting;
2949 glyph->scaled = scaled;
2950 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */
2951
2952 {
2953 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2954 CFF_Driver driver = (CFF_Driver)FT_FACE_DRIVER( face );
2955 #endif
2956
2957
2958 FT_Byte* charstring;
2959 FT_ULong charstring_len;
2960
2961
2962 cff_decoder_init( &decoder, face, size, glyph, hinting,
2963 FT_LOAD_TARGET_MODE( load_flags ) );
2964
2965 /* this is for pure CFFs */
2966 if ( load_flags & FT_LOAD_ADVANCE_ONLY )
2967 decoder.width_only = TRUE;
2968
2969 decoder.builder.no_recurse =
2970 (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
2971
2972 /* now load the unscaled outline */
2973 error = cff_get_glyph_data( face, glyph_index,
2974 &charstring, &charstring_len );
2975 if ( error )
2976 goto Glyph_Build_Finished;
2977
2978 error = cff_decoder_prepare( &decoder, size, glyph_index );
2979 if ( error )
2980 goto Glyph_Build_Finished;
2981
2982 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE
2983 /* choose which CFF renderer to use */
2984 if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
2985 error = cff_decoder_parse_charstrings( &decoder,
2986 charstring,
2987 charstring_len,
2988 0 );
2989 else
2990 #endif
2991 {
2992 error = cf2_decoder_parse_charstrings( &decoder,
2993 charstring,
2994 charstring_len );
2995
2996 /* Adobe's engine uses 16.16 numbers everywhere; */
2997 /* as a consequence, glyphs larger than 2000ppem get rejected */
2998 if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
2999 {
3000 /* this time, we retry unhinted and scale up the glyph later on */
3001 /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */
3002 /* 0x400 for both `x_scale' and `y_scale' in this case) */
3003 hinting = FALSE;
3004 force_scaling = TRUE;
3005 glyph->hint = hinting;
3006
3007 error = cf2_decoder_parse_charstrings( &decoder,
3008 charstring,
3009 charstring_len );
3010 }
3011 }
3012
3013 cff_free_glyph_data( face, &charstring, charstring_len );
3014
3015 if ( error )
3016 goto Glyph_Build_Finished;
3017
3018 #ifdef FT_CONFIG_OPTION_INCREMENTAL
3019 /* Control data and length may not be available for incremental */
3020 /* fonts. */
3021 if ( face->root.internal->incremental_interface )
3022 {
3023 glyph->root.control_data = NULL;
3024 glyph->root.control_len = 0;
3025 }
3026 else
3027 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
3028
3029 /* We set control_data and control_len if charstrings is loaded. */
3030 /* See how charstring loads at cff_index_access_element() in */
3031 /* cffload.c. */
3032 {
3033 CFF_Index csindex = &cff->charstrings_index;
3034
3035
3036 if ( csindex->offsets )
3037 {
3038 glyph->root.control_data = csindex->bytes +
3039 csindex->offsets[glyph_index] - 1;
3040 glyph->root.control_len = (FT_Long)charstring_len;
3041 }
3042 }
3043
3044 Glyph_Build_Finished:
3045 /* save new glyph tables, if no error */
3046 if ( !error )
3047 cff_builder_done( &decoder.builder );
3048 /* XXX: anything to do for broken glyph entry? */
3049 }
3050
3051 #ifdef FT_CONFIG_OPTION_INCREMENTAL
3052
3053 /* Incremental fonts can optionally override the metrics. */
3054 if ( !error &&
3055 face->root.internal->incremental_interface &&
3056 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
3057 {
3058 FT_Incremental_MetricsRec metrics;
3059
3060
3061 metrics.bearing_x = decoder.builder.left_bearing.x;
3062 metrics.bearing_y = 0;
3063 metrics.advance = decoder.builder.advance.x;
3064 metrics.advance_v = decoder.builder.advance.y;
3065
3066 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
3067 face->root.internal->incremental_interface->object,
3068 glyph_index, FALSE, &metrics );
3069
3070 decoder.builder.left_bearing.x = metrics.bearing_x;
3071 decoder.builder.advance.x = metrics.advance;
3072 decoder.builder.advance.y = metrics.advance_v;
3073 }
3074
3075 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
3076
3077 if ( !error )
3078 {
3079 /* Now, set the metrics -- this is rather simple, as */
3080 /* the left side bearing is the xMin, and the top side */
3081 /* bearing the yMax. */
3082
3083 /* For composite glyphs, return only left side bearing and */
3084 /* advance width. */
3085 if ( load_flags & FT_LOAD_NO_RECURSE )
3086 {
3087 FT_Slot_Internal internal = glyph->root.internal;
3088
3089
3090 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
3091 glyph->root.metrics.horiAdvance = decoder.glyph_width;
3092 internal->glyph_matrix = font_matrix;
3093 internal->glyph_delta = font_offset;
3094 internal->glyph_transformed = 1;
3095 }
3096 else
3097 {
3098 FT_BBox cbox;
3099 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
3100 FT_Bool has_vertical_info;
3101
3102
3103 if ( face->horizontal.number_Of_HMetrics )
3104 {
3105 FT_Short horiBearingX = 0;
3106 FT_UShort horiAdvance = 0;
3107
3108
3109 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
3110 glyph_index,
3111 &horiBearingX,
3112 &horiAdvance );
3113 metrics->horiAdvance = horiAdvance;
3114 metrics->horiBearingX = horiBearingX;
3115 glyph->root.linearHoriAdvance = horiAdvance;
3116 }
3117 else
3118 {
3119 /* copy the _unscaled_ advance width */
3120 metrics->horiAdvance = decoder.glyph_width;
3121 glyph->root.linearHoriAdvance = decoder.glyph_width;
3122 }
3123
3124 glyph->root.internal->glyph_transformed = 0;
3125
3126 has_vertical_info = FT_BOOL( face->vertical_info &&
3127 face->vertical.number_Of_VMetrics > 0 );
3128
3129 /* get the vertical metrics from the vmtx table if we have one */
3130 if ( has_vertical_info )
3131 {
3132 FT_Short vertBearingY = 0;
3133 FT_UShort vertAdvance = 0;
3134
3135
3136 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
3137 glyph_index,
3138 &vertBearingY,
3139 &vertAdvance );
3140 metrics->vertBearingY = vertBearingY;
3141 metrics->vertAdvance = vertAdvance;
3142 }
3143 else
3144 {
3145 /* make up vertical ones */
3146 if ( face->os2.version != 0xFFFFU )
3147 metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender -
3148 face->os2.sTypoDescender );
3149 else
3150 metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender -
3151 face->horizontal.Descender );
3152 }
3153
3154 glyph->root.linearVertAdvance = metrics->vertAdvance;
3155
3156 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;
3157
3158 glyph->root.outline.flags = 0;
3159 if ( size && size->root.metrics.y_ppem < 24 )
3160 glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION;
3161
3162 glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL;
3163
3164 /* apply the font matrix, if any */
3165 if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L ||
3166 font_matrix.xy != 0 || font_matrix.yx != 0 )
3167 {
3168 FT_Outline_Transform( &glyph->root.outline, &font_matrix );
3169
3170 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
3171 font_matrix.xx );
3172 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance,
3173 font_matrix.yy );
3174 }
3175
3176 if ( font_offset.x || font_offset.y )
3177 {
3178 FT_Outline_Translate( &glyph->root.outline,
3179 font_offset.x,
3180 font_offset.y );
3181
3182 metrics->horiAdvance += font_offset.x;
3183 metrics->vertAdvance += font_offset.y;
3184 }
3185
3186 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling )
3187 {
3188 /* scale the outline and the metrics */
3189 FT_Int n;
3190 FT_Outline* cur = &glyph->root.outline;
3191 FT_Vector* vec = cur->points;
3192 FT_Fixed x_scale = glyph->x_scale;
3193 FT_Fixed y_scale = glyph->y_scale;
3194
3195
3196 /* First of all, scale the points */
3197 if ( !hinting || !decoder.builder.hints_funcs )
3198 for ( n = cur->n_points; n > 0; n--, vec++ )
3199 {
3200 vec->x = FT_MulFix( vec->x, x_scale );
3201 vec->y = FT_MulFix( vec->y, y_scale );
3202 }
3203
3204 /* Then scale the metrics */
3205 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
3206 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
3207 }
3208
3209 /* compute the other metrics */
3210 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
3211
3212 metrics->width = cbox.xMax - cbox.xMin;
3213 metrics->height = cbox.yMax - cbox.yMin;
3214
3215 metrics->horiBearingX = cbox.xMin;
3216 metrics->horiBearingY = cbox.yMax;
3217
3218 if ( has_vertical_info )
3219 metrics->vertBearingX = metrics->horiBearingX -
3220 metrics->horiAdvance / 2;
3221 else
3222 {
3223 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
3224 ft_synthesize_vertical_metrics( metrics,
3225 metrics->vertAdvance );
3226 }
3227 }
3228 }
3229
3230 return error;
3231 }
3232
3233
3234 /* END */