blob: e9cd8a3e55b7b6105943941ee4e09b38d3ac279e [file] [log] [blame]
David Turnerd2b1f351999-12-16 23:11:37 +00001/*******************************************************************
2 *
3 * t1gload.c 1.0
4 *
5 * Type1 Glyph Loader.
6 *
7 * Copyright 1996-1999 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#include <t1gload.h>
David Turnerefce08d2000-05-11 18:23:52 +000019#include <freetype/internal/ftdebug.h>
20#include <freetype/internal/ftstream.h>
David Turnerd2b1f351999-12-16 23:11:37 +000021
22#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
23#include <t1hinter.h>
24#endif
25
26 /**********************************************************************/
27 /**********************************************************************/
28 /**********************************************************************/
29 /********** *********/
30 /********** *********/
31 /********** GENERIC CHARSTRINGS PARSING *********/
32 /********** *********/
33 /********** *********/
34 /**********************************************************************/
35 /**********************************************************************/
36 /**********************************************************************/
37
38/*********************************************************************
39 *
40 * <Function>
41 * T1_Init_Builder
42 *
43 * <Description>
44 * Initialise a given glyph builder.
45 *
46 * <Input>
47 * builder :: glyph builder to initialise
48 * face :: current face object
49 * size :: current size object
50 * glyph :: current glyph object
51 * funcs :: glyph builder functions (or "methods").
52 *
53 *********************************************************************/
54
55 EXPORT_FUNC
56 void T1_Init_Builder( T1_Builder* builder,
57 T1_Face face,
58 T1_Size size,
59 T1_GlyphSlot glyph,
60 const T1_Builder_Funcs* funcs )
61 {
62 builder->funcs = *funcs;
63 builder->path_begun = 0;
64 builder->load_points = 1;
65
66 builder->face = face;
67 builder->size = size;
68 builder->glyph = glyph;
69 builder->memory = face->root.memory;
70
71 if (glyph)
72 {
73 builder->base = glyph->root.outline;
74 builder->max_points = glyph->max_points;
75 builder->max_contours = glyph->max_contours;
76 }
77
78 if (size)
79 {
80 builder->scale_x = size->root.metrics.x_scale;
81 builder->scale_y = size->root.metrics.y_scale;
82 }
83
84 builder->pos_x = 0;
85 builder->pos_y = 0;
86
87 builder->left_bearing.x = 0;
88 builder->left_bearing.y = 0;
89 builder->advance.x = 0;
90 builder->advance.y = 0;
91
92 builder->base.n_points = 0;
93 builder->base.n_contours = 0;
94 builder->current = builder->base;
95
96 builder->pass = 0;
97 builder->hint_point = 0;
98 }
99
100
101/*********************************************************************
102 *
103 * <Function>
104 * T1_Done_Builder
105 *
106 * <Description>
107 * Finalise a given glyph builder. Its content can still be
108 * used after the call, but the function saves important information
109 * within the corresponding glyph slot.
110 *
111 * <Input>
112 * builder :: glyph builder to initialise
113 *
114 *********************************************************************/
115
116 EXPORT_FUNC
117 void T1_Done_Builder( T1_Builder* builder )
118 {
119 T1_GlyphSlot glyph = builder->glyph;
120
121 if (glyph)
122 {
123 glyph->root.outline = builder->base;
124 glyph->max_points = builder->max_points;
125 glyph->max_contours = builder->max_contours;
126 }
127 }
128
129
130
131/*********************************************************************
132 *
133 * <Function>
134 * T1_Init_Decoder
135 *
136 * <Description>
137 * Initialise a given Type 1 decoder for parsing
138 *
139 * <Input>
140 * decoder :: Type 1 decoder to initialise
141 * funcs :: hinter functions interface
142 *
143 *********************************************************************/
144
145 EXPORT_FUNC
146 void T1_Init_Decoder( T1_Decoder* decoder,
147 const T1_Hinter_Funcs* funcs )
148 {
149 decoder->hinter = *funcs; /* copy hinter interface */
150 decoder->top = 0;
151 decoder->zone = 0;
152
153 decoder->flex_state = 0;
154 decoder->num_flex_vectors = 0;
155
156 /* Clear loader */
157 MEM_Set( &decoder->builder, 0, sizeof(decoder->builder) );
158 }
159
160
161/*********************************************************************
162 *
163 * <Function>
164 * lookup_glyph_by_stdcharcode
165 *
166 * <Description>
167 * Lookup a given glyph by its StandardEncoding charcode. Used
168 * to implement the SEAC Type 1 operator.
169 *
170 * <Input>
171 * face :: current face object
172 * charcode :: charcode to look for
173 *
174 * <Return>
175 * glyph index in font face. Returns -1 if the corresponding
176 * glyph wasn't found.
177 *
178 *********************************************************************/
179
180 static
181 T1_Int lookup_glyph_by_stdcharcode( T1_Face face,
182 T1_Int charcode )
183 {
David Turner3188a3a2000-02-13 13:34:18 +0000184 T1_Int n;
185 const T1_String* glyph_name;
186 PSNames_Interface* psnames = (PSNames_Interface*)face->psnames;
David Turnerd2b1f351999-12-16 23:11:37 +0000187
188 /* check range of standard char code */
189 if (charcode < 0 || charcode > 255)
190 return -1;
191
David Turner3188a3a2000-02-13 13:34:18 +0000192 glyph_name = psnames->adobe_std_strings(
193 psnames->adobe_std_encoding[charcode]);
David Turnerd2b1f351999-12-16 23:11:37 +0000194
David Turner76bbd572000-01-27 13:35:16 +0000195 for ( n = 0; n < face->type1.num_glyphs; n++ )
David Turnerd2b1f351999-12-16 23:11:37 +0000196 {
David Turner76bbd572000-01-27 13:35:16 +0000197 T1_String* name = (T1_String*)face->type1.glyph_names[n];
David Turnerd2b1f351999-12-16 23:11:37 +0000198
199 if ( name && strcmp(name,glyph_name) == 0 )
200 return n;
201 }
202
203 return -1;
204 }
205
206
207/*********************************************************************
208 *
209 * <Function>
210 * t1operator_seac
211 *
212 * <Description>
213 * Implements the "seac" Type 1 operator for a Type 1 decoder
214 *
215 * <Input>
216 * decoder :: current Type 1 decoder
217 * asb :: accent's side bearing
218 * adx :: horizontal position of accent
219 * ady :: vertical position of accent
220 * bchar :: base character's StandardEncoding charcode
221 * achar :: accent character's StandardEncoding charcode
222 *
223 * <Return>
224 * Error code. 0 means success.
225 *
226 *********************************************************************/
227
228 static
229 T1_Error t1operator_seac( T1_Decoder* decoder,
230 T1_Pos asb,
231 T1_Pos adx,
232 T1_Pos ady,
233 T1_Int bchar,
234 T1_Int achar )
235 {
236 T1_Error error;
237 T1_Face face = decoder->builder.face;
238 T1_Int bchar_index, achar_index, n_base_points;
239 FT_Outline* cur = &decoder->builder.current;
240 FT_Outline* base = &decoder->builder.base;
241 T1_Vector left_bearing, advance;
David Turner76bbd572000-01-27 13:35:16 +0000242 T1_Font* type1 = &face->type1;
David Turnerd2b1f351999-12-16 23:11:37 +0000243
244 bchar_index = lookup_glyph_by_stdcharcode( face, bchar );
245 achar_index = lookup_glyph_by_stdcharcode( face, achar );
246
247 if (bchar_index < 0 || achar_index < 0)
248 {
249 FT_ERROR(( "T1.Parse_Seac : invalid seac character code arguments\n" ));
250 return T1_Err_Syntax_Error;
251 }
252
253 /* First load "bchar" in builder */
254 /* now load the unscaled outline */
255 cur->n_points = 0;
256 cur->n_contours = 0;
257 cur->points = base->points + base->n_points;
David Turnered7f62a2000-03-28 11:19:28 +0000258 cur->tags = base->tags + base->n_points;
David Turnerd2b1f351999-12-16 23:11:37 +0000259 cur->contours = base->contours + base->n_contours;
260
261 error = T1_Parse_CharStrings( decoder,
David Turner76bbd572000-01-27 13:35:16 +0000262 type1->charstrings [bchar_index],
263 type1->charstrings_len[bchar_index],
264 type1->num_subrs,
265 type1->subrs,
266 type1->subrs_len );
David Turnerd2b1f351999-12-16 23:11:37 +0000267 if (error) return error;
268
269 n_base_points = cur->n_points;
270
David Turnered7f62a2000-03-28 11:19:28 +0000271 if ( decoder->builder.no_recurse )
David Turnerd2b1f351999-12-16 23:11:37 +0000272 {
David Turnered7f62a2000-03-28 11:19:28 +0000273 /* if we're trying to load a composite glyph, do not load the */
274 /* accent character and return the array of subglyphs.. */
275 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph;
276 FT_SubGlyph* subg;
David Turnerd2b1f351999-12-16 23:11:37 +0000277
David Turnered7f62a2000-03-28 11:19:28 +0000278 /* reallocate subglyph array if necessary */
279 if (glyph->max_subglyphs < 2)
280 {
281 FT_Memory memory = decoder->builder.face->root.memory;
282
283 if ( REALLOC_ARRAY( glyph->subglyphs, glyph->max_subglyphs,
284 2, FT_SubGlyph ) )
285 return error;
286
287 glyph->max_subglyphs = 2;
288 }
289
290 subg = glyph->subglyphs;
291
292 /* subglyph 0 = base character */
293 subg->index = bchar_index;
294 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES |
295 FT_SUBGLYPH_FLAG_USE_MY_METRICS;
296 subg->arg1 = 0;
297 subg->arg2 = 0;
298 subg++;
299
300 /* subglyph 1 = accent character */
301 subg->index = achar_index;
302 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES;
303 subg->arg1 = adx - asb;
304 subg->arg2 = ady;
305
306 /* set up remaining glyph fields */
307 glyph->num_subglyphs = 2;
308 glyph->format = ft_glyph_format_composite;
David Turnerd2b1f351999-12-16 23:11:37 +0000309 }
David Turnered7f62a2000-03-28 11:19:28 +0000310 else
311 {
312 /* save the left bearing and width of the base character */
313 /* as they will be erased by the next load.. */
314 left_bearing = decoder->builder.left_bearing;
315 advance = decoder->builder.advance;
316
317 decoder->builder.left_bearing.x = 0;
318 decoder->builder.left_bearing.y = 0;
319
320 /* Now load "achar" on top of */
321 /* the base outline */
322 /* */
323 cur->n_points = 0;
324 cur->n_contours = 0;
325 cur->points = base->points + base->n_points;
326 cur->tags = base->tags + base->n_points;
327 cur->contours = base->contours + base->n_contours;
328
329 error = T1_Parse_CharStrings( decoder,
330 type1->charstrings [achar_index],
331 type1->charstrings_len[achar_index],
332 type1->num_subrs,
333 type1->subrs,
334 type1->subrs_len );
335 if (error) return error;
336
337 /* adjust contours in accented character outline */
338 {
339 T1_Int n;
340
341 for ( n = 0; n < cur->n_contours; n++ )
342 cur->contours[n] += n_base_points;
343 }
344
345 /* restore the left side bearing and */
346 /* advance width of the base character */
347 decoder->builder.left_bearing = left_bearing;
348 decoder->builder.advance = advance;
349
350 /* Finally, move the accent */
351 FT_Outline_Translate( cur, adx - asb, ady );
352 }
David Turnerd2b1f351999-12-16 23:11:37 +0000353 return T1_Err_Ok;
354 }
355
356/*********************************************************************
357 *
358 * <Function>
359 * t1operator_flex
360 *
361 * <Description>
362 * Implements the "flex" Type 1 operator for a Type 1 decoder
363 *
364 * <Input>
365 * decoder :: current Type 1 decoder
366 * threshold :: threshold
367 * end_x :: position of final flex point
368 * end_y :: position of final flex point
369 *
370 * <Return>
371 * Error code. 0 means success.
372 *
373 *********************************************************************/
374
375 static
376 T1_Error t1operator_flex( T1_Decoder* decoder,
377 T1_Pos threshold,
378 T1_Pos end_x,
379 T1_Pos end_y )
380 {
381 T1_Vector vec;
382 T1_Vector* flex = decoder->flex_vectors;
383 T1_Int n;
384
385 /* we don't even try to test the threshold in the non-hinting */
386 /* builder, even if the flex operator is said to be a path */
387 /* construction statement in the specification. This is better */
388 /* left to the hinter.. */
389
390 flex = decoder->flex_vectors;
391 vec = *flex++;
392
393 for ( n = 0; n < 6; n++ )
394 {
395 flex->x += vec.x;
396 flex->y += vec.y;
397
398 vec = *flex++;
399 }
400
401
402 (void)threshold;
403 (void)end_x;
404 (void)end_y;
405
406 flex = decoder->flex_vectors;
407
408 return decoder->builder.funcs.rcurve_to( &decoder->builder,
409 flex[0].x, flex[0].y,
410 flex[1].x, flex[1].y,
411 flex[2].x, flex[2].y ) ||
412
413 decoder->builder.funcs.rcurve_to( &decoder->builder,
414 flex[3].x, flex[3].y,
415 flex[4].x, flex[4].y,
416 flex[5].x, flex[5].y );
417 }
418
419
420/*********************************************************************
421 *
422 * <Function>
423 * T1_Parse_CharStrings
424 *
425 * <Description>
426 * Parses a given Type 1 charstrings program
427 *
428 * <Input>
429 * decoder :: current Type 1 decoder
430 * charstring_base :: base of the charstring stream
431 * charstring_len :: length in bytes of the charstring stream
432 * num_subrs :: number of sub-routines
433 * subrs_base :: array of sub-routines addresses
434 * subrs_len :: array of sub-routines lengths
435 *
436 * <Return>
437 * Error code. 0 means success.
438 *
439 *********************************************************************/
440
441 EXPORT_FUNC
442 T1_Error T1_Parse_CharStrings( T1_Decoder* decoder,
443 T1_Byte* charstring_base,
444 T1_Int charstring_len,
445 T1_Int num_subrs,
446 T1_Byte** subrs_base,
447 T1_Int* subrs_len )
448 {
449 T1_Error error;
450 T1_Decoder_Zone* zone;
451 T1_Byte* ip;
452 T1_Byte* limit;
453 T1_Builder* builder = &decoder->builder;
454 T1_Builder_Funcs* builds = &builder->funcs;
455 T1_Hinter_Funcs* hints = &decoder->hinter;
456
457 static const T1_Int args_count[ op_max ] =
458 {
459 0, /* none */
460 0, /* endchar */
461 2, /* hsbw */
462 5, /* seac */
463 4, /* sbw */
464 0, /* closepath */
465 1, /* hlineto */
466 1, /* hmoveto */
467 4, /* hvcurveto */
468 2, /* rlineto */
469 2, /* rmoveto */
470 6, /* rrcurveto */
471 4, /* vhcurveto */
472 1, /* vlineto */
473 1, /* vmoveto */
474 0, /* dotsection */
475 2, /* hstem */
476 6, /* hstem3 */
477 2, /* vstem */
478 6, /* vstem3 */
479 2, /* div */
480 -1, /* callothersubr */
481 1, /* callsubr */
482 0, /* pop */
483 0, /* return */
484 2 /* setcurrentpoint */
485 };
486
487 /* First of all, initialise the decoder */
488 decoder->top = decoder->stack;
489 decoder->zone = decoder->zones;
490 zone = decoder->zones;
491
492 builder->path_begun = 0;
493
494 zone->base = charstring_base;
495 limit = zone->limit = charstring_base + charstring_len;
496 ip = zone->cursor = zone->base;
497
498 error = T1_Err_Ok;
499
500 /* now, execute loop */
501 while ( ip < limit )
502 {
503 T1_Int* top = decoder->top;
504 T1_Operator op = op_none;
505 T1_Long value = 0;
506
507 /* First of all, decompress operator or value */
508 switch (*ip++)
509 {
510 case 1: op = op_hstem; break;
511
512 case 3: op = op_vstem; break;
513 case 4: op = op_vmoveto; break;
514 case 5: op = op_rlineto; break;
515 case 6: op = op_hlineto; break;
516 case 7: op = op_vlineto; break;
517 case 8: op = op_rrcurveto; break;
518 case 9: op = op_closepath; break;
519 case 10: op = op_callsubr; break;
520 case 11: op = op_return; break;
521
522 case 13: op = op_hsbw; break;
523 case 14: op = op_endchar; break;
524
525 case 21: op = op_rmoveto; break;
526 case 22: op = op_hmoveto; break;
527
528 case 30: op = op_vhcurveto; break;
529 case 31: op = op_hvcurveto; break;
530
531 case 12:
532 {
533 if (ip > limit)
534 {
535 FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+EOF)\n" ));
536 goto Syntax_Error;
537 }
538
539 switch (*ip++)
540 {
541 case 0: op = op_dotsection; break;
542 case 1: op = op_vstem3; break;
543 case 2: op = op_hstem3; break;
544 case 6: op = op_seac; break;
545 case 7: op = op_sbw; break;
546 case 12: op = op_div; break;
547 case 16: op = op_callothersubr; break;
548 case 17: op = op_pop; break;
549 case 33: op = op_setcurrentpoint; break;
550
551 default:
552 FT_ERROR(( "T1.Parse_CharStrings : invalid escape (12+%d)\n",
553 ip[-1] ));
554 goto Syntax_Error;
555 }
556 }
557 break;
558
559 case 255: /* four bytes integer */
560 {
561 if (ip+4 > limit)
562 {
563 FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
564 goto Syntax_Error;
565 }
566
567 value = ((long)ip[0] << 24) |
568 ((long)ip[1] << 16) |
569 ((long)ip[2] << 8) |
570 ip[3];
571 ip += 4;
572 }
573 break;
574
575 default:
576 if (ip[-1] >= 32)
577 {
578 if (ip[-1] < 247)
579 value = (long)ip[-1] - 139;
580 else
581 {
582 if (++ip > limit)
583 {
584 FT_ERROR(( "T1.Parse_CharStrings : unexpected EOF in integer\n" ));
585 goto Syntax_Error;
586 }
587
588 if (ip[-2] < 251)
589 value = ((long)(ip[-2]-247) << 8) + ip[-1] + 108;
590 else
591 value = -((((long)ip[-2]-251) << 8) + ip[-1] + 108 );
592 }
593 }
594 else
595 {
596 FT_ERROR(( "T1.Parse_CharStrings : invalid byte (%d)\n",
597 ip[-1] ));
598 goto Syntax_Error;
599 }
600 }
601
602 /* push value if needed */
603 if ( op == op_none )
604 {
605 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS )
606 {
607 FT_ERROR(( "T1.Parse_CharStrings : Stack overflow !!\n" ));
608 goto Syntax_Error;
609 }
610
611 *top++ = value;
612 decoder->top = top;
613 }
614
615 else if ( op == op_callothersubr ) /* check arguments differently */
616 {
617 if ( top - decoder->stack < 2)
618 goto Stack_Underflow;
619
620 top -= 2;
621
622 switch (top[1])
623 {
624 case 1: /* start flex feature ----------------------------- */
625 {
626 if (top[0] != 0) goto Unexpected_OtherSubr;
627
628 decoder->flex_state = 1;
629 decoder->num_flex_vectors = 0;
630 decoder->flex_vectors[0].x = 0;
631 decoder->flex_vectors[0].y = 0;
632 }
633 break;
634
635
636 case 2: /* add flex vector ------------------------------- */
637 {
638 T1_Int index;
639 T1_Vector* flex;
640
641 if (top[0] != 0) goto Unexpected_OtherSubr;
642
643 top -= 2;
644 if (top < decoder->stack) goto Stack_Underflow;
645
646 index = decoder->num_flex_vectors++;
647 if (index >= 7)
648 {
649 FT_ERROR(( "T1.Parse_CharStrings: too many flex vectors !\n" ));
650 goto Syntax_Error;
651 }
652
653 flex = decoder->flex_vectors + index;
654 flex->x += top[0];
655 flex->y += top[1];
656
657 }
658 break;
659
660
661 case 0: /* end flex feature ------------------------------ */
662 {
663 if ( decoder->flex_state == 0 ||
664 decoder->num_flex_vectors != 7 )
665 {
666 FT_ERROR(( "T1.Parse_CharStrings: unexpected flex end\n" ));
667 goto Syntax_Error;
668 }
669
670 if (top[0] != 3) goto Unexpected_OtherSubr;
671
672 top -= 3;
673 if (top < decoder->stack) goto Stack_Underflow;
674
675 /* now consume the remaining "pop pop setcurrentpoint" */
676 if ( ip+6 > limit ||
677 ip[0] != 12 || ip[1] != 17 || /* pop */
678 ip[2] != 12 || ip[3] != 17 || /* pop */
679 ip[4] != 12 || ip[5] != 33 ) /* setcurrentpoint */
680 {
681 FT_ERROR(( "T1.Parse_CharStrings: invalid flex charstring\n" ));
682 goto Syntax_Error;
683 }
684
685 decoder->flex_state = 0;
686 decoder->top = top;
687
688 error = t1operator_flex( decoder, top[0], top[1], top[2] );
689 }
690 break;
691
692
693 case 3: /* change hints ------------------------------------ */
694 {
695 if (top[0] != 1) goto Unexpected_OtherSubr;
696
697 /* eat the following "pop" */
698 if (ip+2 > limit)
699 {
700 FT_ERROR(( "T1.Parse_CharStrings: invalid escape (12+%d)\n",
701 ip[-1] ));
702 goto Syntax_Error;
703 }
704
705 if (ip[0] != 12 || ip[1] != 17)
706 {
707 FT_ERROR(( "T1.Parse_CharStrings: 'pop' expected, found (%d %d)\n",
708 ip[0], ip[1] ));
709 goto Syntax_Error;
710 }
711
712 ip += 2;
713 error = hints->change_hints(builder);
714 }
715 break;
716
717
718 default:
719 /* invalid OtherSubrs call */
720 Unexpected_OtherSubr:
721 FT_ERROR(( "T1.Parse_CharStrings: unexpected OtherSubrs [%d %d]\n",
722 top[0], top[1] ));
723 goto Syntax_Error;
724 }
725 decoder->top = top;
726 }
727 else
728 {
729 T1_Int num_args = args_count[op];
730
731 if ( top - decoder->stack < num_args )
732 goto Stack_Underflow;
733
734 top -= num_args;
735
736 switch (op)
737 {
738 case op_endchar:
739 error = builds->end_char( builder );
740 break;
741
742 case op_hsbw:
743 error = builds->set_bearing_point( builder, top[0], 0,
744 top[1], 0 );
745 break;
746
747 case op_seac:
748 /* return immediately after the processing */
749 return t1operator_seac( decoder, top[0], top[1],
750 top[2], top[3], top[4] );
751
752 case op_sbw:
753 error = builds->set_bearing_point( builder, top[0], top[1],
754 top[2], top[3] );
755 break;
756
757 case op_closepath:
758 error = builds->close_path( builder );
759 break;
760
761 case op_hlineto:
762 error = builds->rline_to( builder, top[0], 0 );
763 break;
764
765 case op_hmoveto:
766 error = builds->rmove_to( builder, top[0], 0 );
767 break;
768
769 case op_hvcurveto:
770 error = builds->rcurve_to( builder, top[0], 0,
771 top[1], top[2],
772 0, top[3] );
773 break;
774
775 case op_rlineto:
776 error = builds->rline_to( builder, top[0], top[1] );
777 break;
778
779 case op_rmoveto:
780 /* ignore operator when in flex mode */
781 if (decoder->flex_state == 0)
782 error = builds->rmove_to( builder, top[0], top[1] );
783 else
784 top += 2;
785 break;
786
787 case op_rrcurveto:
788 {
789 error = builds->rcurve_to( builder, top[0], top[1],
790 top[2], top[3],
791 top[4], top[5] );
792 }
793 break;
794
795 case op_vhcurveto:
796 error = builds->rcurve_to( builder, 0, top[0],
797 top[1], top[2],
798 top[3], 0 );
799 break;
800
801 case op_vlineto:
802 error = builds->rline_to( builder, 0, top[0] );
803 break;
804
805 case op_vmoveto:
806 error = builds->rmove_to( builder, 0, top[0] );
807 break;
808
809 case op_dotsection:
810 error = hints->dot_section( builder );
811 break;
812
813 case op_hstem:
814 error = hints->stem( builder, top[0], top[1], 0 );
815 break;
816
817 case op_hstem3:
818 error = hints->stem3( builder, top[0], top[1], top[2],
819 top[3], top[4], top[5], 0 );
820 break;
821
822 case op_vstem:
823 error = hints->stem( builder, top[0], top[1], 1 );
824 break;
825
826 case op_vstem3:
827 error = hints->stem3( builder, top[0], top[1], top[2],
828 top[3], top[4], top[5], 1 );
829 break;
830
831 case op_div:
832 if (top[1])
833 *top++ = top[0] / top[1];
834 else
835 {
836 FT_ERROR(( "T1.Parse_CHarStrings : division by 0\n" ));
837 goto Syntax_Error;
838 }
839 break;
840
841 case op_callsubr:
842 {
843 T1_Int index = top[0];
844
845 if ( index < 0 || index >= num_subrs )
846 {
847 FT_ERROR(( "T1.Parse_CharStrings : invalid subrs index\n" ));
848 goto Syntax_Error;
849 }
850
851 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS )
852 {
853 FT_ERROR(( "T1.Parse_CharStrings : too many nested subrs\n" ));
854 goto Syntax_Error;
855 }
856
857 zone->cursor = ip; /* save current instruction pointer */
858
859 zone++;
860 zone->base = subrs_base[index];
861 zone->limit = zone->base + subrs_len[index];
862 zone->cursor = zone->base;
863
864 if (!zone->base)
865 {
866 FT_ERROR(( "T1.Parse_CharStrings : invoking empty subrs !!\n" ));
867 goto Syntax_Error;
868 }
869
870 decoder->zone = zone;
871 ip = zone->base;
872 limit = zone->limit;
873 }
874 break;
875
876 case op_pop:
877 FT_ERROR(( "T1.Parse_CharStrings : unexpected POP\n" ));
878 goto Syntax_Error;
879
880
881 case op_return:
882 if ( zone <= decoder->zones )
883 {
884 FT_ERROR(( "T1.Parse_CharStrings : unexpected return\n" ));
885 goto Syntax_Error;
886 }
887
888 zone--;
889 ip = zone->cursor;
890 limit = zone->limit;
891 decoder->zone = zone;
892 break;
893
894 case op_setcurrentpoint:
895 FT_ERROR(( "T1.Parse_CharStrings : unexpected SETCURRENTPOINT\n" ));
896 goto Syntax_Error;
897 break;
898
899 default:
900 FT_ERROR(( "T1.Parse_CharStrings : unhandled opcode %d\n", op ));
901 goto Syntax_Error;
902 }
903
904 decoder->top = top;
905 }
906 }
907
908 return error;
909
910 Syntax_Error:
911 return T1_Err_Syntax_Error;
912
913 Stack_Underflow:
914 return T1_Err_Stack_Underflow;
915 }
916
917
918
919/*************************************************************************/
920/* */
921/* <Function> T1_Add_Points */
922/* */
923/* <Description> */
924/* Checks that there is enough room in the current load glyph outline */
925/* to accept "num_points" additional outline points. If not, this */
926/* function grows the load outline's arrays accordingly.. */
927/* */
928/* <Input> */
929/* builder :: pointer to glyph builder object */
930/* num_points :: number of points that will be added later */
931/* */
932/* <Return> */
933/* Type1 error code. 0 means success */
934/* */
935/* <Note> */
936/* This function does NOT update the points count in the glyph builder*/
937/* This must be done by the caller itself, after this function is */
938/* invoked.. */
939/* */
940 LOCAL_FUNC
941 T1_Error T1_Add_Points( T1_Builder* builder,
942 T1_Int num_points )
943 {
944 T1_Int new_points;
945
946 new_points = builder->base.n_points +
947 builder->current.n_points +
948 num_points;
949
950 if ( new_points > builder->max_points )
951 {
952 FT_Memory memory = builder->memory;
953 T1_Error error;
954 T1_Int increment = builder->current.points - builder->base.points;
955 T1_Int current = builder->max_points;
956
957 while ( builder->max_points < new_points )
958 builder->max_points += 16;
959
960 if ( REALLOC_ARRAY( builder->base.points,
961 current, builder->max_points, T1_Vector ) ||
962
David Turner41dbcbf2000-03-09 11:46:25 +0000963 REALLOC_ARRAY( builder->base.tags,
David Turnerd2b1f351999-12-16 23:11:37 +0000964 current, builder->max_points, T1_Byte ) )
965 return error;
966
967 builder->current.points = builder->base.points + increment;
David Turner41dbcbf2000-03-09 11:46:25 +0000968 builder->current.tags = builder->base.tags + increment;
David Turnerd2b1f351999-12-16 23:11:37 +0000969 }
970
971 return T1_Err_Ok;
972 }
973
974/*************************************************************************/
975/* */
976/* <Function> T1_Add_Contours */
977/* */
978/* <Description> */
979/* Checks that there is enough room in the current load glyph outline */
980/* to accept "num_contours" additional contours. If not, this func */
981/* the load outline's arrays accordingly.. */
982/* */
983/* <Input> */
984/* builder :: pointer to glyph builder object */
985/* num_contours :: number of contours that will be added later */
986/* */
987/* <Return> */
988/* Type1 error code. 0 means success */
989/* */
990/* <Note> */
991/* This function does NOT update the contours count in the load glyph */
992/* This must be done by the caller itself, after this function is */
993/* invoked.. */
994/* */
995 LOCAL_FUNC
996 T1_Error T1_Add_Contours( T1_Builder* builder,
997 T1_Int num_contours )
998 {
999 T1_Int new_contours;
1000
1001 new_contours = builder->base.n_contours +
1002 builder->current.n_contours +
1003 num_contours;
1004
1005 if ( new_contours > builder->max_contours && builder->load_points )
1006 {
1007 T1_Error error;
1008 FT_Memory memory = builder->memory;
1009 T1_Int increment = builder->current.contours - builder->base.contours;
1010 T1_Int current = builder->max_contours;
1011
1012 while ( builder->max_contours < new_contours )
1013 builder->max_contours += 4;
1014
1015 if ( REALLOC_ARRAY( builder->base.contours,
1016 current, builder->max_contours, T1_Short ) )
1017 return error;
1018
1019 builder->current.contours = builder->base.contours + increment;
1020 }
1021
1022 return T1_Err_Ok;
1023 }
1024
1025
1026 /**********************************************************************/
1027 /**********************************************************************/
1028 /**********************************************************************/
1029 /********** *********/
1030 /********** *********/
1031 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/
1032 /********** *********/
1033 /********** The following code is in charge of computing *********/
1034 /********** the maximum advance width of the font. It *********/
1035 /********** quickly process each glyph charstring to *********/
1036 /********** extract the value from either a "sbw" or "seac" *********/
1037 /********** operator. *********/
1038 /********** *********/
1039 /**********************************************************************/
1040 /**********************************************************************/
1041 /**********************************************************************/
1042
1043
1044
1045 static
1046 T1_Error maxadv_sbw( T1_Decoder* decoder,
1047 T1_Pos sbx,
1048 T1_Pos sby,
1049 T1_Pos wx,
1050 T1_Pos wy )
1051 {
1052 if (wx > decoder->builder.advance.x)
1053 decoder->builder.advance.x = wx;
1054
1055 (void)sbx;
1056 (void)sby;
1057 (void)wy;
1058 return -1; /* return an error code to exit the Type 1 parser */
1059 /* immediately. */
1060 }
1061
1062
1063 static
1064 T1_Int maxadv_error( void )
1065 {
1066 /* we should never reach this code, unless with a buggy font */
1067 return -2;
1068 }
1069
1070 /* the maxadv_gbuilder_interface is used when computing the maximum */
1071 /* advance width of all glyphs in a given font. We only process the */
1072 /* 'sbw' operator here, and return an error for all others.. */
1073
1074 /* Note that "seac" is processed by the T1_Decoder */
1075 static
1076 const T1_Builder_Funcs maxadv_builder_interface =
1077 {
1078 (T1_Builder_EndChar) maxadv_error,
1079 (T1_Builder_Sbw) maxadv_sbw,
1080 (T1_Builder_ClosePath) maxadv_error,
1081 (T1_Builder_RLineTo) maxadv_error,
1082 (T1_Builder_RMoveTo) maxadv_error,
1083 (T1_Builder_RCurveTo) maxadv_error
1084 };
1085
1086
1087 /* the maxadv_interface is used when computing the maximum advance */
1088 /* with of the set of glyphs in a given font file. We only process */
1089 /* the "seac" operator and return immediately.. */
1090 static
1091 const T1_Hinter_Funcs maxadv_hinter_interface =
1092 {
1093 (T1_Hinter_DotSection) maxadv_error,
1094 (T1_Hinter_ChangeHints) maxadv_error,
1095 (T1_Hinter_Stem) maxadv_error,
1096 (T1_Hinter_Stem3) maxadv_error,
1097 };
1098
1099
1100
1101 LOCAL_FUNC
1102 T1_Error T1_Compute_Max_Advance( T1_Face face,
1103 T1_Int *max_advance )
1104 {
1105 T1_Error error;
1106 T1_Decoder decoder;
1107 T1_Int glyph_index;
David Turner76bbd572000-01-27 13:35:16 +00001108 T1_Font* type1 = &face->type1;
David Turnerd2b1f351999-12-16 23:11:37 +00001109
1110 *max_advance = 0;
1111
1112 /* Initialise load decoder */
1113 T1_Init_Decoder( &decoder, &maxadv_hinter_interface );
1114
1115 T1_Init_Builder( &decoder.builder, face, 0, 0,
1116 &maxadv_builder_interface );
1117
1118 /* For each glyph, parse the glyph charstring and extract */
1119 /* the advance width.. */
David Turner76bbd572000-01-27 13:35:16 +00001120 for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ )
David Turnerd2b1f351999-12-16 23:11:37 +00001121 {
1122 /* now get load the unscaled outline */
1123 error = T1_Parse_CharStrings( &decoder,
David Turner76bbd572000-01-27 13:35:16 +00001124 type1->charstrings [glyph_index],
1125 type1->charstrings_len[glyph_index],
1126 type1->num_subrs,
1127 type1->subrs,
1128 type1->subrs_len );
David Turnerd2b1f351999-12-16 23:11:37 +00001129 /* ignore the error if one occured - skip to next glyph */
1130 (void)error;
1131 }
1132
1133 *max_advance = decoder.builder.advance.x;
1134 return T1_Err_Ok;
1135 }
1136
1137
1138 /**********************************************************************/
1139 /**********************************************************************/
1140 /**********************************************************************/
1141 /********** *********/
1142 /********** *********/
1143 /********** UNHINTED GLYPH LOADER *********/
1144 /********** *********/
1145 /********** The following code is in charge of loading a *********/
1146 /********** single outline. It completely ignores hinting *********/
1147 /********** and is used when FT_LOAD_NO_HINTING is set. *********/
1148 /********** *********/
1149 /********** The Type 1 hinter is located in "t1hint.c" *********/
1150 /********** *********/
1151 /**********************************************************************/
1152 /**********************************************************************/
1153 /**********************************************************************/
1154
1155
1156
1157 static
1158 T1_Error close_open_path( T1_Builder* builder )
1159 {
1160 T1_Error error;
1161 FT_Outline* cur = &builder->current;
1162 T1_Int num_points;
1163 T1_Int first_point;
1164
1165 /* Some fonts, like Hershey, are made of "open paths" which are */
1166 /* now managed directly by FreeType. In this case, it is necessary */
1167 /* to close the path by duplicating its points in reverse order, */
1168 /* which is precisely the purpose of this function */
1169
1170 /* first compute the number of points to duplicate.. */
1171 if (cur->n_contours > 1)
1172 first_point = cur->contours[ cur->n_contours-2 ]+1;
1173 else
1174 first_point = 0;
1175
1176 num_points = cur->n_points - first_point - 2;
1177 if ( num_points > 0 )
1178 {
1179 T1_Vector* source_point;
David Turner41dbcbf2000-03-09 11:46:25 +00001180 char* source_tags;
David Turnerd2b1f351999-12-16 23:11:37 +00001181 T1_Vector* point;
David Turner41dbcbf2000-03-09 11:46:25 +00001182 char* tags;
David Turnerd2b1f351999-12-16 23:11:37 +00001183
1184 error = T1_Add_Points( builder, num_points );
1185 if (error) return error;
1186
1187 point = cur->points + cur->n_points;
David Turner41dbcbf2000-03-09 11:46:25 +00001188 tags = cur->tags + cur->n_points;
David Turnerd2b1f351999-12-16 23:11:37 +00001189
1190 source_point = point - 2;
David Turner41dbcbf2000-03-09 11:46:25 +00001191 source_tags = tags - 2;
David Turnerd2b1f351999-12-16 23:11:37 +00001192
1193 cur->n_points += num_points;
1194
1195 if ( builder->load_points )
1196 do
1197 {
1198 *point++ = *source_point--;
David Turner41dbcbf2000-03-09 11:46:25 +00001199 *tags++ = *source_tags--;
David Turnerd2b1f351999-12-16 23:11:37 +00001200 num_points--;
1201 }
1202 while (num_points > 0);
1203 }
1204
1205 builder->path_begun = 0;
1206 return T1_Err_Ok;
1207 }
1208
1209
1210 static
1211 T1_Error gload_closepath( T1_Builder* builder )
1212 {
1213 FT_Outline* cur = &builder->current;
1214
1215 /* save current contour, if any */
1216 if ( cur->n_contours > 0 )
1217 cur->contours[cur->n_contours-1] = cur->n_points-1;
1218
1219#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
1220 /* hint latest points if needed - this is not strictly required */
1221 /* there, but it helps for debugging, and doesn't affect performance */
1222 if ( builder->pass == 1 )
1223 T1_Hint_Points( builder );
1224#endif
1225
1226 builder->path_begun = 0;
1227 return T1_Err_Ok;
1228 }
1229
1230
1231
1232 static
1233 T1_Error gload_endchar( T1_Builder* builder )
1234 {
1235 FT_Outline* cur = &builder->current;
1236 T1_Error error;
1237
1238 /* close path if needed */
1239 if (builder->path_begun)
1240 {
1241 error = close_open_path( builder );
1242 if (error) return error;
1243 }
1244
1245 error = gload_closepath( builder );
1246
1247 builder->base.n_points += cur->n_points;
1248 builder->base.n_contours += cur->n_contours;
1249
1250 return error;
1251 }
1252
1253
1254
1255 static
1256 T1_Error gload_sbw( T1_Builder* builder,
1257 T1_Pos sbx,
1258 T1_Pos sby,
1259 T1_Pos wx,
1260 T1_Pos wy )
1261 {
1262 builder->left_bearing.x += sbx;
1263 builder->left_bearing.y += sby;
1264 builder->advance.x = wx;
1265 builder->advance.y = wy;
1266
1267 builder->last.x = sbx;
1268 builder->last.y = sby;
1269 return 0;
1270 }
1271
1272
1273
1274
1275 static
1276 T1_Error gload_rlineto( T1_Builder* builder,
1277 T1_Pos dx,
1278 T1_Pos dy )
1279 {
1280 T1_Error error;
1281 FT_Outline* cur = &builder->current;
1282 T1_Vector vec;
1283
1284 /* grow buffer if necessary */
1285 error = T1_Add_Points ( builder, 1 );
1286 if (error) return error;
1287
1288 if ( builder->load_points )
1289 {
1290 /* save point */
1291 vec.x = builder->last.x + dx;
1292 vec.y = builder->last.y + dy;
1293
1294 cur->points[cur->n_points] = vec;
David Turner41dbcbf2000-03-09 11:46:25 +00001295 cur->tags [cur->n_points] = FT_Curve_Tag_On;
David Turnerd2b1f351999-12-16 23:11:37 +00001296
1297 builder->last = vec;
1298 }
1299 cur->n_points++;
1300
1301 builder->path_begun = 1;
1302 return T1_Err_Ok;
1303 }
1304
1305
1306 static
1307 T1_Error gload_rmoveto( T1_Builder* builder,
1308 T1_Pos dx,
1309 T1_Pos dy )
1310 {
1311 T1_Error error;
1312 FT_Outline* cur = &builder->current;
1313 T1_Vector vec;
1314
1315 /* in the case where "path_begun" is set, we have a rmoveto */
1316 /* after some normal path definition. When the face's paint */
1317 /* type is set to 1, this means that we have an "open path", */
1318 /* also called a 'stroke'. The FreeType raster doesn't support */
1319 /* opened path, so we'll close it explicitely there.. */
David Turner76bbd572000-01-27 13:35:16 +00001320 if ( builder->path_begun && builder->face->type1.paint_type == 1 )
David Turnerd2b1f351999-12-16 23:11:37 +00001321 {
David Turner76bbd572000-01-27 13:35:16 +00001322 if ( builder->face->type1.paint_type == 1 )
David Turnerd2b1f351999-12-16 23:11:37 +00001323 {
1324 error = close_open_path( builder );
1325 if (error) return error;
1326 }
1327 }
1328
1329 /* grow buffer if necessary */
1330 error = T1_Add_Contours( builder, 1 ) ||
1331 T1_Add_Points ( builder, 1 );
1332 if (error) return error;
1333
1334 /* save current contour, if any */
1335 if ( cur->n_contours > 0 )
1336 cur->contours[cur->n_contours-1] = cur->n_points-1;
1337
1338 if ( builder->load_points )
1339 {
1340 /* save point */
1341 vec.x = builder->last.x + dx;
1342 vec.y = builder->last.y + dy;
1343 cur->points[cur->n_points] = vec;
David Turner41dbcbf2000-03-09 11:46:25 +00001344 cur->tags [cur->n_points] = FT_Curve_Tag_On;
David Turnerd2b1f351999-12-16 23:11:37 +00001345
1346 builder->last = vec;
1347 }
1348
1349 cur->n_contours++;
1350 cur->n_points++;
1351
1352 return T1_Err_Ok;
1353 }
1354
1355
1356 static
1357 T1_Error gload_rrcurveto( T1_Builder* builder,
1358 T1_Pos dx1,
1359 T1_Pos dy1,
1360 T1_Pos dx2,
1361 T1_Pos dy2,
1362 T1_Pos dx3,
1363 T1_Pos dy3 )
1364 {
1365 T1_Error error;
1366 FT_Outline* cur = &builder->current;
1367 T1_Vector vec;
1368 T1_Vector* points;
David Turner41dbcbf2000-03-09 11:46:25 +00001369 char* tags;
David Turnerd2b1f351999-12-16 23:11:37 +00001370
1371 /* grow buffer if necessary */
1372 error = T1_Add_Points ( builder, 3 );
1373 if (error) return error;
1374
1375 if ( builder->load_points )
1376 {
1377 /* save point */
1378 points = cur->points + cur->n_points;
David Turner41dbcbf2000-03-09 11:46:25 +00001379 tags = cur->tags + cur->n_points;
David Turnerd2b1f351999-12-16 23:11:37 +00001380
1381 vec.x = builder->last.x + dx1;
1382 vec.y = builder->last.y + dy1;
David Turner41dbcbf2000-03-09 11:46:25 +00001383 points[0] = vec; tags[0] = FT_Curve_Tag_Cubic;
David Turnerd2b1f351999-12-16 23:11:37 +00001384
1385 vec.x += dx2;
1386 vec.y += dy2;
David Turner41dbcbf2000-03-09 11:46:25 +00001387 points[1] = vec; tags[1] = FT_Curve_Tag_Cubic;
David Turnerd2b1f351999-12-16 23:11:37 +00001388
1389 vec.x += dx3;
1390 vec.y += dy3;
David Turner41dbcbf2000-03-09 11:46:25 +00001391 points[2] = vec; tags[2] = FT_Curve_Tag_On;
David Turnerd2b1f351999-12-16 23:11:37 +00001392
1393 builder->last = vec;
1394 }
1395
1396 cur->n_points += 3;
1397 builder->path_begun = 1;
1398 return T1_Err_Ok;
1399 }
1400
1401
1402
1403
1404 static
1405 T1_Error gload_ignore( void )
1406 {
1407 return 0;
1408 }
1409
1410
1411 static
1412 const T1_Builder_Funcs gload_builder_interface =
1413 {
1414 gload_endchar,
1415 gload_sbw,
1416 gload_closepath,
1417 gload_rlineto,
1418 gload_rmoveto,
1419 gload_rrcurveto
1420 };
1421
1422
1423 static
1424 const T1_Builder_Funcs gload_builder_interface_null =
1425 {
1426 (T1_Builder_EndChar) gload_ignore,
1427 (T1_Builder_Sbw) gload_sbw, /* record left bearing */
1428 (T1_Builder_ClosePath) gload_ignore,
1429 (T1_Builder_RLineTo) gload_ignore,
1430 (T1_Builder_RMoveTo) gload_ignore,
1431 (T1_Builder_RCurveTo) gload_ignore
1432 };
1433
1434
1435 static
1436 const T1_Hinter_Funcs gload_hinter_interface =
1437 {
1438 (T1_Hinter_DotSection) gload_ignore, /* dotsection */
1439 (T1_Hinter_ChangeHints) gload_ignore, /* changehints */
1440 (T1_Hinter_Stem) gload_ignore, /* hstem & vstem */
1441 (T1_Hinter_Stem3) gload_ignore, /* hstem3 & vestem3 */
1442 };
1443
1444
1445
1446
1447 LOCAL_FUNC
1448 T1_Error T1_Load_Glyph( T1_GlyphSlot glyph,
1449 T1_Size size,
1450 T1_Int glyph_index,
1451 T1_Int load_flags )
1452 {
1453 T1_Error error;
1454 T1_Decoder decoder;
1455 T1_Face face = (T1_Face)glyph->root.face;
1456 T1_Bool hinting;
David Turner76bbd572000-01-27 13:35:16 +00001457 T1_Font* type1 = &face->type1;
David Turnerd2b1f351999-12-16 23:11:37 +00001458
David Turnered7f62a2000-03-28 11:19:28 +00001459 if (load_flags & FT_LOAD_NO_RECURSE)
1460 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
1461
David Turnerd2b1f351999-12-16 23:11:37 +00001462 glyph->x_scale = size->root.metrics.x_scale;
1463 glyph->y_scale = size->root.metrics.y_scale;
1464
1465 glyph->root.outline.n_points = 0;
1466 glyph->root.outline.n_contours = 0;
1467
David Turnerd2b1f351999-12-16 23:11:37 +00001468 glyph->root.format = ft_glyph_format_none;
1469
David Turner1ab77fd2000-02-10 18:08:17 +00001470 hinting = 0;
1471
David Turnerd2b1f351999-12-16 23:11:37 +00001472#ifndef T1_CONFIG_OPTION_DISABLE_HINTER
1473 /*****************************************************************/
1474 /* */
1475 /* Hinter overview : */
1476 /* */
1477 /* This is a two-pass hinter. On the first pass, the hints */
1478 /* are all recorded by the hinter, and no point is loaded */
1479 /* in the outline. */
1480 /* */
1481 /* When the first pass is finished, all stems hints are */
1482 /* grid-fitted at once. */
1483 /* */
1484 /* Then, a second pass is performed to load the outline */
1485 /* points as well as hint/scale them correctly. */
1486 /* */
1487
David Turner1ab77fd2000-02-10 18:08:17 +00001488 hinting = (load_flags & (FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING)) == 0;
1489
David Turnerd2b1f351999-12-16 23:11:37 +00001490 if ( hinting )
1491 {
1492 /* Pass 1 - don't record points, simply stem hints */
1493 T1_Init_Decoder( &decoder, &t1_hinter_funcs );
1494 T1_Init_Builder( &decoder.builder, face, size, glyph,
1495 &gload_builder_interface_null );
1496
1497 glyph->hints->hori_stems.num_stems = 0;
1498 glyph->hints->vert_stems.num_stems = 0;
1499
1500 error = T1_Parse_CharStrings( &decoder,
David Turner76bbd572000-01-27 13:35:16 +00001501 type1->charstrings [glyph_index],
1502 type1->charstrings_len[glyph_index],
1503 type1->num_subrs,
1504 type1->subrs,
1505 type1->subrs_len );
David Turnerd2b1f351999-12-16 23:11:37 +00001506
1507 /* All right, pass 1 is finished, now grid-fit all stem hints */
1508 T1_Hint_Stems( &decoder.builder );
1509
1510 /* Pass 2 - record and scale/hint the points */
1511 T1_Init_Decoder( &decoder, &t1_hinter_funcs );
1512 T1_Init_Builder( &decoder.builder, face, size, glyph,
1513 &gload_builder_interface );
1514
1515 decoder.builder.pass = 1;
David Turnered7f62a2000-03-28 11:19:28 +00001516 decoder.builder.no_recurse = 0;
David Turnerd2b1f351999-12-16 23:11:37 +00001517
1518 error = T1_Parse_CharStrings( &decoder,
David Turner76bbd572000-01-27 13:35:16 +00001519 type1->charstrings [glyph_index],
1520 type1->charstrings_len[glyph_index],
1521 type1->num_subrs,
1522 type1->subrs,
1523 type1->subrs_len );
David Turnerd2b1f351999-12-16 23:11:37 +00001524
1525 /* save new glyph tables */
1526 T1_Done_Builder( &decoder.builder );
1527 }
1528 else
1529#endif
David Turnered7f62a2000-03-28 11:19:28 +00001530
David Turnerd2b1f351999-12-16 23:11:37 +00001531 {
1532 T1_Init_Decoder( &decoder, &gload_hinter_interface );
1533
1534 T1_Init_Builder( &decoder.builder, face, size, glyph,
1535 &gload_builder_interface );
1536
David Turnered7f62a2000-03-28 11:19:28 +00001537 decoder.builder.no_recurse = !!(load_flags & FT_LOAD_NO_RECURSE);
1538
David Turnerd2b1f351999-12-16 23:11:37 +00001539 /* now load the unscaled outline */
1540 error = T1_Parse_CharStrings( &decoder,
David Turner76bbd572000-01-27 13:35:16 +00001541 type1->charstrings [glyph_index],
1542 type1->charstrings_len[glyph_index],
1543 type1->num_subrs,
1544 type1->subrs,
1545 type1->subrs_len );
David Turnerd2b1f351999-12-16 23:11:37 +00001546
1547 /* save new glyph tables */
1548 T1_Done_Builder( &decoder.builder );
1549 }
1550
1551
1552 /* Now, set the metrics.. - this is rather simple, as : */
1553 /* the left side bearing is the xMin, and the top side */
1554 /* bearing the yMax.. */
1555 if (!error)
1556 {
David Turnered7f62a2000-03-28 11:19:28 +00001557 /* for composite glyphs, return only the left side bearing and the */
1558 /* advance width.. */
1559 if ( load_flags & FT_LOAD_NO_RECURSE )
David Turnerd2b1f351999-12-16 23:11:37 +00001560 {
David Turnered7f62a2000-03-28 11:19:28 +00001561 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x;
1562 glyph->root.metrics.horiAdvance = decoder.builder.advance.x;
David Turnerd2b1f351999-12-16 23:11:37 +00001563 }
David Turnered7f62a2000-03-28 11:19:28 +00001564 else
David Turnerd2b1f351999-12-16 23:11:37 +00001565 {
David Turnered7f62a2000-03-28 11:19:28 +00001566 FT_BBox cbox;
1567 FT_Glyph_Metrics* metrics = &glyph->root.metrics;
1568
1569 FT_Outline_Get_CBox( &glyph->root.outline, &cbox );
1570
1571 /* grid fit the bounding box if necessary */
1572 if (hinting)
David Turnerd2b1f351999-12-16 23:11:37 +00001573 {
David Turnered7f62a2000-03-28 11:19:28 +00001574 cbox.xMin &= -64;
1575 cbox.yMin &= -64;
1576 cbox.xMax = ( cbox.xMax+63 ) & -64;
1577 cbox.yMax = ( cbox.yMax+63 ) & -64;
David Turnerd2b1f351999-12-16 23:11:37 +00001578 }
David Turnered7f62a2000-03-28 11:19:28 +00001579
1580 metrics->width = cbox.xMax - cbox.xMin;
1581 metrics->height = cbox.yMax - cbox.yMin;
1582
1583 metrics->horiBearingX = cbox.xMin;
1584 metrics->horiBearingY = cbox.yMax;
1585
1586 /* copy the _unscaled_ advance width */
1587 metrics->horiAdvance = decoder.builder.advance.x;
1588
1589 /* make up vertical metrics */
1590 metrics->vertBearingX = 0;
1591 metrics->vertBearingY = 0;
1592 metrics->vertAdvance = 0;
1593
1594 glyph->root.format = ft_glyph_format_outline;
1595
1596 glyph->root.outline.flags &= ft_outline_owner;
1597
1598 if ( size->root.metrics.y_ppem < 24 )
1599 glyph->root.outline.flags |= ft_outline_high_precision;
David Turner82942cc2000-03-30 08:43:03 +00001600
1601 glyph->root.outline.flags |= ft_outline_reverse_fill;
1602
David Turnered7f62a2000-03-28 11:19:28 +00001603 /*
1604 glyph->root.outline.second_pass = TRUE;
1605 glyph->root.outline.high_precision = ( size->root.metrics.y_ppem < 24 );
1606 glyph->root.outline.dropout_mode = 2;
1607 */
1608
1609 if ( hinting )
1610 {
1611 /* adjust the advance width */
1612 /* XXX : TODO : consider stem hints grid-fit */
1613 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance,
1614 glyph->x_scale );
1615 }
1616 else if ( (load_flags & FT_LOAD_NO_SCALE) == 0 )
1617 {
1618 /* scale the outline and the metrics */
1619 T1_Int n;
1620 FT_Outline* cur = &decoder.builder.base;
1621 T1_Vector* vec = cur->points;
1622 T1_Fixed x_scale = glyph->x_scale;
1623 T1_Fixed y_scale = glyph->y_scale;
1624
1625 /* First of all, scale the points */
1626 for ( n = cur->n_points; n > 0; n--, vec++ )
1627 {
1628 vec->x = FT_MulFix( vec->x, x_scale );
1629 vec->y = FT_MulFix( vec->y, y_scale );
1630 }
1631
1632 /* Then scale the metrics */
1633 metrics->width = FT_MulFix( metrics->width, x_scale );
1634 metrics->height = FT_MulFix( metrics->height, y_scale );
1635
1636 metrics->horiBearingX = FT_MulFix( metrics->horiBearingX, x_scale );
1637 metrics->horiBearingY = FT_MulFix( metrics->horiBearingY, y_scale );
1638 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale );
1639
1640 metrics->vertBearingX = FT_MulFix( metrics->vertBearingX, x_scale );
1641 metrics->vertBearingY = FT_MulFix( metrics->vertBearingY, y_scale );
1642 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, x_scale );
1643
1644 }
David Turnerd2b1f351999-12-16 23:11:37 +00001645 }
1646 }
David Turner82942cc2000-03-30 08:43:03 +00001647
David Turnerd2b1f351999-12-16 23:11:37 +00001648 return error;
1649 }
1650