sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
ttgload.c
1/****************************************************************************
2 *
3 * ttgload.c
4 *
5 * TrueType Glyph Loader (body).
6 *
7 * Copyright (C) 1996-2025 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>
21#include FT_CONFIG_CONFIG_H
25#include <freetype/tttags.h>
26#include <freetype/ftoutln.h>
27#include <freetype/ftdriver.h>
28#include <freetype/ftlist.h>
29
30#include "ttgload.h"
31#include "ttpload.h"
32
33#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
34#include "ttgxvar.h"
35#endif
36
37#include "tterrors.h"
38
39
40 /**************************************************************************
41 *
42 * The macro FT_COMPONENT is used in trace mode. It is an implicit
43 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
44 * messages during execution.
45 */
46#undef FT_COMPONENT
47#define FT_COMPONENT ttgload
48
49
50 /**************************************************************************
51 *
52 * Simple glyph flags.
53 */
54#define ON_CURVE_POINT 0x01 /* same value as FT_CURVE_TAG_ON */
55#define X_SHORT_VECTOR 0x02
56#define Y_SHORT_VECTOR 0x04
57#define REPEAT_FLAG 0x08
58#define X_POSITIVE 0x10 /* two meanings depending on X_SHORT_VECTOR */
59#define SAME_X 0x10
60#define Y_POSITIVE 0x20 /* two meanings depending on Y_SHORT_VECTOR */
61#define SAME_Y 0x20
62#define OVERLAP_SIMPLE 0x40 /* retained as FT_OUTLINE_OVERLAP */
63
64
65 /**************************************************************************
66 *
67 * Composite glyph flags.
68 */
69#define ARGS_ARE_WORDS 0x0001
70#define ARGS_ARE_XY_VALUES 0x0002
71#define ROUND_XY_TO_GRID 0x0004
72#define WE_HAVE_A_SCALE 0x0008
73/* reserved 0x0010 */
74#define MORE_COMPONENTS 0x0020
75#define WE_HAVE_AN_XY_SCALE 0x0040
76#define WE_HAVE_A_2X2 0x0080
77#define WE_HAVE_INSTR 0x0100
78#define USE_MY_METRICS 0x0200
79#define OVERLAP_COMPOUND 0x0400 /* retained as FT_OUTLINE_OVERLAP */
80#define SCALED_COMPONENT_OFFSET 0x0800
81#define UNSCALED_COMPONENT_OFFSET 0x1000
82
83
84#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
85#define IS_DEFAULT_INSTANCE( _face ) \
86 ( !( FT_IS_NAMED_INSTANCE( _face ) || \
87 FT_IS_VARIATION( _face ) ) )
88#else
89#define IS_DEFAULT_INSTANCE( _face ) 1
90#endif
91
92
93 /**************************************************************************
94 *
95 * Return the horizontal metrics in font units for a given glyph.
96 */
97 FT_LOCAL_DEF( void )
98 TT_Get_HMetrics( TT_Face face,
99 FT_UInt idx,
100 FT_Short* lsb,
101 FT_UShort* aw )
102 {
103 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
104
105 FT_TRACE5(( " advance width (font units): %d\n", *aw ));
106 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb ));
107 }
108
109
110 /**************************************************************************
111 *
112 * Return the vertical metrics in font units for a given glyph.
113 * See function `tt_loader_set_pp' below for explanations.
114 */
115 FT_LOCAL_DEF( void )
116 TT_Get_VMetrics( TT_Face face,
117 FT_UInt idx,
118 FT_Pos yMax,
119 FT_Short* tsb,
120 FT_UShort* ah )
121 {
122 if ( face->vertical_info )
123 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
124
125 else if ( face->os2.version != 0xFFFFU )
126 {
127 *tsb = (FT_Short)( face->os2.sTypoAscender - yMax );
128 *ah = (FT_UShort)FT_ABS( face->os2.sTypoAscender -
129 face->os2.sTypoDescender );
130 }
131
132 else
133 {
134 *tsb = (FT_Short)( face->horizontal.Ascender - yMax );
135 *ah = (FT_UShort)FT_ABS( face->horizontal.Ascender -
136 face->horizontal.Descender );
137 }
138
139#ifdef FT_DEBUG_LEVEL_TRACE
140 if ( !face->vertical_info )
141 FT_TRACE5(( " [vertical metrics missing, computing values]\n" ));
142#endif
143
144 FT_TRACE5(( " advance height (font units): %d\n", *ah ));
145 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb ));
146 }
147
148
149 static FT_Error
150 tt_get_metrics( TT_Loader loader,
151 FT_UInt glyph_index )
152 {
153 TT_Face face = loader->face;
154
155 FT_Error error;
156 FT_Stream stream = loader->stream;
157
158 FT_Short left_bearing = 0, top_bearing = 0;
159 FT_UShort advance_width = 0, advance_height = 0;
160
161 /* we must preserve the stream position */
162 /* (which gets altered by the metrics functions) */
163 FT_ULong pos = FT_STREAM_POS();
164
165
166 TT_Get_HMetrics( face, glyph_index,
167 &left_bearing,
168 &advance_width );
169 TT_Get_VMetrics( face, glyph_index,
170 loader->bbox.yMax,
171 &top_bearing,
172 &advance_height );
173
174 if ( FT_STREAM_SEEK( pos ) )
175 return error;
176
177 loader->left_bearing = left_bearing;
178 loader->advance = advance_width;
179 loader->top_bearing = top_bearing;
180 loader->vadvance = advance_height;
181
182#ifdef FT_CONFIG_OPTION_INCREMENTAL
183 /* With the incremental interface, these values are set by */
184 /* a call to `tt_get_metrics_incremental'. */
185 if ( face->root.internal->incremental_interface == NULL )
186#endif
187 {
188 if ( !loader->linear_def )
189 {
190 loader->linear_def = 1;
191 loader->linear = advance_width;
192 }
193 }
194
195 return FT_Err_Ok;
196 }
197
198
199#ifdef FT_CONFIG_OPTION_INCREMENTAL
200
201 static void
202 tt_get_metrics_incremental( TT_Loader loader,
203 FT_UInt glyph_index )
204 {
205 TT_Face face = loader->face;
206
207 FT_Short left_bearing = 0, top_bearing = 0;
208 FT_UShort advance_width = 0, advance_height = 0;
209
210
211 /* If this is an incrementally loaded font check whether there are */
212 /* overriding metrics for this glyph. */
213 if ( face->root.internal->incremental_interface &&
214 face->root.internal->incremental_interface->funcs->get_glyph_metrics )
215 {
216 FT_Incremental_MetricsRec incr_metrics;
217 FT_Error error;
218
219
220 incr_metrics.bearing_x = loader->left_bearing;
221 incr_metrics.bearing_y = 0;
222 incr_metrics.advance = loader->advance;
223 incr_metrics.advance_v = 0;
224
225 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
226 face->root.internal->incremental_interface->object,
227 glyph_index, FALSE, &incr_metrics );
228 if ( error )
229 goto Exit;
230
231 left_bearing = (FT_Short)incr_metrics.bearing_x;
232 advance_width = (FT_UShort)incr_metrics.advance;
233
234#if 0
235
236 /* GWW: Do I do the same for vertical metrics? */
237 incr_metrics.bearing_x = 0;
238 incr_metrics.bearing_y = loader->top_bearing;
239 incr_metrics.advance = loader->vadvance;
240
241 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
242 face->root.internal->incremental_interface->object,
243 glyph_index, TRUE, &incr_metrics );
244 if ( error )
245 goto Exit;
246
247 top_bearing = (FT_Short)incr_metrics.bearing_y;
248 advance_height = (FT_UShort)incr_metrics.advance;
249
250#endif /* 0 */
251
252 loader->left_bearing = left_bearing;
253 loader->advance = advance_width;
254 loader->top_bearing = top_bearing;
255 loader->vadvance = advance_height;
256
257 if ( !loader->linear_def )
258 {
259 loader->linear_def = 1;
260 loader->linear = advance_width;
261 }
262 }
263
264 Exit:
265 return;
266 }
267
268#endif /* FT_CONFIG_OPTION_INCREMENTAL */
269
270
271 /**************************************************************************
272 *
273 * The following functions are used by default with TrueType fonts.
274 * However, they can be replaced by alternatives if we need to support
275 * TrueType-compressed formats (like MicroType) in the future.
276 *
277 */
278
279 FT_CALLBACK_DEF( FT_Error )
280 TT_Access_Glyph_Frame( TT_Loader loader,
281 FT_UInt glyph_index,
282 FT_ULong offset,
283 FT_UInt byte_count )
284 {
285 FT_Error error;
286 FT_Stream stream = loader->stream;
287
288 FT_UNUSED( glyph_index );
289
290
291 /* the following line sets the `error' variable through macros! */
292 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
293 return error;
294
295 loader->cursor = stream->cursor;
296 loader->limit = stream->limit;
297
298 return FT_Err_Ok;
299 }
300
301
302 FT_CALLBACK_DEF( void )
303 TT_Forget_Glyph_Frame( TT_Loader loader )
304 {
305 FT_Stream stream = loader->stream;
306
307
308 FT_FRAME_EXIT();
309 }
310
311
312 FT_CALLBACK_DEF( FT_Error )
313 TT_Load_Glyph_Header( TT_Loader loader )
314 {
315 FT_Byte* p = loader->cursor;
316 FT_Byte* limit = loader->limit;
317
318
319 if ( p + 10 > limit )
320 return FT_THROW( Invalid_Outline );
321
322 loader->n_contours = FT_NEXT_SHORT( p );
323
324 loader->bbox.xMin = FT_NEXT_SHORT( p );
325 loader->bbox.yMin = FT_NEXT_SHORT( p );
326 loader->bbox.xMax = FT_NEXT_SHORT( p );
327 loader->bbox.yMax = FT_NEXT_SHORT( p );
328
329 FT_TRACE5(( " # of contours: %d\n", loader->n_contours ));
330 FT_TRACE5(( " xMin: %4ld xMax: %4ld\n", loader->bbox.xMin,
331 loader->bbox.xMax ));
332 FT_TRACE5(( " yMin: %4ld yMax: %4ld\n", loader->bbox.yMin,
333 loader->bbox.yMax ));
334 loader->cursor = p;
335
336 return FT_Err_Ok;
337 }
338
339
340 FT_CALLBACK_DEF( FT_Error )
341 TT_Load_Simple_Glyph( TT_Loader load )
342 {
343 FT_Error error;
344 FT_Byte* p = load->cursor;
345 FT_Byte* limit = load->limit;
346 FT_GlyphLoader gloader = load->gloader;
347 FT_Outline* outline = &gloader->current.outline;
348 FT_Int n_contours = load->n_contours;
349 FT_Int n_points;
350 FT_UShort n_ins;
351
352 FT_Byte *flag, *flag_limit;
353 FT_Byte c, count;
354 FT_Vector *vec, *vec_limit;
355 FT_Pos x, y;
356 FT_UShort *cont, *cont_limit;
357 FT_Int last;
358
359
360 /* check that we can add the contours to the glyph */
361 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
362 if ( error )
363 goto Fail;
364
365 /* check space for contours array + instructions count */
366 if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit )
367 goto Invalid_Outline;
368
369 /* reading the contours' endpoints & number of points */
370 cont = outline->contours;
371 cont_limit = cont + n_contours;
372
373 last = -1;
374 for ( ; cont < cont_limit; cont++ )
375 {
376 *cont = FT_NEXT_USHORT( p );
377
378 if ( *cont <= last )
379 goto Invalid_Outline;
380
381 last = *cont;
382 }
383
384 n_points = last + 1;
385
386 FT_TRACE5(( " # of points: %d\n", n_points ));
387
388 /* note that we will add four phantom points later */
389 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
390 if ( error )
391 goto Fail;
392
393 /* space checked above */
394 n_ins = FT_NEXT_USHORT( p );
395
396 FT_TRACE5(( " Instructions size: %u\n", n_ins ));
397
398 /* check instructions size */
399 if ( p + n_ins > limit )
400 {
401 FT_TRACE1(( "TT_Load_Simple_Glyph: excessive instruction count\n" ));
402 error = FT_THROW( Too_Many_Hints );
403 goto Fail;
404 }
405
406#ifdef TT_USE_BYTECODE_INTERPRETER
407
408 if ( IS_HINTED( load->load_flags ) )
409 {
410 TT_ExecContext exec = load->exec;
411 FT_Memory memory = exec->memory;
412
413
414 if ( exec->glyphSize )
415 FT_FREE( exec->glyphIns );
416 exec->glyphSize = 0;
417
418 /* we don't trust `maxSizeOfInstructions' in the `maxp' table */
419 /* and thus allocate the bytecode array size by ourselves */
420 if ( n_ins )
421 {
422 if ( FT_DUP( exec->glyphIns, p, n_ins ) )
423 return error;
424
425 exec->glyphSize = n_ins;
426 }
427 }
428
429#endif /* TT_USE_BYTECODE_INTERPRETER */
430
431 p += n_ins;
432
433 /* reading the point tags */
434 flag = outline->tags;
435 flag_limit = flag + n_points;
436
437 FT_ASSERT( flag );
438
439 while ( flag < flag_limit )
440 {
441 if ( p + 1 > limit )
442 goto Invalid_Outline;
443
444 *flag++ = c = FT_NEXT_BYTE( p );
445 if ( c & REPEAT_FLAG )
446 {
447 if ( p + 1 > limit )
448 goto Invalid_Outline;
449
450 count = FT_NEXT_BYTE( p );
451 if ( flag + (FT_Int)count > flag_limit )
452 goto Invalid_Outline;
453
454 for ( ; count > 0; count-- )
455 *flag++ = c;
456 }
457 }
458
459 /* retain the overlap flag */
460 if ( n_points && outline->tags[0] & OVERLAP_SIMPLE )
461 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
462
463 /* reading the X coordinates */
464
465 vec = outline->points;
466 vec_limit = vec + n_points;
467 flag = outline->tags;
468 x = 0;
469
470 for ( ; vec < vec_limit; vec++, flag++ )
471 {
472 FT_Pos delta = 0;
473 FT_Byte f = *flag;
474
475
476 if ( f & X_SHORT_VECTOR )
477 {
478 if ( p + 1 > limit )
479 goto Invalid_Outline;
480
481 delta = (FT_Pos)FT_NEXT_BYTE( p );
482 if ( !( f & X_POSITIVE ) )
483 delta = -delta;
484 }
485 else if ( !( f & SAME_X ) )
486 {
487 if ( p + 2 > limit )
488 goto Invalid_Outline;
489
490 delta = (FT_Pos)FT_NEXT_SHORT( p );
491 }
492
493 x += delta;
494 vec->x = x;
495 }
496
497 /* reading the Y coordinates */
498
499 vec = outline->points;
500 vec_limit = vec + n_points;
501 flag = outline->tags;
502 y = 0;
503
504 for ( ; vec < vec_limit; vec++, flag++ )
505 {
506 FT_Pos delta = 0;
507 FT_Byte f = *flag;
508
509
510 if ( f & Y_SHORT_VECTOR )
511 {
512 if ( p + 1 > limit )
513 goto Invalid_Outline;
514
515 delta = (FT_Pos)FT_NEXT_BYTE( p );
516 if ( !( f & Y_POSITIVE ) )
517 delta = -delta;
518 }
519 else if ( !( f & SAME_Y ) )
520 {
521 if ( p + 2 > limit )
522 goto Invalid_Outline;
523
524 delta = (FT_Pos)FT_NEXT_SHORT( p );
525 }
526
527 y += delta;
528 vec->y = y;
529
530 /* the cast is for stupid compilers */
531 *flag = (FT_Byte)( f & ON_CURVE_POINT );
532 }
533
534 outline->n_points = (FT_UShort)n_points;
535 outline->n_contours = (FT_UShort)n_contours;
536
537 load->cursor = p;
538
539 Fail:
540 return error;
541
542 Invalid_Outline:
543 error = FT_THROW( Invalid_Outline );
544 goto Fail;
545 }
546
547
548 FT_CALLBACK_DEF( FT_Error )
549 TT_Load_Composite_Glyph( TT_Loader loader )
550 {
551 FT_Error error;
552 FT_Byte* p = loader->cursor;
553 FT_Byte* limit = loader->limit;
554 FT_GlyphLoader gloader = loader->gloader;
555 FT_Long num_glyphs = loader->face->root.num_glyphs;
556 FT_SubGlyph subglyph;
557 FT_UInt num_subglyphs;
558
559
560 num_subglyphs = 0;
561
562 do
563 {
564 FT_Fixed xx, xy, yy, yx;
565 FT_UInt count;
566
567
568 /* check that we can load a new subglyph */
569 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
570 if ( error )
571 goto Fail;
572
573 /* check space */
574 if ( p + 4 > limit )
575 goto Invalid_Composite;
576
577 subglyph = gloader->current.subglyphs + num_subglyphs;
578
579 subglyph->arg1 = subglyph->arg2 = 0;
580
581 subglyph->flags = FT_NEXT_USHORT( p );
582 subglyph->index = FT_NEXT_USHORT( p );
583
584 /* we reject composites that have components */
585 /* with invalid glyph indices */
586 if ( subglyph->index >= num_glyphs )
587 goto Invalid_Composite;
588
589 /* check space */
590 count = 2;
591 if ( subglyph->flags & ARGS_ARE_WORDS )
592 count += 2;
593 if ( subglyph->flags & WE_HAVE_A_SCALE )
594 count += 2;
595 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
596 count += 4;
597 else if ( subglyph->flags & WE_HAVE_A_2X2 )
598 count += 8;
599
600 if ( p + count > limit )
601 goto Invalid_Composite;
602
603 /* read arguments */
604 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
605 {
606 if ( subglyph->flags & ARGS_ARE_WORDS )
607 {
608 subglyph->arg1 = FT_NEXT_SHORT( p );
609 subglyph->arg2 = FT_NEXT_SHORT( p );
610 }
611 else
612 {
613 subglyph->arg1 = FT_NEXT_CHAR( p );
614 subglyph->arg2 = FT_NEXT_CHAR( p );
615 }
616 }
617 else
618 {
619 if ( subglyph->flags & ARGS_ARE_WORDS )
620 {
621 subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p );
622 subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p );
623 }
624 else
625 {
626 subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p );
627 subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p );
628 }
629 }
630
631 /* read transform */
632 xx = yy = 0x10000L;
633 xy = yx = 0;
634
635 if ( subglyph->flags & WE_HAVE_A_SCALE )
636 {
637 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
638 yy = xx;
639 }
640 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
641 {
642 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
643 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
644 }
645 else if ( subglyph->flags & WE_HAVE_A_2X2 )
646 {
647 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
648 yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
649 xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
650 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4;
651 }
652
653 subglyph->transform.xx = xx;
654 subglyph->transform.xy = xy;
655 subglyph->transform.yx = yx;
656 subglyph->transform.yy = yy;
657
658 num_subglyphs++;
659
660 } while ( subglyph->flags & MORE_COMPONENTS );
661
662 gloader->current.num_subglyphs = num_subglyphs;
663 FT_TRACE5(( " %u component%s\n",
664 num_subglyphs,
665 num_subglyphs > 1 ? "s" : "" ));
666
667#ifdef FT_DEBUG_LEVEL_TRACE
668 {
669 FT_UInt i;
670
671
672 subglyph = gloader->current.subglyphs;
673
674 for ( i = 0; i < num_subglyphs; i++ )
675 {
676 if ( num_subglyphs > 1 )
677 FT_TRACE7(( " subglyph %u:\n", i ));
678
679 FT_TRACE7(( " glyph index: %d\n", subglyph->index ));
680
681 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
682 FT_TRACE7(( " offset: x=%d, y=%d\n",
683 subglyph->arg1,
684 subglyph->arg2 ));
685 else
686 FT_TRACE7(( " matching points: base=%d, component=%d\n",
687 subglyph->arg1,
688 subglyph->arg2 ));
689
690 if ( subglyph->flags & WE_HAVE_A_SCALE )
691 FT_TRACE7(( " scaling: %f\n",
692 (double)subglyph->transform.xx / 65536 ));
693 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
694 FT_TRACE7(( " scaling: x=%f, y=%f\n",
695 (double)subglyph->transform.xx / 65536,
696 (double)subglyph->transform.yy / 65536 ));
697 else if ( subglyph->flags & WE_HAVE_A_2X2 )
698 {
699 FT_TRACE7(( " scaling: xx=%f, yx=%f\n",
700 (double)subglyph->transform.xx / 65536,
701 (double)subglyph->transform.yx / 65536 ));
702 FT_TRACE7(( " xy=%f, yy=%f\n",
703 (double)subglyph->transform.xy / 65536,
704 (double)subglyph->transform.yy / 65536 ));
705 }
706
707 subglyph++;
708 }
709 }
710#endif /* FT_DEBUG_LEVEL_TRACE */
711
712#ifdef TT_USE_BYTECODE_INTERPRETER
713
714 {
715 FT_Stream stream = loader->stream;
716
717
718 /* we must undo the FT_FRAME_ENTER in order to point */
719 /* to the composite instructions, if we find some. */
720 /* We will process them later. */
721 /* */
722 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
723 p - limit );
724 }
725
726#endif
727
728 loader->cursor = p;
729
730 Fail:
731 return error;
732
733 Invalid_Composite:
734 error = FT_THROW( Invalid_Composite );
735 goto Fail;
736 }
737
738
739 FT_LOCAL_DEF( void )
740 TT_Init_Glyph_Loading( TT_Face face )
741 {
742 face->access_glyph_frame = TT_Access_Glyph_Frame;
743 face->read_glyph_header = TT_Load_Glyph_Header;
744 face->read_simple_glyph = TT_Load_Simple_Glyph;
745 face->read_composite_glyph = TT_Load_Composite_Glyph;
746 face->forget_glyph_frame = TT_Forget_Glyph_Frame;
747 }
748
749
750 static void
751 tt_prepare_zone( TT_GlyphZone zone,
752 FT_GlyphLoad load,
753 FT_UInt start_point,
754 FT_UInt start_contour )
755 {
756 zone->n_points = load->outline.n_points + 4 - (FT_UShort)start_point;
757 zone->n_contours = load->outline.n_contours - (FT_UShort)start_contour;
758 zone->org = load->extra_points + start_point;
759 zone->cur = load->outline.points + start_point;
760 zone->orus = load->extra_points2 + start_point;
761 zone->tags = load->outline.tags + start_point;
762 zone->contours = load->outline.contours + start_contour;
763 zone->first_point = (FT_UShort)start_point;
764 }
765
766
767 /**************************************************************************
768 *
769 * @Function:
770 * TT_Hint_Glyph
771 *
772 * @Description:
773 * Hint the glyph using the zone prepared by the caller. Note that
774 * the zone is supposed to include four phantom points.
775 */
776 static FT_Error
777 TT_Hint_Glyph( TT_Loader loader,
778 FT_Bool is_composite )
779 {
780 TT_GlyphZone zone = &loader->zone;
781
782#ifdef TT_USE_BYTECODE_INTERPRETER
783 TT_ExecContext exec = loader->exec;
784 TT_Size size = loader->size;
785 FT_Long n_ins = exec->glyphSize;
786#else
787 FT_UNUSED( is_composite );
788#endif
789
790
791#ifdef TT_USE_BYTECODE_INTERPRETER
792 /* save original point positions in `org' array */
793 if ( n_ins > 0 )
794 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
795
796 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
797 /* completely refer to the (already) hinted subglyphs. */
798 if ( is_composite )
799 {
800 exec->metrics.x_scale = 1 << 16;
801 exec->metrics.y_scale = 1 << 16;
802
803 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
804 }
805 else
806 {
807 exec->metrics.x_scale = size->metrics->x_scale;
808 exec->metrics.y_scale = size->metrics->y_scale;
809 }
810#endif
811
812 /* round phantom points */
813 zone->cur[zone->n_points - 4].x =
814 FT_PIX_ROUND( zone->cur[zone->n_points - 4].x );
815 zone->cur[zone->n_points - 3].x =
816 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
817 zone->cur[zone->n_points - 2].y =
818 FT_PIX_ROUND( zone->cur[zone->n_points - 2].y );
819 zone->cur[zone->n_points - 1].y =
820 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
821
822#ifdef TT_USE_BYTECODE_INTERPRETER
823
824 if ( n_ins > 0 )
825 {
826 FT_Error error;
827
828
829 TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins );
830
831 exec->is_composite = is_composite;
832 exec->pts = *zone;
833
834 error = TT_Run_Context( exec, size );
835 if ( error && exec->pedantic_hinting )
836 return error;
837
838 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */
839 loader->gloader->current.outline.tags[0] |=
840 ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE;
841 }
842
843#endif
844
845 /* Save possibly modified glyph phantom points unless in v40 backward */
846 /* compatibility mode, where no movement on the x axis means no reason */
847 /* to change bearings or advance widths. */
848
849#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
850 if ( exec->backward_compatibility )
851 return FT_Err_Ok;
852#endif
853
854 loader->pp1 = zone->cur[zone->n_points - 4];
855 loader->pp2 = zone->cur[zone->n_points - 3];
856 loader->pp3 = zone->cur[zone->n_points - 2];
857 loader->pp4 = zone->cur[zone->n_points - 1];
858
859 return FT_Err_Ok;
860 }
861
862
863 /**************************************************************************
864 *
865 * @Function:
866 * TT_Process_Simple_Glyph
867 *
868 * @Description:
869 * Once a simple glyph has been loaded, it needs to be processed.
870 * Usually, this means scaling and hinting through bytecode
871 * interpretation.
872 */
873 static FT_Error
874 TT_Process_Simple_Glyph( TT_Loader loader )
875 {
876 FT_Error error = FT_Err_Ok;
877 FT_GlyphLoader gloader = loader->gloader;
878 FT_Outline* outline = &gloader->current.outline;
879 FT_Int n_points = outline->n_points;
880
881#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
882 FT_Memory memory = loader->face->root.memory;
883 FT_Vector* unrounded = NULL;
884#endif
885
886
887 /* set phantom points */
888 outline->points[n_points ] = loader->pp1;
889 outline->points[n_points + 1] = loader->pp2;
890 outline->points[n_points + 2] = loader->pp3;
891 outline->points[n_points + 3] = loader->pp4;
892
893 n_points += 4;
894
895#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
896
897 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
898 {
899 if ( FT_QNEW_ARRAY( unrounded, n_points ) )
900 goto Exit;
901
902 /* Deltas apply to the unscaled data. */
903 error = TT_Vary_Apply_Glyph_Deltas( loader,
904 outline,
905 unrounded );
906 if ( error )
907 goto Exit;
908 }
909
910#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
911
912 if ( IS_HINTED( loader->load_flags ) )
913 {
914 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
915
916 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
917 loader->zone.n_points );
918 }
919
920 {
921 FT_Vector* vec = outline->points;
922 FT_Vector* limit = outline->points + n_points;
923
924 FT_Fixed x_scale = 0; /* pacify compiler */
925 FT_Fixed y_scale = 0;
926
927 FT_Bool do_scale = FALSE;
928
929
930 {
931 /* scale the glyph */
932 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
933 {
934 x_scale = loader->size->metrics->x_scale;
935 y_scale = loader->size->metrics->y_scale;
936
937 do_scale = TRUE;
938 }
939 }
940
941 if ( do_scale )
942 {
943#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
944 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
945 {
946 FT_Vector* u = unrounded;
947
948
949 for ( ; vec < limit; vec++, u++ )
950 {
951 vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6;
952 vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6;
953 }
954 }
955 else
956#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
957 {
958 for ( ; vec < limit; vec++ )
959 {
960 vec->x = FT_MulFix( vec->x, x_scale );
961 vec->y = FT_MulFix( vec->y, y_scale );
962 }
963 }
964 }
965
966#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
967 /* if we have a HVAR table, `pp1' and/or `pp2' */
968 /* are already adjusted but unscaled */
969 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) &&
970 IS_HINTED( loader->load_flags ) )
971 {
972 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
973 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
974 /* pp1.y and pp2.y are always zero */
975 }
976 else
977#endif
978 {
979 loader->pp1 = outline->points[n_points - 4];
980 loader->pp2 = outline->points[n_points - 3];
981 }
982
983#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
984 /* if we have a VVAR table, `pp3' and/or `pp4' */
985 /* are already adjusted but unscaled */
986 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) &&
987 IS_HINTED( loader->load_flags ) )
988 {
989 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
990 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
991 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
992 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
993 }
994 else
995#endif
996 {
997 loader->pp3 = outline->points[n_points - 2];
998 loader->pp4 = outline->points[n_points - 1];
999 }
1000 }
1001
1002 if ( IS_HINTED( loader->load_flags ) )
1003 error = TT_Hint_Glyph( loader, 0 );
1004
1005#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1006 Exit:
1007 FT_FREE( unrounded );
1008#endif
1009
1010 return error;
1011 }
1012
1013
1014 /**************************************************************************
1015 *
1016 * @Function:
1017 * TT_Process_Composite_Component
1018 *
1019 * @Description:
1020 * Once a composite component has been loaded, it needs to be
1021 * processed. Usually, this means transforming and translating.
1022 */
1023 static FT_Error
1024 TT_Process_Composite_Component( TT_Loader loader,
1025 FT_SubGlyph subglyph,
1026 FT_UInt start_point,
1027 FT_UInt num_base_points )
1028 {
1029 FT_GlyphLoader gloader = loader->gloader;
1030 FT_Outline current;
1031 FT_Bool have_scale;
1032 FT_Pos x, y;
1033
1034
1035 current.points = gloader->base.outline.points +
1036 num_base_points;
1037 current.n_points = gloader->base.outline.n_points -
1038 (FT_UShort)num_base_points;
1039
1040 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE |
1041 WE_HAVE_AN_XY_SCALE |
1042 WE_HAVE_A_2X2 ) );
1043
1044 /* perform the transform required for this subglyph */
1045 if ( have_scale )
1046 FT_Outline_Transform( &current, &subglyph->transform );
1047
1048 /* get offset */
1049 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1050 {
1051 FT_UInt num_points = gloader->base.outline.n_points;
1052 FT_UInt k = (FT_UInt)subglyph->arg1;
1053 FT_UInt l = (FT_UInt)subglyph->arg2;
1054 FT_Vector* p1;
1055 FT_Vector* p2;
1056
1057
1058 /* match l-th point of the newly loaded component to the k-th point */
1059 /* of the previously loaded components. */
1060
1061 /* change to the point numbers used by our outline */
1062 k += start_point;
1063 l += num_base_points;
1064 if ( k >= num_base_points ||
1065 l >= num_points )
1066 return FT_THROW( Invalid_Composite );
1067
1068 p1 = gloader->base.outline.points + k;
1069 p2 = gloader->base.outline.points + l;
1070
1071 x = SUB_LONG( p1->x, p2->x );
1072 y = SUB_LONG( p1->y, p2->y );
1073 }
1074 else
1075 {
1076 x = subglyph->arg1;
1077 y = subglyph->arg2;
1078
1079 if ( !x && !y )
1080 return FT_Err_Ok;
1081
1082 /* Use a default value dependent on */
1083 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old */
1084 /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit. */
1085
1086 if ( have_scale &&
1087#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1088 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1089#else
1090 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1091#endif
1092 {
1093
1094#if 0
1095
1096 /********************************************************************
1097 *
1098 * This algorithm is what Apple documents. But it doesn't work.
1099 */
1100 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx
1101 : -subglyph->transform.xx;
1102 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx
1103 : -subglyph->transform.yx;
1104 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy
1105 : -subglyph->transform.xy;
1106 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy
1107 : -subglyph->transform.yy;
1108 int m = a > b ? a : b;
1109 int n = c > d ? c : d;
1110
1111
1112 if ( a - b <= 33 && a - b >= -33 )
1113 m *= 2;
1114 if ( c - d <= 33 && c - d >= -33 )
1115 n *= 2;
1116 x = FT_MulFix( x, m );
1117 y = FT_MulFix( y, n );
1118
1119#else /* 1 */
1120
1121 /********************************************************************
1122 *
1123 * This algorithm is a guess and works much better than the above.
1124 */
1125 FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx,
1126 subglyph->transform.xy );
1127 FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy,
1128 subglyph->transform.yx );
1129
1130
1131 x = FT_MulFix( x, mac_xscale );
1132 y = FT_MulFix( y, mac_yscale );
1133
1134#endif /* 1 */
1135
1136 }
1137
1138 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1139 {
1140 FT_Fixed x_scale = loader->size->metrics->x_scale;
1141 FT_Fixed y_scale = loader->size->metrics->y_scale;
1142
1143
1144 x = FT_MulFix( x, x_scale );
1145 y = FT_MulFix( y, y_scale );
1146
1147 if ( subglyph->flags & ROUND_XY_TO_GRID &&
1148 IS_HINTED( loader->load_flags ) )
1149 {
1150#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1151 if ( !loader->exec->backward_compatibility )
1152#endif
1153 x = FT_PIX_ROUND( x );
1154
1155 y = FT_PIX_ROUND( y );
1156 }
1157 }
1158 }
1159
1160 if ( x || y )
1161 FT_Outline_Translate( &current, x, y );
1162
1163 return FT_Err_Ok;
1164 }
1165
1166
1167 /**************************************************************************
1168 *
1169 * @Function:
1170 * TT_Process_Composite_Glyph
1171 *
1172 * @Description:
1173 * This is slightly different from TT_Process_Simple_Glyph, in that
1174 * its sole purpose is to hint the glyph. Thus this function is
1175 * only available when bytecode interpreter is enabled.
1176 */
1177 static FT_Error
1178 TT_Process_Composite_Glyph( TT_Loader loader,
1179 FT_UInt start_point,
1180 FT_UInt start_contour )
1181 {
1182 FT_Error error;
1183 FT_Outline* outline = &loader->gloader->base.outline;
1184 FT_UInt i;
1185
1186
1187 /* make room for phantom points */
1188 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1189 outline->n_points + 4,
1190 0 );
1191 if ( error )
1192 return error;
1193
1194 outline->points[outline->n_points ] = loader->pp1;
1195 outline->points[outline->n_points + 1] = loader->pp2;
1196 outline->points[outline->n_points + 2] = loader->pp3;
1197 outline->points[outline->n_points + 3] = loader->pp4;
1198
1199#ifdef TT_USE_BYTECODE_INTERPRETER
1200
1201 {
1202 TT_ExecContext exec = loader->exec;
1203 FT_Memory memory = exec->memory;
1204 FT_Stream stream = loader->stream;
1205 FT_UShort n_ins;
1206
1207
1208 if ( exec->glyphSize )
1209 FT_FREE( exec->glyphIns );
1210 exec->glyphSize = 0;
1211
1212 /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1213 /* so we read them here */
1214 if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1215 FT_READ_USHORT( n_ins ) )
1216 return error;
1217
1218 FT_TRACE5(( " Instructions size = %hu\n", n_ins ));
1219
1220 if ( !n_ins )
1221 return FT_Err_Ok;
1222
1223 /* don't trust `maxSizeOfInstructions'; */
1224 /* only do a rough safety check */
1225 if ( n_ins > loader->byte_len )
1226 {
1227 FT_TRACE1(( "TT_Process_Composite_Glyph:"
1228 " too many instructions (%hu) for glyph with length %u\n",
1229 n_ins, loader->byte_len ));
1230 return FT_THROW( Too_Many_Hints );
1231 }
1232
1233 if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ||
1234 FT_STREAM_READ( exec->glyphIns, n_ins ) )
1235 return error;
1236
1237 exec->glyphSize = n_ins;
1238 }
1239
1240#endif
1241
1242 tt_prepare_zone( &loader->zone, &loader->gloader->base,
1243 start_point, start_contour );
1244
1245 /* Some points are likely touched during execution of */
1246 /* instructions on components. So let's untouch them. */
1247 for ( i = 0; i < loader->zone.n_points - 4U; i++ )
1248 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
1249
1250 return TT_Hint_Glyph( loader, 1 );
1251 }
1252
1253
1254 /*
1255 * Calculate the phantom points
1256 *
1257 * Defining the right side bearing (rsb) as
1258 *
1259 * rsb = aw - (lsb + xmax - xmin)
1260 *
1261 * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
1262 * and `xmax' the glyph's minimum and maximum x value), the OpenType
1263 * specification defines the initial position of horizontal phantom points
1264 * as
1265 *
1266 * pp1 = (round(xmin - lsb), 0) ,
1267 * pp2 = (round(pp1 + aw), 0) .
1268 *
1269 * Note that the rounding to the grid (in the device space) is not
1270 * documented currently in the specification.
1271 *
1272 * However, the specification lacks the precise definition of vertical
1273 * phantom points. Greg Hitchcock provided the following explanation.
1274 *
1275 * - a `vmtx' table is present
1276 *
1277 * For any glyph, the minimum and maximum y values (`ymin' and `ymax')
1278 * are given in the `glyf' table, the top side bearing (tsb) and advance
1279 * height (ah) are given in the `vmtx' table. The bottom side bearing
1280 * (bsb) is then calculated as
1281 *
1282 * bsb = ah - (tsb + ymax - ymin) ,
1283 *
1284 * and the initial position of vertical phantom points is
1285 *
1286 * pp3 = (x, round(ymax + tsb)) ,
1287 * pp4 = (x, round(pp3 - ah)) .
1288 *
1289 * See below for value `x'.
1290 *
1291 * - no `vmtx' table in the font
1292 *
1293 * If there is an `OS/2' table, we set
1294 *
1295 * DefaultAscender = sTypoAscender ,
1296 * DefaultDescender = sTypoDescender ,
1297 *
1298 * otherwise we use data from the `hhea' table:
1299 *
1300 * DefaultAscender = Ascender ,
1301 * DefaultDescender = Descender .
1302 *
1303 * With these two variables we can now set
1304 *
1305 * ah = DefaultAscender - sDefaultDescender ,
1306 * tsb = DefaultAscender - yMax ,
1307 *
1308 * and proceed as if a `vmtx' table was present.
1309 *
1310 * Usually we have
1311 *
1312 * x = aw / 2 , (1)
1313 *
1314 * but there is one compatibility case where it can be set to
1315 *
1316 * x = -DefaultDescender -
1317 * ((DefaultAscender - DefaultDescender - aw) / 2) . (2)
1318 *
1319 * and another one with
1320 *
1321 * x = 0 . (3)
1322 *
1323 * In Windows, the history of those values is quite complicated,
1324 * depending on the hinting engine (that is, the graphics framework).
1325 *
1326 * framework from to formula
1327 * ----------------------------------------------------------
1328 * GDI Windows 98 current (1)
1329 * (Windows 2000 for NT)
1330 * GDI+ Windows XP Windows 7 (2)
1331 * GDI+ Windows 8 current (3)
1332 * DWrite Windows 7 current (3)
1333 *
1334 * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
1335 * (3) for everything else.
1336 *
1337 */
1338 static void
1339 tt_loader_set_pp( TT_Loader loader )
1340 {
1341 loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1342 loader->pp1.y = 0;
1343 loader->pp2.x = loader->pp1.x + loader->advance;
1344 loader->pp2.y = 0;
1345
1346 loader->pp3.x = 0;
1347 loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
1348 loader->pp4.x = 0;
1349 loader->pp4.y = loader->pp3.y - loader->vadvance;
1350
1351#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1352 {
1353 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
1354
1355
1356 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
1357 loader->exec &&
1358 loader->exec->mode != FT_RENDER_MODE_MONO &&
1359 loader->exec->mode != FT_RENDER_MODE_LCD &&
1360 loader->exec->mode != FT_RENDER_MODE_LCD_V )
1361 {
1362 loader->pp3.x = loader->advance / 2;
1363 loader->pp4.x = loader->advance / 2;
1364 }
1365 }
1366#endif
1367 }
1368
1369
1370 /* a utility function to retrieve i-th node from given FT_List */
1371 static FT_ListNode
1372 ft_list_get_node_at( FT_List list,
1373 FT_UInt idx )
1374 {
1375 FT_ListNode cur;
1376
1377
1378 if ( !list )
1379 return NULL;
1380
1381 for ( cur = list->head; cur; cur = cur->next )
1382 {
1383 if ( !idx )
1384 return cur;
1385
1386 idx--;
1387 }
1388
1389 return NULL;
1390 }
1391
1392
1393 /**************************************************************************
1394 *
1395 * @Function:
1396 * load_truetype_glyph
1397 *
1398 * @Description:
1399 * Loads a given truetype glyph. Handles composites and uses a
1400 * TT_Loader object.
1401 */
1402 static FT_Error
1403 load_truetype_glyph( TT_Loader loader,
1404 FT_UInt glyph_index,
1405 FT_UInt recurse_count,
1406 FT_Bool header_only )
1407 {
1408 FT_Error error = FT_Err_Ok;
1409 FT_Fixed x_scale, y_scale;
1410 FT_ULong offset;
1411 TT_Face face = loader->face;
1412 FT_GlyphLoader gloader = loader->gloader;
1413
1414 FT_Bool opened_frame = 0;
1415
1416#ifdef FT_CONFIG_OPTION_INCREMENTAL
1417 FT_StreamRec inc_stream;
1418 FT_Data glyph_data;
1419 FT_Bool glyph_data_loaded = 0;
1420#endif
1421
1422
1423#ifdef FT_DEBUG_LEVEL_TRACE
1424 if ( recurse_count )
1425 FT_TRACE5(( " nesting level: %u\n", recurse_count ));
1426#endif
1427
1428 /* some fonts have an incorrect value of `maxComponentDepth' */
1429 if ( recurse_count > face->max_profile.maxComponentDepth )
1430 {
1431 FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %u\n",
1432 recurse_count ));
1433 face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
1434 }
1435
1436#ifndef FT_CONFIG_OPTION_INCREMENTAL
1437 /* check glyph index */
1438 if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1439 {
1440 error = FT_THROW( Invalid_Glyph_Index );
1441 goto Exit;
1442 }
1443#endif
1444
1445 loader->glyph_index = glyph_index;
1446
1447 if ( loader->load_flags & FT_LOAD_NO_SCALE )
1448 {
1449 x_scale = 0x10000L;
1450 y_scale = 0x10000L;
1451 }
1452 else
1453 {
1454 x_scale = loader->size->metrics->x_scale;
1455 y_scale = loader->size->metrics->y_scale;
1456 }
1457
1458 /* Set `offset' to the start of the glyph relative to the start of */
1459 /* the `glyf' table, and `byte_len' to the length of the glyph in */
1460 /* bytes. */
1461
1462#ifdef FT_CONFIG_OPTION_INCREMENTAL
1463
1464 /* If we are loading glyph data via the incremental interface, set */
1465 /* the loader stream to a memory stream reading the data returned */
1466 /* by the interface. */
1467 if ( face->root.internal->incremental_interface )
1468 {
1469 error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1470 face->root.internal->incremental_interface->object,
1471 glyph_index, &glyph_data );
1472 if ( error )
1473 goto Exit;
1474
1475 glyph_data_loaded = 1;
1476 offset = 0;
1477 loader->byte_len = glyph_data.length;
1478
1479 FT_ZERO( &inc_stream );
1480 FT_Stream_OpenMemory( &inc_stream,
1481 glyph_data.pointer,
1482 glyph_data.length );
1483
1484 loader->stream = &inc_stream;
1485 }
1486 else
1487
1488#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1489 {
1490 FT_ULong len;
1491
1492
1493 offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len );
1494
1495 loader->byte_len = (FT_UInt)len;
1496 }
1497
1498 if ( loader->byte_len > 0 )
1499 {
1500#ifdef FT_CONFIG_OPTION_INCREMENTAL
1501 /* for the incremental interface, `glyf_offset' is always zero */
1502 if ( !face->glyf_offset &&
1503 !face->root.internal->incremental_interface )
1504#else
1505 if ( !face->glyf_offset )
1506#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1507 {
1508 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
1509 error = FT_THROW( Invalid_Table );
1510 goto Exit;
1511 }
1512
1513 error = face->access_glyph_frame( loader, glyph_index,
1514 face->glyf_offset + offset,
1515 loader->byte_len );
1516 if ( error )
1517 goto Exit;
1518
1519 /* read glyph header first */
1520 error = face->read_glyph_header( loader );
1521
1522 face->forget_glyph_frame( loader );
1523
1524 if ( error )
1525 goto Exit;
1526 }
1527
1528 /* a space glyph */
1529 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1530 {
1531 loader->bbox.xMin = 0;
1532 loader->bbox.xMax = 0;
1533 loader->bbox.yMin = 0;
1534 loader->bbox.yMax = 0;
1535 }
1536
1537 /* the metrics must be computed after loading the glyph header */
1538 /* since we need the glyph's `yMax' value in case the vertical */
1539 /* metrics must be emulated */
1540 error = tt_get_metrics( loader, glyph_index );
1541 if ( error )
1542 goto Exit;
1543
1544 if ( header_only )
1545 goto Exit;
1546
1547#ifdef FT_CONFIG_OPTION_INCREMENTAL
1548 tt_get_metrics_incremental( loader, glyph_index );
1549#endif
1550 tt_loader_set_pp( loader );
1551
1552 /* shortcut for empty glyphs */
1553 if ( loader->byte_len == 0 || loader->n_contours == 0 )
1554 {
1555
1556#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1557
1558 if ( !IS_DEFAULT_INSTANCE( FT_FACE( face ) ) )
1559 {
1560 /* a small outline structure with four elements for */
1561 /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1562 FT_Vector points[4];
1563 FT_Outline outline;
1564
1565 /* unrounded values */
1566 FT_Vector unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1567
1568
1569 points[0] = loader->pp1;
1570 points[1] = loader->pp2;
1571 points[2] = loader->pp3;
1572 points[3] = loader->pp4;
1573
1574 outline.n_points = 0;
1575 outline.n_contours = 0;
1576 outline.points = points;
1577 outline.tags = NULL;
1578 outline.contours = NULL;
1579
1580 /* this must be done before scaling */
1581 error = TT_Vary_Apply_Glyph_Deltas( loader,
1582 &outline,
1583 unrounded );
1584 if ( error )
1585 goto Exit;
1586 }
1587
1588#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1589
1590 /* scale phantom points, if necessary; */
1591 /* they get rounded in `TT_Hint_Glyph' */
1592 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1593 {
1594 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1595 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1596 /* pp1.y and pp2.y are always zero */
1597
1598 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1599 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1600 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1601 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1602 }
1603
1604 error = FT_Err_Ok;
1605 goto Exit;
1606 }
1607
1608
1609 /***********************************************************************/
1610 /***********************************************************************/
1611 /***********************************************************************/
1612
1613 /* we now open a frame again, right after the glyph header */
1614 /* (which consists of 10 bytes) */
1615 error = face->access_glyph_frame( loader, glyph_index,
1616 face->glyf_offset + offset + 10,
1617 loader->byte_len - 10 );
1618 if ( error )
1619 goto Exit;
1620
1621 opened_frame = 1;
1622
1623 /* if it is a simple glyph, load it */
1624
1625 if ( loader->n_contours > 0 )
1626 {
1627 error = face->read_simple_glyph( loader );
1628 if ( error )
1629 goto Exit;
1630
1631 /* all data have been read */
1632 face->forget_glyph_frame( loader );
1633 opened_frame = 0;
1634
1635 error = TT_Process_Simple_Glyph( loader );
1636 if ( error )
1637 goto Exit;
1638
1639 FT_GlyphLoader_Add( gloader );
1640 }
1641
1642 /***********************************************************************/
1643 /***********************************************************************/
1644 /***********************************************************************/
1645
1646 /* otherwise, load a composite! */
1647 else if ( loader->n_contours < 0 )
1648 {
1649 FT_Memory memory = face->root.memory;
1650
1651 FT_UInt start_point;
1652 FT_UInt start_contour;
1653 FT_ULong ins_pos; /* position of composite instructions, if any */
1654
1655 FT_ListNode node, node2;
1656
1657
1658 /* normalize the `n_contours' value */
1659 loader->n_contours = -1;
1660
1661 /*
1662 * We store the glyph index directly in the `node->data' pointer,
1663 * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
1664 * double cast to make this portable. Note, however, that this needs
1665 * pointers with a width of at least 32 bits.
1666 */
1667
1668 /* clear the nodes filled by sibling chains */
1669 node = ft_list_get_node_at( &loader->composites, recurse_count );
1670 for ( node2 = node; node2; node2 = node2->next )
1671 node2->data = (void*)-1;
1672
1673 /* check whether we already have a composite glyph with this index */
1674 if ( FT_List_Find( &loader->composites,
1675 FT_UINT_TO_POINTER( glyph_index ) ) )
1676 {
1677 FT_TRACE1(( "TT_Load_Composite_Glyph:"
1678 " infinite recursion detected\n" ));
1679 error = FT_THROW( Invalid_Composite );
1680 goto Exit;
1681 }
1682
1683 else if ( node )
1684 node->data = FT_UINT_TO_POINTER( glyph_index );
1685
1686 else
1687 {
1688 if ( FT_QNEW( node ) )
1689 goto Exit;
1690 node->data = FT_UINT_TO_POINTER( glyph_index );
1691 FT_List_Add( &loader->composites, node );
1692 }
1693
1694 start_point = gloader->base.outline.n_points;
1695 start_contour = gloader->base.outline.n_contours;
1696
1697 /* for each subglyph, read composite header */
1698 error = face->read_composite_glyph( loader );
1699 if ( error )
1700 goto Exit;
1701
1702 /* store the offset of instructions */
1703 ins_pos = loader->ins_pos;
1704
1705 /* all data we need are read */
1706 face->forget_glyph_frame( loader );
1707 opened_frame = 0;
1708
1709#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1710
1711 if ( !IS_DEFAULT_INSTANCE( FT_FACE( face ) ) )
1712 {
1713 FT_UShort i, limit;
1714 FT_SubGlyph subglyph;
1715
1716 FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 };
1717 FT_Vector* unrounded = NULL;
1718
1719
1720 limit = (FT_UShort)gloader->current.num_subglyphs;
1721
1722 /* construct an outline structure for */
1723 /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1724 if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) ||
1725 FT_QNEW_ARRAY( outline.tags, limit ) ||
1726 FT_QNEW_ARRAY( outline.contours, limit ) ||
1727 FT_QNEW_ARRAY( unrounded, limit + 4 ) )
1728 goto Exit1;
1729
1730 outline.n_contours = outline.n_points = limit;
1731
1732 subglyph = gloader->current.subglyphs;
1733
1734 for ( i = 0; i < limit; i++, subglyph++ )
1735 {
1736 /* applying deltas for anchor points doesn't make sense, */
1737 /* but we don't have to specially check this since */
1738 /* unused delta values are zero anyways */
1739 outline.points[i].x = subglyph->arg1;
1740 outline.points[i].y = subglyph->arg2;
1741 outline.tags[i] = ON_CURVE_POINT;
1742 outline.contours[i] = i;
1743 }
1744
1745 outline.points[i++] = loader->pp1;
1746 outline.points[i++] = loader->pp2;
1747 outline.points[i++] = loader->pp3;
1748 outline.points[i ] = loader->pp4;
1749
1750 /* this call provides additional offsets */
1751 /* for each component's translation */
1752 if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader,
1753 &outline,
1754 unrounded ) ) )
1755 goto Exit1;
1756
1757 subglyph = gloader->current.subglyphs;
1758
1759 for ( i = 0; i < limit; i++, subglyph++ )
1760 {
1761 if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1762 {
1763 subglyph->arg1 = (FT_Int16)outline.points[i].x;
1764 subglyph->arg2 = (FT_Int16)outline.points[i].y;
1765 }
1766 }
1767
1768 Exit1:
1769 FT_FREE( outline.points );
1770 FT_FREE( outline.tags );
1771 FT_FREE( outline.contours );
1772 FT_FREE( unrounded );
1773
1774 if ( error )
1775 goto Exit;
1776 }
1777
1778#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1779
1780 /* scale phantom points, if necessary; */
1781 /* they get rounded in `TT_Hint_Glyph' */
1782 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1783 {
1784 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1785 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1786 /* pp1.y and pp2.y are always zero */
1787
1788 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1789 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1790 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1791 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1792 }
1793
1794 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1795 /* `as is' in the glyph slot (the client application will be */
1796 /* responsible for interpreting these data)... */
1797 if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1798 {
1799 FT_GlyphLoader_Add( gloader );
1800 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1801
1802 goto Exit;
1803 }
1804
1805 /*********************************************************************/
1806 /*********************************************************************/
1807 /*********************************************************************/
1808
1809 {
1810 FT_UInt n, num_base_points;
1811 FT_SubGlyph subglyph = NULL;
1812
1813 FT_UInt num_points = start_point;
1814 FT_UInt num_subglyphs = gloader->current.num_subglyphs;
1815 FT_UInt num_base_subgs = gloader->base.num_subglyphs;
1816
1817 FT_Stream old_stream = loader->stream;
1818 FT_UInt old_byte_len = loader->byte_len;
1819
1820
1821 FT_GlyphLoader_Add( gloader );
1822
1823 /* read each subglyph independently */
1824 for ( n = 0; n < num_subglyphs; n++ )
1825 {
1826 FT_Vector pp[4];
1827
1828 FT_Int linear_hadvance;
1829 FT_Int linear_vadvance;
1830
1831
1832 /* Each time we call `load_truetype_glyph' in this loop, the */
1833 /* value of `gloader.base.subglyphs' can change due to table */
1834 /* reallocations. We thus need to recompute the subglyph */
1835 /* pointer on each iteration. */
1836 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1837
1838 pp[0] = loader->pp1;
1839 pp[1] = loader->pp2;
1840 pp[2] = loader->pp3;
1841 pp[3] = loader->pp4;
1842
1843 linear_hadvance = loader->linear;
1844 linear_vadvance = loader->vadvance;
1845
1846 num_base_points = gloader->base.outline.n_points;
1847
1848 error = load_truetype_glyph( loader,
1849 (FT_UInt)subglyph->index,
1850 recurse_count + 1,
1851 FALSE );
1852 if ( error )
1853 goto Exit;
1854
1855 /* restore subglyph pointer */
1856 subglyph = gloader->base.subglyphs + num_base_subgs + n;
1857
1858 /* restore phantom points if necessary */
1859 if ( !( subglyph->flags & USE_MY_METRICS ) )
1860 {
1861 loader->pp1 = pp[0];
1862 loader->pp2 = pp[1];
1863 loader->pp3 = pp[2];
1864 loader->pp4 = pp[3];
1865
1866 loader->linear = linear_hadvance;
1867 loader->vadvance = linear_vadvance;
1868 }
1869
1870 num_points = gloader->base.outline.n_points;
1871
1872 if ( num_points == num_base_points )
1873 continue;
1874
1875 /* gloader->base.outline consists of three parts: */
1876 /* */
1877 /* 0 ----> start_point ----> num_base_points ----> n_points */
1878 /* (1) (2) (3) */
1879 /* */
1880 /* (1) points that exist from the beginning */
1881 /* (2) component points that have been loaded so far */
1882 /* (3) points of the newly loaded component */
1883 error = TT_Process_Composite_Component( loader,
1884 subglyph,
1885 start_point,
1886 num_base_points );
1887 if ( error )
1888 goto Exit;
1889 }
1890
1891 loader->stream = old_stream;
1892 loader->byte_len = old_byte_len;
1893
1894 /* process the glyph */
1895 loader->ins_pos = ins_pos;
1896 if ( IS_HINTED( loader->load_flags ) &&
1897#ifdef TT_USE_BYTECODE_INTERPRETER
1898 subglyph &&
1899 subglyph->flags & WE_HAVE_INSTR &&
1900#endif
1901 num_points > start_point )
1902 {
1903 error = TT_Process_Composite_Glyph( loader,
1904 start_point,
1905 start_contour );
1906 if ( error )
1907 goto Exit;
1908 }
1909 }
1910
1911 /* retain the overlap flag */
1912 if ( gloader->base.num_subglyphs &&
1913 gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND )
1914 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
1915 }
1916
1917 /***********************************************************************/
1918 /***********************************************************************/
1919 /***********************************************************************/
1920
1921 Exit:
1922
1923 if ( opened_frame )
1924 face->forget_glyph_frame( loader );
1925
1926#ifdef FT_CONFIG_OPTION_INCREMENTAL
1927
1928 /* restore the original stream */
1929 loader->stream = face->root.stream;
1930
1931 if ( glyph_data_loaded )
1932 face->root.internal->incremental_interface->funcs->free_glyph_data(
1933 face->root.internal->incremental_interface->object,
1934 &glyph_data );
1935
1936#endif
1937
1938 return error;
1939 }
1940
1941
1942 static FT_Error
1943 compute_glyph_metrics( TT_Loader loader,
1944 FT_UInt glyph_index )
1945 {
1946 TT_Face face = loader->face;
1947 TT_Size size = loader->size;
1948 TT_GlyphSlot glyph = loader->glyph;
1949 FT_BBox bbox;
1950 FT_Fixed y_scale;
1951
1952
1953 y_scale = 0x10000L;
1954 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1955 y_scale = size->metrics->y_scale;
1956
1957 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
1958 FT_Outline_Get_CBox( &glyph->outline, &bbox );
1959 else
1960 bbox = loader->bbox;
1961
1962 /* get the device-independent horizontal advance; it is scaled later */
1963 /* by the base layer. */
1964 glyph->linearHoriAdvance = loader->linear;
1965
1966 glyph->metrics.horiBearingX = bbox.xMin;
1967 glyph->metrics.horiBearingY = bbox.yMax;
1968 if ( loader->widthp )
1969 glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64;
1970 else
1971 glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x );
1972
1973 /* set glyph dimensions */
1974 glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin );
1975 glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
1976
1977 /* Now take care of vertical metrics. In the case where there is */
1978 /* no vertical information within the font (relatively common), */
1979 /* create some metrics manually */
1980 {
1981 FT_Pos top; /* scaled vertical top side bearing */
1982 FT_Pos advance; /* scaled vertical advance height */
1983
1984
1985 /* Get the unscaled top bearing and advance height. */
1986 if ( face->vertical_info &&
1987 face->vertical.number_Of_VMetrics > 0 )
1988 {
1989 top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ),
1990 y_scale );
1991
1992 if ( loader->pp3.y <= loader->pp4.y )
1993 advance = 0;
1994 else
1995 advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y,
1996 loader->pp4.y ),
1997 y_scale );
1998 }
1999 else
2000 {
2001 FT_Pos height;
2002
2003
2004 /* XXX Compute top side bearing and advance height in */
2005 /* Get_VMetrics instead of here. */
2006
2007 /* NOTE: The OS/2 values are the only `portable' ones, */
2008 /* which is why we use them, if there is an OS/2 */
2009 /* table in the font. Otherwise, we use the */
2010 /* values defined in the horizontal header. */
2011
2012 height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
2013 bbox.yMin ),
2014 y_scale );
2015 if ( face->os2.version != 0xFFFFU )
2016 advance = (FT_Pos)( face->os2.sTypoAscender -
2017 face->os2.sTypoDescender );
2018 else
2019 advance = (FT_Pos)( face->horizontal.Ascender -
2020 face->horizontal.Descender );
2021
2022 top = ( advance - height ) / 2;
2023 }
2024
2025#ifdef FT_CONFIG_OPTION_INCREMENTAL
2026 {
2027 FT_Incremental_InterfaceRec* incr;
2028 FT_Incremental_MetricsRec incr_metrics;
2029 FT_Error error;
2030
2031
2032 incr = face->root.internal->incremental_interface;
2033
2034 /* If this is an incrementally loaded font see if there are */
2035 /* overriding metrics for this glyph. */
2036 if ( incr && incr->funcs->get_glyph_metrics )
2037 {
2038 incr_metrics.bearing_x = 0;
2039 incr_metrics.bearing_y = top;
2040 incr_metrics.advance = advance;
2041
2042 error = incr->funcs->get_glyph_metrics( incr->object,
2043 glyph_index,
2044 TRUE,
2045 &incr_metrics );
2046 if ( error )
2047 return error;
2048
2049 top = incr_metrics.bearing_y;
2050 advance = incr_metrics.advance;
2051 }
2052 }
2053
2054 /* GWW: Do vertical metrics get loaded incrementally too? */
2055
2056#endif /* FT_CONFIG_OPTION_INCREMENTAL */
2057
2058 glyph->linearVertAdvance = advance;
2059
2060 /* scale the metrics */
2061 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
2062 {
2063 top = FT_MulFix( top, y_scale );
2064 advance = FT_MulFix( advance, y_scale );
2065 }
2066
2067 /* XXX: for now, we have no better algorithm for the lsb, but it */
2068 /* should work fine. */
2069 /* */
2070 glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
2071 glyph->metrics.horiAdvance / 2 );
2072 glyph->metrics.vertBearingY = top;
2073 glyph->metrics.vertAdvance = advance;
2074 }
2075
2076 return FT_Err_Ok;
2077 }
2078
2079
2080#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2081
2082 static FT_Error
2083 load_sbit_image( TT_Size size,
2084 TT_GlyphSlot glyph,
2085 FT_UInt glyph_index,
2086 FT_Int32 load_flags )
2087 {
2088 TT_Face face = (TT_Face)glyph->face;
2089 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
2090 FT_Error error;
2091 TT_SBit_MetricsRec sbit_metrics;
2092
2093
2094 error = sfnt->load_sbit_image( face,
2095 size->strike_index,
2096 glyph_index,
2097 (FT_UInt)load_flags,
2098 face->root.stream,
2099 &glyph->bitmap,
2100 &sbit_metrics );
2101 if ( !error )
2102 {
2103 glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64;
2104 glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
2105
2106 glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
2107 glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
2108 glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64;
2109
2110 glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
2111 glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
2112 glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64;
2113
2114 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2115
2116 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2117 {
2118 glyph->bitmap_left = sbit_metrics.vertBearingX;
2119 glyph->bitmap_top = sbit_metrics.vertBearingY;
2120 }
2121 else
2122 {
2123 glyph->bitmap_left = sbit_metrics.horiBearingX;
2124 glyph->bitmap_top = sbit_metrics.horiBearingY;
2125 }
2126 }
2127 /* a missing glyph in a bitmap-only font is assumed whitespace */
2128 /* that needs to be constructed using metrics data from `hmtx' */
2129 /* and, optionally, `vmtx' tables */
2130 else if ( FT_ERR_EQ( error, Missing_Bitmap ) &&
2131 !FT_IS_SCALABLE( glyph->face ) &&
2132 face->horz_metrics_size )
2133 {
2134 FT_Fixed x_scale = size->root.metrics.x_scale;
2135 FT_Fixed y_scale = size->root.metrics.y_scale;
2136
2137 FT_Short left_bearing = 0;
2138 FT_Short top_bearing = 0;
2139
2140 FT_UShort advance_width = 0;
2141 FT_UShort advance_height = 0;
2142
2143
2144 TT_Get_HMetrics( face, glyph_index,
2145 &left_bearing,
2146 &advance_width );
2147 TT_Get_VMetrics( face, glyph_index,
2148 0,
2149 &top_bearing,
2150 &advance_height );
2151
2152 glyph->metrics.width = 0;
2153 glyph->metrics.height = 0;
2154
2155 glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
2156 glyph->metrics.horiBearingY = 0;
2157 glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale );
2158
2159 glyph->metrics.vertBearingX = 0;
2160 glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
2161 glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale );
2162
2163 glyph->format = FT_GLYPH_FORMAT_BITMAP;
2164 glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
2165
2166 glyph->bitmap_left = 0;
2167 glyph->bitmap_top = 0;
2168
2169 error = FT_Err_Ok;
2170 }
2171
2172 return error;
2173 }
2174
2175#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2176
2177
2178 static FT_Error
2179 tt_loader_init( TT_Loader loader,
2180 TT_Size size,
2181 TT_GlyphSlot glyph,
2182 FT_Int32 load_flags,
2183 FT_Bool glyf_table_only )
2184 {
2185 TT_Face face = (TT_Face)glyph->face;
2186
2187
2188 FT_ZERO( loader );
2189
2190#ifdef TT_USE_BYTECODE_INTERPRETER
2191
2192 /* load execution context */
2193 if ( IS_HINTED( load_flags ) && !glyf_table_only )
2194 {
2195 FT_Error error;
2196 TT_ExecContext exec;
2197 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags );
2198 FT_Bool grayscale = FT_BOOL( mode != FT_RENDER_MODE_MONO );
2199 FT_Bool reexecute = FALSE;
2200#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2201 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face );
2202#endif
2203
2204
2205 if ( size->bytecode_ready > 0 )
2206 return size->bytecode_ready;
2207 if ( size->bytecode_ready < 0 )
2208 {
2209 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2210
2211
2212 error = tt_size_init_bytecode( size, pedantic );
2213 if ( error )
2214 return error;
2215 }
2216
2217 exec = size->context;
2218
2219#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2220 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2221 {
2222 grayscale = FALSE;
2223
2224 /* any mode change requires a re-execution of the CVT program */
2225 if ( mode != exec->mode )
2226 {
2227 FT_TRACE4(( "tt_loader_init: render mode change,"
2228 " re-executing `prep' table\n" ));
2229
2230 exec->mode = mode;
2231 reexecute = TRUE;
2232 }
2233 }
2234#endif
2235
2236 /* a change from mono to grayscale rendering (and vice versa) */
2237 /* requires a re-execution of the CVT program */
2238 if ( grayscale != exec->grayscale )
2239 {
2240 FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2241 " re-executing `prep' table\n" ));
2242
2243 exec->grayscale = grayscale;
2244 reexecute = TRUE;
2245 }
2246
2247 if ( size->cvt_ready > 0 )
2248 return size->cvt_ready;
2249 if ( size->cvt_ready < 0 || reexecute )
2250 {
2251 error = tt_size_run_prep( size );
2252 if ( error )
2253 return error;
2254 }
2255
2256 error = TT_Load_Context( exec, face, size );
2257 if ( error )
2258 return error;
2259
2260 /* check whether the cvt program has disabled hinting */
2261 if ( size->GS.instruct_control & 1 )
2262 load_flags |= FT_LOAD_NO_HINTING;
2263
2264 /* check whether GS modifications should be reverted */
2265 if ( size->GS.instruct_control & 2 )
2266 size->GS = tt_default_graphics_state;
2267
2268#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2269 /*
2270 * Toggle backward compatibility according to what font wants, except
2271 * when
2272 *
2273 * 1) we have a `tricky' font that heavily relies on the interpreter to
2274 * render glyphs correctly, for example DFKai-SB, or
2275 * 2) FT_RENDER_MODE_MONO (i.e, monochrome rendering) is requested.
2276 *
2277 * In those cases, backward compatibility needs to be turned off to get
2278 * correct rendering. The rendering is then completely up to the
2279 * font's programming.
2280 *
2281 */
2282 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 &&
2283 mode != FT_RENDER_MODE_MONO &&
2284 !FT_IS_TRICKY( glyph->face ) )
2285 exec->backward_compatibility = ( size->GS.instruct_control & 4 ) ^ 4;
2286 else
2287 exec->backward_compatibility = 0;
2288#endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */
2289
2290 loader->exec = exec;
2291
2292 /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */
2293 /* is set or backward compatibility mode of the v38 or v40 */
2294 /* interpreters is active. See `ttinterp.h' for details on */
2295 /* backward compatibility mode. */
2296 if ( IS_HINTED( load_flags ) &&
2297 !( load_flags & FT_LOAD_COMPUTE_METRICS ) &&
2298#ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2299 !exec->backward_compatibility &&
2300#endif
2301 !face->postscript.isFixedPitch )
2302 {
2303 loader->widthp = size->widthp;
2304 }
2305 else
2306 loader->widthp = NULL;
2307 }
2308
2309#endif /* TT_USE_BYTECODE_INTERPRETER */
2310
2311 /* get face's glyph loader */
2312 if ( !glyf_table_only )
2313 {
2314 FT_GlyphLoader gloader = glyph->internal->loader;
2315
2316
2317 FT_GlyphLoader_Rewind( gloader );
2318 loader->gloader = gloader;
2319 }
2320
2321 loader->load_flags = (FT_ULong)load_flags;
2322
2323 loader->face = face;
2324 loader->size = size;
2325 loader->glyph = (FT_GlyphSlot)glyph;
2326 loader->stream = face->root.stream;
2327
2328 loader->composites.head = NULL;
2329 loader->composites.tail = NULL;
2330
2331 return FT_Err_Ok;
2332 }
2333
2334
2335 static void
2336 tt_loader_done( TT_Loader loader )
2337 {
2338 FT_List_Finalize( &loader->composites,
2339 NULL,
2340 loader->face->root.memory,
2341 NULL );
2342 }
2343
2344
2345 /**************************************************************************
2346 *
2347 * @Function:
2348 * TT_Load_Glyph
2349 *
2350 * @Description:
2351 * A function used to load a single glyph within a given glyph slot,
2352 * for a given size.
2353 *
2354 * @InOut:
2355 * glyph ::
2356 * A handle to a target slot object where the glyph
2357 * will be loaded.
2358 *
2359 * @Input:
2360 * size ::
2361 * A handle to the source face size at which the glyph
2362 * must be scaled/loaded.
2363 *
2364 * glyph_index ::
2365 * The index of the glyph in the font file.
2366 *
2367 * load_flags ::
2368 * A flag indicating what to load for this glyph. The
2369 * FT_LOAD_XXX constants can be used to control the
2370 * glyph loading process (e.g., whether the outline
2371 * should be scaled, whether to load bitmaps or not,
2372 * whether to hint the outline, etc).
2373 *
2374 * @Return:
2375 * FreeType error code. 0 means success.
2376 */
2377 FT_LOCAL_DEF( FT_Error )
2378 TT_Load_Glyph( TT_Size size,
2379 TT_GlyphSlot glyph,
2380 FT_UInt glyph_index,
2381 FT_Int32 load_flags )
2382 {
2383 TT_Face face = (TT_Face)glyph->face;
2384 FT_Error error;
2385 TT_LoaderRec loader;
2386
2387
2388 FT_TRACE1(( "TT_Load_Glyph: glyph index %u\n", glyph_index ));
2389
2390#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2391
2392 /* try to load embedded bitmap (if any) */
2393 if ( size->strike_index != 0xFFFFFFFFUL &&
2394 !( load_flags & FT_LOAD_NO_BITMAP &&
2395 FT_IS_SCALABLE( glyph->face ) ) &&
2396 IS_DEFAULT_INSTANCE( glyph->face ) )
2397 {
2398 error = load_sbit_image( size, glyph, glyph_index, load_flags );
2399 if ( !error )
2400 {
2401 if ( FT_IS_SCALABLE( glyph->face ) ||
2402 FT_HAS_SBIX( glyph->face ) )
2403 {
2404 FT_Fixed x_scale = size->root.metrics.x_scale;
2405 FT_Fixed y_scale = size->root.metrics.y_scale;
2406
2407
2408 /* for the bbox we need the header only */
2409 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2410 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2411 tt_loader_done( &loader );
2412 glyph->linearHoriAdvance = loader.linear;
2413 glyph->linearVertAdvance = loader.vadvance;
2414
2415 /* Bitmaps from the 'sbix' table need special treatment: */
2416 /* if there is a glyph contour, the bitmap origin must be */
2417 /* shifted to be relative to the lower left corner of the */
2418 /* glyph bounding box, also taking the left-side bearing */
2419 /* (or top bearing) into account. */
2420 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX &&
2421 loader.n_contours > 0 )
2422 {
2423 FT_Int bitmap_left;
2424 FT_Int bitmap_top;
2425
2426
2427 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2428 {
2429 /* This is a guess, since Apple's CoreText engine doesn't */
2430 /* really do vertical typesetting. */
2431 bitmap_left = loader.bbox.xMin;
2432 bitmap_top = loader.top_bearing;
2433 }
2434 else
2435 {
2436 bitmap_left = loader.left_bearing;
2437 bitmap_top = loader.bbox.yMin;
2438 }
2439
2440 glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6;
2441 glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6;
2442 }
2443
2444 /* sanity checks: if `xxxAdvance' in the sbit metric */
2445 /* structure isn't set, use `linearXXXAdvance' */
2446 if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
2447 glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
2448 x_scale );
2449 if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
2450 glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
2451 y_scale );
2452 }
2453
2454 goto Exit;
2455 }
2456 else if ( !FT_IS_SCALABLE( glyph->face ) )
2457 goto Exit;
2458 }
2459
2460 if ( load_flags & FT_LOAD_SBITS_ONLY )
2461 {
2462 error = FT_THROW( Invalid_Argument );
2463 goto Exit;
2464 }
2465
2466#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2467
2468 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
2469 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.ppem )
2470 {
2471 error = FT_THROW( Invalid_Size_Handle );
2472 goto Exit;
2473 }
2474
2475#ifdef FT_CONFIG_OPTION_SVG
2476
2477 /* check for OT-SVG */
2478 if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 &&
2479 ( load_flags & FT_LOAD_COLOR ) &&
2480 face->svg )
2481 {
2482 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
2483
2484
2485 FT_TRACE3(( "Trying to load SVG glyph\n" ));
2486
2487 error = sfnt->load_svg_doc( glyph, glyph_index );
2488 if ( !error )
2489 {
2490 FT_Fixed x_scale = size->root.metrics.x_scale;
2491 FT_Fixed y_scale = size->root.metrics.y_scale;
2492
2493 FT_Short leftBearing;
2494 FT_Short topBearing;
2495 FT_UShort advanceX;
2496 FT_UShort advanceY;
2497
2498
2499 FT_TRACE3(( "Successfully loaded SVG glyph\n" ));
2500
2501 glyph->format = FT_GLYPH_FORMAT_SVG;
2502
2503 sfnt->get_metrics( face,
2504 FALSE,
2505 glyph_index,
2506 &leftBearing,
2507 &advanceX );
2508 sfnt->get_metrics( face,
2509 TRUE,
2510 glyph_index,
2511 &topBearing,
2512 &advanceY );
2513
2514 glyph->linearHoriAdvance = advanceX;
2515 glyph->linearVertAdvance = advanceY;
2516
2517 glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale );
2518 glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale );
2519
2520 goto Exit;
2521 }
2522
2523 FT_TRACE3(( "Failed to load SVG glyph\n" ));
2524 }
2525
2526 /* return immediately if we only want SVG glyphs */
2527 if ( load_flags & FT_LOAD_SVG_ONLY )
2528 {
2529 error = FT_THROW( Invalid_Argument );
2530 goto Exit;
2531 }
2532
2533#endif /* FT_CONFIG_OPTION_SVG */
2534
2535 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
2536 if ( error )
2537 goto Exit;
2538
2539 /* done if we are only interested in the `hdmx` advance */
2540 if ( load_flags & FT_LOAD_ADVANCE_ONLY &&
2541 !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) &&
2542 loader.widthp )
2543 {
2544 glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64;
2545 goto Done;
2546 }
2547
2548 /* main loading loop */
2549 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
2550 if ( !error )
2551 {
2552 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2553 {
2554 glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2555 glyph->subglyphs = loader.gloader->base.subglyphs;
2556 }
2557 else
2558 {
2559 glyph->format = FT_GLYPH_FORMAT_OUTLINE;
2560
2561 glyph->outline = loader.gloader->base.outline;
2562 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2563
2564 /* Set the `high precision' bit flag. This is _critical_ to */
2565 /* get correct output for monochrome TrueType glyphs at all */
2566 /* sizes using the bytecode interpreter. */
2567 if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2568 size->metrics->y_ppem < 24 )
2569 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2570
2571 /* Translate array so that (0,0) is the glyph's origin. Note */
2572 /* that this behaviour is independent on the value of bit 1 of */
2573 /* the `flags' field in the `head' table -- at least major */
2574 /* applications like Acroread indicate that. */
2575 if ( loader.pp1.x )
2576 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2577 }
2578
2579#ifdef TT_USE_BYTECODE_INTERPRETER
2580
2581 if ( IS_HINTED( load_flags ) )
2582 {
2583 glyph->control_data = loader.exec->glyphIns;
2584 glyph->control_len = loader.exec->glyphSize;
2585
2586 if ( loader.exec->GS.scan_control )
2587 {
2588 /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2589 switch ( loader.exec->GS.scan_type )
2590 {
2591 case 0: /* simple drop-outs including stubs */
2592 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2593 break;
2594 case 1: /* simple drop-outs excluding stubs */
2595 /* nothing; it's the default rendering mode */
2596 break;
2597 case 4: /* smart drop-outs including stubs */
2598 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2599 FT_OUTLINE_INCLUDE_STUBS;
2600 break;
2601 case 5: /* smart drop-outs excluding stubs */
2602 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2603 break;
2604
2605 default: /* no drop-out control */
2606 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2607 break;
2608 }
2609 }
2610 else
2611 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2612 }
2613
2614#endif /* TT_USE_BYTECODE_INTERPRETER */
2615
2616 error = compute_glyph_metrics( &loader, glyph_index );
2617 }
2618
2619 FT_TRACE1(( " subglyphs = %u, contours = %hu, points = %hu,"
2620 " flags = 0x%.3x\n",
2621 loader.gloader->base.num_subglyphs,
2622 glyph->outline.n_contours,
2623 glyph->outline.n_points,
2624 glyph->outline.flags ));
2625
2626 Done:
2627 tt_loader_done( &loader );
2628
2629 Exit:
2630 FT_TRACE1(( error ? " failed (error code 0x%x)\n" : "",
2631 error ));
2632
2633 return error;
2634 }
2635
2636
2637/* END */