• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * ttgload.c
4  *
5  *   TrueType Glyph Loader (body).
6  *
7  * Copyright (C) 1996-2021 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                       subglyph->transform.xx / 65536.0 ));
741         else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
742           FT_TRACE7(( "      scaling: x=%f, y=%f\n",
743                       subglyph->transform.xx / 65536.0,
744                       subglyph->transform.yy / 65536.0 ));
745         else if ( subglyph->flags & WE_HAVE_A_2X2 )
746         {
747           FT_TRACE7(( "      scaling: xx=%f, yx=%f\n",
748                       subglyph->transform.xx / 65536.0,
749                       subglyph->transform.yx / 65536.0 ));
750           FT_TRACE7(( "               xy=%f, yy=%f\n",
751                       subglyph->transform.xy / 65536.0,
752                       subglyph->transform.yy / 65536.0 ));
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 -
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     outline->tags[n_points    ] = 0;
974     outline->tags[n_points + 1] = 0;
975     outline->tags[n_points + 2] = 0;
976     outline->tags[n_points + 3] = 0;
977 
978     n_points += 4;
979 
980 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
981 
982     if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
983     {
984       if ( FT_NEW_ARRAY( unrounded, n_points ) )
985         goto Exit;
986 
987       /* Deltas apply to the unscaled data. */
988       error = TT_Vary_Apply_Glyph_Deltas( loader->face,
989                                           loader->glyph_index,
990                                           outline,
991                                           unrounded,
992                                           (FT_UInt)n_points );
993 
994       /* recalculate linear horizontal and vertical advances */
995       /* if we don't have HVAR and VVAR, respectively        */
996 
997       /* XXX: change all FreeType modules to store `linear' and `vadvance' */
998       /*      in 26.6 format before the `base' module scales them to 16.16 */
999       if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
1000         loader->linear = FT_PIX_ROUND( unrounded[n_points - 3].x -
1001                                        unrounded[n_points - 4].x ) / 64;
1002       if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
1003         loader->vadvance = FT_PIX_ROUND( unrounded[n_points - 1].x -
1004                                          unrounded[n_points - 2].x ) / 64;
1005 
1006       if ( error )
1007         goto Exit;
1008     }
1009 
1010 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1011 
1012     if ( IS_HINTED( loader->load_flags ) )
1013     {
1014       tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
1015 
1016       FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
1017                      loader->zone.n_points + 4 );
1018     }
1019 
1020     {
1021 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1022       TT_Face    face   = loader->face;
1023       TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
1024 
1025       FT_String*  family         = face->root.family_name;
1026       FT_UInt     ppem           = loader->size->metrics->x_ppem;
1027       FT_String*  style          = face->root.style_name;
1028       FT_UInt     x_scale_factor = 1000;
1029 #endif
1030 
1031       FT_Vector*  vec   = outline->points;
1032       FT_Vector*  limit = outline->points + n_points;
1033 
1034       FT_Fixed  x_scale = 0; /* pacify compiler */
1035       FT_Fixed  y_scale = 0;
1036 
1037       FT_Bool  do_scale = FALSE;
1038 
1039 
1040 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1041 
1042       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
1043       {
1044         /* scale, but only if enabled and only if TT hinting is being used */
1045         if ( IS_HINTED( loader->load_flags ) )
1046           x_scale_factor = sph_test_tweak_x_scaling( face,
1047                                                      family,
1048                                                      ppem,
1049                                                      style,
1050                                                      loader->glyph_index );
1051         /* scale the glyph */
1052         if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
1053              x_scale_factor != 1000                         )
1054         {
1055           x_scale = FT_MulDiv( loader->size->metrics->x_scale,
1056                                (FT_Long)x_scale_factor, 1000 );
1057           y_scale = loader->size->metrics->y_scale;
1058 
1059           /* compensate for any scaling by de/emboldening; */
1060           /* the amount was determined via experimentation */
1061           if ( x_scale_factor != 1000 && ppem > 11 )
1062           {
1063 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1064             FT_Vector*  orig_points = outline->points;
1065 
1066 
1067             if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
1068               outline->points = unrounded;
1069 #endif
1070             FT_Outline_EmboldenXY( outline,
1071                                    FT_MulFix( 1280 * ppem,
1072                                               1000 - x_scale_factor ),
1073                                    0 );
1074 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1075             if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
1076               outline->points = orig_points;
1077 #endif
1078           }
1079           do_scale = TRUE;
1080         }
1081       }
1082       else
1083 
1084 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
1085 
1086       {
1087         /* scale the glyph */
1088         if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1089         {
1090           x_scale = loader->size->metrics->x_scale;
1091           y_scale = loader->size->metrics->y_scale;
1092 
1093           do_scale = TRUE;
1094         }
1095       }
1096 
1097       if ( do_scale )
1098       {
1099 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1100         if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) )
1101         {
1102           FT_Vector*  u = unrounded;
1103 
1104 
1105           for ( ; vec < limit; vec++, u++ )
1106           {
1107             vec->x = ( FT_MulFix( u->x, x_scale ) + 32 ) >> 6;
1108             vec->y = ( FT_MulFix( u->y, y_scale ) + 32 ) >> 6;
1109           }
1110         }
1111         else
1112 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1113         {
1114           for ( ; vec < limit; vec++ )
1115           {
1116             vec->x = FT_MulFix( vec->x, x_scale );
1117             vec->y = FT_MulFix( vec->y, y_scale );
1118           }
1119         }
1120       }
1121 
1122 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1123       /* if we have a HVAR table, `pp1' and/or `pp2' */
1124       /* are already adjusted but unscaled           */
1125       if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) &&
1126            IS_HINTED( loader->load_flags )                                 )
1127       {
1128         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1129         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1130         /* pp1.y and pp2.y are always zero */
1131       }
1132       else
1133 #endif
1134       {
1135         loader->pp1 = outline->points[n_points - 4];
1136         loader->pp2 = outline->points[n_points - 3];
1137       }
1138 
1139 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1140       /* if we have a VVAR table, `pp3' and/or `pp4' */
1141       /* are already adjusted but unscaled           */
1142       if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) &&
1143            IS_HINTED( loader->load_flags )                                 )
1144       {
1145         loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1146         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1147         loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1148         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1149       }
1150       else
1151 #endif
1152       {
1153         loader->pp3 = outline->points[n_points - 2];
1154         loader->pp4 = outline->points[n_points - 1];
1155       }
1156     }
1157 
1158     if ( IS_HINTED( loader->load_flags ) )
1159     {
1160       loader->zone.n_points += 4;
1161 
1162       error = TT_Hint_Glyph( loader, 0 );
1163     }
1164 
1165 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1166   Exit:
1167     FT_FREE( unrounded );
1168 #endif
1169 
1170     return error;
1171   }
1172 
1173 
1174   /**************************************************************************
1175    *
1176    * @Function:
1177    *   TT_Process_Composite_Component
1178    *
1179    * @Description:
1180    *   Once a composite component has been loaded, it needs to be
1181    *   processed.  Usually, this means transforming and translating.
1182    */
1183   static FT_Error
TT_Process_Composite_Component(TT_Loader loader,FT_SubGlyph subglyph,FT_UInt start_point,FT_UInt num_base_points)1184   TT_Process_Composite_Component( TT_Loader    loader,
1185                                   FT_SubGlyph  subglyph,
1186                                   FT_UInt      start_point,
1187                                   FT_UInt      num_base_points )
1188   {
1189     FT_GlyphLoader  gloader = loader->gloader;
1190     FT_Outline      current;
1191     FT_Bool         have_scale;
1192     FT_Pos          x, y;
1193 
1194 
1195     current.points   = gloader->base.outline.points +
1196                          num_base_points;
1197     current.n_points = gloader->base.outline.n_points -
1198                          (short)num_base_points;
1199 
1200     have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
1201                                               WE_HAVE_AN_XY_SCALE |
1202                                               WE_HAVE_A_2X2       ) );
1203 
1204     /* perform the transform required for this subglyph */
1205     if ( have_scale )
1206       FT_Outline_Transform( &current, &subglyph->transform );
1207 
1208     /* get offset */
1209     if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
1210     {
1211       FT_UInt     num_points = (FT_UInt)gloader->base.outline.n_points;
1212       FT_UInt     k = (FT_UInt)subglyph->arg1;
1213       FT_UInt     l = (FT_UInt)subglyph->arg2;
1214       FT_Vector*  p1;
1215       FT_Vector*  p2;
1216 
1217 
1218       /* match l-th point of the newly loaded component to the k-th point */
1219       /* of the previously loaded components.                             */
1220 
1221       /* change to the point numbers used by our outline */
1222       k += start_point;
1223       l += num_base_points;
1224       if ( k >= num_base_points ||
1225            l >= num_points      )
1226         return FT_THROW( Invalid_Composite );
1227 
1228       p1 = gloader->base.outline.points + k;
1229       p2 = gloader->base.outline.points + l;
1230 
1231       x = p1->x - p2->x;
1232       y = p1->y - p2->y;
1233     }
1234     else
1235     {
1236       x = subglyph->arg1;
1237       y = subglyph->arg2;
1238 
1239       if ( !x && !y )
1240         return FT_Err_Ok;
1241 
1242       /* Use a default value dependent on                                  */
1243       /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old */
1244       /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit.            */
1245 
1246       if ( have_scale &&
1247 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
1248            !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
1249 #else
1250             ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
1251 #endif
1252       {
1253 
1254 #if 0
1255 
1256         /********************************************************************
1257          *
1258          * This algorithm is what Apple documents.  But it doesn't work.
1259          */
1260         int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
1261                                             : -subglyph->transform.xx;
1262         int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
1263                                             : -subglyph->transform.yx;
1264         int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
1265                                             : -subglyph->transform.xy;
1266         int  d = subglyph->transform.yy > 0 ?  subglyph->transform.yy
1267                                             : -subglyph->transform.yy;
1268         int  m = a > b ? a : b;
1269         int  n = c > d ? c : d;
1270 
1271 
1272         if ( a - b <= 33 && a - b >= -33 )
1273           m *= 2;
1274         if ( c - d <= 33 && c - d >= -33 )
1275           n *= 2;
1276         x = FT_MulFix( x, m );
1277         y = FT_MulFix( y, n );
1278 
1279 #else /* 1 */
1280 
1281         /********************************************************************
1282          *
1283          * This algorithm is a guess and works much better than the above.
1284          */
1285         FT_Fixed  mac_xscale = FT_Hypot( subglyph->transform.xx,
1286                                          subglyph->transform.xy );
1287         FT_Fixed  mac_yscale = FT_Hypot( subglyph->transform.yy,
1288                                          subglyph->transform.yx );
1289 
1290 
1291         x = FT_MulFix( x, mac_xscale );
1292         y = FT_MulFix( y, mac_yscale );
1293 
1294 #endif /* 1 */
1295 
1296       }
1297 
1298       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1299       {
1300         FT_Fixed  x_scale = loader->size->metrics->x_scale;
1301         FT_Fixed  y_scale = loader->size->metrics->y_scale;
1302 
1303 
1304         x = FT_MulFix( x, x_scale );
1305         y = FT_MulFix( y, y_scale );
1306 
1307         if ( subglyph->flags & ROUND_XY_TO_GRID )
1308         {
1309           TT_Face    face   = loader->face;
1310           TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
1311 
1312 
1313           if ( IS_HINTED( loader->load_flags ) )
1314           {
1315             /*
1316              * We round the horizontal offset only if there is hinting along
1317              * the x axis; this corresponds to integer advance width values.
1318              *
1319              * Theoretically, a glyph's bytecode can toggle ClearType's
1320              * `backward compatibility' mode, which would allow modification
1321              * of the advance width.  In reality, however, applications
1322              * neither allow nor expect modified advance widths if subpixel
1323              * rendering is active.
1324              *
1325              */
1326             if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 )
1327               x = FT_PIX_ROUND( x );
1328 
1329             y = FT_PIX_ROUND( y );
1330           }
1331         }
1332       }
1333     }
1334 
1335     if ( x || y )
1336       FT_Outline_Translate( &current, x, y );
1337 
1338     return FT_Err_Ok;
1339   }
1340 
1341 
1342   /**************************************************************************
1343    *
1344    * @Function:
1345    *   TT_Process_Composite_Glyph
1346    *
1347    * @Description:
1348    *   This is slightly different from TT_Process_Simple_Glyph, in that
1349    *   its sole purpose is to hint the glyph.  Thus this function is
1350    *   only available when bytecode interpreter is enabled.
1351    */
1352   static FT_Error
TT_Process_Composite_Glyph(TT_Loader loader,FT_UInt start_point,FT_UInt start_contour)1353   TT_Process_Composite_Glyph( TT_Loader  loader,
1354                               FT_UInt    start_point,
1355                               FT_UInt    start_contour )
1356   {
1357     FT_Error     error;
1358     FT_Outline*  outline;
1359     FT_UInt      i;
1360 
1361 
1362     outline = &loader->gloader->base.outline;
1363 
1364     /* make room for phantom points */
1365     error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1366                                          outline->n_points + 4,
1367                                          0 );
1368     if ( error )
1369       return error;
1370 
1371     outline->points[outline->n_points    ] = loader->pp1;
1372     outline->points[outline->n_points + 1] = loader->pp2;
1373     outline->points[outline->n_points + 2] = loader->pp3;
1374     outline->points[outline->n_points + 3] = loader->pp4;
1375 
1376     outline->tags[outline->n_points    ] = 0;
1377     outline->tags[outline->n_points + 1] = 0;
1378     outline->tags[outline->n_points + 2] = 0;
1379     outline->tags[outline->n_points + 3] = 0;
1380 
1381 #ifdef TT_USE_BYTECODE_INTERPRETER
1382 
1383     {
1384       FT_Stream  stream = loader->stream;
1385       FT_UShort  n_ins, max_ins;
1386       FT_ULong   tmp;
1387 
1388 
1389       /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1390       /* so we read them here                                             */
1391       if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1392            FT_READ_USHORT( n_ins )           )
1393         return error;
1394 
1395       FT_TRACE5(( "  Instructions size = %hu\n", n_ins ));
1396 
1397       /* check it */
1398       max_ins = loader->face->max_profile.maxSizeOfInstructions;
1399       if ( n_ins > max_ins )
1400       {
1401         /* don't trust `maxSizeOfInstructions'; */
1402         /* only do a rough safety check         */
1403         if ( n_ins > loader->byte_len )
1404         {
1405           FT_TRACE1(( "TT_Process_Composite_Glyph:"
1406                       " too many instructions (%hu) for glyph with length %u\n",
1407                       n_ins, loader->byte_len ));
1408           return FT_THROW( Too_Many_Hints );
1409         }
1410 
1411         tmp   = loader->exec->glyphSize;
1412         error = Update_Max( loader->exec->memory,
1413                             &tmp,
1414                             sizeof ( FT_Byte ),
1415                             (void*)&loader->exec->glyphIns,
1416                             n_ins );
1417 
1418         loader->exec->glyphSize = (FT_UShort)tmp;
1419         if ( error )
1420           return error;
1421       }
1422       else if ( n_ins == 0 )
1423         return FT_Err_Ok;
1424 
1425       if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
1426         return error;
1427 
1428       loader->glyph->control_data = loader->exec->glyphIns;
1429       loader->glyph->control_len  = n_ins;
1430     }
1431 
1432 #endif
1433 
1434     tt_prepare_zone( &loader->zone, &loader->gloader->base,
1435                      start_point, start_contour );
1436 
1437     /* Some points are likely touched during execution of  */
1438     /* instructions on components.  So let's untouch them. */
1439     for ( i = 0; i < loader->zone.n_points; i++ )
1440       loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH;
1441 
1442     loader->zone.n_points += 4;
1443 
1444     return TT_Hint_Glyph( loader, 1 );
1445   }
1446 
1447 
1448   /*
1449    * Calculate the phantom points
1450    *
1451    * Defining the right side bearing (rsb) as
1452    *
1453    *   rsb = aw - (lsb + xmax - xmin)
1454    *
1455    * (with `aw' the advance width, `lsb' the left side bearing, and `xmin'
1456    * and `xmax' the glyph's minimum and maximum x value), the OpenType
1457    * specification defines the initial position of horizontal phantom points
1458    * as
1459    *
1460    *   pp1 = (round(xmin - lsb), 0)      ,
1461    *   pp2 = (round(pp1 + aw), 0)        .
1462    *
1463    * Note that the rounding to the grid (in the device space) is not
1464    * documented currently in the specification.
1465    *
1466    * However, the specification lacks the precise definition of vertical
1467    * phantom points.  Greg Hitchcock provided the following explanation.
1468    *
1469    * - a `vmtx' table is present
1470    *
1471    *   For any glyph, the minimum and maximum y values (`ymin' and `ymax')
1472    *   are given in the `glyf' table, the top side bearing (tsb) and advance
1473    *   height (ah) are given in the `vmtx' table.  The bottom side bearing
1474    *   (bsb) is then calculated as
1475    *
1476    *     bsb = ah - (tsb + ymax - ymin)       ,
1477    *
1478    *   and the initial position of vertical phantom points is
1479    *
1480    *     pp3 = (x, round(ymax + tsb))       ,
1481    *     pp4 = (x, round(pp3 - ah))         .
1482    *
1483    *   See below for value `x'.
1484    *
1485    * - no `vmtx' table in the font
1486    *
1487    *   If there is an `OS/2' table, we set
1488    *
1489    *     DefaultAscender = sTypoAscender       ,
1490    *     DefaultDescender = sTypoDescender     ,
1491    *
1492    *   otherwise we use data from the `hhea' table:
1493    *
1494    *     DefaultAscender = Ascender         ,
1495    *     DefaultDescender = Descender       .
1496    *
1497    *   With these two variables we can now set
1498    *
1499    *     ah = DefaultAscender - sDefaultDescender    ,
1500    *     tsb = DefaultAscender - yMax                ,
1501    *
1502    *   and proceed as if a `vmtx' table was present.
1503    *
1504    * Usually we have
1505    *
1506    *   x = aw / 2      ,                                                (1)
1507    *
1508    * but there is one compatibility case where it can be set to
1509    *
1510    *   x = -DefaultDescender -
1511    *         ((DefaultAscender - DefaultDescender - aw) / 2)     .      (2)
1512    *
1513    * and another one with
1514    *
1515    *   x = 0     .                                                      (3)
1516    *
1517    * In Windows, the history of those values is quite complicated,
1518    * depending on the hinting engine (that is, the graphics framework).
1519    *
1520    *   framework        from                 to       formula
1521    *  ----------------------------------------------------------
1522    *    GDI       Windows 98               current      (1)
1523    *              (Windows 2000 for NT)
1524    *    GDI+      Windows XP               Windows 7    (2)
1525    *    GDI+      Windows 8                current      (3)
1526    *    DWrite    Windows 7                current      (3)
1527    *
1528    * For simplicity, FreeType uses (1) for grayscale subpixel hinting and
1529    * (3) for everything else.
1530    *
1531    */
1532   static void
tt_loader_set_pp(TT_Loader loader)1533   tt_loader_set_pp( TT_Loader  loader )
1534   {
1535     FT_Bool  subpixel_hinting = 0;
1536     FT_Bool  grayscale        = 0;
1537     FT_Bool  use_aw_2         = 0;
1538 
1539 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
1540     TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face );
1541 #endif
1542 
1543 
1544 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
1545     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
1546     {
1547       subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting
1548                                       : 0;
1549       grayscale        = loader->exec ? loader->exec->grayscale
1550                                       : 0;
1551     }
1552 #endif
1553 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
1554     if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
1555     {
1556       subpixel_hinting = loader->exec ? loader->exec->subpixel_hinting_lean
1557                                       : 0;
1558       grayscale        = loader->exec ? loader->exec->grayscale_cleartype
1559                                       : 0;
1560     }
1561 #endif
1562 
1563     use_aw_2 = FT_BOOL( subpixel_hinting && grayscale );
1564 
1565     loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
1566     loader->pp1.y = 0;
1567     loader->pp2.x = loader->pp1.x + loader->advance;
1568     loader->pp2.y = 0;
1569 
1570     loader->pp3.x = use_aw_2 ? loader->advance / 2 : 0;
1571     loader->pp3.y = loader->bbox.yMax + loader->top_bearing;
1572     loader->pp4.x = use_aw_2 ? loader->advance / 2 : 0;
1573     loader->pp4.y = loader->pp3.y - loader->vadvance;
1574   }
1575 
1576 
1577   /* a utility function to retrieve i-th node from given FT_List */
1578   static FT_ListNode
ft_list_get_node_at(FT_List list,FT_UInt idx)1579   ft_list_get_node_at( FT_List  list,
1580                        FT_UInt  idx )
1581   {
1582     FT_ListNode  cur;
1583 
1584 
1585     if ( !list )
1586       return NULL;
1587 
1588     for ( cur = list->head; cur; cur = cur->next )
1589     {
1590       if ( !idx )
1591         return cur;
1592 
1593       idx--;
1594     }
1595 
1596     return NULL;
1597   }
1598 
1599 
1600   /**************************************************************************
1601    *
1602    * @Function:
1603    *   load_truetype_glyph
1604    *
1605    * @Description:
1606    *   Loads a given truetype glyph.  Handles composites and uses a
1607    *   TT_Loader object.
1608    */
1609   static FT_Error
load_truetype_glyph(TT_Loader loader,FT_UInt glyph_index,FT_UInt recurse_count,FT_Bool header_only)1610   load_truetype_glyph( TT_Loader  loader,
1611                        FT_UInt    glyph_index,
1612                        FT_UInt    recurse_count,
1613                        FT_Bool    header_only )
1614   {
1615     FT_Error        error   = FT_Err_Ok;
1616     FT_Fixed        x_scale, y_scale;
1617     FT_ULong        offset;
1618     TT_Face         face    = loader->face;
1619     FT_GlyphLoader  gloader = loader->gloader;
1620 
1621     FT_Bool  opened_frame = 0;
1622 
1623 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1624     FT_StreamRec    inc_stream;
1625     FT_Data         glyph_data;
1626     FT_Bool         glyph_data_loaded = 0;
1627 #endif
1628 
1629 
1630 #ifdef FT_DEBUG_LEVEL_TRACE
1631     if ( recurse_count )
1632       FT_TRACE5(( "  nesting level: %d\n", recurse_count ));
1633 #endif
1634 
1635     /* some fonts have an incorrect value of `maxComponentDepth' */
1636     if ( recurse_count > face->max_profile.maxComponentDepth )
1637     {
1638       FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n",
1639                   recurse_count ));
1640       face->max_profile.maxComponentDepth = (FT_UShort)recurse_count;
1641     }
1642 
1643 #ifndef FT_CONFIG_OPTION_INCREMENTAL
1644     /* check glyph index */
1645     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1646     {
1647       error = FT_THROW( Invalid_Glyph_Index );
1648       goto Exit;
1649     }
1650 #endif
1651 
1652     loader->glyph_index = glyph_index;
1653 
1654     if ( loader->load_flags & FT_LOAD_NO_SCALE )
1655     {
1656       x_scale = 0x10000L;
1657       y_scale = 0x10000L;
1658     }
1659     else
1660     {
1661       x_scale = loader->size->metrics->x_scale;
1662       y_scale = loader->size->metrics->y_scale;
1663     }
1664 
1665     /* Set `offset' to the start of the glyph relative to the start of */
1666     /* the `glyf' table, and `byte_len' to the length of the glyph in  */
1667     /* bytes.                                                          */
1668 
1669 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1670 
1671     /* If we are loading glyph data via the incremental interface, set */
1672     /* the loader stream to a memory stream reading the data returned  */
1673     /* by the interface.                                               */
1674     if ( face->root.internal->incremental_interface )
1675     {
1676       error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1677                 face->root.internal->incremental_interface->object,
1678                 glyph_index, &glyph_data );
1679       if ( error )
1680         goto Exit;
1681 
1682       glyph_data_loaded = 1;
1683       offset            = 0;
1684       loader->byte_len  = glyph_data.length;
1685 
1686       FT_ZERO( &inc_stream );
1687       FT_Stream_OpenMemory( &inc_stream,
1688                             glyph_data.pointer,
1689                             glyph_data.length );
1690 
1691       loader->stream = &inc_stream;
1692     }
1693     else
1694 
1695 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1696 
1697       offset = tt_face_get_location( face, glyph_index, &loader->byte_len );
1698 
1699     if ( loader->byte_len > 0 )
1700     {
1701 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1702       /* for the incremental interface, `glyf_offset' is always zero */
1703       if ( !face->glyf_offset                          &&
1704            !face->root.internal->incremental_interface )
1705 #else
1706       if ( !face->glyf_offset )
1707 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
1708       {
1709         FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
1710         error = FT_THROW( Invalid_Table );
1711         goto Exit;
1712       }
1713 
1714       error = face->access_glyph_frame( loader, glyph_index,
1715                                         face->glyf_offset + offset,
1716                                         loader->byte_len );
1717       if ( error )
1718         goto Exit;
1719 
1720       /* read glyph header first */
1721       error = face->read_glyph_header( loader );
1722 
1723       face->forget_glyph_frame( loader );
1724 
1725       if ( error )
1726         goto Exit;
1727     }
1728 
1729     /* a space glyph */
1730     if ( loader->byte_len == 0 || loader->n_contours == 0 )
1731     {
1732       loader->bbox.xMin = 0;
1733       loader->bbox.xMax = 0;
1734       loader->bbox.yMin = 0;
1735       loader->bbox.yMax = 0;
1736     }
1737 
1738     /* the metrics must be computed after loading the glyph header */
1739     /* since we need the glyph's `yMax' value in case the vertical */
1740     /* metrics must be emulated                                    */
1741     error = tt_get_metrics( loader, glyph_index );
1742     if ( error )
1743       goto Exit;
1744 
1745     if ( header_only )
1746       goto Exit;
1747 
1748     if ( loader->byte_len == 0 || loader->n_contours == 0 )
1749     {
1750 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1751       tt_get_metrics_incremental( loader, glyph_index );
1752 #endif
1753       tt_loader_set_pp( loader );
1754 
1755 
1756 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1757 
1758       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1759            FT_IS_VARIATION( FT_FACE( face ) )      )
1760       {
1761         /* a small outline structure with four elements for */
1762         /* communication with `TT_Vary_Apply_Glyph_Deltas'  */
1763         FT_Vector   points[4];
1764         char        tags[4]     = { 1, 1, 1, 1 };
1765         short       contours[4] = { 0, 1, 2, 3 };
1766         FT_Outline  outline;
1767 
1768         /* unrounded values */
1769         FT_Vector  unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
1770 
1771 
1772         points[0].x = loader->pp1.x;
1773         points[0].y = loader->pp1.y;
1774         points[1].x = loader->pp2.x;
1775         points[1].y = loader->pp2.y;
1776 
1777         points[2].x = loader->pp3.x;
1778         points[2].y = loader->pp3.y;
1779         points[3].x = loader->pp4.x;
1780         points[3].y = loader->pp4.y;
1781 
1782         outline.n_points   = 4;
1783         outline.n_contours = 4;
1784         outline.points     = points;
1785         outline.tags       = tags;
1786         outline.contours   = contours;
1787 
1788         /* this must be done before scaling */
1789         error = TT_Vary_Apply_Glyph_Deltas( loader->face,
1790                                             glyph_index,
1791                                             &outline,
1792                                             unrounded,
1793                                             (FT_UInt)outline.n_points );
1794         if ( error )
1795           goto Exit;
1796 
1797         loader->pp1.x = points[0].x;
1798         loader->pp1.y = points[0].y;
1799         loader->pp2.x = points[1].x;
1800         loader->pp2.y = points[1].y;
1801 
1802         loader->pp3.x = points[2].x;
1803         loader->pp3.y = points[2].y;
1804         loader->pp4.x = points[3].x;
1805         loader->pp4.y = points[3].y;
1806 
1807         /* recalculate linear horizontal and vertical advances */
1808         /* if we don't have HVAR and VVAR, respectively        */
1809         if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
1810           loader->linear = FT_PIX_ROUND( unrounded[1].x -
1811                                          unrounded[0].x ) / 64;
1812         if ( !( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
1813           loader->vadvance = FT_PIX_ROUND( unrounded[3].x -
1814                                            unrounded[2].x ) / 64;
1815       }
1816 
1817 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1818 
1819       /* scale phantom points, if necessary; */
1820       /* they get rounded in `TT_Hint_Glyph' */
1821       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1822       {
1823         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1824         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1825         /* pp1.y and pp2.y are always zero */
1826 
1827         loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
1828         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1829         loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
1830         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1831       }
1832 
1833       error = FT_Err_Ok;
1834       goto Exit;
1835     }
1836 
1837 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1838     tt_get_metrics_incremental( loader, glyph_index );
1839 #endif
1840     tt_loader_set_pp( loader );
1841 
1842 
1843     /***********************************************************************/
1844     /***********************************************************************/
1845     /***********************************************************************/
1846 
1847     /* we now open a frame again, right after the glyph header */
1848     /* (which consists of 10 bytes)                            */
1849     error = face->access_glyph_frame( loader, glyph_index,
1850                                       face->glyf_offset + offset + 10,
1851                                       loader->byte_len - 10 );
1852     if ( error )
1853       goto Exit;
1854 
1855     opened_frame = 1;
1856 
1857     /* if it is a simple glyph, load it */
1858 
1859     if ( loader->n_contours > 0 )
1860     {
1861       error = face->read_simple_glyph( loader );
1862       if ( error )
1863         goto Exit;
1864 
1865       /* all data have been read */
1866       face->forget_glyph_frame( loader );
1867       opened_frame = 0;
1868 
1869       error = TT_Process_Simple_Glyph( loader );
1870       if ( error )
1871         goto Exit;
1872 
1873       FT_GlyphLoader_Add( gloader );
1874     }
1875 
1876     /***********************************************************************/
1877     /***********************************************************************/
1878     /***********************************************************************/
1879 
1880     /* otherwise, load a composite! */
1881     else if ( loader->n_contours < 0 )
1882     {
1883       FT_Memory  memory = face->root.memory;
1884 
1885       FT_UInt   start_point;
1886       FT_UInt   start_contour;
1887       FT_ULong  ins_pos;  /* position of composite instructions, if any */
1888 
1889       FT_ListNode  node, node2;
1890 
1891 
1892       /* normalize the `n_contours' value */
1893       loader->n_contours = -1;
1894 
1895       /*
1896        * We store the glyph index directly in the `node->data' pointer,
1897        * following the glib solution (cf. macro `GUINT_TO_POINTER') with a
1898        * double cast to make this portable.  Note, however, that this needs
1899        * pointers with a width of at least 32 bits.
1900        */
1901 
1902       /* clear the nodes filled by sibling chains */
1903       node = ft_list_get_node_at( &loader->composites, recurse_count );
1904       for ( node2 = node; node2; node2 = node2->next )
1905         node2->data = (void*)-1;
1906 
1907       /* check whether we already have a composite glyph with this index */
1908       if ( FT_List_Find( &loader->composites,
1909                          FT_UINT_TO_POINTER( glyph_index ) ) )
1910       {
1911         FT_TRACE1(( "TT_Load_Composite_Glyph:"
1912                     " infinite recursion detected\n" ));
1913         error = FT_THROW( Invalid_Composite );
1914         goto Exit;
1915       }
1916 
1917       else if ( node )
1918         node->data = FT_UINT_TO_POINTER( glyph_index );
1919 
1920       else
1921       {
1922         if ( FT_QNEW( node ) )
1923           goto Exit;
1924         node->data = FT_UINT_TO_POINTER( glyph_index );
1925         FT_List_Add( &loader->composites, node );
1926       }
1927 
1928       start_point   = (FT_UInt)gloader->base.outline.n_points;
1929       start_contour = (FT_UInt)gloader->base.outline.n_contours;
1930 
1931       /* for each subglyph, read composite header */
1932       error = face->read_composite_glyph( loader );
1933       if ( error )
1934         goto Exit;
1935 
1936       /* store the offset of instructions */
1937       ins_pos = loader->ins_pos;
1938 
1939       /* all data we need are read */
1940       face->forget_glyph_frame( loader );
1941       opened_frame = 0;
1942 
1943 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1944 
1945       if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) ||
1946            FT_IS_VARIATION( FT_FACE( face ) )      )
1947       {
1948         short        i, limit;
1949         FT_SubGlyph  subglyph;
1950 
1951         FT_Outline  outline;
1952         FT_Vector*  points    = NULL;
1953         char*       tags      = NULL;
1954         short*      contours  = NULL;
1955         FT_Vector*  unrounded = NULL;
1956 
1957 
1958         limit = (short)gloader->current.num_subglyphs;
1959 
1960         /* construct an outline structure for              */
1961         /* communication with `TT_Vary_Apply_Glyph_Deltas' */
1962         outline.n_points   = (short)( gloader->current.num_subglyphs + 4 );
1963         outline.n_contours = outline.n_points;
1964 
1965         outline.points   = NULL;
1966         outline.tags     = NULL;
1967         outline.contours = NULL;
1968 
1969         if ( FT_NEW_ARRAY( points, outline.n_points )    ||
1970              FT_NEW_ARRAY( tags, outline.n_points )      ||
1971              FT_NEW_ARRAY( contours, outline.n_points )  ||
1972              FT_NEW_ARRAY( unrounded, outline.n_points ) )
1973           goto Exit1;
1974 
1975         subglyph = gloader->current.subglyphs;
1976 
1977         for ( i = 0; i < limit; i++, subglyph++ )
1978         {
1979           /* applying deltas for anchor points doesn't make sense, */
1980           /* but we don't have to specially check this since       */
1981           /* unused delta values are zero anyways                  */
1982           points[i].x = subglyph->arg1;
1983           points[i].y = subglyph->arg2;
1984           tags[i]     = 1;
1985           contours[i] = i;
1986         }
1987 
1988         points[i].x = loader->pp1.x;
1989         points[i].y = loader->pp1.y;
1990         tags[i]     = 1;
1991         contours[i] = i;
1992 
1993         i++;
1994         points[i].x = loader->pp2.x;
1995         points[i].y = loader->pp2.y;
1996         tags[i]     = 1;
1997         contours[i] = i;
1998 
1999         i++;
2000         points[i].x = loader->pp3.x;
2001         points[i].y = loader->pp3.y;
2002         tags[i]     = 1;
2003         contours[i] = i;
2004 
2005         i++;
2006         points[i].x = loader->pp4.x;
2007         points[i].y = loader->pp4.y;
2008         tags[i]     = 1;
2009         contours[i] = i;
2010 
2011         outline.points   = points;
2012         outline.tags     = tags;
2013         outline.contours = contours;
2014 
2015         /* this call provides additional offsets */
2016         /* for each component's translation      */
2017         if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas(
2018                              face,
2019                              glyph_index,
2020                              &outline,
2021                              unrounded,
2022                              (FT_UInt)outline.n_points ) ) )
2023           goto Exit1;
2024 
2025         subglyph = gloader->current.subglyphs;
2026 
2027         for ( i = 0; i < limit; i++, subglyph++ )
2028         {
2029           if ( subglyph->flags & ARGS_ARE_XY_VALUES )
2030           {
2031             subglyph->arg1 = (FT_Int16)points[i].x;
2032             subglyph->arg2 = (FT_Int16)points[i].y;
2033           }
2034         }
2035 
2036         loader->pp1.x = points[i + 0].x;
2037         loader->pp1.y = points[i + 0].y;
2038         loader->pp2.x = points[i + 1].x;
2039         loader->pp2.y = points[i + 1].y;
2040 
2041         loader->pp3.x = points[i + 2].x;
2042         loader->pp3.y = points[i + 2].y;
2043         loader->pp4.x = points[i + 3].x;
2044         loader->pp4.y = points[i + 3].y;
2045 
2046         /* recalculate linear horizontal and vertical advances */
2047         /* if we don't have HVAR and VVAR, respectively        */
2048         if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) )
2049           loader->linear =
2050             FT_PIX_ROUND( unrounded[outline.n_points - 3].x -
2051                           unrounded[outline.n_points - 4].x ) / 64;
2052         if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) )
2053           loader->vadvance =
2054             FT_PIX_ROUND( unrounded[outline.n_points - 1].x -
2055                           unrounded[outline.n_points - 2].x ) / 64;
2056 
2057       Exit1:
2058         FT_FREE( outline.points );
2059         FT_FREE( outline.tags );
2060         FT_FREE( outline.contours );
2061         FT_FREE( unrounded );
2062 
2063         if ( error )
2064           goto Exit;
2065       }
2066 
2067 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
2068 
2069       /* scale phantom points, if necessary; */
2070       /* they get rounded in `TT_Hint_Glyph' */
2071       if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
2072       {
2073         loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
2074         loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
2075         /* pp1.y and pp2.y are always zero */
2076 
2077         loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale );
2078         loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
2079         loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale );
2080         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
2081       }
2082 
2083       /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
2084       /* `as is' in the glyph slot (the client application will be     */
2085       /* responsible for interpreting these data)...                   */
2086       if ( loader->load_flags & FT_LOAD_NO_RECURSE )
2087       {
2088         FT_GlyphLoader_Add( gloader );
2089         loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
2090 
2091         goto Exit;
2092       }
2093 
2094       /*********************************************************************/
2095       /*********************************************************************/
2096       /*********************************************************************/
2097 
2098       {
2099         FT_UInt      n, num_base_points;
2100         FT_SubGlyph  subglyph       = NULL;
2101 
2102         FT_UInt      num_points     = start_point;
2103         FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
2104         FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
2105 
2106         FT_Stream    old_stream     = loader->stream;
2107         FT_UInt      old_byte_len   = loader->byte_len;
2108 
2109 
2110         FT_GlyphLoader_Add( gloader );
2111 
2112         /* read each subglyph independently */
2113         for ( n = 0; n < num_subglyphs; n++ )
2114         {
2115           FT_Vector  pp[4];
2116 
2117           FT_Int  linear_hadvance;
2118           FT_Int  linear_vadvance;
2119 
2120 
2121           /* Each time we call `load_truetype_glyph' in this loop, the */
2122           /* value of `gloader.base.subglyphs' can change due to table */
2123           /* reallocations.  We thus need to recompute the subglyph    */
2124           /* pointer on each iteration.                                */
2125           subglyph = gloader->base.subglyphs + num_base_subgs + n;
2126 
2127           pp[0] = loader->pp1;
2128           pp[1] = loader->pp2;
2129           pp[2] = loader->pp3;
2130           pp[3] = loader->pp4;
2131 
2132           linear_hadvance = loader->linear;
2133           linear_vadvance = loader->vadvance;
2134 
2135           num_base_points = (FT_UInt)gloader->base.outline.n_points;
2136 
2137           error = load_truetype_glyph( loader,
2138                                        (FT_UInt)subglyph->index,
2139                                        recurse_count + 1,
2140                                        FALSE );
2141           if ( error )
2142             goto Exit;
2143 
2144           /* restore subglyph pointer */
2145           subglyph = gloader->base.subglyphs + num_base_subgs + n;
2146 
2147           /* restore phantom points if necessary */
2148           if ( !( subglyph->flags & USE_MY_METRICS ) )
2149           {
2150             loader->pp1 = pp[0];
2151             loader->pp2 = pp[1];
2152             loader->pp3 = pp[2];
2153             loader->pp4 = pp[3];
2154 
2155             loader->linear   = linear_hadvance;
2156             loader->vadvance = linear_vadvance;
2157           }
2158 
2159           num_points = (FT_UInt)gloader->base.outline.n_points;
2160 
2161           if ( num_points == num_base_points )
2162             continue;
2163 
2164           /* gloader->base.outline consists of three parts:           */
2165           /*                                                          */
2166           /* 0 ----> start_point ----> num_base_points ----> n_points */
2167           /*    (1)               (2)                   (3)           */
2168           /*                                                          */
2169           /* (1) points that exist from the beginning                 */
2170           /* (2) component points that have been loaded so far        */
2171           /* (3) points of the newly loaded component                 */
2172           error = TT_Process_Composite_Component( loader,
2173                                                   subglyph,
2174                                                   start_point,
2175                                                   num_base_points );
2176           if ( error )
2177             goto Exit;
2178         }
2179 
2180         loader->stream   = old_stream;
2181         loader->byte_len = old_byte_len;
2182 
2183         /* process the glyph */
2184         loader->ins_pos = ins_pos;
2185         if ( IS_HINTED( loader->load_flags ) &&
2186 #ifdef TT_USE_BYTECODE_INTERPRETER
2187              subglyph                        &&
2188              subglyph->flags & WE_HAVE_INSTR &&
2189 #endif
2190              num_points > start_point )
2191         {
2192           error = TT_Process_Composite_Glyph( loader,
2193                                               start_point,
2194                                               start_contour );
2195           if ( error )
2196             goto Exit;
2197         }
2198       }
2199 
2200       /* retain the overlap flag */
2201       if ( gloader->base.num_subglyphs                         &&
2202            gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND )
2203         gloader->base.outline.flags |= FT_OUTLINE_OVERLAP;
2204     }
2205 
2206     /***********************************************************************/
2207     /***********************************************************************/
2208     /***********************************************************************/
2209 
2210   Exit:
2211 
2212     if ( opened_frame )
2213       face->forget_glyph_frame( loader );
2214 
2215 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2216 
2217     if ( glyph_data_loaded )
2218       face->root.internal->incremental_interface->funcs->free_glyph_data(
2219         face->root.internal->incremental_interface->object,
2220         &glyph_data );
2221 
2222 #endif
2223 
2224     return error;
2225   }
2226 
2227 
2228   static FT_Error
compute_glyph_metrics(TT_Loader loader,FT_UInt glyph_index)2229   compute_glyph_metrics( TT_Loader  loader,
2230                          FT_UInt    glyph_index )
2231   {
2232     TT_Face    face   = loader->face;
2233 #if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
2234     defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2235     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
2236 #endif
2237 
2238     FT_BBox       bbox;
2239     FT_Fixed      y_scale;
2240     TT_GlyphSlot  glyph = loader->glyph;
2241     TT_Size       size  = loader->size;
2242 
2243 
2244     y_scale = 0x10000L;
2245     if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
2246       y_scale = size->metrics->y_scale;
2247 
2248     if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
2249       FT_Outline_Get_CBox( &glyph->outline, &bbox );
2250     else
2251       bbox = loader->bbox;
2252 
2253     /* get the device-independent horizontal advance; it is scaled later */
2254     /* by the base layer.                                                */
2255     glyph->linearHoriAdvance = loader->linear;
2256 
2257     glyph->metrics.horiBearingX = bbox.xMin;
2258     glyph->metrics.horiBearingY = bbox.yMax;
2259     glyph->metrics.horiAdvance  = SUB_LONG(loader->pp2.x, loader->pp1.x);
2260 
2261     /* Adjust advance width to the value contained in the hdmx table   */
2262     /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */
2263     /* mode of the v40 interpreter is active.  See `ttinterp.h' for    */
2264     /* details on backward compatibility mode.                         */
2265     if (
2266 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2267          !( driver->interpreter_version == TT_INTERPRETER_VERSION_40  &&
2268             ( loader->exec && loader->exec->backward_compatibility  ) ) &&
2269 #endif
2270          !face->postscript.isFixedPitch                                 &&
2271          IS_HINTED( loader->load_flags )                                &&
2272          !( loader->load_flags & FT_LOAD_COMPUTE_METRICS )              )
2273     {
2274       FT_Byte*  widthp;
2275 
2276 
2277       widthp = tt_face_get_device_metrics( face,
2278                                            size->metrics->x_ppem,
2279                                            glyph_index );
2280 
2281 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2282 
2283       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2284       {
2285         FT_Bool  ignore_x_mode;
2286 
2287 
2288         ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
2289                                  FT_RENDER_MODE_MONO );
2290 
2291         if ( widthp                                                   &&
2292              ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
2293                 !ignore_x_mode                                      ||
2294                 SPH_OPTION_BITMAP_WIDTHS                            ) )
2295           glyph->metrics.horiAdvance = *widthp * 64;
2296       }
2297       else
2298 
2299 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2300 
2301       {
2302         if ( widthp )
2303           glyph->metrics.horiAdvance = *widthp * 64;
2304       }
2305     }
2306 
2307     /* set glyph dimensions */
2308     glyph->metrics.width  = SUB_LONG( bbox.xMax, bbox.xMin );
2309     glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin );
2310 
2311     /* Now take care of vertical metrics.  In the case where there is */
2312     /* no vertical information within the font (relatively common),   */
2313     /* create some metrics manually                                   */
2314     {
2315       FT_Pos  top;      /* scaled vertical top side bearing  */
2316       FT_Pos  advance;  /* scaled vertical advance height    */
2317 
2318 
2319       /* Get the unscaled top bearing and advance height. */
2320       if ( face->vertical_info                   &&
2321            face->vertical.number_Of_VMetrics > 0 )
2322       {
2323         top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ),
2324                                    y_scale );
2325 
2326         if ( loader->pp3.y <= loader->pp4.y )
2327           advance = 0;
2328         else
2329           advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y,
2330                                                     loader->pp4.y ),
2331                                           y_scale );
2332       }
2333       else
2334       {
2335         FT_Pos  height;
2336 
2337 
2338         /* XXX Compute top side bearing and advance height in  */
2339         /*     Get_VMetrics instead of here.                   */
2340 
2341         /* NOTE: The OS/2 values are the only `portable' ones, */
2342         /*       which is why we use them, if there is an OS/2 */
2343         /*       table in the font.  Otherwise, we use the     */
2344         /*       values defined in the horizontal header.      */
2345 
2346         height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax,
2347                                                 bbox.yMin ),
2348                                       y_scale );
2349         if ( face->os2.version != 0xFFFFU )
2350           advance = (FT_Pos)( face->os2.sTypoAscender -
2351                               face->os2.sTypoDescender );
2352         else
2353           advance = (FT_Pos)( face->horizontal.Ascender -
2354                               face->horizontal.Descender );
2355 
2356         top = ( advance - height ) / 2;
2357       }
2358 
2359 #ifdef FT_CONFIG_OPTION_INCREMENTAL
2360       {
2361         FT_Incremental_InterfaceRec*  incr;
2362         FT_Incremental_MetricsRec     incr_metrics;
2363         FT_Error                      error;
2364 
2365 
2366         incr = face->root.internal->incremental_interface;
2367 
2368         /* If this is an incrementally loaded font see if there are */
2369         /* overriding metrics for this glyph.                       */
2370         if ( incr && incr->funcs->get_glyph_metrics )
2371         {
2372           incr_metrics.bearing_x = 0;
2373           incr_metrics.bearing_y = top;
2374           incr_metrics.advance   = advance;
2375 
2376           error = incr->funcs->get_glyph_metrics( incr->object,
2377                                                   glyph_index,
2378                                                   TRUE,
2379                                                   &incr_metrics );
2380           if ( error )
2381             return error;
2382 
2383           top     = incr_metrics.bearing_y;
2384           advance = incr_metrics.advance;
2385         }
2386       }
2387 
2388       /* GWW: Do vertical metrics get loaded incrementally too? */
2389 
2390 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
2391 
2392       glyph->linearVertAdvance = advance;
2393 
2394       /* scale the metrics */
2395       if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
2396       {
2397         top     = FT_MulFix( top,     y_scale );
2398         advance = FT_MulFix( advance, y_scale );
2399       }
2400 
2401       /* XXX: for now, we have no better algorithm for the lsb, but it */
2402       /*      should work fine.                                        */
2403       /*                                                               */
2404       glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX,
2405                                               glyph->metrics.horiAdvance / 2 );
2406       glyph->metrics.vertBearingY = top;
2407       glyph->metrics.vertAdvance  = advance;
2408     }
2409 
2410     return FT_Err_Ok;
2411   }
2412 
2413 
2414 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2415 
2416   static FT_Error
load_sbit_image(TT_Size size,TT_GlyphSlot glyph,FT_UInt glyph_index,FT_Int32 load_flags)2417   load_sbit_image( TT_Size       size,
2418                    TT_GlyphSlot  glyph,
2419                    FT_UInt       glyph_index,
2420                    FT_Int32      load_flags )
2421   {
2422     TT_Face             face;
2423     SFNT_Service        sfnt;
2424     FT_Stream           stream;
2425     FT_Error            error;
2426     TT_SBit_MetricsRec  sbit_metrics;
2427 
2428 
2429     face   = (TT_Face)glyph->face;
2430     sfnt   = (SFNT_Service)face->sfnt;
2431     stream = face->root.stream;
2432 
2433     error = sfnt->load_sbit_image( face,
2434                                    size->strike_index,
2435                                    glyph_index,
2436                                    (FT_UInt)load_flags,
2437                                    stream,
2438                                    &glyph->bitmap,
2439                                    &sbit_metrics );
2440     if ( !error )
2441     {
2442       glyph->outline.n_points   = 0;
2443       glyph->outline.n_contours = 0;
2444 
2445       glyph->metrics.width  = (FT_Pos)sbit_metrics.width  * 64;
2446       glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64;
2447 
2448       glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64;
2449       glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64;
2450       glyph->metrics.horiAdvance  = (FT_Pos)sbit_metrics.horiAdvance  * 64;
2451 
2452       glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64;
2453       glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64;
2454       glyph->metrics.vertAdvance  = (FT_Pos)sbit_metrics.vertAdvance  * 64;
2455 
2456       glyph->format = FT_GLYPH_FORMAT_BITMAP;
2457 
2458       if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
2459       {
2460         glyph->bitmap_left = sbit_metrics.vertBearingX;
2461         glyph->bitmap_top  = sbit_metrics.vertBearingY;
2462       }
2463       else
2464       {
2465         glyph->bitmap_left = sbit_metrics.horiBearingX;
2466         glyph->bitmap_top  = sbit_metrics.horiBearingY;
2467       }
2468     }
2469 
2470     return error;
2471   }
2472 
2473 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2474 
2475 
2476   static FT_Error
tt_loader_init(TT_Loader loader,TT_Size size,TT_GlyphSlot glyph,FT_Int32 load_flags,FT_Bool glyf_table_only)2477   tt_loader_init( TT_Loader     loader,
2478                   TT_Size       size,
2479                   TT_GlyphSlot  glyph,
2480                   FT_Int32      load_flags,
2481                   FT_Bool       glyf_table_only )
2482   {
2483     TT_Face    face;
2484     FT_Stream  stream;
2485 
2486 #ifdef TT_USE_BYTECODE_INTERPRETER
2487     FT_Error   error;
2488     FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2489 #if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \
2490     defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2491     TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face );
2492 #endif
2493 #endif
2494 
2495 
2496     face   = (TT_Face)glyph->face;
2497     stream = face->root.stream;
2498 
2499     FT_ZERO( loader );
2500 
2501 #ifdef TT_USE_BYTECODE_INTERPRETER
2502 
2503     /* load execution context */
2504     if ( IS_HINTED( load_flags ) && !glyf_table_only )
2505     {
2506       TT_ExecContext  exec;
2507       FT_Bool         grayscale = TRUE;
2508 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2509       FT_Bool         subpixel_hinting_lean;
2510       FT_Bool         grayscale_cleartype;
2511 #endif
2512 
2513 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2514       FT_Bool  subpixel_hinting = FALSE;
2515 
2516 #if 0
2517       /* not used yet */
2518       FT_Bool  compatible_widths;
2519       FT_Bool  symmetrical_smoothing;
2520       FT_Bool  bgr;
2521       FT_Bool  vertical_lcd;
2522       FT_Bool  subpixel_positioned;
2523       FT_Bool  gray_cleartype;
2524 #endif
2525 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2526 
2527       FT_Bool  reexecute = FALSE;
2528 
2529 
2530       if ( size->bytecode_ready < 0 || size->cvt_ready < 0 )
2531       {
2532         error = tt_size_ready_bytecode( size, pedantic );
2533         if ( error )
2534           return error;
2535       }
2536       else if ( size->bytecode_ready )
2537         return size->bytecode_ready;
2538       else if ( size->cvt_ready )
2539         return size->cvt_ready;
2540 
2541       /* query new execution context */
2542       exec = size->context;
2543       if ( !exec )
2544         return FT_THROW( Could_Not_Find_Context );
2545 
2546 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2547       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2548       {
2549         subpixel_hinting_lean =
2550           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2551                    FT_RENDER_MODE_MONO               );
2552         grayscale_cleartype =
2553           FT_BOOL( subpixel_hinting_lean         &&
2554                    !( ( load_flags         &
2555                         FT_LOAD_TARGET_LCD )   ||
2556                       ( load_flags           &
2557                         FT_LOAD_TARGET_LCD_V ) ) );
2558         exec->vertical_lcd_lean =
2559           FT_BOOL( subpixel_hinting_lean    &&
2560                    ( load_flags           &
2561                      FT_LOAD_TARGET_LCD_V ) );
2562       }
2563       else
2564       {
2565         subpixel_hinting_lean   = FALSE;
2566         grayscale_cleartype     = FALSE;
2567         exec->vertical_lcd_lean = FALSE;
2568       }
2569 #endif
2570 
2571 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2572 
2573       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2574       {
2575         subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) !=
2576                                       FT_RENDER_MODE_MONO               )  &&
2577                                     SPH_OPTION_SET_SUBPIXEL                );
2578 
2579         if ( subpixel_hinting )
2580           grayscale = FALSE;
2581         else if ( SPH_OPTION_SET_GRAYSCALE )
2582         {
2583           grayscale        = TRUE;
2584           subpixel_hinting = FALSE;
2585         }
2586         else
2587           grayscale = FALSE;
2588 
2589         if ( FT_IS_TRICKY( glyph->face ) )
2590           subpixel_hinting = FALSE;
2591 
2592         exec->ignore_x_mode      = subpixel_hinting || grayscale;
2593         exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
2594         if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
2595           exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
2596 
2597 #if 1
2598         exec->compatible_widths     = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
2599         exec->symmetrical_smoothing = TRUE;
2600         exec->bgr                   = FALSE;
2601         exec->vertical_lcd          = FALSE;
2602         exec->subpixel_positioned   = TRUE;
2603         exec->gray_cleartype        = FALSE;
2604 #else /* 0 */
2605         exec->compatible_widths =
2606           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2607                    TT_LOAD_COMPATIBLE_WIDTHS );
2608         exec->symmetrical_smoothing =
2609           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2610                    TT_LOAD_SYMMETRICAL_SMOOTHING );
2611         exec->bgr =
2612           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2613                    TT_LOAD_BGR );
2614         exec->vertical_lcd =
2615           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2616                    TT_LOAD_VERTICAL_LCD );
2617         exec->subpixel_positioned =
2618           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2619                    TT_LOAD_SUBPIXEL_POSITIONED );
2620         exec->gray_cleartype =
2621           FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2622                    TT_LOAD_GRAY_CLEARTYPE );
2623 #endif /* 0 */
2624 
2625       }
2626       else
2627 
2628 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2629 
2630 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2631       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2632         grayscale = FT_BOOL( !subpixel_hinting_lean               &&
2633                              FT_LOAD_TARGET_MODE( load_flags ) !=
2634                                FT_RENDER_MODE_MONO                );
2635       else
2636 #endif
2637         grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
2638                                FT_RENDER_MODE_MONO             );
2639 
2640       error = TT_Load_Context( exec, face, size );
2641       if ( error )
2642         return error;
2643 
2644 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2645 
2646       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
2647       {
2648         /* a change from mono to subpixel rendering (and vice versa) */
2649         /* requires a re-execution of the CVT program                */
2650         if ( subpixel_hinting != exec->subpixel_hinting )
2651         {
2652           FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2653                       " re-executing `prep' table\n" ));
2654 
2655           exec->subpixel_hinting = subpixel_hinting;
2656           reexecute              = TRUE;
2657         }
2658 
2659         /* a change from mono to grayscale rendering (and vice versa) */
2660         /* requires a re-execution of the CVT program                 */
2661         if ( grayscale != exec->grayscale )
2662         {
2663           FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2664                       " re-executing `prep' table\n" ));
2665 
2666           exec->grayscale = grayscale;
2667           reexecute       = TRUE;
2668         }
2669       }
2670       else
2671 
2672 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */
2673 
2674       {
2675 
2676 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
2677         if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 )
2678         {
2679           /* a change from mono to subpixel rendering (and vice versa) */
2680           /* requires a re-execution of the CVT program                */
2681           if ( subpixel_hinting_lean != exec->subpixel_hinting_lean )
2682           {
2683             FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
2684                         " re-executing `prep' table\n" ));
2685 
2686             exec->subpixel_hinting_lean = subpixel_hinting_lean;
2687             reexecute                   = TRUE;
2688           }
2689 
2690           /* a change from colored to grayscale subpixel rendering (and */
2691           /* vice versa) requires a re-execution of the CVT program     */
2692           if ( grayscale_cleartype != exec->grayscale_cleartype )
2693           {
2694             FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change,"
2695                         " re-executing `prep' table\n" ));
2696 
2697             exec->grayscale_cleartype = grayscale_cleartype;
2698             reexecute                 = TRUE;
2699           }
2700         }
2701 #endif
2702 
2703         /* a change from mono to grayscale rendering (and vice versa) */
2704         /* requires a re-execution of the CVT program                 */
2705         if ( grayscale != exec->grayscale )
2706         {
2707           FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
2708                       " re-executing `prep' table\n" ));
2709 
2710           exec->grayscale = grayscale;
2711           reexecute       = TRUE;
2712         }
2713       }
2714 
2715       if ( reexecute )
2716       {
2717         error = tt_size_run_prep( size, pedantic );
2718         if ( error )
2719           return error;
2720         error = TT_Load_Context( exec, face, size );
2721         if ( error )
2722           return error;
2723       }
2724 
2725       /* check whether the cvt program has disabled hinting */
2726       if ( exec->GS.instruct_control & 1 )
2727         load_flags |= FT_LOAD_NO_HINTING;
2728 
2729       /* load default graphics state -- if needed */
2730       if ( exec->GS.instruct_control & 2 )
2731         exec->GS = tt_default_graphics_state;
2732 
2733 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY
2734       /* check whether we have a font hinted for ClearType --           */
2735       /* note that this flag can also be modified in a glyph's bytecode */
2736       if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 &&
2737            exec->GS.instruct_control & 4                            )
2738         exec->ignore_x_mode = 0;
2739 #endif
2740 
2741       exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
2742       loader->exec = exec;
2743       loader->instructions = exec->glyphIns;
2744     }
2745 
2746 #endif /* TT_USE_BYTECODE_INTERPRETER */
2747 
2748     /* get face's glyph loader */
2749     if ( !glyf_table_only )
2750     {
2751       FT_GlyphLoader  gloader = glyph->internal->loader;
2752 
2753 
2754       FT_GlyphLoader_Rewind( gloader );
2755       loader->gloader = gloader;
2756     }
2757 
2758     loader->load_flags = (FT_ULong)load_flags;
2759 
2760     loader->face   = face;
2761     loader->size   = size;
2762     loader->glyph  = (FT_GlyphSlot)glyph;
2763     loader->stream = stream;
2764 
2765     loader->composites.head = NULL;
2766     loader->composites.tail = NULL;
2767 
2768     return FT_Err_Ok;
2769   }
2770 
2771 
2772   static void
tt_loader_done(TT_Loader loader)2773   tt_loader_done( TT_Loader  loader )
2774   {
2775     FT_List_Finalize( &loader->composites,
2776                       NULL,
2777                       loader->face->root.memory,
2778                       NULL );
2779   }
2780 
2781 
2782   /**************************************************************************
2783    *
2784    * @Function:
2785    *   TT_Load_Glyph
2786    *
2787    * @Description:
2788    *   A function used to load a single glyph within a given glyph slot,
2789    *   for a given size.
2790    *
2791    * @Input:
2792    *   glyph ::
2793    *     A handle to a target slot object where the glyph
2794    *     will be loaded.
2795    *
2796    *   size ::
2797    *     A handle to the source face size at which the glyph
2798    *     must be scaled/loaded.
2799    *
2800    *   glyph_index ::
2801    *     The index of the glyph in the font file.
2802    *
2803    *   load_flags ::
2804    *     A flag indicating what to load for this glyph.  The
2805    *     FT_LOAD_XXX constants can be used to control the
2806    *     glyph loading process (e.g., whether the outline
2807    *     should be scaled, whether to load bitmaps or not,
2808    *     whether to hint the outline, etc).
2809    *
2810    * @Return:
2811    *   FreeType error code.  0 means success.
2812    */
2813   FT_LOCAL_DEF( FT_Error )
TT_Load_Glyph(TT_Size size,TT_GlyphSlot glyph,FT_UInt glyph_index,FT_Int32 load_flags)2814   TT_Load_Glyph( TT_Size       size,
2815                  TT_GlyphSlot  glyph,
2816                  FT_UInt       glyph_index,
2817                  FT_Int32      load_flags )
2818   {
2819     FT_Error      error;
2820     TT_LoaderRec  loader;
2821 
2822 
2823     FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index ));
2824 
2825 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
2826 
2827     /* try to load embedded bitmap (if any) */
2828     if ( size->strike_index != 0xFFFFFFFFUL      &&
2829          ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
2830          IS_DEFAULT_INSTANCE( glyph->face )      )
2831     {
2832       FT_Fixed  x_scale = size->root.metrics.x_scale;
2833       FT_Fixed  y_scale = size->root.metrics.y_scale;
2834 
2835 
2836       error = load_sbit_image( size, glyph, glyph_index, load_flags );
2837       if ( FT_ERR_EQ( error, Missing_Bitmap ) )
2838       {
2839         /* the bitmap strike is incomplete and misses the requested glyph; */
2840         /* if we have a bitmap-only font, return an empty glyph            */
2841         if ( !FT_IS_SCALABLE( glyph->face ) )
2842         {
2843           TT_Face  face = (TT_Face)glyph->face;
2844 
2845           FT_Short  left_bearing = 0;
2846           FT_Short  top_bearing  = 0;
2847 
2848           FT_UShort  advance_width  = 0;
2849           FT_UShort  advance_height = 0;
2850 
2851 
2852           /* to return an empty glyph, however, we need metrics data   */
2853           /* from the `hmtx' (or `vmtx') table; the assumption is that */
2854           /* empty glyphs are missing intentionally, representing      */
2855           /* whitespace - not having at least horizontal metrics is    */
2856           /* thus considered an error                                  */
2857           if ( !face->horz_metrics_size )
2858             return error;
2859 
2860           /* we now construct an empty bitmap glyph */
2861           TT_Get_HMetrics( face, glyph_index,
2862                            &left_bearing,
2863                            &advance_width );
2864           TT_Get_VMetrics( face, glyph_index,
2865                            0,
2866                            &top_bearing,
2867                            &advance_height );
2868 
2869           glyph->outline.n_points   = 0;
2870           glyph->outline.n_contours = 0;
2871 
2872           glyph->metrics.width  = 0;
2873           glyph->metrics.height = 0;
2874 
2875           glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale );
2876           glyph->metrics.horiBearingY = 0;
2877           glyph->metrics.horiAdvance  = FT_MulFix( advance_width, x_scale );
2878 
2879           glyph->metrics.vertBearingX = 0;
2880           glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale );
2881           glyph->metrics.vertAdvance  = FT_MulFix( advance_height, y_scale );
2882 
2883           glyph->format            = FT_GLYPH_FORMAT_BITMAP;
2884           glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
2885 
2886           glyph->bitmap_left = 0;
2887           glyph->bitmap_top  = 0;
2888 
2889           return FT_Err_Ok;
2890         }
2891       }
2892       else if ( error )
2893       {
2894         /* return error if font is not scalable */
2895         if ( !FT_IS_SCALABLE( glyph->face ) )
2896           return error;
2897       }
2898       else
2899       {
2900         if ( FT_IS_SCALABLE( glyph->face ) )
2901         {
2902           /* for the bbox we need the header only */
2903           (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
2904           (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE );
2905           tt_loader_done( &loader );
2906           glyph->linearHoriAdvance = loader.linear;
2907           glyph->linearVertAdvance = loader.vadvance;
2908 
2909           /* sanity checks: if `xxxAdvance' in the sbit metric */
2910           /* structure isn't set, use `linearXXXAdvance'      */
2911           if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
2912             glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance,
2913                                                     x_scale );
2914           if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance )
2915             glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance,
2916                                                     y_scale );
2917         }
2918 
2919         return FT_Err_Ok;
2920       }
2921     }
2922 
2923 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
2924 
2925     /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
2926     if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
2927     {
2928       error = FT_THROW( Invalid_Size_Handle );
2929       goto Exit;
2930     }
2931 
2932     if ( load_flags & FT_LOAD_SBITS_ONLY )
2933     {
2934       error = FT_THROW( Invalid_Argument );
2935       goto Exit;
2936     }
2937 
2938     error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
2939     if ( error )
2940       goto Exit;
2941 
2942     glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
2943     glyph->num_subglyphs = 0;
2944     glyph->outline.flags = 0;
2945 
2946     /* main loading loop */
2947     error = load_truetype_glyph( &loader, glyph_index, 0, FALSE );
2948     if ( !error )
2949     {
2950       if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
2951       {
2952         glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
2953         glyph->subglyphs     = loader.gloader->base.subglyphs;
2954       }
2955       else
2956       {
2957         glyph->outline        = loader.gloader->base.outline;
2958         glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
2959 
2960         /* Translate array so that (0,0) is the glyph's origin.  Note  */
2961         /* that this behaviour is independent on the value of bit 1 of */
2962         /* the `flags' field in the `head' table -- at least major     */
2963         /* applications like Acroread indicate that.                   */
2964         if ( loader.pp1.x )
2965           FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
2966       }
2967 
2968 #ifdef TT_USE_BYTECODE_INTERPRETER
2969 
2970       if ( IS_HINTED( load_flags ) )
2971       {
2972         if ( loader.exec->GS.scan_control )
2973         {
2974           /* convert scan conversion mode to FT_OUTLINE_XXX flags */
2975           switch ( loader.exec->GS.scan_type )
2976           {
2977           case 0: /* simple drop-outs including stubs */
2978             glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
2979             break;
2980           case 1: /* simple drop-outs excluding stubs */
2981             /* nothing; it's the default rendering mode */
2982             break;
2983           case 4: /* smart drop-outs including stubs */
2984             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
2985                                     FT_OUTLINE_INCLUDE_STUBS;
2986             break;
2987           case 5: /* smart drop-outs excluding stubs  */
2988             glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
2989             break;
2990 
2991           default: /* no drop-out control */
2992             glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2993             break;
2994           }
2995         }
2996         else
2997           glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2998       }
2999 
3000 #endif /* TT_USE_BYTECODE_INTERPRETER */
3001 
3002       error = compute_glyph_metrics( &loader, glyph_index );
3003     }
3004 
3005     /* Set the `high precision' bit flag.                           */
3006     /* This is _critical_ to get correct output for monochrome      */
3007     /* TrueType glyphs at all sizes using the bytecode interpreter. */
3008     /*                                                              */
3009     if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
3010          size->metrics->y_ppem < 24         )
3011       glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
3012 
3013     FT_TRACE1(( "  subglyphs = %u, contours = %hd, points = %hd,"
3014                 " flags = 0x%.3x\n",
3015                 loader.gloader->base.num_subglyphs,
3016                 glyph->outline.n_contours,
3017                 glyph->outline.n_points,
3018                 glyph->outline.flags ));
3019 
3020     tt_loader_done( &loader );
3021 
3022   Exit:
3023 #ifdef FT_DEBUG_LEVEL_TRACE
3024     if ( error )
3025       FT_TRACE1(( "  failed (error code 0x%x)\n",
3026                   error ));
3027 #endif
3028 
3029     return error;
3030   }
3031 
3032 
3033 /* END */
3034