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