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