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