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