]> git.saurik.com Git - wxWidgets.git/blob - src/freetype/cid/cidgload.c
minor flicker reduction in the virtual list ctrl
[wxWidgets.git] / src / freetype / cid / cidgload.c
1 /***************************************************************************/
2 /* */
3 /* cidgload.c */
4 /* */
5 /* CID-keyed Type1 Glyph Loader (body). */
6 /* */
7 /* Copyright 1996-2000 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 #ifdef FT_FLAT_COMPILE
20
21 #include "cidload.h"
22 #include "cidgload.h"
23
24 #else
25
26 #include <cid/cidload.h>
27 #include <cid/cidgload.h>
28
29 #endif
30
31
32 #include <freetype/internal/ftdebug.h>
33 #include <freetype/internal/ftstream.h>
34 #include <freetype/ftoutln.h>
35
36
37 /*************************************************************************/
38 /* */
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
41 /* messages during execution. */
42 /* */
43 #undef FT_COMPONENT
44 #define FT_COMPONENT trace_cidgload
45
46
47 /* forward */
48 static
49 FT_Error cid_load_glyph( CID_Decoder* decoder,
50 FT_UInt glyph_index );
51
52
53 typedef enum CID_Operator_
54 {
55 op_none = 0,
56
57 op_endchar,
58 op_hsbw,
59 op_seac,
60 op_sbw,
61 op_closepath,
62
63 op_hlineto,
64 op_hmoveto,
65 op_hvcurveto,
66 op_rlineto,
67 op_rmoveto,
68 op_rrcurveto,
69 op_vhcurveto,
70 op_vlineto,
71 op_vmoveto,
72
73 op_dotsection,
74
75 op_hstem,
76 op_hstem3,
77 op_vstem,
78 op_vstem3,
79
80 op_div,
81 op_callothersubr,
82 op_callsubr,
83 op_pop,
84 op_return,
85 op_setcurrentpoint,
86
87 op_max /* never remove this one */
88
89 } CID_Operator;
90
91 static
92 const FT_Int t1_args_count[op_max] =
93 {
94 0, /* none */
95 0, /* endchar */
96 2, /* hsbw */
97 5, /* seac */
98 4, /* sbw */
99 0, /* closepath */
100
101 1, /* hlineto */
102 1, /* hmoveto */
103 4, /* hvcurveto */
104 2, /* rlineto */
105 2, /* rmoveto */
106 6, /* rrcurveto */
107 4, /* vhcurveto */
108 1, /* vlineto */
109 1, /* vmoveto */
110
111 0, /* dotsection */
112
113 2, /* hstem */
114 6, /* hstem3 */
115 2, /* vstem */
116 6, /* vstem3 */
117
118 2, /* div */
119 -1, /* callothersubr */
120 1, /* callsubr */
121 0, /* pop */
122 0, /* return */
123 2 /* setcurrentpoint */
124 };
125
126
127 /*************************************************************************/
128 /*************************************************************************/
129 /*************************************************************************/
130 /********** *********/
131 /********** *********/
132 /********** GENERIC CHARSTRING PARSING *********/
133 /********** *********/
134 /********** *********/
135 /*************************************************************************/
136 /*************************************************************************/
137 /*************************************************************************/
138
139
140 /*************************************************************************/
141 /* */
142 /* <Function> */
143 /* CID_Init_Builder */
144 /* */
145 /* <Description> */
146 /* Initializes a given glyph builder. */
147 /* */
148 /* <InOut> */
149 /* builder :: A pointer to the glyph builder to initialize. */
150 /* */
151 /* <Input> */
152 /* face :: The current face object. */
153 /* */
154 /* size :: The current size object. */
155 /* */
156 /* glyph :: The current glyph object. */
157 /* */
158 LOCAL_FUNC
159 void CID_Init_Builder( CID_Builder* builder,
160 CID_Face face,
161 CID_Size size,
162 CID_GlyphSlot glyph )
163 {
164 builder->path_begun = 0;
165 builder->load_points = 1;
166
167 builder->face = face;
168 builder->glyph = glyph;
169 builder->memory = face->root.memory;
170
171 if ( glyph )
172 {
173 FT_GlyphLoader* loader = glyph->root.loader;
174
175
176 builder->loader = loader;
177 builder->base = &loader->base.outline;
178 builder->current = &loader->current.outline;
179
180 FT_GlyphLoader_Rewind( loader );
181 }
182
183 if ( size )
184 {
185 builder->scale_x = size->root.metrics.x_scale;
186 builder->scale_y = size->root.metrics.y_scale;
187 }
188
189 builder->pos_x = 0;
190 builder->pos_y = 0;
191
192 builder->left_bearing.x = 0;
193 builder->left_bearing.y = 0;
194 builder->advance.x = 0;
195 builder->advance.y = 0;
196
197 }
198
199
200 /*************************************************************************/
201 /* */
202 /* <Function> */
203 /* CID_Done_Builder */
204 /* */
205 /* <Description> */
206 /* Finalizes a given glyph builder. Its contents can still be used */
207 /* after the call, but the function saves important information */
208 /* within the corresponding glyph slot. */
209 /* */
210 /* <Input> */
211 /* builder :: A pointer to the glyph builder to finalize. */
212 /* */
213 LOCAL_FUNC
214 void CID_Done_Builder( CID_Builder* builder )
215 {
216 CID_GlyphSlot glyph = builder->glyph;
217
218
219 if ( glyph )
220 glyph->root.outline = *builder->base;
221 }
222
223
224 /*************************************************************************/
225 /* */
226 /* <Function> */
227 /* CID_Init_Decoder */
228 /* */
229 /* <Description> */
230 /* Initializes a given glyph decoder. */
231 /* */
232 /* <InOut> */
233 /* decoder :: A pointer to the glyph builder to initialize. */
234 /* */
235 LOCAL_FUNC
236 void CID_Init_Decoder( CID_Decoder* decoder )
237 {
238 MEM_Set( decoder, 0, sizeof ( *decoder ) );
239
240 decoder->font_matrix.xx = 0x10000L;
241 decoder->font_matrix.yy = 0x10000L;
242 }
243
244
245 /* check that there is enough space for `count' more points */
246 static
247 FT_Error check_points( CID_Builder* builder,
248 FT_Int count )
249 {
250 return FT_GlyphLoader_Check_Points( builder->loader, count, 0 );
251 }
252
253
254 /* add a new point, but do not check space */
255 static
256 void add_point( CID_Builder* builder,
257 FT_Pos x,
258 FT_Pos y,
259 FT_Byte flag )
260 {
261 FT_Outline* outline = builder->current;
262
263
264 if ( builder->load_points )
265 {
266 FT_Vector* point = outline->points + outline->n_points;
267 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points;
268
269
270 point->x = x;
271 point->y = y;
272 *control = flag ? FT_Curve_Tag_On : FT_Curve_Tag_Cubic;
273
274 builder->last = *point;
275 }
276
277 outline->n_points++;
278 }
279
280
281 /* check space for a new on-curve point, then add it */
282 static
283 FT_Error add_point1( CID_Builder* builder,
284 FT_Pos x,
285 FT_Pos y )
286 {
287 FT_Error error;
288
289
290 error = check_points( builder, 1 );
291 if ( !error )
292 add_point( builder, x, y, 1 );
293
294 return error;
295 }
296
297
298 /* check room for a new contour, then add it */
299 static
300 FT_Error add_contour( CID_Builder* builder )
301 {
302 FT_Outline* outline = builder->current;
303 FT_Error error;
304
305
306 if ( !builder->load_points )
307 {
308 outline->n_contours++;
309 return T1_Err_Ok;
310 }
311
312 error = FT_GlyphLoader_Check_Points( builder->loader, 0, 1 );
313 if ( !error )
314 {
315 if ( outline->n_contours > 0 )
316 outline->contours[outline->n_contours - 1] = outline->n_points - 1;
317
318 outline->n_contours++;
319 }
320 return error;
321 }
322
323
324 /* if a path has been started, add its first on-curve point */
325 static
326 FT_Error start_point( CID_Builder* builder,
327 FT_Pos x,
328 FT_Pos y )
329 {
330 /* test whether we are building a new contour */
331 if ( !builder->path_begun )
332 {
333 FT_Error error;
334
335
336 builder->path_begun = 1;
337 error = add_contour( builder );
338 if ( error )
339 return error;
340 }
341
342 return add_point1( builder, x, y );
343 }
344
345
346 /* close the current contour */
347 static
348 void close_contour( CID_Builder* builder )
349 {
350 FT_Outline* outline = builder->current;
351
352
353 /* XXX: We must not include the last point in the path if it */
354 /* is located on the first point. */
355 if ( outline->n_points > 1 )
356 {
357 FT_Int first = 0;
358 FT_Vector* p1 = outline->points + first;
359 FT_Vector* p2 = outline->points + outline->n_points - 1;
360
361
362 if ( outline->n_contours > 1 )
363 {
364 first = outline->contours[outline->n_contours - 2] + 1;
365 p1 = outline->points + first;
366 }
367
368 if ( p1->x == p2->x && p1->y == p2->y )
369 outline->n_points--;
370 }
371
372 if ( outline->n_contours > 0 )
373 outline->contours[outline->n_contours - 1] = outline->n_points - 1;
374 }
375
376
377 #if 0
378
379
380 /*************************************************************************/
381 /* */
382 /* <Function> */
383 /* lookup_glyph_by_stdcharcode */
384 /* */
385 /* <Description> */
386 /* Looks up a given glyph by its StandardEncoding charcode. Used */
387 /* to implement the SEAC Type 1 operator. */
388 /* */
389 /* <Input> */
390 /* face :: The current face object. */
391 /* */
392 /* charcode :: The character code to look for. */
393 /* */
394 /* <Return> */
395 /* A glyph index in the font face. Returns -1 if the corresponding */
396 /* glyph wasn't found. */
397 /* */
398 static
399 FT_Int lookup_glyph_by_stdcharcode( CID_Face face,
400 FT_Int charcode )
401 {
402 FT_Int n;
403 const FT_String* glyph_name;
404 PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
405
406
407 /* check range of standard char code */
408 if ( charcode < 0 || charcode > 255 )
409 return -1;
410
411 glyph_name = psnames->adobe_std_strings(
412 psnames->adobe_std_encoding[charcode]);
413
414 for ( n = 0; n < face->cid.cid_count; n++ )
415 {
416 FT_String* name = (FT_String*)face->type1.glyph_names[n];
417
418
419 if ( name && strcmp( name, glyph_name ) == 0 )
420 return n;
421 }
422
423 return -1;
424 }
425
426
427 #endif /* 0 */
428
429
430 /*************************************************************************/
431 /* */
432 /* <Function> */
433 /* t1operator_seac */
434 /* */
435 /* <Description> */
436 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */
437 /* */
438 /* <Input> */
439 /* decoder :: The current CID decoder. */
440 /* */
441 /* asb :: The accent's side bearing. */
442 /* */
443 /* adx :: The horizontal offset of the accent. */
444 /* */
445 /* ady :: The vertical offset of the accent. */
446 /* */
447 /* bchar :: The base character's StandardEncoding charcode. */
448 /* */
449 /* achar :: The accent character's StandardEncoding charcode. */
450 /* */
451 /* <Return> */
452 /* FreeType error code. 0 means success. */
453 /* */
454 static
455 FT_Error t1operator_seac( CID_Decoder* decoder,
456 FT_Pos asb,
457 FT_Pos adx,
458 FT_Pos ady,
459 FT_Int bchar,
460 FT_Int achar )
461 {
462 FT_Error error;
463 FT_Int bchar_index, achar_index, n_base_points;
464 FT_Outline* base = decoder->builder.base;
465 FT_Vector left_bearing, advance;
466
467
468 bchar_index = bchar;
469 achar_index = achar;
470
471 if ( bchar_index < 0 || achar_index < 0 )
472 {
473 FT_ERROR(( "t1operator_seac:" ));
474 FT_ERROR(( " invalid seac character code arguments\n" ));
475 return T1_Err_Syntax_Error;
476 }
477
478 /* if we are trying to load a composite glyph, do not load the */
479 /* accent character and return the array of subglyphs. */
480 if ( decoder->builder.no_recurse )
481 {
482 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
483 FT_GlyphLoader* loader = glyph->loader;
484 FT_SubGlyph* subg;
485
486
487 /* reallocate subglyph array if necessary */
488 error = FT_GlyphLoader_Check_Subglyphs( loader, 2 );
489 if ( error )
490 goto Exit;
491
492 subg = loader->current.subglyphs;
493
494 /* subglyph 0 = base character */
495 subg->index = bchar_index;
496 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
497 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
498 subg->arg1 = 0;
499 subg->arg2 = 0;
500 subg++;
501
502 /* subglyph 1 = accent character */
503 subg->index = achar_index;
504 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
505 subg->arg1 = adx - asb;
506 subg->arg2 = ady;
507
508 /* set up remaining glyph fields */
509 glyph->num_subglyphs = 2;
510 glyph->subglyphs = loader->current.subglyphs;
511 glyph->format = ft_glyph_format_composite;
512
513 loader->current.num_subglyphs = 2;
514 }
515
516 /* First load `bchar' in builder */
517 /* now load the unscaled outline */
518 if ( decoder->builder.loader )
519 FT_GlyphLoader_Prepare( decoder->builder.loader );
520
521 error = cid_load_glyph( decoder, bchar_index ); /* load one glyph */
522 if ( error )
523 goto Exit;
524
525 n_base_points = base->n_points;
526
527 {
528 /* save the left bearing and width of the base character */
529 /* as they will be erased by the next load. */
530
531 left_bearing = decoder->builder.left_bearing;
532 advance = decoder->builder.advance;
533
534 decoder->builder.left_bearing.x = 0;
535 decoder->builder.left_bearing.y = 0;
536
537 /* Now load `achar' on top of */
538 /* the base outline */
539 error = cid_load_glyph( decoder, achar_index );
540 if ( error )
541 return error;
542
543 /* restore the left side bearing and */
544 /* advance width of the base character */
545
546 decoder->builder.left_bearing = left_bearing;
547 decoder->builder.advance = advance;
548
549 /* Finally, move the accent */
550 if ( decoder->builder.load_points )
551 {
552 FT_Outline dummy;
553
554
555 dummy.n_points = base->n_points - n_base_points;
556 dummy.points = base->points + n_base_points;
557 FT_Outline_Translate( &dummy, adx - asb, ady );
558 }
559 }
560
561 Exit:
562 return error;
563 }
564
565
566 #define USE_ARGS( n ) do \
567 { \
568 top -= n; \
569 if ( top < decoder->stack ) \
570 goto Stack_Underflow; \
571 } while ( 0 )
572
573
574 /*************************************************************************/
575 /* */
576 /* <Function> */
577 /* CID_Parse_CharStrings */
578 /* */
579 /* <Description> */
580 /* Parses a given CID charstrings program. */
581 /* */
582 /* <InOut> */
583 /* decoder :: The current CID decoder. */
584 /* */
585 /* <Input> */
586 /* charstring_base :: The base of the charstring stream. */
587 /* */
588 /* charstring_len :: The length in bytes of the charstring stream. */
589 /* */
590 /* <Return> */
591 /* FreeType error code. 0 means success. */
592 /* */
593 LOCAL_FUNC
594 FT_Error CID_Parse_CharStrings( CID_Decoder* decoder,
595 FT_Byte* charstring_base,
596 FT_Int charstring_len )
597 {
598 FT_Error error;
599 CID_Decoder_Zone* zone;
600 FT_Byte* ip;
601 FT_Byte* limit;
602 CID_Builder* builder = &decoder->builder;
603 FT_Outline* outline;
604 FT_Pos x, y;
605
606
607 /* First of all, initialize the decoder */
608 decoder->top = decoder->stack;
609 decoder->zone = decoder->zones;
610 zone = decoder->zones;
611
612 builder->path_begun = 0;
613
614 zone->base = charstring_base;
615 limit = zone->limit = charstring_base + charstring_len;
616 ip = zone->cursor = zone->base;
617
618 error = T1_Err_Ok;
619 outline = builder->current;
620
621 x = builder->pos_x;
622 y = builder->pos_y;
623
624 /* now, execute loop */
625 while ( ip < limit )
626 {
627 FT_Int* top = decoder->top;
628 CID_Operator op = op_none;
629 FT_Long value = 0;
630
631
632 /********************************************************************/
633 /* */
634 /* Decode operator or operand */
635 /* */
636
637 /* First of all, decompress operator or value */
638 switch ( *ip++ )
639 {
640 case 1:
641 op = op_hstem;
642 break;
643
644 case 3:
645 op = op_vstem;
646 break;
647 case 4:
648 op = op_vmoveto;
649 break;
650 case 5:
651 op = op_rlineto;
652 break;
653 case 6:
654 op = op_hlineto;
655 break;
656 case 7:
657 op = op_vlineto;
658 break;
659 case 8:
660 op = op_rrcurveto;
661 break;
662 case 9:
663 op = op_closepath;
664 break;
665 case 10:
666 op = op_callsubr;
667 break;
668 case 11:
669 op = op_return;
670 break;
671
672 case 13:
673 op = op_hsbw;
674 break;
675 case 14:
676 op = op_endchar;
677 break;
678
679 case 21:
680 op = op_rmoveto;
681 break;
682 case 22:
683 op = op_hmoveto;
684 break;
685
686 case 30:
687 op = op_vhcurveto;
688 break;
689 case 31:
690 op = op_hvcurveto;
691 break;
692
693 case 12:
694 if ( ip > limit )
695 {
696 FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+EOF)\n" ));
697 goto Syntax_Error;
698 }
699
700 switch ( *ip++ )
701 {
702 case 0:
703 op = op_dotsection;
704 break;
705 case 1:
706 op = op_vstem3;
707 break;
708 case 2:
709 op = op_hstem3;
710 break;
711 case 6:
712 op = op_seac;
713 break;
714 case 7:
715 op = op_sbw;
716 break;
717 case 12:
718 op = op_div;
719 break;
720 case 16:
721 op = op_callothersubr;
722 break;
723 case 17:
724 op = op_pop;
725 break;
726 case 33:
727 op = op_setcurrentpoint;
728 break;
729
730 default:
731 FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
732 ip[-1] ));
733 goto Syntax_Error;
734 }
735 break;
736
737 case 255: /* four bytes integer */
738 if ( ip + 4 > limit )
739 {
740 FT_ERROR(( "CID_Parse_CharStrings: unexpected EOF in integer\n" ));
741 goto Syntax_Error;
742 }
743
744 value = ( (long)ip[0] << 24 ) |
745 ( (long)ip[1] << 16 ) |
746 ( (long)ip[2] << 8 ) |
747 ip[3];
748 ip += 4;
749 break;
750
751 default:
752 if ( ip[-1] >= 32 )
753 {
754 if ( ip[-1] < 247 )
755 value = (long)ip[-1] - 139;
756 else
757 {
758 if ( ++ip > limit )
759 {
760 FT_ERROR(( "CID_Parse_CharStrings:" ));
761 FT_ERROR(( " unexpected EOF in integer\n" ));
762 goto Syntax_Error;
763 }
764
765 if ( ip[-2] < 251 )
766 value = ( (long)( ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
767 else
768 value = -( ( ( (long)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
769 }
770 }
771 else
772 {
773 FT_ERROR(( "CID_Parse_CharStrings: invalid byte (%d)\n",
774 ip[-1] ));
775 goto Syntax_Error;
776 }
777 }
778
779 /********************************************************************/
780 /* */
781 /* Push value on stack, or process operator */
782 /* */
783 if ( op == op_none )
784 {
785 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
786 {
787 FT_ERROR(( "CID_Parse_CharStrings: Stack overflow!\n" ));
788 goto Syntax_Error;
789 }
790
791 FT_TRACE4(( " %ld", value ));
792 *top++ = value;
793 decoder->top = top;
794 }
795 else if ( op == op_callothersubr ) /* callothersubr */
796 {
797 FT_TRACE4(( " callothersubr" ));
798
799 if ( top - decoder->stack < 2 )
800 goto Stack_Underflow;
801
802 top -= 2;
803 switch ( top[1] )
804 {
805 case 1: /* start flex feature ---------------------- */
806 if ( top[0] != 0 )
807 goto Unexpected_OtherSubr;
808
809 decoder->flex_state = 1;
810 decoder->num_flex_vectors = 0;
811 if ( start_point( builder, x, y ) ||
812 check_points( builder, 6 ) )
813 goto Memory_Error;
814 break;
815
816 case 2: /* add flex vectors ------------------------ */
817 {
818 FT_Int index;
819
820
821 if ( top[0] != 0 )
822 goto Unexpected_OtherSubr;
823
824 /* note that we should not add a point for index 0. */
825 /* this will move our current position to the flex */
826 /* point without adding any point to the outline */
827 index = decoder->num_flex_vectors++;
828 if ( index > 0 && index < 7 )
829 add_point( builder,
830 x,
831 y,
832 (FT_Byte)( index==3 || index==6 ) );
833 }
834 break;
835
836 case 0: /* end flex feature ------------------------- */
837 if ( top[0] != 3 )
838 goto Unexpected_OtherSubr;
839
840 if ( decoder->flex_state == 0 ||
841 decoder->num_flex_vectors != 7 )
842 {
843 FT_ERROR(( "CID_Parse_CharStrings: unexpected flex end\n" ));
844 goto Syntax_Error;
845 }
846
847 /* now consume the remaining `pop pop setcurpoint' */
848 if ( ip + 6 > limit ||
849 ip[0] != 12 || ip[1] != 17 || /* pop */
850 ip[2] != 12 || ip[3] != 17 || /* pop */
851 ip[4] != 12 || ip[5] != 33 ) /* setcurpoint */
852 {
853 FT_ERROR(( "CID_Parse_CharStrings: invalid flex charstring\n" ));
854 goto Syntax_Error;
855 }
856
857 ip += 6;
858 decoder->flex_state = 0;
859 break;
860
861 case 3: /* change hints ---------------------------- */
862 if ( top[0] != 1 )
863 goto Unexpected_OtherSubr;
864
865 /* eat the following `pop' */
866 if ( ip + 2 > limit )
867 {
868 FT_ERROR(( "CID_Parse_CharStrings: invalid escape (12+%d)\n",
869 ip[-1] ));
870 goto Syntax_Error;
871 }
872
873 if ( ip[0] != 12 || ip[1] != 17 )
874 {
875 FT_ERROR(( "CID_Parse_CharStrings:" ));
876 FT_ERROR(( " `pop' expected, found (%d %d)\n",
877 ip[0], ip[1] ));
878 goto Syntax_Error;
879 }
880 ip += 2;
881 break;
882
883 case 12:
884 case 13:
885 /* counter control hints, clear stack */
886 top = decoder->stack;
887 break;
888
889 #if 0
890
891 case 14:
892 case 15:
893 case 16:
894 case 17:
895 case 18: /* multiple masters */
896 {
897 T1_Blend* blend = decoder->blend;
898 FT_UInt num_points, nn, mm;
899 FT_Int* delta;
900 FT_Int* values;
901
902
903 if ( !blend )
904 {
905 FT_ERROR(( "CID_Parse_CharStrings:" ));
906 FT_ERROR(( " unexpected multiple masters operator!\n" ));
907 goto Syntax_Error;
908 }
909
910 num_points = top[1] - 13 + ( top[1] == 18 );
911 if ( top[0] != num_points * blend->num_designs )
912 {
913 FT_ERROR(( "CID_Parse_CharStrings:" ));
914 FT_ERROR(( " incorrect number of mm arguments\n" ));
915 goto Syntax_Error;
916 }
917
918 top -= blend->num_designs * num_points;
919 if ( top < decoder->stack )
920 goto Stack_Underflow;
921
922 /* We want to compute: */
923 /* */
924 /* a0*w0 + a1*w1 + ... + ak*wk */
925 /* */
926 /* but we only have the a0, a1-a0, a2-a0, .. ak-a0. */
927 /* However, given that w0 + w1 + ... + wk == 1, we can */
928 /* rewrite it easily as: */
929 /* */
930 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + .. + (ak-a0)*wk */
931 /* */
932 /* where k == num_designs-1 */
933 /* */
934 /* I guess that's why it's written in this `compact' */
935 /* form... */
936 /* */
937 delta = top + num_points;
938 values = top;
939 for ( nn = 0; nn < num_points; nn++ )
940 {
941 FT_Int x = values[0];
942
943
944 for ( mm = 1; mm < blend->num_designs; mm++ )
945 x += FT_MulFix( *delta++, blend->weight_vector[mm] );
946
947 *values++ = x;
948 }
949 /* note that `top' will be incremented later by calls to `pop' */
950 }
951 break;
952
953 #endif
954
955 default:
956 Unexpected_OtherSubr:
957 FT_ERROR(( "CID_Parse_CharStrings: invalid othersubr [%d %d]!\n",
958 top[0], top[1] ));
959 goto Syntax_Error;
960 }
961 decoder->top = top;
962 }
963 else /* general operator */
964 {
965 FT_Int num_args = t1_args_count[op];
966
967
968 if ( top - decoder->stack < num_args )
969 goto Stack_Underflow;
970
971 top -= num_args;
972
973 switch ( op )
974 {
975 case op_endchar:
976 FT_TRACE4(( " endchar" ));
977
978 close_contour( builder );
979
980 /* add current outline to the glyph slot */
981 FT_GlyphLoader_Add( builder->loader );
982
983 /* return now! */
984 FT_TRACE4(( "\n\n" ));
985 return T1_Err_Ok;
986
987 case op_hsbw:
988 FT_TRACE4(( " hsbw" ));
989
990 builder->left_bearing.x += top[0];
991 builder->advance.x = top[1];
992 builder->advance.y = 0;
993
994 builder->last.x = x = top[0];
995 builder->last.y = y = 0;
996
997 /* The `metrics_only' indicates that we only want to compute */
998 /* the glyph's metrics (lsb + advance width), not load the */
999 /* rest of it. So exit immediately. */
1000 if ( builder->metrics_only )
1001 return T1_Err_Ok;
1002
1003 break;
1004
1005 case op_seac:
1006 /* return immediately after processing */
1007 return t1operator_seac( decoder, top[0], top[1],
1008 top[2], top[3], top[4] );
1009
1010 case op_sbw:
1011 FT_TRACE4(( " sbw" ));
1012
1013 builder->left_bearing.x += top[0];
1014 builder->left_bearing.y += top[1];
1015 builder->advance.x = top[2];
1016 builder->advance.y = top[3];
1017
1018 builder->last.x = x = top[0];
1019 builder->last.y = y = top[1];
1020
1021 /* The `metrics_only' indicates that we only want to compute */
1022 /* the glyph's metrics (lsb + advance width), not load the */
1023 /* rest of it. So exit immediately. */
1024 if ( builder->metrics_only )
1025 return T1_Err_Ok;
1026
1027 break;
1028
1029 case op_closepath:
1030 FT_TRACE4(( " closepath" ));
1031
1032 close_contour( builder );
1033 builder->path_begun = 0;
1034 break;
1035
1036 case op_hlineto:
1037 FT_TRACE4(( " hlineto" ));
1038
1039 if ( start_point( builder, x, y ) )
1040 goto Memory_Error;
1041
1042 x += top[0];
1043 goto Add_Line;
1044
1045 case op_hmoveto:
1046 FT_TRACE4(( " hmoveto" ));
1047
1048 x += top[0];
1049 break;
1050
1051 case op_hvcurveto:
1052 FT_TRACE4(( " hvcurveto" ));
1053
1054 if ( start_point( builder, x, y ) ||
1055 check_points( builder, 3 ) )
1056 goto Memory_Error;
1057
1058 x += top[0];
1059 add_point( builder, x, y, 0 );
1060
1061 x += top[1];
1062 y += top[2];
1063 add_point( builder, x, y, 0 );
1064
1065 y += top[3];
1066 add_point( builder, x, y, 1 );
1067
1068 break;
1069
1070 case op_rlineto:
1071 FT_TRACE4(( " rlineto" ));
1072
1073 if ( start_point( builder, x, y ) )
1074 goto Memory_Error;
1075
1076 x += top[0];
1077 y += top[1];
1078
1079 Add_Line:
1080 if ( add_point1( builder, x, y ) )
1081 goto Memory_Error;
1082 break;
1083
1084 case op_rmoveto:
1085 FT_TRACE4(( " rmoveto" ));
1086
1087 x += top[0];
1088 y += top[1];
1089 break;
1090
1091 case op_rrcurveto:
1092 FT_TRACE4(( " rcurveto" ));
1093
1094 if ( start_point( builder, x, y ) ||
1095 check_points( builder, 3 ) )
1096 goto Memory_Error;
1097
1098 x += top[0];
1099 y += top[1];
1100 add_point( builder, x, y, 0 );
1101
1102 x += top[2];
1103 y += top[3];
1104 add_point( builder, x, y, 0 );
1105
1106 x += top[4];
1107 y += top[5];
1108 add_point( builder, x, y, 1 );
1109
1110 break;
1111
1112 case op_vhcurveto:
1113 FT_TRACE4(( " vhcurveto" ));
1114
1115 if ( start_point( builder, x, y ) ||
1116 check_points( builder, 3 ) )
1117 goto Memory_Error;
1118
1119 y += top[0];
1120 add_point( builder, x, y, 0 );
1121
1122 x += top[1];
1123 y += top[2];
1124 add_point( builder, x, y, 0 );
1125
1126 x += top[3];
1127 add_point( builder, x, y, 1 );
1128
1129 break;
1130
1131 case op_vlineto:
1132 FT_TRACE4(( " vlineto" ));
1133
1134 if ( start_point( builder, x, y ) )
1135 goto Memory_Error;
1136
1137 y += top[0];
1138 goto Add_Line;
1139
1140 case op_vmoveto:
1141 FT_TRACE4(( " vmoveto" ));
1142
1143 y += top[0];
1144 break;
1145
1146 case op_div:
1147 FT_TRACE4(( " div" ));
1148
1149 if ( top[1] )
1150 {
1151 *top = top[0] / top[1];
1152 top++;
1153 }
1154 else
1155 {
1156 FT_ERROR(( "CID_Parse_CharStrings: division by 0\n" ));
1157 goto Syntax_Error;
1158 }
1159 break;
1160
1161 case op_callsubr:
1162 {
1163 FT_Int index;
1164
1165
1166 FT_TRACE4(( " callsubr" ));
1167
1168 index = top[0];
1169 if ( index < 0 || index >= (FT_Int)decoder->subrs->num_subrs )
1170 {
1171 FT_ERROR(( "CID_Parse_CharStrings: invalid subrs index\n" ));
1172 goto Syntax_Error;
1173 }
1174
1175 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
1176 {
1177 FT_ERROR(( "CID_Parse_CharStrings: too many nested subrs\n" ));
1178 goto Syntax_Error;
1179 }
1180
1181 zone->cursor = ip; /* save current instruction pointer */
1182
1183 zone++;
1184 zone->base = decoder->subrs->code[index] + decoder->lenIV;
1185 zone->limit = decoder->subrs->code[index + 1];
1186 zone->cursor = zone->base;
1187
1188 if ( !zone->base )
1189 {
1190 FT_ERROR(( "CID_Parse_CharStrings: invoking empty subrs!\n" ));
1191 goto Syntax_Error;
1192 }
1193
1194 decoder->zone = zone;
1195 ip = zone->base;
1196 limit = zone->limit;
1197 }
1198 break;
1199
1200 case op_pop:
1201 FT_TRACE4(( " pop" ));
1202
1203 /* theoretically, the arguments are already on the stack */
1204 top++;
1205 break;
1206
1207 case op_return:
1208 FT_TRACE4(( " return" ));
1209
1210 if ( zone <= decoder->zones )
1211 {
1212 FT_ERROR(( "CID_Parse_CharStrings: unexpected return\n" ));
1213 goto Syntax_Error;
1214 }
1215
1216 zone--;
1217 ip = zone->cursor;
1218 limit = zone->limit;
1219 decoder->zone = zone;
1220
1221 break;
1222
1223 case op_dotsection:
1224 FT_TRACE4(( " dotsection" ));
1225
1226 break;
1227
1228 case op_hstem:
1229 FT_TRACE4(( " hstem" ));
1230
1231 break;
1232
1233 case op_hstem3:
1234 FT_TRACE4(( " hstem3" ));
1235
1236 break;
1237
1238 case op_vstem:
1239 FT_TRACE4(( " vstem" ));
1240
1241 break;
1242
1243 case op_vstem3:
1244 FT_TRACE4(( " vstem3" ));
1245
1246 break;
1247
1248 case op_setcurrentpoint:
1249 FT_TRACE4(( " setcurrentpoint" ));
1250
1251 FT_ERROR(( "CID_Parse_CharStrings:" ));
1252 FT_ERROR(( " unexpected `setcurrentpoint'\n" ));
1253 goto Syntax_Error;
1254
1255 default:
1256 FT_ERROR(( "CID_Parse_CharStrings: unhandled opcode %d\n", op ));
1257 goto Syntax_Error;
1258 }
1259
1260 decoder->top = top;
1261
1262 } /* general operator processing */
1263
1264 } /* while ip < limit */
1265
1266 FT_TRACE4(( "..end..\n\n" ));
1267
1268 return error;
1269
1270 Syntax_Error:
1271 return T1_Err_Syntax_Error;
1272
1273 Stack_Underflow:
1274 return T1_Err_Stack_Underflow;
1275
1276 Memory_Error:
1277 return builder->error;
1278 }
1279
1280
1281 #if 0
1282
1283
1284 /*************************************************************************/
1285 /*************************************************************************/
1286 /*************************************************************************/
1287 /********** *********/
1288 /********** *********/
1289 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
1290 /********** *********/
1291 /********** The following code is in charge of computing *********/
1292 /********** the maximum advance width of the font. It *********/
1293 /********** quickly processes each glyph charstring to *********/
1294 /********** extract the value from either a `sbw' or `seac' *********/
1295 /********** operator. *********/
1296 /********** *********/
1297 /*************************************************************************/
1298 /*************************************************************************/
1299 /*************************************************************************/
1300
1301
1302 LOCAL_FUNC
1303 FT_Error CID_Compute_Max_Advance( CID_Face face,
1304 FT_Int* max_advance )
1305 {
1306 FT_Error error;
1307 CID_Decoder decoder;
1308 FT_Int glyph_index;
1309
1310
1311 *max_advance = 0;
1312
1313 /* Initialize load decoder */
1314 CID_Init_Decoder( &decoder );
1315 CID_Init_Builder( &decoder.builder, face, 0, 0 );
1316
1317 decoder.builder.metrics_only = 1;
1318 decoder.builder.load_points = 0;
1319
1320 /* for each glyph, parse the glyph charstring and extract */
1321 /* the advance width */
1322 for ( glyph_index = 0; glyph_index < face->root.num_glyphs;
1323 glyph_index++ )
1324 {
1325 /* now get load the unscaled outline */
1326 error = cid_load_glyph( &decoder, glyph_index );
1327 /* ignore the error if one occurred - skip to next glyph */
1328 }
1329
1330 *max_advance = decoder.builder.advance.x;
1331
1332 return T1_Err_Ok;
1333 }
1334
1335
1336 #endif /* 0 */
1337
1338
1339 /*************************************************************************/
1340 /*************************************************************************/
1341 /*************************************************************************/
1342 /********** *********/
1343 /********** *********/
1344 /********** UNHINTED GLYPH LOADER *********/
1345 /********** *********/
1346 /********** The following code is in charge of loading a *********/
1347 /********** single outline. It completely ignores hinting *********/
1348 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
1349 /********** *********/
1350 /*************************************************************************/
1351 /*************************************************************************/
1352 /*************************************************************************/
1353
1354
1355 static
1356 FT_Error cid_load_glyph( CID_Decoder* decoder,
1357 FT_UInt glyph_index )
1358 {
1359 CID_Face face = decoder->builder.face;
1360 CID_Info* cid = &face->cid;
1361 FT_Byte* p;
1362 FT_UInt entry_len = cid->fd_bytes + cid->gd_bytes;
1363 FT_UInt fd_select;
1364 FT_ULong off1, glyph_len;
1365 FT_Stream stream = face->root.stream;
1366 FT_Error error = 0;
1367
1368
1369 /* read the CID font dict index and charstring offset from the CIDMap */
1370 if ( FILE_Seek( cid->data_offset + cid->cidmap_offset +
1371 glyph_index * entry_len) ||
1372 ACCESS_Frame( 2 * entry_len ) )
1373 goto Exit;
1374
1375 p = (FT_Byte*)stream->cursor;
1376 fd_select = (FT_UInt) cid_get_offset( &p, (FT_Byte)cid->fd_bytes );
1377 off1 = (FT_ULong)cid_get_offset( &p, (FT_Byte)cid->gd_bytes );
1378 p += cid->fd_bytes;
1379 glyph_len = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1;
1380
1381 FORGET_Frame();
1382
1383 /* now, if the glyph is not empty, set up the subrs array, and parse */
1384 /* the charstrings */
1385 if ( glyph_len > 0 )
1386 {
1387 CID_FontDict* dict;
1388 FT_Byte* charstring;
1389 FT_UInt lenIV;
1390 FT_Memory memory = face->root.memory;
1391
1392
1393 /* setup subrs */
1394 decoder->subrs = face->subrs + fd_select;
1395
1396 /* setup font matrix */
1397 dict = cid->font_dicts + fd_select;
1398 decoder->font_matrix = dict->font_matrix;
1399 lenIV = dict->private_dict.lenIV;
1400 decoder->lenIV = lenIV;
1401
1402 /* the charstrings are encoded (stupid!) */
1403 /* load the charstrings, then execute it */
1404
1405 if ( ALLOC( charstring, glyph_len ) )
1406 goto Exit;
1407
1408 if ( !FILE_Read_At( cid->data_offset + off1, charstring, glyph_len ) )
1409 {
1410 cid_decrypt( charstring, glyph_len, 4330 );
1411 error = CID_Parse_CharStrings( decoder,
1412 charstring + lenIV,
1413 glyph_len - lenIV );
1414 }
1415
1416 FREE( charstring );
1417 }
1418
1419 Exit:
1420 return error;
1421 }
1422
1423
1424 LOCAL_FUNC
1425 FT_Error CID_Load_Glyph( CID_GlyphSlot glyph,
1426 CID_Size size,
1427 FT_Int glyph_index,
1428 FT_Int load_flags )
1429 {
1430 FT_Error error;
1431 CID_Decoder decoder;
1432 CID_Face face = (CID_Face)glyph->root.face;
1433 FT_Bool hinting;
1434
1435
1436 if ( load_flags & FT_LOAD_NO_RECURSE )
1437 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
1438
1439 glyph->x_scale = size->root.metrics.x_scale;
1440 glyph->y_scale = size->root.metrics.y_scale;
1441
1442 glyph->root.outline.n_points = 0;
1443 glyph->root.outline.n_contours = 0;
1444
1445 hinting = ( load_flags & FT_LOAD_NO_SCALE ) == 0 &&
1446 ( load_flags & FT_LOAD_NO_HINTING ) == 0;
1447
1448 glyph->root.format = ft_glyph_format_outline;
1449
1450 {
1451 CID_Init_Decoder( &decoder );
1452 CID_Init_Builder( &decoder.builder, face, size, glyph );
1453
1454 /* set up the decoder */
1455 decoder.builder.no_recurse =
1456 (FT_Bool)( load_flags & FT_LOAD_NO_RECURSE );
1457
1458 error = cid_load_glyph( &decoder, glyph_index );
1459
1460 /* save new glyph tables */
1461 CID_Done_Builder( &decoder.builder );
1462 }
1463
1464 /* Now, set the metrics - this is rather simple, as */
1465 /* the left side bearing is the xMin, and the top side */
1466 /* bearing the yMax. */
1467 if ( !error )
1468 {
1469 /* for composite glyphs, return only the left side bearing and the */
1470 /* advance width */
1471 if ( load_flags & FT_LOAD_NO_RECURSE )
1472 {
1473 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
1474 glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
1475 }
1476 else
1477 {
1478 FT_BBox cbox;
1479 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
1480
1481
1482 /* copy the _unscaled_ advance width */
1483 metrics->horiAdvance = decoder.builder.advance.x;
1484
1485 /* make up vertical metrics */
1486 metrics->vertBearingX = 0;
1487 metrics->vertBearingY = 0;
1488 metrics->vertAdvance = 0;
1489
1490 glyph->root.format = ft_glyph_format_outline;
1491
1492 glyph->root.outline.flags &= ft_outline_owner;
1493 if ( size && size->root.metrics.y_ppem < 24 )
1494 glyph->root.outline.flags |= ft_outline_high_precision;
1495
1496 glyph->root.outline.flags |= ft_outline_reverse_fill;
1497
1498 #if 0
1499 glyph->root.outline.second_pass = TRUE;
1500 glyph->root.outline.high_precision = size->root.metrics.y_ppem < 24;
1501 glyph->root.outline.dropout_mode = 2;
1502 #endif
1503
1504 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 )
1505 {
1506 /* scale the outline and the metrics */
1507 FT_Int n;
1508 FT_Outline* cur = &glyph->root.outline;
1509 FT_Vector* vec = cur->points;
1510 FT_Fixed x_scale = glyph->x_scale;
1511 FT_Fixed y_scale = glyph->y_scale;
1512
1513
1514 /* First of all, scale the points */
1515 for ( n = cur->n_points; n > 0; n--, vec++ )
1516 {
1517 vec->x = FT_MulFix( vec->x, x_scale );
1518 vec->y = FT_MulFix( vec->y, y_scale );
1519 }
1520
1521 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
1522
1523 /* Then scale the metrics */
1524 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
1525 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale );
1526
1527 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
1528 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
1529 }
1530
1531 /* apply the font matrix */
1532 FT_Outline_Transform( &glyph->root.outline, &decoder.font_matrix );
1533
1534 /* compute the other metrics */
1535 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
1536
1537 /* grid fit the bounding box if necessary */
1538 if ( hinting )
1539 {
1540 cbox.xMin &= -64;
1541 cbox.yMin &= -64;
1542 cbox.xMax = ( cbox.xMax + 63 ) & -64;
1543 cbox.yMax = ( cbox.yMax + 63 ) & -64;
1544 }
1545
1546 metrics->width = cbox.xMax - cbox.xMin;
1547 metrics->height = cbox.yMax - cbox.yMin;
1548
1549 metrics->horiBearingX = cbox.xMin;
1550 metrics->horiBearingY = cbox.yMax;
1551 }
1552 }
1553
1554 return error;
1555 }
1556
1557
1558 /* END */