source: trunk/poppler/freetype2/src/truetype/ttgload.c @ 262

Last change on this file since 262 was 262, checked in by Eugene Romanenko, 12 years ago

PDF plugin: freetype library updated to version 2.3.8

File size: 66.4 KB
Line 
1/***************************************************************************/
2/*                                                                         */
3/*  ttgload.c                                                              */
4/*                                                                         */
5/*    TrueType Glyph Loader (body).                                        */
6/*                                                                         */
7/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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
27#include "ttgload.h"
28#include "ttpload.h"
29
30#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
31#include "ttgxvar.h"
32#endif
33
34#include "tterrors.h"
35
36
37  /*************************************************************************/
38  /*                                                                       */
39  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
40  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
41  /* messages during execution.                                            */
42  /*                                                                       */
43#undef  FT_COMPONENT
44#define FT_COMPONENT  trace_ttgload
45
46
47  /*************************************************************************/
48  /*                                                                       */
49  /* Composite font flags.                                                 */
50  /*                                                                       */
51#define ARGS_ARE_WORDS             0x0001
52#define ARGS_ARE_XY_VALUES         0x0002
53#define ROUND_XY_TO_GRID           0x0004
54#define WE_HAVE_A_SCALE            0x0008
55/* reserved                        0x0010 */
56#define MORE_COMPONENTS            0x0020
57#define WE_HAVE_AN_XY_SCALE        0x0040
58#define WE_HAVE_A_2X2              0x0080
59#define WE_HAVE_INSTR              0x0100
60#define USE_MY_METRICS             0x0200
61#define OVERLAP_COMPOUND           0x0400
62#define SCALED_COMPONENT_OFFSET    0x0800
63#define UNSCALED_COMPONENT_OFFSET  0x1000
64
65
66  /*************************************************************************/
67  /*                                                                       */
68  /* Returns the horizontal metrics in font units for a given glyph.  If   */
69  /* `check' is true, take care of monospaced fonts by returning the       */
70  /* advance width maximum.                                                */
71  /*                                                                       */
72  FT_LOCAL_DEF(void)
73  TT_Get_HMetrics( TT_Face     face,
74                   FT_UInt     idx,
75                   FT_Bool     check,
76                   FT_Short*   lsb,
77                   FT_UShort*  aw )
78  {
79    ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw );
80
81    if ( check && face->postscript.isFixedPitch )
82      *aw = face->horizontal.advance_Width_Max;
83  }
84
85
86  /*************************************************************************/
87  /*                                                                       */
88  /* Returns the vertical metrics in font units for a given glyph.         */
89  /* Greg Hitchcock from Microsoft told us that if there were no `vmtx'    */
90  /* table, typoAscender/Descender from the `OS/2' table would be used     */
91  /* instead, and if there were no `OS/2' table, use ascender/descender    */
92  /* from the `hhea' table.  But that is not what Microsoft's rasterizer   */
93  /* apparently does: It uses the ppem value as the advance height, and    */
94  /* sets the top side bearing to be zero.                                 */
95  /*                                                                       */
96  /* The monospace `check' is probably not meaningful here, but we leave   */
97  /* it in for a consistent interface.                                     */
98  /*                                                                       */
99  FT_LOCAL_DEF(void)
100  TT_Get_VMetrics( TT_Face     face,
101                   FT_UInt     idx,
102                   FT_Bool     check,
103                   FT_Short*   tsb,
104                   FT_UShort*  ah )
105  {
106    FT_UNUSED( check );
107
108    if ( face->vertical_info )
109      ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah );
110
111#if 1             /* Empirically determined, at variance with what MS said */
112
113    else
114    {
115      *tsb = 0;
116      *ah  = face->root.units_per_EM;
117    }
118
119#else      /* This is what MS said to do.  It isn't what they do, however. */
120
121    else if ( face->os2.version != 0xFFFFU )
122    {
123      *tsb = face->os2.sTypoAscender;
124      *ah  = face->os2.sTypoAscender - face->os2.sTypoDescender;
125    }
126    else
127    {
128      *tsb = face->horizontal.Ascender;
129      *ah  = face->horizontal.Ascender - face->horizontal.Descender;
130    }
131
132#endif
133
134  }
135
136
137  /*************************************************************************/
138  /*                                                                       */
139  /* Translates an array of coordinates.                                   */
140  /*                                                                       */
141  static void
142  translate_array( FT_UInt     n,
143                   FT_Vector*  coords,
144                   FT_Pos      delta_x,
145                   FT_Pos      delta_y )
146  {
147    FT_UInt  k;
148
149
150    if ( delta_x )
151      for ( k = 0; k < n; k++ )
152        coords[k].x += delta_x;
153
154    if ( delta_y )
155      for ( k = 0; k < n; k++ )
156        coords[k].y += delta_y;
157  }
158
159
160#undef  IS_HINTED
161#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
162
163
164  /*************************************************************************/
165  /*                                                                       */
166  /* The following functions are used by default with TrueType fonts.      */
167  /* However, they can be replaced by alternatives if we need to support   */
168  /* TrueType-compressed formats (like MicroType) in the future.           */
169  /*                                                                       */
170  /*************************************************************************/
171
172  FT_CALLBACK_DEF( FT_Error )
173  TT_Access_Glyph_Frame( TT_Loader  loader,
174                         FT_UInt    glyph_index,
175                         FT_ULong   offset,
176                         FT_UInt    byte_count )
177  {
178    FT_Error   error;
179    FT_Stream  stream = loader->stream;
180
181    /* for non-debug mode */
182    FT_UNUSED( glyph_index );
183
184
185    FT_TRACE5(( "Glyph %ld\n", glyph_index ));
186
187    /* the following line sets the `error' variable through macros! */
188    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) )
189      return error;
190
191    loader->cursor = stream->cursor;
192    loader->limit  = stream->limit;
193
194    return TT_Err_Ok;
195  }
196
197
198  FT_CALLBACK_DEF( void )
199  TT_Forget_Glyph_Frame( TT_Loader  loader )
200  {
201    FT_Stream  stream = loader->stream;
202
203
204    FT_FRAME_EXIT();
205  }
206
207
208  FT_CALLBACK_DEF( FT_Error )
209  TT_Load_Glyph_Header( TT_Loader  loader )
210  {
211    FT_Byte*  p     = loader->cursor;
212    FT_Byte*  limit = loader->limit;
213
214
215    if ( p + 10 > limit )
216      return TT_Err_Invalid_Outline;
217
218    loader->n_contours = FT_NEXT_SHORT( p );
219
220    loader->bbox.xMin = FT_NEXT_SHORT( p );
221    loader->bbox.yMin = FT_NEXT_SHORT( p );
222    loader->bbox.xMax = FT_NEXT_SHORT( p );
223    loader->bbox.yMax = FT_NEXT_SHORT( p );
224
225    FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
226    FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
227                                            loader->bbox.xMax ));
228    FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
229                                            loader->bbox.yMax ));
230    loader->cursor = p;
231
232    return TT_Err_Ok;
233  }
234
235
236  FT_CALLBACK_DEF( FT_Error )
237  TT_Load_Simple_Glyph( TT_Loader  load )
238  {
239    FT_Error        error;
240    FT_Byte*        p          = load->cursor;
241    FT_Byte*        limit      = load->limit;
242    FT_GlyphLoader  gloader    = load->gloader;
243    FT_Int          n_contours = load->n_contours;
244    FT_Outline*     outline;
245    TT_Face         face       = (TT_Face)load->face;
246    FT_UShort       n_ins;
247    FT_Int          n_points;
248
249    FT_Byte         *flag, *flag_limit;
250    FT_Byte         c, count;
251    FT_Vector       *vec, *vec_limit;
252    FT_Pos          x;
253    FT_Short        *cont, *cont_limit, prev_cont;
254    FT_Int          xy_size = 0;
255
256
257    /* check that we can add the contours to the glyph */
258    error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours );
259    if ( error )
260      goto Fail;
261
262    /* reading the contours' endpoints & number of points */
263    cont       = gloader->current.outline.contours;
264    cont_limit = cont + n_contours;
265
266    /* check space for contours array + instructions count */
267    if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit )
268      goto Invalid_Outline;
269
270    prev_cont = FT_NEXT_USHORT( p );
271
272    if ( n_contours > 0 )
273      cont[0] = prev_cont;
274
275    for ( cont++; cont < cont_limit; cont++ )
276    {
277      cont[0] = FT_NEXT_USHORT( p );
278      if ( cont[0] <= prev_cont )
279      {
280        /* unordered contours: this is invalid */
281        error = FT_Err_Invalid_Table;
282        goto Fail;
283      }
284      prev_cont = cont[0];
285    }
286
287    n_points = 0;
288    if ( n_contours > 0 )
289    {
290      n_points = cont[-1] + 1;
291      if ( n_points < 0 )
292        goto Invalid_Outline;
293    }
294
295    /* note that we will add four phantom points later */
296    error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 );
297    if ( error )
298      goto Fail;
299
300    /* we'd better check the contours table right now */
301    outline = &gloader->current.outline;
302
303    for ( cont = outline->contours + 1; cont < cont_limit; cont++ )
304      if ( cont[-1] >= cont[0] )
305        goto Invalid_Outline;
306
307    /* reading the bytecode instructions */
308    load->glyph->control_len  = 0;
309    load->glyph->control_data = 0;
310
311    if ( p + 2 > limit )
312      goto Invalid_Outline;
313
314    n_ins = FT_NEXT_USHORT( p );
315
316    FT_TRACE5(( "  Instructions size: %u\n", n_ins ));
317
318    if ( n_ins > face->max_profile.maxSizeOfInstructions )
319    {
320      FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions (%d)\n",
321                  n_ins ));
322      error = TT_Err_Too_Many_Hints;
323      goto Fail;
324    }
325
326    if ( ( limit - p ) < n_ins )
327    {
328      FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" ));
329      error = TT_Err_Too_Many_Hints;
330      goto Fail;
331    }
332
333#ifdef TT_USE_BYTECODE_INTERPRETER
334
335    if ( IS_HINTED( load->load_flags ) )
336    {
337      load->glyph->control_len  = n_ins;
338      load->glyph->control_data = load->exec->glyphIns;
339
340      FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins );
341    }
342
343#endif /* TT_USE_BYTECODE_INTERPRETER */
344
345    p += n_ins;
346
347    /* reading the point tags */
348    flag       = (FT_Byte*)outline->tags;
349    flag_limit = flag + n_points;
350
351    FT_ASSERT( flag != NULL );
352
353    while ( flag < flag_limit )
354    {
355      if ( p + 1 > limit )
356        goto Invalid_Outline;
357
358      *flag++ = c = FT_NEXT_BYTE( p );
359      if ( c & 8 )
360      {
361        if ( p + 1 > limit )
362          goto Invalid_Outline;
363
364        count = FT_NEXT_BYTE( p );
365        if ( flag + (FT_Int)count > flag_limit )
366          goto Invalid_Outline;
367
368        for ( ; count > 0; count-- )
369          *flag++ = c;
370      }
371    }
372
373    /* reading the X coordinates */
374
375    vec       = outline->points;
376    vec_limit = vec + n_points;
377    flag      = (FT_Byte*)outline->tags;
378    x         = 0;
379
380    if ( p + xy_size > limit )
381      goto Invalid_Outline;
382
383    for ( ; vec < vec_limit; vec++, flag++ )
384    {
385      FT_Pos   y = 0;
386      FT_Byte  f = *flag;
387
388
389      if ( f & 2 )
390      {
391        if ( p + 1 > limit )
392          goto Invalid_Outline;
393
394        y = (FT_Pos)FT_NEXT_BYTE( p );
395        if ( ( f & 16 ) == 0 )
396          y = -y;
397      }
398      else if ( ( f & 16 ) == 0 )
399      {
400        if ( p + 2 > limit )
401          goto Invalid_Outline;
402
403        y = (FT_Pos)FT_NEXT_SHORT( p );
404      }
405
406      x     += y;
407      vec->x = x;
408      /* the cast is for stupid compilers */
409      *flag  = (FT_Byte)( f & ~( 2 | 16 ) );
410    }
411
412    /* reading the Y coordinates */
413
414    vec       = gloader->current.outline.points;
415    vec_limit = vec + n_points;
416    flag      = (FT_Byte*)outline->tags;
417    x         = 0;
418
419    for ( ; vec < vec_limit; vec++, flag++ )
420    {
421      FT_Pos   y = 0;
422      FT_Byte  f = *flag;
423
424
425      if ( f & 4 )
426      {
427        if ( p + 1 > limit )
428          goto Invalid_Outline;
429
430        y = (FT_Pos)FT_NEXT_BYTE( p );
431        if ( ( f & 32 ) == 0 )
432          y = -y;
433      }
434      else if ( ( f & 32 ) == 0 )
435      {
436        if ( p + 2 > limit )
437          goto Invalid_Outline;
438
439        y = (FT_Pos)FT_NEXT_SHORT( p );
440      }
441
442      x     += y;
443      vec->y = x;
444      /* the cast is for stupid compilers */
445      *flag  = (FT_Byte)( f & FT_CURVE_TAG_ON );
446    }
447
448    outline->n_points   = (FT_UShort)n_points;
449    outline->n_contours = (FT_Short) n_contours;
450
451    load->cursor = p;
452
453  Fail:
454    return error;
455
456  Invalid_Outline:
457    error = TT_Err_Invalid_Outline;
458    goto Fail;
459  }
460
461
462  FT_CALLBACK_DEF( FT_Error )
463  TT_Load_Composite_Glyph( TT_Loader  loader )
464  {
465    FT_Error        error;
466    FT_Byte*        p       = loader->cursor;
467    FT_Byte*        limit   = loader->limit;
468    FT_GlyphLoader  gloader = loader->gloader;
469    FT_SubGlyph     subglyph;
470    FT_UInt         num_subglyphs;
471
472
473    num_subglyphs = 0;
474
475    do
476    {
477      FT_Fixed  xx, xy, yy, yx;
478      FT_UInt   count;
479
480
481      /* check that we can load a new subglyph */
482      error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 );
483      if ( error )
484        goto Fail;
485
486      /* check space */
487      if ( p + 4 > limit )
488        goto Invalid_Composite;
489
490      subglyph = gloader->current.subglyphs + num_subglyphs;
491
492      subglyph->arg1 = subglyph->arg2 = 0;
493
494      subglyph->flags = FT_NEXT_USHORT( p );
495      subglyph->index = FT_NEXT_USHORT( p );
496
497      /* check space */
498      count = 2;
499      if ( subglyph->flags & ARGS_ARE_WORDS )
500        count += 2;
501      if ( subglyph->flags & WE_HAVE_A_SCALE )
502        count += 2;
503      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
504        count += 4;
505      else if ( subglyph->flags & WE_HAVE_A_2X2 )
506        count += 8;
507
508      if ( p + count > limit )
509        goto Invalid_Composite;
510
511      /* read arguments */
512      if ( subglyph->flags & ARGS_ARE_WORDS )
513      {
514        subglyph->arg1 = FT_NEXT_SHORT( p );
515        subglyph->arg2 = FT_NEXT_SHORT( p );
516      }
517      else
518      {
519        subglyph->arg1 = FT_NEXT_CHAR( p );
520        subglyph->arg2 = FT_NEXT_CHAR( p );
521      }
522
523      /* read transform */
524      xx = yy = 0x10000L;
525      xy = yx = 0;
526
527      if ( subglyph->flags & WE_HAVE_A_SCALE )
528      {
529        xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
530        yy = xx;
531      }
532      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
533      {
534        xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
535        yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
536      }
537      else if ( subglyph->flags & WE_HAVE_A_2X2 )
538      {
539        xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
540        yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
541        xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
542        yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2;
543      }
544
545      subglyph->transform.xx = xx;
546      subglyph->transform.xy = xy;
547      subglyph->transform.yx = yx;
548      subglyph->transform.yy = yy;
549
550      num_subglyphs++;
551
552    } while ( subglyph->flags & MORE_COMPONENTS );
553
554    gloader->current.num_subglyphs = num_subglyphs;
555
556#ifdef TT_USE_BYTECODE_INTERPRETER
557
558    {
559      FT_Stream  stream = loader->stream;
560
561
562      /* we must undo the FT_FRAME_ENTER in order to point */
563      /* to the composite instructions, if we find some.   */
564      /* We will process them later.                       */
565      /*                                                   */
566      loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
567                                    p - limit );
568    }
569
570#endif
571
572    loader->cursor = p;
573
574  Fail:
575    return error;
576
577  Invalid_Composite:
578    error = TT_Err_Invalid_Composite;
579    goto Fail;
580  }
581
582
583  FT_LOCAL_DEF( void )
584  TT_Init_Glyph_Loading( TT_Face  face )
585  {
586    face->access_glyph_frame   = TT_Access_Glyph_Frame;
587    face->read_glyph_header    = TT_Load_Glyph_Header;
588    face->read_simple_glyph    = TT_Load_Simple_Glyph;
589    face->read_composite_glyph = TT_Load_Composite_Glyph;
590    face->forget_glyph_frame   = TT_Forget_Glyph_Frame;
591  }
592
593
594  static void
595  tt_prepare_zone( TT_GlyphZone  zone,
596                   FT_GlyphLoad  load,
597                   FT_UInt       start_point,
598                   FT_UInt       start_contour )
599  {
600    zone->n_points    = (FT_UShort)( load->outline.n_points - start_point );
601    zone->n_contours  = (FT_Short) ( load->outline.n_contours -
602                                       start_contour );
603    zone->org         = load->extra_points + start_point;
604    zone->cur         = load->outline.points + start_point;
605    zone->orus        = load->extra_points2 + start_point;
606    zone->tags        = (FT_Byte*)load->outline.tags + start_point;
607    zone->contours    = (FT_UShort*)load->outline.contours + start_contour;
608    zone->first_point = (FT_UShort)start_point;
609  }
610
611
612  /*************************************************************************/
613  /*                                                                       */
614  /* <Function>                                                            */
615  /*    TT_Hint_Glyph                                                      */
616  /*                                                                       */
617  /* <Description>                                                         */
618  /*    Hint the glyph using the zone prepared by the caller.  Note that   */
619  /*    the zone is supposed to include four phantom points.               */
620  /*                                                                       */
621  static FT_Error
622  TT_Hint_Glyph( TT_Loader  loader,
623                 FT_Bool    is_composite )
624  {
625    TT_GlyphZone  zone = &loader->zone;
626    FT_Pos        origin;
627
628#ifdef TT_USE_BYTECODE_INTERPRETER
629    FT_UInt       n_ins;
630#else
631    FT_UNUSED( is_composite );
632#endif
633
634
635#ifdef TT_USE_BYTECODE_INTERPRETER
636    n_ins = loader->glyph->control_len;
637#endif
638
639    origin = zone->cur[zone->n_points - 4].x;
640    origin = FT_PIX_ROUND( origin ) - origin;
641    if ( origin )
642      translate_array( zone->n_points, zone->cur, origin, 0 );
643
644#ifdef TT_USE_BYTECODE_INTERPRETER
645    /* save original point position in org */
646    if ( n_ins > 0 )
647      FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points );
648
649    /* Reset graphics state. */
650    loader->exec->GS = ((TT_Size)loader->size)->GS;
651
652    /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */
653    /*      completely refer to the (already) hinted subglyphs.     */
654    if ( is_composite )
655    {
656      loader->exec->metrics.x_scale = 1 << 16;
657      loader->exec->metrics.y_scale = 1 << 16;
658
659      FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points );
660    }
661    else
662    {
663      loader->exec->metrics.x_scale =
664        ((TT_Size)loader->size)->metrics.x_scale;
665      loader->exec->metrics.y_scale =
666        ((TT_Size)loader->size)->metrics.y_scale;
667    }
668#endif
669
670    /* round pp2 and pp4 */
671    zone->cur[zone->n_points - 3].x =
672      FT_PIX_ROUND( zone->cur[zone->n_points - 3].x );
673    zone->cur[zone->n_points - 1].y =
674      FT_PIX_ROUND( zone->cur[zone->n_points - 1].y );
675
676#ifdef TT_USE_BYTECODE_INTERPRETER
677
678    if ( n_ins > 0 )
679    {
680      FT_Bool   debug;
681      FT_Error  error;
682
683
684      error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph,
685                                loader->exec->glyphIns, n_ins );
686      if ( error )
687        return error;
688
689      loader->exec->is_composite = is_composite;
690      loader->exec->pts          = *zone;
691
692      debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) &&
693                       ((TT_Size)loader->size)->debug             );
694
695      error = TT_Run_Context( loader->exec, debug );
696      if ( error && loader->exec->pedantic_hinting )
697        return error;
698    }
699
700#endif
701
702    /* save glyph phantom points */
703    if ( !loader->preserve_pps )
704    {
705      loader->pp1 = zone->cur[zone->n_points - 4];
706      loader->pp2 = zone->cur[zone->n_points - 3];
707      loader->pp3 = zone->cur[zone->n_points - 2];
708      loader->pp4 = zone->cur[zone->n_points - 1];
709    }
710
711    return TT_Err_Ok;
712  }
713
714
715  /*************************************************************************/
716  /*                                                                       */
717  /* <Function>                                                            */
718  /*    TT_Process_Simple_Glyph                                            */
719  /*                                                                       */
720  /* <Description>                                                         */
721  /*    Once a simple glyph has been loaded, it needs to be processed.     */
722  /*    Usually, this means scaling and hinting through bytecode           */
723  /*    interpretation.                                                    */
724  /*                                                                       */
725  static FT_Error
726  TT_Process_Simple_Glyph( TT_Loader  loader )
727  {
728    FT_GlyphLoader  gloader = loader->gloader;
729    FT_Error        error   = TT_Err_Ok;
730    FT_Outline*     outline;
731    FT_Int          n_points;
732
733
734    outline  = &gloader->current.outline;
735    n_points = outline->n_points;
736
737    /* set phantom points */
738
739    outline->points[n_points    ] = loader->pp1;
740    outline->points[n_points + 1] = loader->pp2;
741    outline->points[n_points + 2] = loader->pp3;
742    outline->points[n_points + 3] = loader->pp4;
743
744    outline->tags[n_points    ] = 0;
745    outline->tags[n_points + 1] = 0;
746    outline->tags[n_points + 2] = 0;
747    outline->tags[n_points + 3] = 0;
748
749    n_points += 4;
750
751#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
752
753    if ( ((TT_Face)loader->face)->doblend )
754    {
755      /* Deltas apply to the unscaled data. */
756      FT_Vector*  deltas;
757      FT_Memory   memory = loader->face->memory;
758      FT_Int      i;
759
760
761      error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
762                                        loader->glyph_index,
763                                        &deltas,
764                                        n_points );
765      if ( error )
766        return error;
767
768      for ( i = 0; i < n_points; ++i )
769      {
770        outline->points[i].x += deltas[i].x;
771        outline->points[i].y += deltas[i].y;
772      }
773
774      FT_FREE( deltas );
775    }
776
777#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
778
779    if ( IS_HINTED( loader->load_flags ) )
780    {
781      tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 );
782
783      FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur,
784                     loader->zone.n_points + 4 );
785    }
786
787    /* scale the glyph */
788    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
789    {
790      FT_Vector*  vec     = outline->points;
791      FT_Vector*  limit   = outline->points + n_points;
792      FT_Fixed    x_scale = ((TT_Size)loader->size)->metrics.x_scale;
793      FT_Fixed    y_scale = ((TT_Size)loader->size)->metrics.y_scale;
794
795
796      for ( ; vec < limit; vec++ )
797      {
798        vec->x = FT_MulFix( vec->x, x_scale );
799        vec->y = FT_MulFix( vec->y, y_scale );
800      }
801
802      loader->pp1 = outline->points[n_points - 4];
803      loader->pp2 = outline->points[n_points - 3];
804      loader->pp3 = outline->points[n_points - 2];
805      loader->pp4 = outline->points[n_points - 1];
806    }
807
808    if ( IS_HINTED( loader->load_flags ) )
809    {
810      loader->zone.n_points += 4;
811
812      error = TT_Hint_Glyph( loader, 0 );
813    }
814
815    return error;
816  }
817
818
819  /*************************************************************************/
820  /*                                                                       */
821  /* <Function>                                                            */
822  /*    TT_Process_Composite_Component                                     */
823  /*                                                                       */
824  /* <Description>                                                         */
825  /*    Once a composite component has been loaded, it needs to be         */
826  /*    processed.  Usually, this means transforming and translating.      */
827  /*                                                                       */
828  static FT_Error
829  TT_Process_Composite_Component( TT_Loader    loader,
830                                  FT_SubGlyph  subglyph,
831                                  FT_UInt      start_point,
832                                  FT_UInt      num_base_points )
833  {
834    FT_GlyphLoader  gloader    = loader->gloader;
835    FT_Vector*      base_vec   = gloader->base.outline.points;
836    FT_UInt         num_points = gloader->base.outline.n_points;
837    FT_Bool         have_scale;
838    FT_Pos          x, y;
839
840
841    have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE     |
842                                              WE_HAVE_AN_XY_SCALE |
843                                              WE_HAVE_A_2X2       ) );
844
845    /* perform the transform required for this subglyph */
846    if ( have_scale )
847    {
848      FT_UInt  i;
849
850
851      for ( i = num_base_points; i < num_points; i++ )
852        FT_Vector_Transform( base_vec + i, &subglyph->transform );
853    }
854
855    /* get offset */
856    if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
857    {
858      FT_UInt     k = subglyph->arg1;
859      FT_UInt     l = subglyph->arg2;
860      FT_Vector*  p1;
861      FT_Vector*  p2;
862
863
864      /* match l-th point of the newly loaded component to the k-th point */
865      /* of the previously loaded components.                             */
866
867      /* change to the point numbers used by our outline */
868      k += start_point;
869      l += num_base_points;
870      if ( k >= num_base_points ||
871           l >= num_points      )
872        return TT_Err_Invalid_Composite;
873
874      p1 = gloader->base.outline.points + k;
875      p2 = gloader->base.outline.points + l;
876
877      x = p1->x - p2->x;
878      y = p1->y - p2->y;
879    }
880    else
881    {
882      x = subglyph->arg1;
883      y = subglyph->arg2;
884
885      if ( !x && !y )
886        return TT_Err_Ok;
887
888  /* Use a default value dependent on                                     */
889  /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
890  /* fonts which don't set the xxx_COMPONENT_OFFSET bit.                  */
891
892      if ( have_scale &&
893#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED
894           !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) )
895#else
896            ( subglyph->flags & SCALED_COMPONENT_OFFSET ) )
897#endif
898      {
899
900#if 0
901
902  /*************************************************************************/
903  /*                                                                       */
904  /* This algorithm is what Apple documents.  But it doesn't work.         */
905  /*                                                                       */
906        int  a = subglyph->transform.xx > 0 ?  subglyph->transform.xx
907                                            : -subglyph->transform.xx;
908        int  b = subglyph->transform.yx > 0 ?  subglyph->transform.yx
909                                            : -subglyph->transform.yx;
910        int  c = subglyph->transform.xy > 0 ?  subglyph->transform.xy
911                                            : -subglyph->transform.xy;
912        int  d = subglyph->transform.yy > 0 ? subglyph->transform.yy
913                                            : -subglyph->transform.yy;
914        int  m = a > b ? a : b;
915        int  n = c > d ? c : d;
916
917
918        if ( a - b <= 33 && a - b >= -33 )
919          m *= 2;
920        if ( c - d <= 33 && c - d >= -33 )
921          n *= 2;
922        x = FT_MulFix( x, m );
923        y = FT_MulFix( y, n );
924
925#else /* 0 */
926
927  /*************************************************************************/
928  /*                                                                       */
929  /* This algorithm is a guess and works much better than the above.       */
930  /*                                                                       */
931        FT_Fixed  mac_xscale = FT_SqrtFixed(
932                                 FT_MulFix( subglyph->transform.xx,
933                                            subglyph->transform.xx ) +
934                                 FT_MulFix( subglyph->transform.xy,
935                                            subglyph->transform.xy ) );
936        FT_Fixed  mac_yscale = FT_SqrtFixed(
937                                 FT_MulFix( subglyph->transform.yy,
938                                            subglyph->transform.yy ) +
939                                 FT_MulFix( subglyph->transform.yx,
940                                            subglyph->transform.yx ) );
941
942
943        x = FT_MulFix( x, mac_xscale );
944        y = FT_MulFix( y, mac_yscale );
945
946#endif /* 0 */
947
948      }
949
950      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
951      {
952        FT_Fixed  x_scale = ((TT_Size)loader->size)->metrics.x_scale;
953        FT_Fixed  y_scale = ((TT_Size)loader->size)->metrics.y_scale;
954
955
956        x = FT_MulFix( x, x_scale );
957        y = FT_MulFix( y, y_scale );
958
959        if ( subglyph->flags & ROUND_XY_TO_GRID )
960        {
961          x = FT_PIX_ROUND( x );
962          y = FT_PIX_ROUND( y );
963        }
964      }
965    }
966
967    if ( x || y )
968      translate_array( num_points - num_base_points,
969                       base_vec + num_base_points,
970                       x, y );
971
972    return TT_Err_Ok;
973  }
974
975
976  /*************************************************************************/
977  /*                                                                       */
978  /* <Function>                                                            */
979  /*    TT_Process_Composite_Glyph                                         */
980  /*                                                                       */
981  /* <Description>                                                         */
982  /*    This is slightly different from TT_Process_Simple_Glyph, in that   */
983  /*    its sole purpose is to hint the glyph.  Thus this function is      */
984  /*    only available when bytecode interpreter is enabled.               */
985  /*                                                                       */
986  static FT_Error
987  TT_Process_Composite_Glyph( TT_Loader  loader,
988                              FT_UInt    start_point,
989                              FT_UInt    start_contour )
990  {
991    FT_Error     error;
992    FT_Outline*  outline;
993    FT_UInt      i;
994
995
996    outline = &loader->gloader->base.outline;
997
998    /* make room for phantom points */
999    error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader,
1000                                         outline->n_points + 4,
1001                                         0 );
1002    if ( error )
1003      return error;
1004
1005    outline->points[outline->n_points    ] = loader->pp1;
1006    outline->points[outline->n_points + 1] = loader->pp2;
1007    outline->points[outline->n_points + 2] = loader->pp3;
1008    outline->points[outline->n_points + 3] = loader->pp4;
1009
1010    outline->tags[outline->n_points    ] = 0;
1011    outline->tags[outline->n_points + 1] = 0;
1012    outline->tags[outline->n_points + 2] = 0;
1013    outline->tags[outline->n_points + 3] = 0;
1014
1015#ifdef TT_USE_BYTECODE_INTERPRETER
1016
1017    {
1018      FT_Stream  stream = loader->stream;
1019      FT_UShort  n_ins;
1020
1021
1022      /* TT_Load_Composite_Glyph only gives us the offset of instructions */
1023      /* so we read them here                                             */
1024      if ( FT_STREAM_SEEK( loader->ins_pos ) ||
1025           FT_READ_USHORT( n_ins )           )
1026        return error;
1027
1028      FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
1029
1030      /* check it */
1031      if ( n_ins > ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions )
1032      {
1033        FT_TRACE0(( "TT_Process_Composite_Glyph: Too many instructions (%d)\n",
1034                    n_ins ));
1035
1036        return TT_Err_Too_Many_Hints;
1037      }
1038      else if ( n_ins == 0 )
1039        return TT_Err_Ok;
1040
1041      if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
1042        return error;
1043
1044      loader->glyph->control_data = loader->exec->glyphIns;
1045      loader->glyph->control_len  = n_ins;
1046    }
1047
1048#endif
1049
1050    tt_prepare_zone( &loader->zone, &loader->gloader->base,
1051                     start_point, start_contour );
1052
1053    /* Some points are likely touched during execution of  */
1054    /* instructions on components.  So let's untouch them. */
1055    for ( i = start_point; i < loader->zone.n_points; i++ )
1056      loader->zone.tags[i] &= ~( FT_CURVE_TAG_TOUCH_X |
1057                                 FT_CURVE_TAG_TOUCH_Y );
1058
1059    loader->zone.n_points += 4;
1060
1061    return TT_Hint_Glyph( loader, 1 );
1062  }
1063
1064
1065  /* Calculate the four phantom points.                     */
1066  /* The first two stand for horizontal origin and advance. */
1067  /* The last two stand for vertical origin and advance.    */
1068#define TT_LOADER_SET_PP( loader )                                          \
1069          do {                                                              \
1070            (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \
1071            (loader)->pp1.y = 0;                                            \
1072            (loader)->pp2.x = (loader)->pp1.x + (loader)->advance;          \
1073            (loader)->pp2.y = 0;                                            \
1074            (loader)->pp3.x = 0;                                            \
1075            (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax;  \
1076            (loader)->pp4.x = 0;                                            \
1077            (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance;         \
1078          } while ( 0 )
1079
1080
1081  /*************************************************************************/
1082  /*                                                                       */
1083  /* <Function>                                                            */
1084  /*    load_truetype_glyph                                                */
1085  /*                                                                       */
1086  /* <Description>                                                         */
1087  /*    Loads a given truetype glyph.  Handles composites and uses a       */
1088  /*    TT_Loader object.                                                  */
1089  /*                                                                       */
1090  static FT_Error
1091  load_truetype_glyph( TT_Loader  loader,
1092                       FT_UInt    glyph_index,
1093                       FT_UInt    recurse_count )
1094  {
1095    FT_Error        error;
1096    FT_Fixed        x_scale, y_scale;
1097    FT_ULong        offset;
1098    TT_Face         face         = (TT_Face)loader->face;
1099    FT_GlyphLoader  gloader      = loader->gloader;
1100    FT_Bool         opened_frame = 0;
1101
1102#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1103    FT_Vector*      deltas       = NULL;
1104#endif
1105
1106#ifdef FT_CONFIG_OPTION_INCREMENTAL
1107    FT_StreamRec    inc_stream;
1108    FT_Data         glyph_data;
1109    FT_Bool         glyph_data_loaded = 0;
1110#endif
1111
1112
1113    /* some fonts have an incorrect value of `maxComponentDepth', */
1114    /* thus we allow depth 1 to catch the majority of them        */
1115    if ( recurse_count > 1                                   &&
1116         recurse_count > face->max_profile.maxComponentDepth )
1117    {
1118      error = TT_Err_Invalid_Composite;
1119      goto Exit;
1120    }
1121
1122    /* check glyph index */
1123    if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
1124    {
1125      error = TT_Err_Invalid_Glyph_Index;
1126      goto Exit;
1127    }
1128
1129    loader->glyph_index = glyph_index;
1130
1131    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1132    {
1133      x_scale = ((TT_Size)loader->size)->metrics.x_scale;
1134      y_scale = ((TT_Size)loader->size)->metrics.y_scale;
1135    }
1136    else
1137    {
1138      x_scale = 0x10000L;
1139      y_scale = 0x10000L;
1140    }
1141
1142    /* get metrics, horizontal and vertical */
1143    {
1144      FT_Short   left_bearing = 0, top_bearing = 0;
1145      FT_UShort  advance_width = 0, advance_height = 0;
1146
1147
1148      TT_Get_HMetrics( face, glyph_index,
1149                       (FT_Bool)!( loader->load_flags &
1150                                   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1151                       &left_bearing,
1152                       &advance_width );
1153      TT_Get_VMetrics( face, glyph_index,
1154                       (FT_Bool)!( loader->load_flags &
1155                                   FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ),
1156                       &top_bearing,
1157                       &advance_height );
1158
1159#ifdef FT_CONFIG_OPTION_INCREMENTAL
1160
1161      /* If this is an incrementally loaded font see if there are */
1162      /* overriding metrics for this glyph.                       */
1163      if ( face->root.internal->incremental_interface &&
1164           face->root.internal->incremental_interface->funcs->get_glyph_metrics )
1165      {
1166        FT_Incremental_MetricsRec  metrics;
1167
1168
1169        metrics.bearing_x = left_bearing;
1170        metrics.bearing_y = 0;
1171        metrics.advance = advance_width;
1172        error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1173                  face->root.internal->incremental_interface->object,
1174                  glyph_index, FALSE, &metrics );
1175        if ( error )
1176          goto Exit;
1177        left_bearing  = (FT_Short)metrics.bearing_x;
1178        advance_width = (FT_UShort)metrics.advance;
1179
1180#if 0
1181
1182        /* GWW: Do I do the same for vertical metrics? */
1183        metrics.bearing_x = 0;
1184        metrics.bearing_y = top_bearing;
1185        metrics.advance = advance_height;
1186        error = face->root.internal->incremental_interface->funcs->get_glyph_metrics(
1187                  face->root.internal->incremental_interface->object,
1188                  glyph_index, TRUE, &metrics );
1189        if ( error )
1190          goto Exit;
1191        top_bearing  = (FT_Short)metrics.bearing_y;
1192        advance_height = (FT_UShort)metrics.advance;
1193
1194#endif /* 0 */
1195
1196      }
1197
1198#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1199
1200      loader->left_bearing = left_bearing;
1201      loader->advance      = advance_width;
1202      loader->top_bearing  = top_bearing;
1203      loader->vadvance     = advance_height;
1204
1205      if ( !loader->linear_def )
1206      {
1207        loader->linear_def = 1;
1208        loader->linear     = advance_width;
1209      }
1210    }
1211
1212    /* Set `offset' to the start of the glyph relative to the start of */
1213    /* the `glyf' table, and `byte_len' to the length of the glyph in  */
1214    /* bytes.                                                          */
1215
1216#ifdef FT_CONFIG_OPTION_INCREMENTAL
1217
1218    /* If we are loading glyph data via the incremental interface, set */
1219    /* the loader stream to a memory stream reading the data returned  */
1220    /* by the interface.                                               */
1221    if ( face->root.internal->incremental_interface )
1222    {
1223      error = face->root.internal->incremental_interface->funcs->get_glyph_data(
1224                face->root.internal->incremental_interface->object,
1225                glyph_index, &glyph_data );
1226      if ( error )
1227        goto Exit;
1228
1229      glyph_data_loaded = 1;
1230      offset            = 0;
1231      loader->byte_len  = glyph_data.length;
1232
1233      FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) );
1234      FT_Stream_OpenMemory( &inc_stream,
1235                            glyph_data.pointer, glyph_data.length );
1236
1237      loader->stream = &inc_stream;
1238    }
1239    else
1240
1241#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1242
1243      offset = tt_face_get_location( face, glyph_index,
1244                                     (FT_UInt*)&loader->byte_len );
1245
1246    if ( loader->byte_len > 0 )
1247    {
1248      if ( !loader->glyf_offset )
1249      {
1250        FT_TRACE2(( "no `glyf' table but non-zero `loca' entry!\n" ));
1251        error = TT_Err_Invalid_Table;
1252        goto Exit;
1253      }
1254
1255      error = face->access_glyph_frame( loader, glyph_index,
1256                                        loader->glyf_offset + offset,
1257                                        loader->byte_len );
1258      if ( error )
1259        goto Exit;
1260
1261      opened_frame = 1;
1262
1263      /* read first glyph header */
1264      error = face->read_glyph_header( loader );
1265      if ( error )
1266        goto Exit;
1267    }
1268
1269    if ( loader->byte_len == 0 || loader->n_contours == 0 )
1270    {
1271      loader->bbox.xMin = 0;
1272      loader->bbox.xMax = 0;
1273      loader->bbox.yMin = 0;
1274      loader->bbox.yMax = 0;
1275
1276      TT_LOADER_SET_PP( loader );
1277
1278#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1279
1280      if ( ((TT_Face)(loader->face))->doblend )
1281      {
1282        /* this must be done before scaling */
1283        FT_Memory  memory = loader->face->memory;
1284
1285
1286        error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face),
1287                                          glyph_index, &deltas, 4 );
1288        if ( error )
1289          goto Exit;
1290
1291        loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y;
1292        loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y;
1293        loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y;
1294        loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y;
1295
1296        FT_FREE( deltas );
1297      }
1298
1299#endif
1300
1301      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1302      {
1303        loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1304        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1305        loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1306        loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1307      }
1308
1309      error = TT_Err_Ok;
1310      goto Exit;
1311    }
1312
1313    TT_LOADER_SET_PP( loader );
1314
1315    /***********************************************************************/
1316    /***********************************************************************/
1317    /***********************************************************************/
1318
1319    /* if it is a simple glyph, load it */
1320
1321    if ( loader->n_contours > 0 )
1322    {
1323      error = face->read_simple_glyph( loader );
1324      if ( error )
1325        goto Exit;
1326
1327      /* all data have been read */
1328      face->forget_glyph_frame( loader );
1329      opened_frame = 0;
1330
1331      error = TT_Process_Simple_Glyph( loader );
1332      if ( error )
1333        goto Exit;
1334
1335      FT_GlyphLoader_Add( gloader );
1336    }
1337
1338    /***********************************************************************/
1339    /***********************************************************************/
1340    /***********************************************************************/
1341
1342    /* otherwise, load a composite! */
1343    else if ( loader->n_contours == -1 )
1344    {
1345      FT_UInt   start_point;
1346      FT_UInt   start_contour;
1347      FT_ULong  ins_pos;  /* position of composite instructions, if any */
1348
1349
1350      start_point   = gloader->base.outline.n_points;
1351      start_contour = gloader->base.outline.n_contours;
1352
1353      /* for each subglyph, read composite header */
1354      error = face->read_composite_glyph( loader );
1355      if ( error )
1356        goto Exit;
1357
1358      /* store the offset of instructions */
1359      ins_pos = loader->ins_pos;
1360
1361      /* all data we need are read */
1362      face->forget_glyph_frame( loader );
1363      opened_frame = 0;
1364
1365#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1366
1367      if ( face->doblend )
1368      {
1369        FT_Int       i, limit;
1370        FT_SubGlyph  subglyph;
1371        FT_Memory    memory = face->root.memory;
1372
1373
1374        /* this provides additional offsets */
1375        /* for each component's translation */
1376
1377        if ( ( error = TT_Vary_Get_Glyph_Deltas(
1378                         face,
1379                         glyph_index,
1380                         &deltas,
1381                         gloader->current.num_subglyphs + 4 )) != 0 )
1382          goto Exit;
1383
1384        subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs;
1385        limit    = gloader->current.num_subglyphs;
1386
1387        for ( i = 0; i < limit; ++i, ++subglyph )
1388        {
1389          if ( subglyph->flags & ARGS_ARE_XY_VALUES )
1390          {
1391            subglyph->arg1 += deltas[i].x;
1392            subglyph->arg2 += deltas[i].y;
1393          }
1394        }
1395
1396        loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y;
1397        loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y;
1398        loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y;
1399        loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y;
1400
1401        FT_FREE( deltas );
1402      }
1403
1404#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1405
1406      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1407      {
1408        loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
1409        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
1410        loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale );
1411        loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
1412      }
1413
1414      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
1415      /* `as is' in the glyph slot (the client application will be     */
1416      /* responsible for interpreting these data)...                   */
1417      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
1418      {
1419        FT_GlyphLoader_Add( gloader );
1420        loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE;
1421
1422        goto Exit;
1423      }
1424
1425      /*********************************************************************/
1426      /*********************************************************************/
1427      /*********************************************************************/
1428
1429      {
1430        FT_UInt      n, num_base_points;
1431        FT_SubGlyph  subglyph       = 0;
1432
1433        FT_UInt      num_points     = start_point;
1434        FT_UInt      num_subglyphs  = gloader->current.num_subglyphs;
1435        FT_UInt      num_base_subgs = gloader->base.num_subglyphs;
1436
1437        FT_Stream    old_stream     = loader->stream;
1438
1439
1440        FT_GlyphLoader_Add( gloader );
1441
1442        /* read each subglyph independently */
1443        for ( n = 0; n < num_subglyphs; n++ )
1444        {
1445          FT_Vector  pp[4];
1446
1447
1448          /* Each time we call load_truetype_glyph in this loop, the   */
1449          /* value of `gloader.base.subglyphs' can change due to table */
1450          /* reallocations.  We thus need to recompute the subglyph    */
1451          /* pointer on each iteration.                                */
1452          subglyph = gloader->base.subglyphs + num_base_subgs + n;
1453
1454          pp[0] = loader->pp1;
1455          pp[1] = loader->pp2;
1456          pp[2] = loader->pp3;
1457          pp[3] = loader->pp4;
1458
1459          num_base_points = gloader->base.outline.n_points;
1460
1461          error = load_truetype_glyph( loader, subglyph->index,
1462                                       recurse_count + 1 );
1463          if ( error )
1464            goto Exit;
1465
1466          /* restore subglyph pointer */
1467          subglyph = gloader->base.subglyphs + num_base_subgs + n;
1468
1469          if ( !( subglyph->flags & USE_MY_METRICS ) )
1470          {
1471            loader->pp1 = pp[0];
1472            loader->pp2 = pp[1];
1473            loader->pp3 = pp[2];
1474            loader->pp4 = pp[3];
1475          }
1476
1477          num_points = gloader->base.outline.n_points;
1478
1479          if ( num_points == num_base_points )
1480            continue;
1481
1482          /* gloader->base.outline consists of three parts:               */
1483          /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */
1484          /*                                                              */
1485          /* (1): exists from the beginning                               */
1486          /* (2): components that have been loaded so far                 */
1487          /* (3): the newly loaded component                              */
1488          TT_Process_Composite_Component( loader, subglyph, start_point,
1489                                          num_base_points );
1490        }
1491
1492        loader->stream = old_stream;
1493
1494        /* process the glyph */
1495        loader->ins_pos = ins_pos;
1496        if ( IS_HINTED( loader->load_flags ) &&
1497
1498#ifdef TT_USE_BYTECODE_INTERPRETER
1499
1500             subglyph->flags & WE_HAVE_INSTR &&
1501
1502#endif
1503
1504             num_points > start_point )
1505          TT_Process_Composite_Glyph( loader, start_point, start_contour );
1506
1507      }
1508    }
1509    else
1510    {
1511      /* invalid composite count (negative but not -1) */
1512      error = TT_Err_Invalid_Outline;
1513      goto Exit;
1514    }
1515
1516    /***********************************************************************/
1517    /***********************************************************************/
1518    /***********************************************************************/
1519
1520  Exit:
1521
1522    if ( opened_frame )
1523      face->forget_glyph_frame( loader );
1524
1525#ifdef FT_CONFIG_OPTION_INCREMENTAL
1526
1527    if ( glyph_data_loaded )
1528      face->root.internal->incremental_interface->funcs->free_glyph_data(
1529        face->root.internal->incremental_interface->object,
1530        &glyph_data );
1531
1532#endif
1533
1534    return error;
1535  }
1536
1537
1538  static FT_Error
1539  compute_glyph_metrics( TT_Loader  loader,
1540                         FT_UInt    glyph_index )
1541  {
1542    FT_BBox       bbox;
1543    TT_Face       face = (TT_Face)loader->face;
1544    FT_Fixed      y_scale;
1545    TT_GlyphSlot  glyph = loader->glyph;
1546    TT_Size       size = (TT_Size)loader->size;
1547
1548
1549    y_scale = 0x10000L;
1550    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1551      y_scale = size->root.metrics.y_scale;
1552
1553    if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE )
1554      FT_Outline_Get_CBox( &glyph->outline, &bbox );
1555    else
1556      bbox = loader->bbox;
1557
1558    /* get the device-independent horizontal advance; it is scaled later */
1559    /* by the base layer.                                                */
1560    {
1561      FT_Pos  advance = loader->linear;
1562
1563
1564      /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */
1565      /* correctly support DynaLab fonts, which have an incorrect       */
1566      /* `advance_Width_Max' field!  It is used, to my knowledge,       */
1567      /* exclusively in the X-TrueType font server.                     */
1568      /*                                                                */
1569      if ( face->postscript.isFixedPitch                                     &&
1570           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
1571        advance = face->horizontal.advance_Width_Max;
1572
1573      /* we need to return the advance in font units in linearHoriAdvance, */
1574      /* it will be scaled later by the base layer.                        */
1575      glyph->linearHoriAdvance = advance;
1576    }
1577
1578    glyph->metrics.horiBearingX = bbox.xMin;
1579    glyph->metrics.horiBearingY = bbox.yMax;
1580    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
1581
1582    /* Now take care of vertical metrics.  In the case where there is    */
1583    /* no vertical information within the font (relatively common), make */
1584    /* up some metrics by `hand'...                                      */
1585
1586    {
1587      FT_Pos  top;      /* scaled vertical top side bearing  */
1588      FT_Pos  advance;  /* scaled vertical advance height    */
1589
1590
1591      /* Get the unscaled top bearing and advance height. */
1592      if ( face->vertical_info &&
1593           face->vertical.number_Of_VMetrics > 0 )
1594      {
1595        top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax,
1596                                   y_scale );
1597
1598        if ( loader->pp3.y <= loader->pp4.y )
1599          advance = 0;
1600        else
1601          advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y,
1602                                          y_scale );
1603      }
1604      else
1605      {
1606        FT_Pos  height;
1607
1608
1609        /* XXX Compute top side bearing and advance height in  */
1610        /*     Get_VMetrics instead of here.                   */
1611
1612        /* NOTE: The OS/2 values are the only `portable' ones, */
1613        /*       which is why we use them, if there is an OS/2 */
1614        /*       table in the font.  Otherwise, we use the     */
1615        /*       values defined in the horizontal header.      */
1616
1617        height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin,
1618                                      y_scale );
1619        if ( face->os2.version != 0xFFFFU )
1620          advance = (FT_Pos)( face->os2.sTypoAscender -
1621                              face->os2.sTypoDescender );
1622        else
1623          advance = (FT_Pos)( face->horizontal.Ascender -
1624                              face->horizontal.Descender );
1625
1626        top = ( advance - height ) / 2;
1627      }
1628
1629#ifdef FT_CONFIG_OPTION_INCREMENTAL
1630      {
1631        FT_Incremental_InterfaceRec*  incr;
1632        FT_Incremental_MetricsRec     metrics;
1633        FT_Error                      error;
1634
1635
1636        incr = face->root.internal->incremental_interface;
1637
1638        /* If this is an incrementally loaded font see if there are */
1639        /* overriding metrics for this glyph.                       */
1640        if ( incr && incr->funcs->get_glyph_metrics )
1641        {
1642          metrics.bearing_x = 0;
1643          metrics.bearing_y = top;
1644          metrics.advance   = advance;
1645
1646          error = incr->funcs->get_glyph_metrics( incr->object,
1647                                                  glyph_index,
1648                                                  TRUE,
1649                                                  &metrics );
1650          if ( error )
1651            return error;
1652
1653          top     = metrics.bearing_y;
1654          advance = metrics.advance;
1655        }
1656      }
1657
1658      /* GWW: Do vertical metrics get loaded incrementally too? */
1659
1660#endif /* FT_CONFIG_OPTION_INCREMENTAL */
1661
1662      glyph->linearVertAdvance = advance;
1663
1664      /* scale the metrics */
1665      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1666      {
1667        top     = FT_MulFix( top, y_scale );
1668        advance = FT_MulFix( advance, y_scale );
1669      }
1670
1671      /* XXX: for now, we have no better algorithm for the lsb, but it */
1672      /*      should work fine.                                        */
1673      /*                                                               */
1674      glyph->metrics.vertBearingX = ( bbox.xMin - bbox.xMax ) / 2;
1675      glyph->metrics.vertBearingY = top;
1676      glyph->metrics.vertAdvance  = advance;
1677    }
1678
1679    /* adjust advance width to the value contained in the hdmx table */
1680    if ( !face->postscript.isFixedPitch  &&
1681         IS_HINTED( loader->load_flags ) )
1682    {
1683      FT_Byte*  widthp;
1684
1685
1686      widthp = tt_face_get_device_metrics( face,
1687                                           size->root.metrics.x_ppem,
1688                                           glyph_index );
1689
1690      if ( widthp )
1691        glyph->metrics.horiAdvance = *widthp << 6;
1692    }
1693
1694    /* set glyph dimensions */
1695    glyph->metrics.width  = bbox.xMax - bbox.xMin;
1696    glyph->metrics.height = bbox.yMax - bbox.yMin;
1697
1698    return 0;
1699  }
1700
1701
1702#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1703
1704  static FT_Error
1705  load_sbit_image( TT_Size       size,
1706                   TT_GlyphSlot  glyph,
1707                   FT_UInt       glyph_index,
1708                   FT_Int32      load_flags )
1709  {
1710    TT_Face             face;
1711    SFNT_Service        sfnt;
1712    FT_Stream           stream;
1713    FT_Error            error;
1714    TT_SBit_MetricsRec  metrics;
1715
1716
1717    face   = (TT_Face)glyph->face;
1718    sfnt   = (SFNT_Service)face->sfnt;
1719    stream = face->root.stream;
1720
1721    error = sfnt->load_sbit_image( face,
1722                                   size->strike_index,
1723                                   glyph_index,
1724                                   (FT_Int)load_flags,
1725                                   stream,
1726                                   &glyph->bitmap,
1727                                   &metrics );
1728    if ( !error )
1729    {
1730      glyph->outline.n_points   = 0;
1731      glyph->outline.n_contours = 0;
1732
1733      glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
1734      glyph->metrics.height = (FT_Pos)metrics.height << 6;
1735
1736      glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1737      glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1738      glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
1739
1740      glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1741      glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1742      glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
1743
1744      glyph->format = FT_GLYPH_FORMAT_BITMAP;
1745      if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1746      {
1747        glyph->bitmap_left = metrics.vertBearingX;
1748        glyph->bitmap_top  = metrics.vertBearingY;
1749      }
1750      else
1751      {
1752        glyph->bitmap_left = metrics.horiBearingX;
1753        glyph->bitmap_top  = metrics.horiBearingY;
1754      }
1755    }
1756
1757    return error;
1758  }
1759
1760#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1761
1762
1763  static FT_Error
1764  tt_loader_init( TT_Loader     loader,
1765                  TT_Size       size,
1766                  TT_GlyphSlot  glyph,
1767                  FT_Int32      load_flags )
1768  {
1769    TT_Face    face;
1770    FT_Stream  stream;
1771
1772
1773    face   = (TT_Face)glyph->face;
1774    stream = face->root.stream;
1775
1776    FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) );
1777
1778#ifdef TT_USE_BYTECODE_INTERPRETER
1779
1780    /* load execution context */
1781    if ( IS_HINTED( load_flags ) )
1782    {
1783      TT_ExecContext  exec;
1784      FT_Bool         grayscale;
1785
1786
1787      if ( !size->cvt_ready )
1788      {
1789        FT_Error  error = tt_size_ready_bytecode( size );
1790        if ( error )
1791          return error;
1792      }
1793
1794      /* query new execution context */
1795      exec = size->debug ? size->context
1796                         : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
1797      if ( !exec )
1798        return TT_Err_Could_Not_Find_Context;
1799
1800      grayscale =
1801        FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
1802
1803      TT_Load_Context( exec, face, size );
1804
1805      /* a change from mono to grayscale rendering (and vice versa) */
1806      /* requires a re-execution of the CVT program                 */
1807      if ( grayscale != exec->grayscale )
1808      {
1809        FT_UInt  i;
1810
1811
1812        exec->grayscale = grayscale;
1813
1814        for ( i = 0; i < size->cvt_size; i++ )
1815          size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
1816        tt_size_run_prep( size );
1817      }
1818
1819      /* see whether the cvt program has disabled hinting */
1820      if ( exec->GS.instruct_control & 1 )
1821        load_flags |= FT_LOAD_NO_HINTING;
1822
1823      /* load default graphics state -- if needed */
1824      if ( exec->GS.instruct_control & 2 )
1825        exec->GS = tt_default_graphics_state;
1826
1827      exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
1828      loader->exec = exec;
1829      loader->instructions = exec->glyphIns;
1830    }
1831
1832#endif /* TT_USE_BYTECODE_INTERPRETER */
1833
1834    /* seek to the beginning of the glyph table -- for Type 42 fonts     */
1835    /* the table might be accessed from a Postscript stream or something */
1836    /* else...                                                           */
1837
1838#ifdef FT_CONFIG_OPTION_INCREMENTAL
1839
1840    if ( face->root.internal->incremental_interface )
1841      loader->glyf_offset = 0;
1842    else
1843
1844#endif
1845
1846    {
1847      FT_Error  error = face->goto_table( face, TTAG_glyf, stream, 0 );
1848
1849
1850      if ( error == TT_Err_Table_Missing )
1851        loader->glyf_offset = 0;
1852      else if ( error )
1853      {
1854        FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" ));
1855        return error;
1856      }
1857      else
1858        loader->glyf_offset = FT_STREAM_POS();
1859    }
1860
1861    /* get face's glyph loader */
1862    {
1863      FT_GlyphLoader  gloader = glyph->internal->loader;
1864
1865
1866      FT_GlyphLoader_Rewind( gloader );
1867      loader->gloader = gloader;
1868    }
1869
1870    loader->load_flags = load_flags;
1871
1872    loader->face   = (FT_Face)face;
1873    loader->size   = (FT_Size)size;
1874    loader->glyph  = (FT_GlyphSlot)glyph;
1875    loader->stream = stream;
1876
1877    return TT_Err_Ok;
1878  }
1879
1880
1881  /*************************************************************************/
1882  /*                                                                       */
1883  /* <Function>                                                            */
1884  /*    TT_Load_Glyph                                                      */
1885  /*                                                                       */
1886  /* <Description>                                                         */
1887  /*    A function used to load a single glyph within a given glyph slot,  */
1888  /*    for a given size.                                                  */
1889  /*                                                                       */
1890  /* <Input>                                                               */
1891  /*    glyph       :: A handle to a target slot object where the glyph    */
1892  /*                   will be loaded.                                     */
1893  /*                                                                       */
1894  /*    size        :: A handle to the source face size at which the glyph */
1895  /*                   must be scaled/loaded.                              */
1896  /*                                                                       */
1897  /*    glyph_index :: The index of the glyph in the font file.            */
1898  /*                                                                       */
1899  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
1900  /*                   FT_LOAD_XXX constants can be used to control the    */
1901  /*                   glyph loading process (e.g., whether the outline    */
1902  /*                   should be scaled, whether to load bitmaps or not,   */
1903  /*                   whether to hint the outline, etc).                  */
1904  /*                                                                       */
1905  /* <Return>                                                              */
1906  /*    FreeType error code.  0 means success.                             */
1907  /*                                                                       */
1908  FT_LOCAL_DEF( FT_Error )
1909  TT_Load_Glyph( TT_Size       size,
1910                 TT_GlyphSlot  glyph,
1911                 FT_UInt       glyph_index,
1912                 FT_Int32      load_flags )
1913  {
1914    TT_Face       face;
1915    FT_Error      error;
1916    TT_LoaderRec  loader;
1917
1918
1919    face   = (TT_Face)glyph->face;
1920    error  = TT_Err_Ok;
1921
1922#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1923
1924    /* try to load embedded bitmap if any              */
1925    /*                                                 */
1926    /* XXX: The convention should be emphasized in     */
1927    /*      the documents because it can be confusing. */
1928    if ( size->strike_index != 0xFFFFFFFFUL      &&
1929         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
1930    {
1931      error = load_sbit_image( size, glyph, glyph_index, load_flags );
1932      if ( !error )
1933        return TT_Err_Ok;
1934    }
1935
1936#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1937
1938    /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
1939    if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
1940      return TT_Err_Invalid_Size_Handle;
1941
1942    if ( load_flags & FT_LOAD_SBITS_ONLY )
1943      return TT_Err_Invalid_Argument;
1944
1945    error = tt_loader_init( &loader, size, glyph, load_flags );
1946    if ( error )
1947      return error;
1948
1949    glyph->format        = FT_GLYPH_FORMAT_OUTLINE;
1950    glyph->num_subglyphs = 0;
1951    glyph->outline.flags = 0;
1952
1953    /* main loading loop */
1954    error = load_truetype_glyph( &loader, glyph_index, 0 );
1955    if ( !error )
1956    {
1957      if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE )
1958      {
1959        glyph->num_subglyphs = loader.gloader->base.num_subglyphs;
1960        glyph->subglyphs     = loader.gloader->base.subglyphs;
1961      }
1962      else
1963      {
1964        glyph->outline        = loader.gloader->base.outline;
1965        glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS;
1966
1967        /* In case bit 1 of the `flags' field in the `head' table isn't */
1968        /* set, translate array so that (0,0) is the glyph's origin.    */
1969        if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
1970          FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
1971      }
1972
1973#ifdef TT_USE_BYTECODE_INTERPRETER
1974
1975      if ( IS_HINTED( load_flags ) )
1976      {
1977        if ( loader.exec->GS.scan_control )
1978        {
1979          /* convert scan conversion mode to FT_OUTLINE_XXX flags */
1980          switch ( loader.exec->GS.scan_type )
1981          {
1982          case 0: /* simple drop-outs including stubs */
1983            glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
1984            break;
1985          case 1: /* simple drop-outs excluding stubs */
1986            /* nothing; it's the default rendering mode */
1987            break;
1988          case 4: /* smart drop-outs including stubs */
1989            glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
1990                                    FT_OUTLINE_INCLUDE_STUBS;
1991            break;
1992          case 5: /* smart drop-outs excluding stubs  */
1993            glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
1994            break;
1995
1996          default: /* no drop-out control */
1997            glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
1998            break;
1999          }
2000        }
2001        else 
2002          glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
2003      }
2004
2005#endif /* TT_USE_BYTECODE_INTERPRETER */
2006
2007      compute_glyph_metrics( &loader, glyph_index );
2008    }
2009
2010    /* Set the `high precision' bit flag.                           */
2011    /* This is _critical_ to get correct output for monochrome      */
2012    /* TrueType glyphs at all sizes using the bytecode interpreter. */
2013    /*                                                              */
2014    if ( !( load_flags & FT_LOAD_NO_SCALE ) &&
2015         size->root.metrics.y_ppem < 24     )
2016      glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION;
2017
2018    return error;
2019  }
2020
2021
2022/* END */
Note: See TracBrowser for help on using the repository browser.