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