[LOCALSPL]
[reactos.git] / reactos / lib / 3rdparty / freetype / src / truetype / ttgload.c.old
1 /***************************************************************************/
2 /* */
3 /* ttgload.c */
4 /* */
5 /* TrueType Glyph Loader (body). */
6 /* */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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_CALC_H
22 #include FT_INTERNAL_STREAM_H
23 #include FT_INTERNAL_SFNT_H
24 #include FT_TRUETYPE_TAGS_H
25 #include FT_OUTLINE_H
26
27 #include "ttgload.h"
28 #include "ttpload.h"
29
30 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
31 #include "ttgxvar.h"
32 #endif
33
34 #include "tterrors.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_ttgload
45
46
47 /*************************************************************************/
48 /* */
49 /* Composite font flags. */
50 /* */
51 #define ARGS_ARE_WORDS 0x0001
52 #define ARGS_ARE_XY_VALUES 0x0002
53 #define ROUND_XY_TO_GRID 0x0004
54 #define WE_HAVE_A_SCALE 0x0008
55 /* reserved 0x0010 */
56 #define MORE_COMPONENTS 0x0020
57 #define WE_HAVE_AN_XY_SCALE 0x0040
58 #define WE_HAVE_A_2X2 0x0080
59 #define WE_HAVE_INSTR 0x0100
60 #define USE_MY_METRICS 0x0200
61 #define OVERLAP_COMPOUND 0x0400
62 #define SCALED_COMPONENT_OFFSET 0x0800
63 #define UNSCALED_COMPONENT_OFFSET 0x1000
64
65
66 /*************************************************************************/
67 /* */
68 /* Returns the horizontal metrics in font units for a given glyph. If */
69 /* `check' is true, take care of monospaced fonts by returning the */
70 /* advance width maximum. */
71 /* */
72 static void
73 Get_HMetrics( TT_Face face,
74 FT_UInt idx,
75 FT_Bool check,
76 FT_Short* lsb,
77 FT_UShort* aw )
78 {
79 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
80
81 if ( check && face->postscript.isFixedPitch )
82 *aw = face->horizontal.advance_Width_Max;
83 }
84
85
86 /*************************************************************************/
87 /* */
88 /* Returns the vertical metrics in font units for a given glyph. */
89 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */
90 /* table, typoAscender/Descender from the `OS/2' table would be used */
91 /* instead, and if there were no `OS/2' table, use ascender/descender */
92 /* from the `hhea' table. But that is not what Microsoft's rasterizer */
93 /* apparently does: It uses the ppem value as the advance height, and */
94 /* sets the top side bearing to be zero. */
95 /* */
96 /* The monospace `check' is probably not meaningful here, but we leave */
97 /* it in for a consistent interface. */
98 /* */
99 static void
100 Get_VMetrics( TT_Face face,
101 FT_UInt idx,
102 FT_Bool check,
103 FT_Short* tsb,
104 FT_UShort* ah )
105 {
106 FT_UNUSED( check );
107
108 if ( face->vertical_info )
109 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
110
111 #if 1 /* Empirically determined, at variance with what MS said */
112
113 else
114 {
115 *tsb = 0;
116 *ah = face->root.units_per_EM;
117 }
118
119 #else /* This is what MS said to do. It isn't what they do, however. */
120
121 else if ( face->os2.version != 0xFFFFU )
122 {
123 *tsb = face->os2.sTypoAscender;
124 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender;
125 }
126 else
127 {
128 *tsb = face->horizontal.Ascender;
129 *ah = face->horizontal.Ascender - face->horizontal.Descender;
130 }
131
132 #endif
133
134 }
135
136
137 /*************************************************************************/
138 /* */
139 /* Translates an array of coordinates. */
140 /* */
141 static void
142 translate_array( FT_UInt n,
143 FT_Vector* coords,
144 FT_Pos delta_x,
145 FT_Pos delta_y )
146 {
147 FT_UInt k;
148
149
150 if ( delta_x )
151 for ( k = 0; k < n; k++ )
152 coords[k].x += delta_x;
153
154 if ( delta_y )
155 for ( k = 0; k < n; k++ )
156 coords[k].y += delta_y;
157 }
158
159
160 #undef IS_HINTED
161 #define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
162
163
164 /*************************************************************************/
165 /* */
166 /* The following functions are used by default with TrueType fonts. */
167 /* However, they can be replaced by alternatives if we need to support */
168 /* TrueType-compressed formats (like MicroType) in the future. */
169 /* */
170 /*************************************************************************/
171
172 FT_CALLBACK_DEF( FT_Error )
173 TT_Access_Glyph_Frame( TT_Loader loader,
174 FT_UInt glyph_index,
175 FT_ULong offset,
176 FT_UInt byte_count )
177 {
178 FT_Error error;
179 FT_Stream stream = loader->stream;
180
181 /* for non-debug mode */
182 FT_UNUSED( glyph_index );
183
184
185 FT_TRACE5(( "Glyph %ld\n", glyph_index ));
186
187 /* the following line sets the `error' variable through macros! */
188 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
189 return error;
190
191 loader->cursor = stream->cursor;
192 loader->limit = stream->limit;
193
194 return TT_Err_Ok;
195 }
196
197
198 FT_CALLBACK_DEF( void )
199 TT_Forget_Glyph_Frame( TT_Loader loader )
200 {
201 FT_Stream stream = loader->stream;
202
203
204 FT_FRAME_EXIT();
205 }
206
207
208 FT_CALLBACK_DEF( FT_Error )
209 TT_Load_Glyph_Header( TT_Loader loader )
210 {
211 FT_Byte* p = loader->cursor;
212 FT_Byte* limit = loader->limit;
213
214
215 if ( p + 10 > limit )
216 return TT_Err_Invalid_Outline;
217
218 loader->n_contours = FT_NEXT_SHORT( p );
219
220 loader->bbox.xMin = FT_NEXT_SHORT( p );
221 loader->bbox.yMin = FT_NEXT_SHORT( p );
222 loader->bbox.xMax = FT_NEXT_SHORT( p );
223 loader->bbox.yMax = FT_NEXT_SHORT( p );
224
225 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
226 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin,
227 loader->bbox.xMax ));
228 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin,
229 loader->bbox.yMax ));
230 loader->cursor = p;
231
232 return TT_Err_Ok;
233 }
234
235
236 FT_CALLBACK_DEF( FT_Error )
237 TT_Load_Simple_Glyph( TT_Loader load )
238 {
239 FT_Error error;
240 FT_Byte* p = load->cursor;
241 FT_Byte* limit = load->limit;
242 FT_GlyphLoader gloader = load->gloader;
243 FT_Int n_contours = load->n_contours;
244 FT_Outline* outline;
245 TT_Face face = (TT_Face)load->face;
246 FT_UShort n_ins;
247 FT_Int n, n_points;
248
249 FT_Byte *flag, *flag_limit;
250 FT_Byte c, count;
251 FT_Vector *vec, *vec_limit;
252 FT_Pos x;
253 FT_Short *cont, *cont_limit;
254
255
256 /* check that we can add the contours to the glyph */
257 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
258 if ( error )
259 goto Fail;
260
261 /* reading the contours' endpoints & number of points */
262 cont = gloader->current.outline.contours;
263 cont_limit = cont + n_contours;
264
265 /* check space for contours array + instructions count */
266 if ( n_contours >= 0xFFF || p + (n_contours + 1) * 2 > limit )
267 goto Invalid_Outline;
268
269 for ( ; cont < cont_limit; cont++ )
270 cont[0] = FT_NEXT_USHORT( p );
271
272 n_points = 0;
273 if ( n_contours > 0 )
274 n_points = cont[-1] + 1;
275
276 /* note that we will add four phantom points later */
277 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
278 if ( error )
279 goto Fail;
280
281 /* we'd better check the contours table right now */
282 outline = &gloader->current.outline;
283
284 for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
285 if ( cont[-1] >= cont[0] )
286 goto Invalid_Outline;
287
288 /* reading the bytecode instructions */
289 load->glyph->control_len = 0;
290 load->glyph->control_data = 0;
291
292 if ( p + 2 > limit )
293 goto Invalid_Outline;
294
295 n_ins = FT_NEXT_USHORT( p );
296
297 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
298
299 if ( n_ins > face->max_profile.maxSizeOfInstructions )
300 {
301 FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" ));
302 error = TT_Err_Too_Many_Hints;
303 goto Fail;
304 }
305
306 if ( ( limit - p ) < n_ins )
307 {
308 FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
309 error = TT_Err_Too_Many_Hints;
310 goto Fail;
311 }
312
313 #ifdef TT_USE_BYTECODE_INTERPRETER
314
315 if ( IS_HINTED( load->load_flags ) )
316 {
317 load->glyph->control_len = n_ins;
318 load->glyph->control_data = load->exec->glyphIns;
319
320 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
321 }
322
323 #endif /* TT_USE_BYTECODE_INTERPRETER */
324
325 p += n_ins;
326
327 /* reading the point tags */
328 flag = (FT_Byte*)outline->tags;
329 flag_limit = flag + n_points;
330
331 FT_ASSERT( flag != NULL );
332
333 while ( flag < flag_limit )
334 {
335 if ( p + 1 > limit )
336 goto Invalid_Outline;
337
338 *flag++ = c = FT_NEXT_BYTE( p );
339 if ( c & 8 )
340 {
341 if ( p + 1 > limit )
342 goto Invalid_Outline;
343
344 count = FT_NEXT_BYTE( p );
345 if ( flag + (FT_Int)count > flag_limit )
346 goto Invalid_Outline;
347
348 for ( ; count > 0; count-- )
349 *flag++ = c;
350 }
351 }
352
353 /* reading the X coordinates */
354
355 vec = outline->points;
356 vec_limit = vec + n_points;
357 flag = (FT_Byte*)outline->tags;
358 x = 0;
359
360 for ( ; vec < vec_limit; vec++, flag++ )
361 {
362 FT_Pos y = 0;
363
364
365 if ( *flag & 2 )
366 {
367 if ( p + 1 > limit )
368 goto Invalid_Outline;
369
370 y = (FT_Pos)FT_NEXT_BYTE( p );
371 if ( ( *flag & 16 ) == 0 )
372 y = -y;
373 }
374 else if ( ( *flag & 16 ) == 0 )
375 {
376 if ( p + 2 > limit )
377 goto Invalid_Outline;
378
379 y = (FT_Pos)FT_NEXT_SHORT( p );
380 }
381
382 x += y;
383 vec->x = x;
384 }
385
386 /* reading the Y coordinates */
387
388 vec = gloader->current.outline.points;
389 vec_limit = vec + n_points;
390 flag = (FT_Byte*)outline->tags;
391 x = 0;
392
393 for ( ; vec < vec_limit; vec++, flag++ )
394 {
395 FT_Pos y = 0;
396
397
398 if ( *flag & 4 )
399 {
400 if ( p +1 > limit )
401 goto Invalid_Outline;
402
403 y = (FT_Pos)FT_NEXT_BYTE( p );
404 if ( ( *flag & 32 ) == 0 )
405 y = -y;
406 }
407 else if ( ( *flag & 32 ) == 0 )
408 {
409 if ( p + 2 > limit )
410 goto Invalid_Outline;
411
412 y = (FT_Pos)FT_NEXT_SHORT( p );
413 }
414
415 x += y;
416 vec->y = x;
417 }
418
419 /* clear the touch tags */
420 for ( n = 0; n < n_points; n++ )
421 outline->tags[n] &= FT_CURVE_TAG_ON;
422
423 outline->n_points = (FT_UShort)n_points;
424 outline->n_contours = (FT_Short) n_contours;
425
426 load->cursor = p;
427
428 Fail:
429 return error;
430
431 Invalid_Outline:
432 error = TT_Err_Invalid_Outline;
433 goto Fail;
434 }
435
436
437 FT_CALLBACK_DEF( FT_Error )
438 TT_Load_Composite_Glyph( TT_Loader loader )
439 {
440 FT_Error error;
441 FT_Byte* p = loader->cursor;
442 FT_Byte* limit = loader->limit;
443 FT_GlyphLoader gloader = loader->gloader;
444 FT_SubGlyph subglyph;
445 FT_UInt num_subglyphs;
446
447
448 num_subglyphs = 0;
449
450 do
451 {
452 FT_Fixed xx, xy, yy, yx;
453 FT_UInt count;
454
455
456 /* check that we can load a new subglyph */
457 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
458 if ( error )
459 goto Fail;
460
461 /* check space */
462 if ( p + 4 > limit )
463 goto Invalid_Composite;
464
465 subglyph = gloader->current.subglyphs + num_subglyphs;
466
467 subglyph->arg1 = subglyph->arg2 = 0;
468
469 subglyph->flags = FT_NEXT_USHORT( p );
470 subglyph->index = FT_NEXT_USHORT( p );
471
472 /* check space */
473 count = 2;
474 if ( subglyph->flags & ARGS_ARE_WORDS )
475 count += 2;
476 if ( subglyph->flags & WE_HAVE_A_SCALE )
477 count += 2;
478 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
479 count += 4;
480 else if ( subglyph->flags & WE_HAVE_A_2X2 )
481 count += 8;
482
483 if ( p + count > limit )
484 goto Invalid_Composite;
485
486 /* read arguments */
487 if ( subglyph->flags & ARGS_ARE_WORDS )
488 {
489 subglyph->arg1 = FT_NEXT_SHORT( p );
490 subglyph->arg2 = FT_NEXT_SHORT( p );
491 }
492 else
493 {
494 subglyph->arg1 = FT_NEXT_CHAR( p );
495 subglyph->arg2 = FT_NEXT_CHAR( p );
496 }
497
498 /* read transform */
499 xx = yy = 0x10000L;
500 xy = yx = 0;
501
502 if ( subglyph->flags & WE_HAVE_A_SCALE )
503 {
504 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
505 yy = xx;
506 }
507 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
508 {
509 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
510 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
511 }
512 else if ( subglyph->flags & WE_HAVE_A_2X2 )
513 {
514 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
515 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
516 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
517 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
518 }
519
520 subglyph->transform.xx = xx;
521 subglyph->transform.xy = xy;
522 subglyph->transform.yx = yx;
523 subglyph->transform.yy = yy;
524
525 num_subglyphs++;
526
527 } while ( subglyph->flags & MORE_COMPONENTS );
528
529 gloader->current.num_subglyphs = num_subglyphs;
530
531 #ifdef TT_USE_BYTECODE_INTERPRETER
532
533 {
534 FT_Stream stream = loader->stream;
535
536
537 /* we must undo the FT_FRAME_ENTER in order to point to the */
538 /* composite instructions, if we find some. */
539 /* we will process them later... */
540 /* */
541 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
542 p - limit );
543 }
544
545 #endif
546
547 loader->cursor = p;
548
549 Fail:
550 return error;
551
552 Invalid_Composite:
553 error = TT_Err_Invalid_Composite;
554 goto Fail;
555 }
556
557
558 FT_LOCAL_DEF( void )
559 TT_Init_Glyph_Loading( TT_Face face )
560 {
561 face->access_glyph_frame = TT_Access_Glyph_Frame;
562 face->read_glyph_header = TT_Load_Glyph_Header;
563 face->read_simple_glyph = TT_Load_Simple_Glyph;
564 face->read_composite_glyph = TT_Load_Composite_Glyph;
565 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
566 }
567
568
569 static void
570 tt_prepare_zone( TT_GlyphZone zone,
571 FT_GlyphLoad load,
572 FT_UInt start_point,
573 FT_UInt start_contour )
574 {
575 zone->n_points = (FT_UShort)( load->outline.n_points - start_point );
576 zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour );
577 zone->org = load->extra_points + start_point;
578 zone->cur = load->outline.points + start_point;
579 zone->orus = load->extra_points2 + start_point;
580 zone->tags = (FT_Byte*)load->outline.tags + start_point;
581 zone->contours = (FT_UShort*)load->outline.contours + start_contour;
582 zone->first_point = (FT_UShort)start_point;
583 }
584
585
586 /*************************************************************************/
587 /* */
588 /* <Function> */
589 /* TT_Hint_Glyph */
590 /* */
591 /* <Description> */
592 /* Hint the glyph using the zone prepared by the caller. Note that */
593 /* the zone is supposed to include four phantom points. */
594 /* */
595 static FT_Error
596 TT_Hint_Glyph( TT_Loader loader,
597 FT_Bool is_composite )
598 {
599 TT_GlyphZone zone = &loader->zone;
600 FT_Pos origin;
601
602 #ifdef TT_USE_BYTECODE_INTERPRETER
603 FT_UInt n_ins;
604 #else
605 FT_UNUSED( is_composite );
606 #endif
607
608
609 #ifdef TT_USE_BYTECODE_INTERPRETER
610 n_ins = loader->glyph->control_len;
611 #endif
612
613 origin = zone->cur[zone->n_points - 4].x;
614 origin = FT_PIX_ROUND( origin ) - origin;
615 if ( origin )
616 translate_array( zone->n_points, zone->cur, origin, 0 );
617
618 #ifdef TT_USE_BYTECODE_INTERPRETER
619 /* save original point position in org */
620 if ( n_ins > 0 )
621 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
622 #endif
623
624 /* round pp2 and pp4 */
625 zone->cur[zone->n_points - 3].x =
626 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
627 zone->cur[zone->n_points - 1].y =
628 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
629
630 #ifdef TT_USE_BYTECODE_INTERPRETER
631
632 if ( n_ins > 0 )
633 {
634 FT_Bool debug;
635 FT_Error error;
636
637
638 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
639 loader->exec->glyphIns, n_ins );
640 if ( error )
641 return error;
642
643 loader->exec->is_composite = is_composite;
644 loader->exec->pts = *zone;
645
646 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
647 ((TT_Size)loader->size)->debug );
648
649 error = TT_Run_Context( loader->exec, debug );
650 if ( error && loader->exec->pedantic_hinting )
651 return error;
652 }
653
654 #endif
655
656 /* save glyph phantom points */
657 if ( !loader->preserve_pps )
658 {
659 loader->pp1 = zone->cur[zone->n_points - 4];
660 loader->pp2 = zone->cur[zone->n_points - 3];
661 loader->pp3 = zone->cur[zone->n_points - 2];
662 loader->pp4 = zone->cur[zone->n_points - 1];
663 }
664
665 return TT_Err_Ok;
666 }
667
668
669 /*************************************************************************/
670 /* */
671 /* <Function> */
672 /* TT_Process_Simple_Glyph */
673 /* */
674 /* <Description> */
675 /* Once a simple glyph has been loaded, it needs to be processed. */
676 /* Usually, this means scaling and hinting through bytecode */
677 /* interpretation. */
678 /* */
679 static FT_Error
680 TT_Process_Simple_Glyph( TT_Loader loader )
681 {
682 FT_GlyphLoader gloader = loader->gloader;
683 FT_Error error = TT_Err_Ok;
684 FT_Outline* outline;
685 FT_UInt n_points;
686
687
688 outline = &gloader->current.outline;
689 n_points = outline->n_points;
690
691 /* set phantom points */
692
693 outline->points[n_points ] = loader->pp1;
694 outline->points[n_points + 1] = loader->pp2;
695 outline->points[n_points + 2] = loader->pp3;
696 outline->points[n_points + 3] = loader->pp4;
697
698 outline->tags[n_points ] = 0;
699 outline->tags[n_points + 1] = 0;
700 outline->tags[n_points + 2] = 0;
701 outline->tags[n_points + 3] = 0;
702
703 n_points += 4;
704
705 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
706
707 if ( ((TT_Face)loader->face)->doblend )
708 {
709 /* Deltas apply to the unscaled data. */
710 FT_Vector* deltas;
711 FT_Memory memory = loader->face->memory;
712 FT_UInt i;
713
714
715 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
716 loader->glyph_index,
717 &deltas,
718 n_points );
719 if ( error )
720 return error;
721
722 for ( i = 0; i < n_points; ++i )
723 {
724 outline->points[i].x += deltas[i].x;
725 outline->points[i].y += deltas[i].y;
726 }
727
728 FT_FREE( deltas );
729 }
730
731 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
732
733 if ( IS_HINTED( loader->load_flags ) )
734 {
735 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
736
737 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
738 loader->zone.n_points + 4 );
739 }
740
741 /* scale the glyph */
742 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
743 {
744 FT_Vector* vec = outline->points;
745 FT_Vector* limit = outline->points + n_points;
746 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
747 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
748
749
750 for ( ; vec < limit; vec++ )
751 {
752 vec->x = FT_MulFix( vec->x, x_scale );
753 vec->y = FT_MulFix( vec->y, y_scale );
754 }
755
756 loader->pp1 = outline->points[n_points - 4];
757 loader->pp2 = outline->points[n_points - 3];
758 loader->pp3 = outline->points[n_points - 2];
759 loader->pp4 = outline->points[n_points - 1];
760 }
761
762 if ( IS_HINTED( loader->load_flags ) )
763 {
764 loader->zone.n_points += 4;
765
766 error = TT_Hint_Glyph( loader, 0 );
767 }
768
769 return error;
770 }
771
772
773 /*************************************************************************/
774 /* */
775 /* <Function> */
776 /* TT_Process_Composite_Component */
777 /* */
778 /* <Description> */
779 /* Once a composite component has been loaded, it needs to be */
780 /* processed. Usually, this means transforming and translating. */
781 /* */
782 static FT_Error
783 TT_Process_Composite_Component( TT_Loader loader,
784 FT_SubGlyph subglyph,
785 FT_UInt start_point,
786 FT_UInt num_base_points )
787 {
788 FT_GlyphLoader gloader = loader->gloader;
789 FT_Vector* base_vec = gloader->base.outline.points;
790 FT_UInt num_points = gloader->base.outline.n_points;
791 FT_Bool have_scale;
792 FT_Pos x, y;
793
794
795 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
796 WE_HAVE_AN_XY_SCALE |
797 WE_HAVE_A_2X2 ) );
798
799 /* perform the transform required for this subglyph */
800 if ( have_scale )
801 {
802 FT_UInt i;
803
804
805 for ( i = num_base_points; i < num_points; i++ )
806 FT_Vector_Transform( base_vec + i, &subglyph->transform );
807 }
808
809 /* get offset */
810 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
811 {
812 FT_UInt k = subglyph->arg1;
813 FT_UInt l = subglyph->arg2;
814 FT_Vector* p1;
815 FT_Vector* p2;
816
817
818 /* match l-th point of the newly loaded component to the k-th point */
819 /* of the previously loaded components. */
820
821 /* change to the point numbers used by our outline */
822 k += start_point;
823 l += num_base_points;
824 if ( k >= num_base_points ||
825 l >= num_points )
826 return TT_Err_Invalid_Composite;
827
828 p1 = gloader->base.outline.points + k;
829 p2 = gloader->base.outline.points + l;
830
831 x = p1->x - p2->x;
832 y = p1->y - p2->y;
833 }
834 else
835 {
836 x = subglyph->arg1;
837 y = subglyph->arg2;
838
839 if ( !x && !y )
840 return TT_Err_Ok;
841
842 /* Use a default value dependent on */
843 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */
844 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */
845
846 if ( have_scale &&
847 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
848 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
849 #else
850 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
851 #endif
852 {
853
854 #if 0
855
856 /*************************************************************************/
857 /* */
858 /* This algorithm is what Apple documents. But it doesn't work. */
859 /* */
860 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
861 : -subglyph->transform.xx;
862 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
863 : -subglyph->transform.yx;
864 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
865 : -subglyph->transform.xy;
866 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
867 : -subglyph->transform.yy;
868 int m = a > b ? a : b;
869 int n = c > d ? c : d;
870
871
872 if ( a - b <= 33 && a - b >= -33 )
873 m *= 2;
874 if ( c - d <= 33 && c - d >= -33 )
875 n *= 2;
876 x = FT_MulFix( x, m );
877 y = FT_MulFix( y, n );
878
879 #else /* 0 */
880
881 /*************************************************************************/
882 /* */
883 /* This algorithm is a guess and works much better than the above. */
884 /* */
885 FT_Fixed mac_xscale = FT_SqrtFixed(
886 FT_MulFix( subglyph->transform.xx,
887 subglyph->transform.xx ) +
888 FT_MulFix( subglyph->transform.xy,
889 subglyph->transform.xy ) );
890 FT_Fixed mac_yscale = FT_SqrtFixed(
891 FT_MulFix( subglyph->transform.yy,
892 subglyph->transform.yy ) +
893 FT_MulFix( subglyph->transform.yx,
894 subglyph->transform.yx ) );
895
896
897 x = FT_MulFix( x, mac_xscale );
898 y = FT_MulFix( y, mac_yscale );
899
900 #endif /* 0 */
901
902 }
903
904 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
905 {
906 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale;
907 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale;
908
909
910 x = FT_MulFix( x, x_scale );
911 y = FT_MulFix( y, y_scale );
912
913 if ( subglyph->flags & ROUND_XY_TO_GRID )
914 {
915 x = FT_PIX_ROUND( x );
916 y = FT_PIX_ROUND( y );
917 }
918 }
919 }
920
921 if ( x || y )
922 translate_array( num_points - num_base_points,
923 base_vec + num_base_points,
924 x, y );
925
926 return TT_Err_Ok;
927 }
928
929
930 /*************************************************************************/
931 /* */
932 /* <Function> */
933 /* TT_Process_Composite_Glyph */
934 /* */
935 /* <Description> */
936 /* This is slightly different from TT_Process_Simple_Glyph, in that */
937 /* its sole purpose is to hint the glyph. Thus this function is */
938 /* only available when bytecode interpreter is enabled. */
939 /* */
940 static FT_Error
941 TT_Process_Composite_Glyph( TT_Loader loader,
942 FT_UInt start_point,
943 FT_UInt start_contour )
944 {
945 FT_Error error;
946 FT_Outline* outline;
947 FT_UInt i;
948
949
950 outline = &loader->gloader->base.outline;
951
952 /* make room for phantom points */
953 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
954 outline->n_points + 4,
955 0 );
956 if ( error )
957 return error;
958
959 outline->points[outline->n_points ] = loader->pp1;
960 outline->points[outline->n_points + 1] = loader->pp2;
961 outline->points[outline->n_points + 2] = loader->pp3;
962 outline->points[outline->n_points + 3] = loader->pp4;
963
964 outline->tags[outline->n_points ] = 0;
965 outline->tags[outline->n_points + 1] = 0;
966 outline->tags[outline->n_points + 2] = 0;
967 outline->tags[outline->n_points + 3] = 0;
968
969 #ifdef TT_USE_BYTECODE_INTERPRETER
970
971 {
972 FT_Stream stream = loader->stream;
973 FT_UShort n_ins;
974
975
976 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
977 /* so we read them here */
978 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
979 FT_READ_USHORT( n_ins ) )
980 return error;
981
982 FT_TRACE5(( " Instructions size = %d\n", n_ins ));
983
984 /* check it */
985 if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
986 {
987 FT_TRACE0(( "Too many instructions (%d)\n", n_ins ));
988
989 return TT_Err_Too_Many_Hints;
990 }
991 else if ( n_ins == 0 )
992 return TT_Err_Ok;
993
994 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
995 return error;
996
997 loader->glyph->control_data = loader->exec->glyphIns;
998 loader->glyph->control_len = n_ins;
999 }
1000
1001 #endif
1002
1003 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1004 start_point, start_contour );
1005
1006 /* Some points are likely touched during execution of */
1007 /* instructions on components. So let's untouch them. */
1008 for ( i = start_point; i < loader->zone.n_points; i++ )
1009 loader->zone.tags[i] &= ~( FT_CURVE_TAG_TOUCH_X |
1010 FT_CURVE_TAG_TOUCH_Y );
1011
1012 loader->zone.n_points += 4;
1013
1014 return TT_Hint_Glyph( loader, 1 );
1015 }
1016
1017
1018 /* Calculate the four phantom points. */
1019 /* The first two stand for horizontal origin and advance. */
1020 /* The last two stand for vertical origin and advance. */
1021 #define TT_LOADER_SET_PP( loader ) \
1022 do { \
1023 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
1024 (loader)->pp1.y = 0; \
1025 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \
1026 (loader)->pp2.y = 0; \
1027 (loader)->pp3.x = 0; \
1028 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \
1029 (loader)->pp4.x = 0; \
1030 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \
1031 } while ( 0 )
1032
1033
1034 /*************************************************************************/
1035 /* */
1036 /* <Function> */
1037 /* load_truetype_glyph */
1038 /* */
1039 /* <Description> */
1040 /* Loads a given truetype glyph. Handles composites and uses a */
1041 /* TT_Loader object. */
1042 /* */
1043 static FT_Error
1044 load_truetype_glyph( TT_Loader loader,
1045 FT_UInt glyph_index,
1046 FT_UInt recurse_count )
1047 {
1048 FT_Error error;
1049 FT_Fixed x_scale, y_scale;
1050 FT_ULong offset;
1051 TT_Face face = (TT_Face)loader->face;
1052 FT_GlyphLoader gloader = loader->gloader;
1053 FT_Bool opened_frame = 0;
1054
1055 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1056 FT_Vector* deltas = NULL;
1057 #endif
1058
1059 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1060 FT_StreamRec inc_stream;
1061 FT_Data glyph_data;
1062 FT_Bool glyph_data_loaded = 0;
1063 #endif
1064
1065
1066 if ( recurse_count > face->max_profile.maxComponentDepth )
1067 {
1068 error = TT_Err_Invalid_Composite;
1069 goto Exit;
1070 }
1071
1072 /* check glyph index */
1073 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1074 {
1075 error = TT_Err_Invalid_Glyph_Index;
1076 goto Exit;
1077 }
1078
1079 loader->glyph_index = glyph_index;
1080
1081 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1082 {
1083 x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1084 y_scale = ((TT_Size)loader->size)->metrics.y_scale;
1085 }
1086 else
1087 {
1088 x_scale = 0x10000L;
1089 y_scale = 0x10000L;
1090 }
1091
1092 /* get metrics, horizontal and vertical */
1093 {
1094 FT_Short left_bearing = 0, top_bearing = 0;
1095 FT_UShort advance_width = 0, advance_height = 0;
1096
1097
1098 Get_HMetrics( face, glyph_index,
1099 (FT_Bool)!( loader->load_flags &
1100 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1101 &left_bearing,
1102 &advance_width );
1103 Get_VMetrics( face, glyph_index,
1104 (FT_Bool)!( loader->load_flags &
1105 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1106 &top_bearing,
1107 &advance_height );
1108
1109 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1110
1111 /* If this is an incrementally loaded font see if there are */
1112 /* overriding metrics for this glyph. */
1113 if ( face->root.internal->incremental_interface &&
1114 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
1115 {
1116 FT_Incremental_MetricsRec metrics;
1117
1118
1119 metrics.bearing_x = left_bearing;
1120 metrics.bearing_y = 0;
1121 metrics.advance = advance_width;
1122 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1123 face->root.internal->incremental_interface->object,
1124 glyph_index, FALSE, &metrics );
1125 if ( error )
1126 goto Exit;
1127 left_bearing = (FT_Short)metrics.bearing_x;
1128 advance_width = (FT_UShort)metrics.advance;
1129
1130 #if 0
1131
1132 /* GWW: Do I do the same for vertical metrics? */
1133 metrics.bearing_x = 0;
1134 metrics.bearing_y = top_bearing;
1135 metrics.advance = advance_height;
1136 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1137 face->root.internal->incremental_interface->object,
1138 glyph_index, TRUE, &metrics );
1139 if ( error )
1140 goto Exit;
1141 top_bearing = (FT_Short)metrics.bearing_y;
1142 advance_height = (FT_UShort)metrics.advance;
1143
1144 #endif /* 0 */
1145
1146 }
1147
1148 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1149
1150 loader->left_bearing = left_bearing;
1151 loader->advance = advance_width;
1152 loader->top_bearing = top_bearing;
1153 loader->vadvance = advance_height;
1154
1155 if ( !loader->linear_def )
1156 {
1157 loader->linear_def = 1;
1158 loader->linear = advance_width;
1159 }
1160 }
1161
1162 /* Set `offset' to the start of the glyph relative to the start of */
1163 /* the `glyf' table, and `byte_len' to the length of the glyph in */
1164 /* bytes. */
1165
1166 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1167
1168 /* If we are loading glyph data via the incremental interface, set */
1169 /* the loader stream to a memory stream reading the data returned */
1170 /* by the interface. */
1171 if ( face->root.internal->incremental_interface )
1172 {
1173 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1174 face->root.internal->incremental_interface->object,
1175 glyph_index, &glyph_data );
1176 if ( error )
1177 goto Exit;
1178
1179 glyph_data_loaded = 1;
1180 offset = 0;
1181 loader->byte_len = glyph_data.length;
1182
1183 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
1184 FT_Stream_OpenMemory( &inc_stream,
1185 glyph_data.pointer, glyph_data.length );
1186
1187 loader->stream = &inc_stream;
1188 }
1189 else
1190
1191 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1192
1193 offset = tt_face_get_location( face, glyph_index,
1194 (FT_UInt*)&loader->byte_len );
1195
1196 if ( loader->byte_len == 0 )
1197 {
1198 /* as described by Frederic Loyer, these are spaces or */
1199 /* the unknown glyph. */
1200 loader->bbox.xMin = 0;
1201 loader->bbox.xMax = 0;
1202 loader->bbox.yMin = 0;
1203 loader->bbox.yMax = 0;
1204
1205 TT_LOADER_SET_PP( loader );
1206
1207 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1208
1209 if ( ((TT_Face)(loader->face))->doblend )
1210 {
1211 /* this must be done before scaling */
1212 FT_Memory memory = loader->face->memory;
1213
1214
1215 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
1216 glyph_index, &deltas, 4 );
1217 if ( error )
1218 goto Exit;
1219
1220 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
1221 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
1222 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
1223 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
1224
1225 FT_FREE( deltas );
1226 }
1227
1228 #endif
1229
1230 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1231 {
1232 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1233 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1234 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1235 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1236 }
1237
1238 error = TT_Err_Ok;
1239 goto Exit;
1240 }
1241
1242 error = face->access_glyph_frame( loader, glyph_index,
1243 loader->glyf_offset + offset,
1244 loader->byte_len );
1245 if ( error )
1246 goto Exit;
1247
1248 opened_frame = 1;
1249
1250 /* read first glyph header */
1251 error = face->read_glyph_header( loader );
1252 if ( error )
1253 goto Exit;
1254
1255 TT_LOADER_SET_PP( loader );
1256
1257 /***********************************************************************/
1258 /***********************************************************************/
1259 /***********************************************************************/
1260
1261 /* if it is a simple glyph, load it */
1262
1263 if ( loader->n_contours >= 0 )
1264 {
1265 error = face->read_simple_glyph( loader );
1266 if ( error )
1267 goto Exit;
1268
1269 /* all data have been read */
1270 face->forget_glyph_frame( loader );
1271 opened_frame = 0;
1272
1273 error = TT_Process_Simple_Glyph( loader );
1274 if ( error )
1275 goto Exit;
1276
1277 FT_GlyphLoader_Add( gloader );
1278 }
1279
1280 /***********************************************************************/
1281 /***********************************************************************/
1282 /***********************************************************************/
1283
1284 /* otherwise, load a composite! */
1285 else if ( loader->n_contours == -1 )
1286 {
1287 FT_UInt start_point;
1288 FT_UInt start_contour;
1289 FT_ULong ins_pos; /* position of composite instructions, if any */
1290
1291
1292 start_point = gloader->base.outline.n_points;
1293 start_contour = gloader->base.outline.n_contours;
1294
1295 /* for each subglyph, read composite header */
1296 error = face->read_composite_glyph( loader );
1297 if ( error )
1298 goto Exit;
1299
1300 /* store the offset of instructions */
1301 ins_pos = loader->ins_pos;
1302
1303 /* all data we need are read */
1304 face->forget_glyph_frame( loader );
1305 opened_frame = 0;
1306
1307 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1308
1309 if ( face->doblend )
1310 {
1311 FT_Int i, limit;
1312 FT_SubGlyph subglyph;
1313 FT_Memory memory = face->root.memory;
1314
1315
1316 /* this provides additional offsets */
1317 /* for each component's translation */
1318
1319 if ( (error = TT_Vary_Get_Glyph_Deltas(
1320 face,
1321 glyph_index,
1322 &deltas,
1323 gloader->current.num_subglyphs + 4 )) != 0 )
1324 goto Exit;
1325
1326 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
1327 limit = gloader->current.num_subglyphs;
1328
1329 for ( i = 0; i < limit; ++i, ++subglyph )
1330 {
1331 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1332 {
1333 subglyph->arg1 += deltas[i].x;
1334 subglyph->arg2 += deltas[i].y;
1335 }
1336 }
1337
1338 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
1339 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
1340 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
1341 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
1342
1343 FT_FREE( deltas );
1344 }
1345
1346 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1347
1348 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1349 {
1350 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1351 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1352 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1353 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1354 }
1355
1356 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1357 /* `as is' in the glyph slot (the client application will be */
1358 /* responsible for interpreting these data)... */
1359 /* */
1360 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1361 {
1362 FT_GlyphLoader_Add( gloader );
1363 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1364
1365 goto Exit;
1366 }
1367
1368 /*********************************************************************/
1369 /*********************************************************************/
1370 /*********************************************************************/
1371
1372 {
1373 FT_UInt n, num_base_points;
1374 FT_SubGlyph subglyph = 0;
1375
1376 FT_UInt num_points = start_point;
1377 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1378 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
1379
1380
1381 FT_GlyphLoader_Add( gloader );
1382
1383 /* read each subglyph independently */
1384 for ( n = 0; n < num_subglyphs; n++ )
1385 {
1386 FT_Vector pp[4];
1387
1388
1389 /* Each time we call load_truetype_glyph in this loop, the */
1390 /* value of `gloader.base.subglyphs' can change due to table */
1391 /* reallocations. We thus need to recompute the subglyph */
1392 /* pointer on each iteration. */
1393 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1394
1395 pp[0] = loader->pp1;
1396 pp[1] = loader->pp2;
1397 pp[2] = loader->pp3;
1398 pp[3] = loader->pp4;
1399
1400 num_base_points = gloader->base.outline.n_points;
1401
1402 error = load_truetype_glyph( loader, subglyph->index,
1403 recurse_count + 1 );
1404 if ( error )
1405 goto Exit;
1406
1407 /* restore subglyph pointer */
1408 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1409
1410 if ( !( subglyph->flags & USE_MY_METRICS ) )
1411 {
1412 loader->pp1 = pp[0];
1413 loader->pp2 = pp[1];
1414 loader->pp3 = pp[2];
1415 loader->pp4 = pp[3];
1416 }
1417
1418 num_points = gloader->base.outline.n_points;
1419
1420 if ( num_points == num_base_points )
1421 continue;
1422
1423 /* gloader->base.outline consists of three part: */
1424 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
1425 /* */
1426 /* (1): exist from the beginning */
1427 /* (2): components that have been loaded so far */
1428 /* (3): the newly loaded component */
1429 TT_Process_Composite_Component( loader, subglyph, start_point,
1430 num_base_points );
1431 }
1432
1433
1434 /* process the glyph */
1435 loader->ins_pos = ins_pos;
1436 if ( IS_HINTED( loader->load_flags ) &&
1437
1438 #ifdef TT_USE_BYTECODE_INTERPRETER
1439
1440 subglyph->flags & WE_HAVE_INSTR &&
1441
1442 #endif
1443
1444 num_points > start_point )
1445 TT_Process_Composite_Glyph( loader, start_point, start_contour );
1446
1447 }
1448 }
1449 else
1450 {
1451 /* invalid composite count ( negative but not -1 ) */
1452 error = TT_Err_Invalid_Outline;
1453 goto Exit;
1454 }
1455
1456 /***********************************************************************/
1457 /***********************************************************************/
1458 /***********************************************************************/
1459
1460 Exit:
1461
1462 if ( opened_frame )
1463 face->forget_glyph_frame( loader );
1464
1465 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1466
1467 if ( glyph_data_loaded )
1468 face->root.internal->incremental_interface->funcs->free_glyph_data(
1469 face->root.internal->incremental_interface->object,
1470 &glyph_data );
1471
1472 #endif
1473
1474 return error;
1475 }
1476
1477
1478 static FT_Error
1479 compute_glyph_metrics( TT_Loader loader,
1480 FT_UInt glyph_index )
1481 {
1482 FT_BBox bbox;
1483 TT_Face face = (TT_Face)loader->face;
1484 FT_Fixed y_scale;
1485 TT_GlyphSlot glyph = loader->glyph;
1486 TT_Size size = (TT_Size)loader->size;
1487
1488
1489 y_scale = 0x10000L;
1490 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1491 y_scale = size->root.metrics.y_scale;
1492
1493 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
1494 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1495 else
1496 bbox = loader->bbox;
1497
1498 /* get the device-independent horizontal advance. It is scaled later */
1499 /* by the base layer. */
1500 {
1501 FT_Pos advance = loader->linear;
1502
1503
1504 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1505 /* correctly support DynaLab fonts, which have an incorrect */
1506 /* `advance_Width_Max' field! It is used, to my knowledge, */
1507 /* exclusively in the X-TrueType font server. */
1508 /* */
1509 if ( face->postscript.isFixedPitch &&
1510 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
1511 advance = face->horizontal.advance_Width_Max;
1512
1513 /* we need to return the advance in font units in linearHoriAdvance, */
1514 /* it will be scaled later by the base layer. */
1515 glyph->linearHoriAdvance = advance;
1516 }
1517
1518 glyph->metrics.horiBearingX = bbox.xMin;
1519 glyph->metrics.horiBearingY = bbox.yMax;
1520 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
1521
1522 /* Now take care of vertical metrics. In the case where there is */
1523 /* no vertical information within the font (relatively common), make */
1524 /* up some metrics by `hand'... */
1525
1526 {
1527 FT_Pos top; /* scaled vertical top side bearing */
1528 FT_Pos advance; /* scaled vertical advance height */
1529
1530
1531 /* Get the unscaled top bearing and advance height. */
1532 if ( face->vertical_info &&
1533 face->vertical.number_Of_VMetrics > 0 )
1534 {
1535 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
1536 y_scale );
1537
1538 if ( loader->pp3.y <= loader->pp4.y )
1539 advance = 0;
1540 else
1541 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
1542 y_scale );
1543 }
1544 else
1545 {
1546 FT_Pos height;
1547
1548
1549 /* XXX Compute top side bearing and advance height in */
1550 /* Get_VMetrics instead of here. */
1551
1552 /* NOTE: The OS/2 values are the only `portable' ones, */
1553 /* which is why we use them, if there is an OS/2 */
1554 /* table in the font. Otherwise, we use the */
1555 /* values defined in the horizontal header. */
1556
1557 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
1558 y_scale );
1559 if ( face->os2.version != 0xFFFFU )
1560 advance = (FT_Pos)( face->os2.sTypoAscender -
1561 face->os2.sTypoDescender );
1562 else
1563 advance = (FT_Pos)( face->horizontal.Ascender -
1564 face->horizontal.Descender );
1565
1566 top = ( advance - height ) / 2;
1567 }
1568
1569 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1570 {
1571 FT_Incremental_InterfaceRec* incr;
1572 FT_Incremental_MetricsRec metrics;
1573 FT_Error error;
1574
1575
1576 incr = face->root.internal->incremental_interface;
1577
1578 /* If this is an incrementally loaded font see if there are */
1579 /* overriding metrics for this glyph. */
1580 if ( incr && incr->funcs->get_glyph_metrics )
1581 {
1582 metrics.bearing_x = 0;
1583 metrics.bearing_y = top;
1584 metrics.advance = advance;
1585
1586 error = incr->funcs->get_glyph_metrics( incr->object,
1587 glyph_index,
1588 TRUE,
1589 &metrics );
1590 if ( error )
1591 return error;
1592
1593 top = metrics.bearing_y;
1594 advance = metrics.advance;
1595 }
1596 }
1597
1598 /* GWW: Do vertical metrics get loaded incrementally too? */
1599
1600 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1601
1602 glyph->linearVertAdvance = advance;
1603
1604 /* scale the metrics */
1605 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1606 {
1607 top = FT_MulFix( top, y_scale );
1608 advance = FT_MulFix( advance, y_scale );
1609 }
1610
1611 /* XXX: for now, we have no better algorithm for the lsb, but it */
1612 /* should work fine. */
1613 /* */
1614 glyph->metrics.vertBearingX = ( bbox.xMin - bbox.xMax ) / 2;
1615 glyph->metrics.vertBearingY = top;
1616 glyph->metrics.vertAdvance = advance;
1617 }
1618
1619 /* adjust advance width to the value contained in the hdmx table */
1620 if ( !face->postscript.isFixedPitch &&
1621 IS_HINTED( loader->load_flags ) )
1622 {
1623 FT_Byte* widthp;
1624
1625
1626 widthp = tt_face_get_device_metrics( face,
1627 size->root.metrics.x_ppem,
1628 glyph_index );
1629
1630 if ( widthp )
1631 glyph->metrics.horiAdvance = *widthp << 6;
1632 }
1633
1634 /* set glyph dimensions */
1635 glyph->metrics.width = bbox.xMax - bbox.xMin;
1636 glyph->metrics.height = bbox.yMax - bbox.yMin;
1637
1638 return 0;
1639 }
1640
1641
1642 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1643
1644 static FT_Error
1645 load_sbit_image( TT_Size size,
1646 TT_GlyphSlot glyph,
1647 FT_UInt glyph_index,
1648 FT_Int32 load_flags )
1649 {
1650 TT_Face face;
1651 SFNT_Service sfnt;
1652 FT_Stream stream;
1653 FT_Error error;
1654 TT_SBit_MetricsRec metrics;
1655
1656
1657 face = (TT_Face)glyph->face;
1658 sfnt = (SFNT_Service)face->sfnt;
1659 stream = face->root.stream;
1660
1661 error = sfnt->load_sbit_image( face,
1662 size->strike_index,
1663 glyph_index,
1664 (FT_Int)load_flags,
1665 stream,
1666 &glyph->bitmap,
1667 &metrics );
1668 if ( !error )
1669 {
1670 glyph->outline.n_points = 0;
1671 glyph->outline.n_contours = 0;
1672
1673 glyph->metrics.width = (FT_Pos)metrics.width << 6;
1674 glyph->metrics.height = (FT_Pos)metrics.height << 6;
1675
1676 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1677 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1678 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6;
1679
1680 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1681 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1682 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6;
1683
1684 glyph->format = FT_GLYPH_FORMAT_BITMAP;
1685 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1686 {
1687 glyph->bitmap_left = metrics.vertBearingX;
1688 glyph->bitmap_top = metrics.vertBearingY;
1689 }
1690 else
1691 {
1692 glyph->bitmap_left = metrics.horiBearingX;
1693 glyph->bitmap_top = metrics.horiBearingY;
1694 }
1695 }
1696
1697 return error;
1698 }
1699
1700 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1701
1702
1703 static FT_Error
1704 tt_loader_init( TT_Loader loader,
1705 TT_Size size,
1706 TT_GlyphSlot glyph,
1707 FT_Int32 load_flags )
1708 {
1709 TT_Face face;
1710 FT_Stream stream;
1711
1712
1713 face = (TT_Face)glyph->face;
1714 stream = face->root.stream;
1715
1716 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
1717
1718 #ifdef TT_USE_BYTECODE_INTERPRETER
1719
1720 /* load execution context */
1721 if ( IS_HINTED( load_flags ) )
1722 {
1723 TT_ExecContext exec;
1724 FT_Bool grayscale;
1725
1726
1727 if ( !size->cvt_ready )
1728 {
1729 FT_Error error = tt_size_ready_bytecode( size );
1730 if ( error )
1731 return error;
1732 }
1733
1734 /* query new execution context */
1735 exec = size->debug ? size->context
1736 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
1737 if ( !exec )
1738 return TT_Err_Could_Not_Find_Context;
1739
1740 grayscale =
1741 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
1742
1743 TT_Load_Context( exec, face, size );
1744
1745 /* a change from mono to grayscale rendering (and vice versa) */
1746 /* requires a re-execution of the CVT program */
1747 if ( grayscale != exec->grayscale )
1748 {
1749 FT_UInt i;
1750
1751
1752 exec->grayscale = grayscale;
1753
1754 for ( i = 0; i < size->cvt_size; i++ )
1755 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
1756 tt_size_run_prep( size );
1757 }
1758
1759 /* see if the cvt program has disabled hinting */
1760 if ( exec->GS.instruct_control & 1 )
1761 load_flags |= FT_LOAD_NO_HINTING;
1762
1763 /* load default graphics state - if needed */
1764 if ( exec->GS.instruct_control & 2 )
1765 exec->GS = tt_default_graphics_state;
1766
1767 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
1768 loader->exec = exec;
1769 loader->instructions = exec->glyphIns;
1770 }
1771
1772 #endif /* TT_USE_BYTECODE_INTERPRETER */
1773
1774 /* seek to the beginning of the glyph table. For Type 42 fonts */
1775 /* the table might be accessed from a Postscript stream or something */
1776 /* else... */
1777
1778 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1779
1780 if ( face->root.internal->incremental_interface )
1781 loader->glyf_offset = 0;
1782 else
1783
1784 #endif
1785
1786 {
1787 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 );
1788
1789
1790 if ( error )
1791 {
1792 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
1793 return error;
1794 }
1795 loader->glyf_offset = FT_STREAM_POS();
1796 }
1797
1798 /* get face's glyph loader */
1799 {
1800 FT_GlyphLoader gloader = glyph->internal->loader;
1801
1802
1803 FT_GlyphLoader_Rewind( gloader );
1804 loader->gloader = gloader;
1805 }
1806
1807 loader->load_flags = load_flags;
1808
1809 loader->face = (FT_Face)face;
1810 loader->size = (FT_Size)size;
1811 loader->glyph = (FT_GlyphSlot)glyph;
1812 loader->stream = stream;
1813
1814 return TT_Err_Ok;
1815 }
1816
1817
1818 /*************************************************************************/
1819 /* */
1820 /* <Function> */
1821 /* TT_Load_Glyph */
1822 /* */
1823 /* <Description> */
1824 /* A function used to load a single glyph within a given glyph slot, */
1825 /* for a given size. */
1826 /* */
1827 /* <Input> */
1828 /* glyph :: A handle to a target slot object where the glyph */
1829 /* will be loaded. */
1830 /* */
1831 /* size :: A handle to the source face size at which the glyph */
1832 /* must be scaled/loaded. */
1833 /* */
1834 /* glyph_index :: The index of the glyph in the font file. */
1835 /* */
1836 /* load_flags :: A flag indicating what to load for this glyph. The */
1837 /* FT_LOAD_XXX constants can be used to control the */
1838 /* glyph loading process (e.g., whether the outline */
1839 /* should be scaled, whether to load bitmaps or not, */
1840 /* whether to hint the outline, etc). */
1841 /* */
1842 /* <Return> */
1843 /* FreeType error code. 0 means success. */
1844 /* */
1845 FT_LOCAL_DEF( FT_Error )
1846 TT_Load_Glyph( TT_Size size,
1847 TT_GlyphSlot glyph,
1848 FT_UInt glyph_index,
1849 FT_Int32 load_flags )
1850 {
1851 TT_Face face;
1852 FT_Stream stream;
1853 FT_Error error;
1854 TT_LoaderRec loader;
1855
1856
1857 face = (TT_Face)glyph->face;
1858 stream = face->root.stream;
1859 error = TT_Err_Ok;
1860
1861 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1862
1863 /* try to load embedded bitmap if any */
1864 /* */
1865 /* XXX: The convention should be emphasized in */
1866 /* the documents because it can be confusing. */
1867 if ( size->strike_index != 0xFFFFFFFFUL &&
1868 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
1869 {
1870 error = load_sbit_image( size, glyph, glyph_index, load_flags );
1871 if ( !error )
1872 return TT_Err_Ok;
1873 }
1874
1875 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1876
1877 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
1878 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
1879 return TT_Err_Invalid_Size_Handle;
1880
1881 if ( load_flags & FT_LOAD_SBITS_ONLY )
1882 return TT_Err_Invalid_Argument;
1883
1884 error = tt_loader_init( &loader, size, glyph, load_flags );
1885 if ( error )
1886 return error;
1887
1888 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
1889 glyph->num_subglyphs = 0;
1890 glyph->outline.flags = 0;
1891
1892 /* Main loading loop */
1893 error = load_truetype_glyph( &loader, glyph_index, 0 );
1894 if ( !error )
1895 {
1896 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
1897 {
1898 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
1899 glyph->subglyphs = loader.gloader->base.subglyphs;
1900 }
1901 else
1902 {
1903 glyph->outline = loader.gloader->base.outline;
1904 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
1905
1906 /* In case bit 1 of the `flags' field in the `head' table isn't */
1907 /* set, translate array so that (0,0) is the glyph's origin. */
1908 if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
1909 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
1910 }
1911
1912 compute_glyph_metrics( &loader, glyph_index );
1913 }
1914
1915 /* Set the `high precision' bit flag. */
1916 /* This is _critical_ to get correct output for monochrome */
1917 /* TrueType glyphs at all sizes using the bytecode interpreter. */
1918 /* */
1919 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
1920 size->root.metrics.y_ppem < 24 )
1921 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
1922
1923 return error;
1924 }
1925
1926
1927 /* END */