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