ttgload.c revision 2a98b3c431091de7434f9bde087a4f5c47f463ba
1/***************************************************************************/
2/*                                                                         */
3/*  ttgload.c                                                              */
4/*                                                                         */
5/*    TrueType Glyph Loader (body).                                        */
6/*                                                                         */
7/*  Copyright 1996-2000 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 <freetype/internal/ftdebug.h>
20#include <freetype/internal/ftcalc.h>
21#include <freetype/internal/ftstream.h>
22#include <freetype/internal/sfnt.h>
23#include <freetype/tttags.h>
24
25
26#include <ttgload.h>
27
28#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
29#include <ttinterp.h>
30#endif
31
32
33  /*************************************************************************/
34  /*                                                                       */
35  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
36  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
37  /* messages during execution.                                            */
38  /*                                                                       */
39#undef  FT_COMPONENT
40#define FT_COMPONENT  trace_ttgload
41
42
43  /*************************************************************************/
44  /*                                                                       */
45  /* Composite font flags.                                                 */
46  /*                                                                       */
47#define ARGS_ARE_WORDS       0x001
48#define ARGS_ARE_XY_VALUES   0x002
49#define ROUND_XY_TO_GRID     0x004
50#define WE_HAVE_A_SCALE      0x008
51/* reserved                  0x010 */
52#define MORE_COMPONENTS      0x020
53#define WE_HAVE_AN_XY_SCALE  0x040
54#define WE_HAVE_A_2X2        0x080
55#define WE_HAVE_INSTR        0x100
56#define USE_MY_METRICS       0x200
57
58
59
60  /*************************************************************************/
61  /*                                                                       */
62  /* <Function>                                                            */
63  /*    TT_Get_Metrics                                                     */
64  /*                                                                       */
65  /* <Description>                                                         */
66  /*    Returns the horizontal or vertical metrics in font units for a     */
67  /*    given glyph.  The metrics are the left side bearing (resp. top     */
68  /*    side bearing) and advance width (resp. advance height).            */
69  /*                                                                       */
70  /* <Input>                                                               */
71  /*    header  :: A pointer to either the horizontal or vertical metrics  */
72  /*               structure.                                              */
73  /*                                                                       */
74  /*    index   :: The glyph index.                                        */
75  /*                                                                       */
76  /* <Output>                                                              */
77  /*    bearing :: The bearing, either left side or top side.              */
78  /*                                                                       */
79  /*    advance :: The advance width resp. advance height.                 */
80  /*                                                                       */
81  /* <Note>                                                                */
82  /*    This function will much probably move to another component in the  */
83  /*    near future, but I haven't decided which yet.                      */
84  /*                                                                       */
85  LOCAL_FUNC
86  void  TT_Get_Metrics( TT_HoriHeader*  header,
87                        FT_UInt         index,
88                        FT_Short*       bearing,
89                        FT_UShort*      advance )
90  {
91    TT_LongMetrics*  longs_m;
92    FT_UShort        k = header->number_Of_HMetrics;
93
94
95    if ( index < k )
96    {
97      longs_m  = (TT_LongMetrics*)header->long_metrics + index;
98      *bearing = longs_m->bearing;
99      *advance = longs_m->advance;
100    }
101    else
102    {
103      *bearing = ((TT_ShortMetrics*)header->short_metrics)[index - k];
104      *advance = ((TT_LongMetrics*)header->long_metrics)[k - 1].advance;
105    }
106  }
107
108
109  /*************************************************************************/
110  /*                                                                       */
111  /*    Returns the horizontal metrics in font units for a given glyph.    */
112  /*    If `check' is true, take care of monospaced fonts by returning the */
113  /*    advance width maximum.                                             */
114  /*                                                                       */
115  static
116  void Get_HMetrics( TT_Face     face,
117                     FT_UInt     index,
118                     FT_Bool     check,
119                     FT_Short*   lsb,
120                     FT_UShort*  aw )
121  {
122    TT_Get_Metrics( &face->horizontal, index, lsb, aw );
123
124    if ( check && face->postscript.isFixedPitch )
125      *aw = face->horizontal.advance_Width_Max;
126  }
127
128
129  /*************************************************************************/
130  /*                                                                       */
131  /*    Returns the advance width table for a given pixel size if it is    */
132  /*    found in the font's `hdmx' table (if any).                         */
133  /*                                                                       */
134  static
135  FT_Byte*  Get_Advance_Widths( TT_Face    face,
136                                FT_UShort  ppem )
137  {
138    FT_UShort  n;
139
140    for ( n = 0; n < face->hdmx.num_records; n++ )
141      if ( face->hdmx.records[n].ppem == ppem )
142        return face->hdmx.records[n].widths;
143
144    return NULL;
145  }
146
147
148#define cur_to_org( n, zone )  \
149          MEM_Copy( (zone)->org, (zone)->cur, n * sizeof ( FT_Vector ) )
150
151#define org_to_cur( n, zone )  \
152          MEM_Copy( (zone)->cur, (zone)->org, n * sizeof ( FT_Vector ) )
153
154
155  /*************************************************************************/
156  /*                                                                       */
157  /*    Translates an array of coordinates.                                */
158  /*                                                                       */
159  static
160  void  translate_array( FT_UInt     n,
161                         FT_Vector*  coords,
162                         FT_Pos      delta_x,
163                         FT_Pos      delta_y )
164  {
165    FT_UInt  k;
166
167    if ( delta_x )
168      for ( k = 0; k < n; k++ )
169        coords[k].x += delta_x;
170
171    if ( delta_y )
172      for ( k = 0; k < n; k++ )
173        coords[k].y += delta_y;
174  }
175
176
177  static  void  tt_prepare_zone( TT_GlyphZone*  zone,
178                                 FT_GlyphLoad*  load,
179                                 FT_UInt        start_point,
180                                 FT_UInt        start_contour )
181  {
182    zone->n_points   = load->outline.n_points - start_point;
183    zone->n_contours = load->outline.n_contours - start_contour;
184    zone->org        = load->extra_points + start_point;
185    zone->cur        = load->outline.points + start_point;
186    zone->tags       = (FT_Byte*)load->outline.tags + start_point;
187    zone->contours   = (FT_UShort*)load->outline.contours + start_contour;
188  }
189
190
191#undef  IS_HINTED
192#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
193
194
195  /*************************************************************************/
196  /*                                                                       */
197  /*  The following functions are used by default with TrueType fonts.     */
198  /*  However, they can be replaced by alternatives if we need to support  */
199  /*  TrueType-compressed formats (like MicroType) in the future..         */
200  /*                                                                       */
201
202  static
203  FT_Error  TT_Access_Glyph_Frame( TT_Loader*  loader,
204                                   FT_UInt     glyph_index,
205                                   FT_ULong    offset,
206                                   FT_UInt     byte_count )
207  {
208    FT_Error  error;
209    FT_Stream stream = loader->stream;
210
211    /* the following line sets the 'error' variable through macros !! */
212    (void)( FILE_Seek( offset ) || ACCESS_Frame( byte_count ) );
213
214    FT_TRACE5(( "Glyph %ld\n", glyph_index ));
215    return error;
216  }
217
218
219
220  static
221  void      TT_Forget_Glyph_Frame( TT_Loader*  loader )
222  {
223    FT_Stream  stream = loader->stream;
224    FORGET_Frame();
225  }
226
227
228
229  static
230  FT_Error  TT_Load_Glyph_Header( TT_Loader*  loader )
231  {
232    FT_Stream   stream = loader->stream;
233
234    loader->n_contours = GET_Short();
235
236    loader->bbox.xMin = GET_Short();
237    loader->bbox.yMin = GET_Short();
238    loader->bbox.xMax = GET_Short();
239    loader->bbox.yMax = GET_Short();
240
241    FT_TRACE5(( "  # of contours: %d\n", loader->n_contours ));
242    FT_TRACE5(( "  xMin: %4d  xMax: %4d\n", loader->bbox.xMin,
243                                            loader->bbox.xMax ));
244    FT_TRACE5(( "  yMin: %4d  yMax: %4d\n", loader->bbox.yMin,
245                                            loader->bbox.yMax ));
246
247    return FT_Err_Ok;
248  }
249
250
251
252  static
253  FT_Error  TT_Load_Simple_Glyph( TT_Loader*  load,
254                                  FT_Int      n_contours )
255  {
256    FT_Error         error;
257    FT_Stream        stream  = load->stream;
258    FT_GlyphLoader*  gloader = load->gloader;
259    FT_Outline*      outline;
260    TT_Face          face    = (TT_Face)load->face;
261    TT_GlyphSlot     slot    = (TT_GlyphSlot)load->glyph;
262    FT_UShort        n_ins;
263    FT_Int           n, n_points;
264
265
266    /* reading the contours endpoints & number of points */
267    {
268      short*  cur   = gloader->current.outline.contours;
269      short*  limit = cur + n_contours;
270
271      for ( ; cur < limit; cur++ )
272        cur[0] = GET_UShort();
273
274      n_points = 0;
275      if (n_contours > 0)
276        n_points = cur[-1]+1;
277
278      error = FT_GlyphLoader_Check_Points( gloader, n_points+2, 0 );
279      if (error) goto Fail;
280
281      outline = &gloader->current.outline;
282    }
283
284
285    /* reading the bytecode instructions */
286    slot->control_len  = 0;
287    slot->control_data = 0;
288
289    n_ins = GET_UShort();
290
291    FT_TRACE5(( "  Instructions size: %d\n", n_ins ));
292
293    if ( n_ins > face->max_profile.maxSizeOfInstructions )
294    {
295      FT_TRACE0(( "ERROR: Too many instructions!\n" ));
296      error = TT_Err_Too_Many_Ins;
297      goto Fail;
298    }
299
300    if ( stream->cursor + n_ins > stream->limit )
301    {
302      FT_TRACE0(( "ERROR: Instruction count mismatch!\n" ));
303      error = TT_Err_Too_Many_Ins;
304      goto Fail;
305    }
306
307#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
308    if ( ( load->load_flags                               &
309         ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 &&
310           load->instructions )
311    {
312      slot->control_len  = n_ins;
313      slot->control_data = load->instructions;
314
315      MEM_Copy( load->instructions, stream->cursor, n_ins );
316    }
317#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
318
319    stream->cursor += n_ins;
320
321    /* reading the point tags */
322
323    {
324      FT_Byte*  flag  = (FT_Byte*)outline->tags;
325      FT_Byte*  limit = flag + n_points;
326      FT_Byte   c, count;
327
328      for ( ; flag < limit; flag++ )
329      {
330        *flag = c = GET_Byte();
331        if ( c & 8 )
332        {
333          for ( count = GET_Byte(); count > 0; count-- )
334            *++flag = c;
335        }
336      }
337    }
338
339    /* reading the X coordinates */
340
341    {
342      FT_Vector*  vec   = outline->points;
343      FT_Vector*  limit = vec + n_points;
344      FT_Byte*    flag  = (FT_Byte*)outline->tags;
345      FT_Pos      x     = 0;
346
347
348      for ( ; vec < limit; vec++, flag++ )
349      {
350        FT_Pos  y = 0;
351
352
353        if ( *flag & 2 )
354        {
355          y = GET_Byte();
356          if ( ( *flag & 16 ) == 0 )
357            y = -y;
358        }
359        else if ( ( *flag & 16 ) == 0 )
360          y = GET_Short();
361
362        x     += y;
363        vec->x = x;
364      }
365    }
366
367    /* reading the Y coordinates */
368
369    {
370      FT_Vector*  vec   = gloader->current.outline.points;
371      FT_Vector*  limit = vec + n_points;
372      FT_Byte*    flag  = (FT_Byte*)outline->tags;
373      FT_Pos      x     = 0;
374
375
376      for ( ; vec < limit; vec++, flag++ )
377      {
378        FT_Pos  y = 0;
379
380
381        if ( *flag & 4 )
382        {
383          y = GET_Byte();
384          if ( ( *flag & 32 ) == 0 )
385            y = -y;
386        }
387        else if ( ( *flag & 32 ) == 0 )
388          y = GET_Short();
389
390        x     += y;
391        vec->y = x;
392      }
393    }
394
395    /* clear the touch tags */
396    for ( n = 0; n < n_points; n++ )
397      outline->tags[n] &= FT_Curve_Tag_On;
398
399    outline->n_points   = n_points;
400    outline->n_contours = n_contours;
401
402  Fail:
403    return error;
404  }
405
406
407  static
408  FT_Error  TT_Load_Composite_Glyph( TT_Loader*  loader,
409                                     FT_UInt     byte_count )
410  {
411    FT_Error         error;
412    FT_Stream        stream = loader->stream;
413    FT_GlyphLoader*  gloader   = loader->gloader;
414    FT_SubGlyph*     subglyph;
415    FT_UInt          num_subglyphs;
416
417    num_subglyphs = 0;
418    do
419    {
420      FT_Fixed  xx, xy, yy, yx;
421
422      /* check that we can load a new subglyph */
423      error = FT_GlyphLoader_Check_Subglyphs( gloader, num_subglyphs+1 );
424      if (error) goto Fail;
425
426      subglyph = gloader->current.subglyphs + num_subglyphs;
427
428      subglyph->arg1 = subglyph->arg2 = 0;
429
430      subglyph->flags = GET_UShort();
431      subglyph->index = GET_UShort();
432
433      /* read arguments */
434      if ( subglyph->flags & ARGS_ARE_WORDS )
435      {
436        subglyph->arg1 = GET_Short();
437        subglyph->arg2 = GET_Short();
438      }
439      else
440      {
441        subglyph->arg1 = GET_Char();
442        subglyph->arg2 = GET_Char();
443      }
444
445      /* read transform */
446      xx = yy = 0x10000L;
447      xy = yx = 0;
448
449      if ( subglyph->flags & WE_HAVE_A_SCALE )
450      {
451        xx = (FT_Fixed)GET_Short() << 2;
452        yy = xx;
453      }
454      else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE )
455      {
456        xx = (FT_Fixed)GET_Short() << 2;
457        yy = (FT_Fixed)GET_Short() << 2;
458      }
459      else if ( subglyph->flags & WE_HAVE_A_2X2 )
460      {
461        xx = (FT_Fixed)GET_Short() << 2;
462        xy = (FT_Fixed)GET_Short() << 2;
463        yx = (FT_Fixed)GET_Short() << 2;
464        yy = (FT_Fixed)GET_Short() << 2;
465      }
466
467      subglyph->transform.xx = xx;
468      subglyph->transform.xy = xy;
469      subglyph->transform.yx = yx;
470      subglyph->transform.yy = yy;
471
472      num_subglyphs++;
473    }
474    while (subglyph->flags & MORE_COMPONENTS);
475
476    gloader->current.num_subglyphs = num_subglyphs;
477
478#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
479    {
480      /* we must undo the ACCESS_Frame in order to point to the */
481      /* composite instructions, if we find some.               */
482      /* we will process them later...                          */
483      /*                                                        */
484      loader->ins_pos = FILE_Pos() + stream->cursor - stream->limit;
485    }
486#endif
487
488  Fail:
489    return error;
490  }
491
492
493
494  /*************************************************************************/
495  /*                                                                       */
496  /* <Function>                                                            */
497  /*    TT_Process_Simple_Glyph                                            */
498  /*                                                                       */
499  /* <Description>                                                         */
500  /*    Once a simple glyph has been loaded, it needs to be processed.     */
501  /*    Usually, this means scaling and hinting through bytecode           */
502  /*    interpretation..                                                   */
503  /*                                                                       */
504  static
505  FT_Error   TT_Process_Simple_Glyph( TT_Loader*  load,
506                                      FT_Bool     debug )
507  {
508    FT_GlyphLoader*  gloader  = load->gloader;
509    FT_Outline*      outline  = &gloader->current.outline;
510    FT_UInt          n_points = outline->n_points;
511    FT_UInt          n_ins;
512    TT_GlyphZone*    zone     = &load->zone;
513    FT_Error         error    = FT_Err_Ok;
514
515    n_ins = load->glyph->control_len;
516
517    /* add shadow points */
518
519    /* Now add the two shadow points at n and n + 1.    */
520    /* We need the left side bearing and advance width. */
521
522    {
523      FT_Vector*  pp1;
524      FT_Vector*  pp2;
525
526      /* pp1 = xMin - lsb */
527      pp1    = outline->points + n_points;
528      pp1->x = load->bbox.xMin - load->left_bearing;
529      pp1->y = 0;
530
531      /* pp2 = pp1 + aw */
532      pp2    = pp1 + 1;
533      pp2->x = pp1->x + load->advance;
534      pp2->y = 0;
535
536      outline->tags[n_points    ] = 0;
537      outline->tags[n_points + 1] = 0;
538    }
539
540    /* Note that we return two more points that are not */
541    /* part of the glyph outline.                       */
542
543    n_points           += 2;
544
545    /* set up zone for hinting */
546    tt_prepare_zone( zone, &gloader->current, 0, 0 );
547
548    /* eventually scale the glyph */
549    if (!(load->load_flags & FT_LOAD_NO_SCALE))
550    {
551      FT_Vector*  vec     = zone->cur;
552      FT_Vector*  limit   = vec + n_points;
553      FT_Fixed    x_scale = load->size->metrics.x_scale;
554      FT_Fixed    y_scale = load->size->metrics.y_scale;
555
556      /* first scale the glyph points */
557      for ( ; vec < limit; vec++ )
558      {
559        vec->x = FT_MulFix( vec->x, x_scale );
560        vec->y = FT_MulFix( vec->y, y_scale );
561      }
562    }
563
564    cur_to_org( n_points, zone );
565
566    /* eventually hint the glyph */
567    if ( IS_HINTED(load->load_flags) )
568    {
569      FT_Pos  x = zone->org[n_points-2].x;
570
571      x = ( ( x + 32 ) & -64 ) - x;
572      translate_array( n_points, zone->org, x, 0 );
573
574      org_to_cur( n_points, zone );
575
576      zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64;
577
578#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
579      /* now consider hinting */
580      if ( n_ins > 0 )
581      {
582        error = TT_Set_CodeRange( load->exec, tt_coderange_glyph,
583                                  load->exec->glyphIns, n_ins );
584        if ( error ) goto Exit;
585
586        load->exec->is_composite     = FALSE;
587        load->exec->pedantic_hinting = (FT_Bool)(load->load_flags &
588                                                 FT_LOAD_PEDANTIC);
589        load->exec->pts              = *zone;
590        load->exec->pts.n_points    += 2;
591
592        error = TT_Run_Context( load->exec, debug );
593        if ( error && load->exec->pedantic_hinting )
594          goto Exit;
595
596        error = FT_Err_Ok;  /* ignore bytecode errors in non-pedantic mode */
597      }
598#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
599    }
600
601    /* save glyph phantom points */
602    if ( !load->preserve_pps )
603    {
604      load->pp1 = zone->cur[n_points - 2];
605      load->pp2 = zone->cur[n_points - 1];
606    }
607
608  Exit:
609    return error;
610  }
611
612
613
614
615
616
617  /*************************************************************************/
618  /*                                                                       */
619  /* <Function>                                                            */
620  /*    load_truetype_glyph                                                */
621  /*                                                                       */
622  /* <Description>                                                         */
623  /*    Loads a given truetype glyph.  Handles composites and uses a       */
624  /*    TT_Loader object.                                                  */
625  /*                                                                       */
626  static
627  FT_Error  load_truetype_glyph( TT_Loader*  loader,
628                                 FT_UInt     glyph_index )
629  {
630    FT_Stream        stream = loader->stream;
631    FT_Error         error;
632    TT_Face          face   = (TT_Face)loader->face;
633    FT_ULong         offset;
634    FT_Int           contours_count;
635    FT_UInt          index, num_points, num_contours, count;
636    FT_Fixed         x_scale, y_scale;
637    FT_ULong         ins_offset;
638    FT_GlyphLoader*  gloader = loader->gloader;
639    FT_Bool          opened_frame = 0;
640
641
642    /* check glyph index */
643    index = glyph_index;
644    if ( index >= (FT_UInt)face->root.num_glyphs )
645    {
646      error = TT_Err_Invalid_Glyph_Index;
647      goto Exit;
648    }
649
650    loader->glyph_index = glyph_index;
651    num_contours = 0;
652    num_points   = 0;
653    ins_offset   = 0;
654
655    x_scale = 0x10000L;
656    y_scale = 0x10000L;
657    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
658    {
659      x_scale = loader->size->metrics.x_scale;
660      y_scale = loader->size->metrics.y_scale;
661    }
662
663    /* get horizontal metrics */
664    {
665      FT_Short   left_bearing;
666      FT_UShort  advance_width;
667
668
669      Get_HMetrics( face, index,
670                    (FT_Bool)!(loader->load_flags &
671                                 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH),
672                    &left_bearing,
673                    &advance_width );
674
675      loader->left_bearing = left_bearing;
676      loader->advance      = advance_width;
677    }
678
679    offset = face->glyph_locations[index];
680    count  = 0;
681
682    if ( index < (FT_UInt)face->num_locations - 1 )
683       count = face->glyph_locations[index + 1] - offset;
684
685    if ( count == 0 )
686    {
687      /* as described by Frederic Loyer, these are spaces, and */
688      /* not the unknown glyph.                                */
689      loader->bbox.xMin = 0;
690      loader->bbox.xMax = 0;
691      loader->bbox.yMin = 0;
692      loader->bbox.yMax = 0;
693
694      loader->pp1.x = 0;
695      loader->pp2.x = loader->advance;
696
697      if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
698        loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
699
700#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
701      if ( loader->exec )
702        loader->exec->glyphSize = 0;
703#endif
704      error = FT_Err_Ok;
705      goto Exit;
706    }
707
708    offset = loader->glyf_offset + offset;
709
710    /* access glyph frame */
711    error = TT_Access_Glyph_Frame( loader, glyph_index, offset, count );
712    if (error) goto Exit;
713
714    opened_frame = 1;
715
716    /* read first glyph header */
717    error = TT_Load_Glyph_Header( loader );
718    if (error) goto Fail;
719
720    contours_count = loader->n_contours;
721
722    count -= 10;
723
724    loader->pp1.x = loader->bbox.xMin - loader->left_bearing;
725    loader->pp1.y = 0;
726    loader->pp2.x = loader->pp1.x + loader->advance;
727    loader->pp2.y = 0;
728
729    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
730    {
731      loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale );
732      loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale );
733    }
734
735    /***********************************************************************/
736    /***********************************************************************/
737    /***********************************************************************/
738
739    /* if it is a simple glyph, load it */
740
741    if ( contours_count >= 0 )
742    {
743      /* check that we can add the contours to the glyph */
744      error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count );
745      if (error) goto Fail;
746
747      error = TT_Load_Simple_Glyph( loader, contours_count );
748      if (error) goto Fail;
749
750#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
751      {
752        TT_Size size = (TT_Size)loader->size;
753        error = TT_Process_Simple_Glyph( loader,
754                                         (FT_Bool)( size && size->debug ) );
755      }
756#else
757      error = Process_Simple_Glyph( loader, 0 );
758#endif
759      if ( error ) goto Fail;
760
761      FT_GlyphLoader_Add( gloader );
762
763      /* Note: We could have put the simple loader source there */
764      /*       but the code is fat enough already :-)           */
765    }
766
767    /***********************************************************************/
768    /***********************************************************************/
769    /***********************************************************************/
770
771    /* otherwise, load a composite! */
772    else
773    {
774      TT_GlyphSlot  glyph = (TT_GlyphSlot)loader->glyph;
775      FT_UInt       start_point, start_contour;
776
777      /* for each subglyph, read composite header */
778      start_point   = gloader->base.outline.n_points;
779      start_contour = gloader->base.outline.n_contours;
780
781
782      error = TT_Load_Composite_Glyph( loader, count );
783      if (error) goto Fail;
784
785      TT_Forget_Glyph_Frame( loader );
786      opened_frame = 0;
787
788      /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */
789      /* `as is' in the glyph slot (the client application will be     */
790      /* responsible for interpreting this data)...                    */
791      /*                                                               */
792      if ( loader->load_flags & FT_LOAD_NO_RECURSE )
793      {
794        /* set up remaining glyph fields */
795        FT_GlyphLoader_Add( gloader );
796
797        glyph->num_subglyphs  = gloader->base.num_subglyphs;
798        glyph->format         = ft_glyph_format_composite;
799        glyph->subglyphs      = gloader->base.subglyphs;
800
801        goto Exit;
802      }
803
804
805    /***********************************************************************/
806    /***********************************************************************/
807    /***********************************************************************/
808
809      /*********************************************************************/
810      /* Now, read each subglyph independently..                           */
811      {
812        FT_Int        n, num_base_points, num_new_points;
813        FT_SubGlyph*  subglyph;
814
815        FT_UInt num_subglyphs  = gloader->current.num_subglyphs;
816        FT_UInt num_base_subgs = gloader->base.num_subglyphs;
817
818
819        FT_GlyphLoader_Add( gloader );
820
821        for ( n = 0; n < num_subglyphs; n++ )
822        {
823          FT_Vector  pp1, pp2;
824          FT_Pos     x, y;
825
826          /* each time we call load_truetype_glyph in this loop, the   */
827          /* value of 'gloader.base.subglyphs' can change due to table */
828          /* reallocations. We thus need to recompute the subglyph     */
829          /* pointer on each iteration..                               */
830          subglyph = gloader->base.subglyphs + num_base_subgs + n;
831
832          pp1 = loader->pp1;
833          pp2 = loader->pp2;
834
835          num_base_points = gloader->base.outline.n_points;
836
837          error = load_truetype_glyph( loader, subglyph->index );
838          if ( error )
839            goto Fail;
840
841          subglyph = gloader->base.subglyphs + num_base_subgs + n;
842
843          if ( subglyph->flags & USE_MY_METRICS )
844          {
845            pp1 = loader->pp1;
846            pp2 = loader->pp2;
847          }
848          else
849          {
850            loader->pp1 = pp1;
851            loader->pp2 = pp2;
852          }
853
854          num_points   = gloader->base.outline.n_points;
855
856          num_new_points = num_points - num_base_points;
857
858          /* now perform the transform required for this subglyph */
859
860          if ( subglyph->flags & ( WE_HAVE_A_SCALE     |
861                                   WE_HAVE_AN_XY_SCALE |
862                                   WE_HAVE_A_2X2       ) )
863          {
864            FT_Vector*  cur   = gloader->base.outline.points + num_base_points;
865            FT_Vector*  org   = gloader->base.extra_points   + num_base_points;
866            FT_Vector*  limit = cur + num_new_points;
867
868            for ( ; cur < limit; cur++, org++ )
869            {
870              FT_Vector_Transform( cur, &subglyph->transform );
871              FT_Vector_Transform( org, &subglyph->transform );
872            }
873          }
874
875          /* apply offset */
876
877          if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) )
878          {
879            FT_Int      k = subglyph->arg1;
880            FT_UInt     l = subglyph->arg2;
881            FT_Vector*  p1;
882            FT_Vector*  p2;
883
884            if ( start_point + k >= num_base_points          ||
885                               l >= (FT_UInt)num_new_points  )
886            {
887              error = TT_Err_Invalid_Composite;
888              goto Fail;
889            }
890
891            l += num_base_points;
892
893            p1 = gloader->base.outline.points + start_point + k;
894            p2 = gloader->base.outline.points + start_point + l;
895
896            x = p1->x - p2->x;
897            y = p1->y - p2->y;
898          }
899          else
900          {
901            x = subglyph->arg1;
902            y = subglyph->arg2;
903
904            if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
905            {
906              x = FT_MulFix( x, x_scale );
907              y = FT_MulFix( y, y_scale );
908
909              if ( subglyph->flags & ROUND_XY_TO_GRID )
910              {
911                x = ( x + 32 ) & -64;
912                y = ( y + 32 ) & -64;
913              }
914            }
915          }
916
917          translate_array( num_new_points, loader->zone.cur, x, y );
918          cur_to_org( num_new_points, &loader->zone );
919        }
920
921    /***********************************************************************/
922    /***********************************************************************/
923    /***********************************************************************/
924
925        /* we have finished loading all sub-glyphs, now, look for */
926        /* instructions for this composite!                       */
927
928#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
929
930        if ( num_subglyphs > 0               &&
931             loader->exec                    &&
932             loader->ins_pos > 0             &&
933             subglyph->flags & WE_HAVE_INSTR )
934        {
935          FT_UShort       n_ins;
936          TT_ExecContext  exec = loader->exec;
937          FT_UInt         n_points = loader->base.n_points;
938          TT_GlyphZone*   pts;
939          FT_Vector*      pp1;
940
941
942          /* read size of instructions */
943          if ( FILE_Seek( loader->ins_pos ) ||
944               READ_UShort(n_ins)         )
945            goto Fail;
946          FT_TRACE5(( "  Instructions size = %d\n", n_ins ));
947
948          /* in some fonts ?? */
949          if (n_ins == 0xFFFF)
950            n_ins = 0;
951
952          /* check it */
953          if ( n_ins > face->max_profile.maxSizeOfInstructions )
954          {
955            FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n",
956                        n_ins, subglyph->index ));
957            return TT_Err_Too_Many_Ins;
958          }
959
960          /* read the instructions */
961          if ( FILE_Read( exec->glyphIns, n_ins ) )
962            goto Fail;
963
964          glyph->control_data = exec->glyphIns;
965          glyph->control_len  = n_ins;
966
967          error = TT_Set_CodeRange( exec,
968                                    tt_coderange_glyph,
969                                    exec->glyphIns,
970                                    n_ins );
971          if ( error )
972            goto Fail;
973
974          /* prepare the execution context */
975          tt_prepare_zone( &exec->pts, &gloader->base, start_point, start_contour );
976          pts = &exec->pts;
977
978          pts->n_points   = num_points + 2;
979          pts->n_contours = num_contours;
980
981          /* add phantom points */
982          pp1    = pts->cur + num_points;
983          pp1[0] = loader->pp1;
984          pp1[1] = loader->pp2;
985
986          pts->tags[num_points + 1] = 0;
987          pts->tags[num_points + 2] = 0;
988
989          /* if hinting, round the phantom points */
990          if ( IS_HINTED( loader->load_flags ) )
991          {
992            pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 );
993            pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 );
994          }
995
996          {
997            FT_UInt  k;
998
999
1000            for ( k = 0; k < n_points; k++ )
1001              pts->tags[k] &= FT_Curve_Tag_On;
1002          }
1003
1004          cur_to_org( n_points, pts );
1005
1006          /* now consider hinting */
1007          if ( IS_HINTED(loader->load_flags) && n_ins > 0 )
1008          {
1009            exec->is_composite     = TRUE;
1010            exec->pedantic_hinting =
1011                (FT_Bool)(loader->load_flags & FT_LOAD_PEDANTIC);
1012
1013            error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug );
1014            if ( error && exec->pedantic_hinting )
1015              goto Fail;
1016          }
1017
1018          /* save glyph origin and advance points */
1019          loader->pp1 = pp1[0];
1020          loader->pp2 = pp1[1];
1021        }
1022#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1023      }
1024      /* end of composite loading */
1025    }
1026
1027    /***********************************************************************/
1028    /***********************************************************************/
1029    /***********************************************************************/
1030    /***********************************************************************/
1031
1032  Fail:
1033    if (opened_frame)
1034      TT_Forget_Glyph_Frame( loader );
1035
1036  Exit:
1037    return error;
1038  }
1039
1040
1041  static
1042  void  compute_glyph_metrics( TT_Loader*  loader,
1043                               FT_UInt     glyph_index )
1044  {
1045    FT_BBox       bbox;
1046    TT_Face       face = (TT_Face)loader->face;
1047    FT_Fixed      x_scale, y_scale;
1048    TT_GlyphSlot  glyph = loader->glyph;
1049    TT_Size       size = (TT_Size)loader->size;
1050
1051    x_scale = 0x10000L;
1052    y_scale = 0x10000L;
1053    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
1054    {
1055      x_scale = size->root.metrics.x_scale;
1056      y_scale = size->root.metrics.y_scale;
1057    }
1058
1059    if ( glyph->format != ft_glyph_format_composite )
1060    {
1061      glyph->outline.flags &= ~ft_outline_single_pass;
1062
1063      /* copy outline to our glyph slot */
1064      FT_GlyphLoader_Copy_Points( glyph->loader, loader->gloader );
1065      glyph->outline = glyph->loader->base.outline;
1066
1067      /* translate array so that (0,0) is the glyph's origin */
1068      FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 );
1069
1070      FT_Outline_Get_CBox( &glyph->outline, &bbox );
1071
1072      if ( IS_HINTED( loader->load_flags ) )
1073      {
1074        /* grid-fit the bounding box */
1075        bbox.xMin &= -64;
1076        bbox.yMin &= -64;
1077        bbox.xMax  = ( bbox.xMax + 63 ) & -64;
1078        bbox.yMax  = ( bbox.yMax + 63 ) & -64;
1079      }
1080    }
1081    else
1082      bbox = loader->bbox;
1083
1084    /* get the device-independent horizontal advance. It is scaled later */
1085    /* by the base layer..                                               */
1086    {
1087      FT_Pos  advance = loader->advance;
1088
1089      /* the flag FT_LOAD_NO_ADVANCE_CHECK was introduced to      */
1090      /* correctly support DynaLab fonts, which have an incorrect */
1091      /* `advance_Width_Max' field!  It is used, to my knowledge, */
1092      /* exclusively in the X-TrueType font server.               */
1093      /*                                                          */
1094      if ( face->postscript.isFixedPitch                                    &&
1095           ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 )
1096        advance = face->horizontal.advance_Width_Max;
1097
1098      /* we need to return the advance in font units in linearHoriAdvance, */
1099      /* it will be scaled later by the base layer..                       */
1100      glyph->linearHoriAdvance = advance;
1101    }
1102
1103    glyph->metrics.horiBearingX = bbox.xMin;
1104    glyph->metrics.horiBearingY = bbox.yMax;
1105    glyph->metrics.horiAdvance  = loader->pp2.x - loader->pp1.x;
1106
1107    /* Now take care of vertical metrics.  In the case where there is    */
1108    /* no vertical information within the font (relatively common), make */
1109    /* up some metrics by `hand'...                                      */
1110
1111    {
1112      FT_Short   top_bearing;    /* vertical top side bearing (EM units) */
1113      FT_UShort  advance_height; /* vertical advance height   (EM units) */
1114
1115      FT_Pos  left;     /* scaled vertical left side bearing         */
1116      FT_Pos  Top;      /* scaled original vertical top side bearing */
1117      FT_Pos  top;      /* scaled vertical top side bearing          */
1118      FT_Pos  advance;  /* scaled vertical advance height            */
1119
1120
1121      /* Get the unscaled `tsb' and `ah' */
1122      if ( face->vertical_info                   &&
1123           face->vertical.number_Of_VMetrics > 0 )
1124      {
1125        /* Don't assume that both the vertical header and vertical */
1126        /* metrics are present in the same font :-)                */
1127
1128        TT_Get_Metrics( (TT_HoriHeader*)&face->vertical,
1129                        glyph_index,
1130                        &top_bearing,
1131                        &advance_height );
1132      }
1133      else
1134      {
1135        /* Make up the distances from the horizontal header.   */
1136
1137        /* NOTE: The OS/2 values are the only `portable' ones, */
1138        /*       which is why we use them, if there is an OS/2 */
1139        /*       table in the font.  Otherwise, we use the     */
1140        /*       values defined in the horizontal header.      */
1141        /*                                                     */
1142        /* NOTE2: The sTypoDescender is negative, which is why */
1143        /*        we compute the baseline-to-baseline distance */
1144        /*        here with:                                   */
1145        /*             ascender - descender + linegap          */
1146        /*                                                     */
1147        if ( face->os2.version != 0xFFFF )
1148        {
1149          top_bearing    = face->os2.sTypoLineGap / 2;
1150          advance_height = (FT_UShort)( face->os2.sTypoAscender -
1151                                        face->os2.sTypoDescender +
1152                                        face->os2.sTypoLineGap );
1153        }
1154        else
1155        {
1156          top_bearing    = face->horizontal.Line_Gap / 2;
1157          advance_height = (FT_UShort)( face->horizontal.Ascender  +
1158                                        face->horizontal.Descender +
1159                                        face->horizontal.Line_Gap );
1160        }
1161      }
1162
1163      /* We must adjust the top_bearing value from the bounding box given */
1164      /* in the glyph header to te bounding box calculated with           */
1165      /* FT_Get_Outline_CBox().                                           */
1166
1167      /* scale the metrics */
1168      if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) )
1169      {
1170        Top     = FT_MulFix( top_bearing, y_scale );
1171        top     = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale )
1172                    - bbox.yMax;
1173        advance = FT_MulFix( advance_height, y_scale );
1174      }
1175      else
1176      {
1177        Top     = top_bearing;
1178        top     = top_bearing + loader->bbox.yMax - bbox.yMax;
1179        advance = advance_height;
1180      }
1181
1182      /* set the advance height in design units. It is scaled later by the */
1183      /* base layer..                                                      */
1184      glyph->linearVertAdvance = advance_height;
1185
1186      /* XXX: for now, we have no better algorithm for the lsb, but it    */
1187      /*      should work fine.                                           */
1188      /*                                                                  */
1189      left = ( bbox.xMin - bbox.xMax ) / 2;
1190
1191      /* grid-fit them if necessary */
1192      if ( IS_HINTED( loader->load_flags ) )
1193      {
1194        left   &= -64;
1195        top     = ( top + 63     ) & -64;
1196        advance = ( advance + 32 ) & -64;
1197      }
1198
1199      glyph->metrics.vertBearingX = left;
1200      glyph->metrics.vertBearingY = top;
1201      glyph->metrics.vertAdvance  = advance;
1202    }
1203
1204    /* Adjust advance width to the value contained in the hdmx table. */
1205    if ( !face->postscript.isFixedPitch && size &&
1206         IS_HINTED( loader->load_flags )        )
1207    {
1208      FT_Byte* widths = Get_Advance_Widths( face,
1209                                            size->root.metrics.x_ppem );
1210      if ( widths )
1211        glyph->metrics.horiAdvance = widths[glyph_index] << 6;
1212    }
1213
1214    /* set glyph dimensions */
1215    glyph->metrics.width  = bbox.xMax - bbox.xMin;
1216    glyph->metrics.height = bbox.yMax - bbox.yMin;
1217
1218  }
1219
1220
1221  /*************************************************************************/
1222  /*                                                                       */
1223  /* <Function>                                                            */
1224  /*    TT_Load_Glyph                                                      */
1225  /*                                                                       */
1226  /* <Description>                                                         */
1227  /*    A function used to load a single glyph within a given glyph slot,  */
1228  /*    for a given size.                                                  */
1229  /*                                                                       */
1230  /* <Input>                                                               */
1231  /*    glyph       :: A handle to a target slot object where the glyph    */
1232  /*                   will be loaded.                                     */
1233  /*                                                                       */
1234  /*    size        :: A handle to the source face size at which the glyph */
1235  /*                   must be scaled/loaded.                              */
1236  /*                                                                       */
1237  /*    glyph_index :: The index of the glyph in the font file.            */
1238  /*                                                                       */
1239  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
1240  /*                   FT_LOAD_XXX constants can be used to control the    */
1241  /*                   glyph loading process (e.g., whether the outline    */
1242  /*                   should be scaled, whether to load bitmaps or not,   */
1243  /*                   whether to hint the outline, etc).                  */
1244  /*                                                                       */
1245  /* <Return>                                                              */
1246  /*    TrueType error code.  0 means success.                             */
1247  /*                                                                       */
1248  LOCAL_FUNC
1249  FT_Error  TT_Load_Glyph( TT_Size       size,
1250                           TT_GlyphSlot  glyph,
1251                           FT_UShort     glyph_index,
1252                           FT_UInt       load_flags )
1253  {
1254    SFNT_Interface*  sfnt;
1255    TT_Face          face;
1256    FT_Stream        stream;
1257    FT_Memory        memory;
1258    FT_Error         error;
1259    TT_Loader        loader;
1260
1261
1262    face   = (TT_Face)glyph->face;
1263    sfnt   = (SFNT_Interface*)face->sfnt;
1264    stream = face->root.stream;
1265    memory = face->root.memory;
1266    error  = 0;
1267
1268    if ( !size || ( load_flags & FT_LOAD_NO_SCALE )   ||
1269                  ( load_flags & FT_LOAD_NO_RECURSE ) )
1270    {
1271      size        = NULL;
1272      load_flags |= FT_LOAD_NO_SCALE   |
1273                    FT_LOAD_NO_HINTING |
1274                    FT_LOAD_NO_BITMAP;
1275    }
1276
1277    glyph->num_subglyphs = 0;
1278
1279#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1280
1281    /* try to load embedded bitmap if any */
1282    if ( size                                    &&
1283         ( load_flags & FT_LOAD_NO_BITMAP ) == 0 &&
1284         sfnt->load_sbits                        )
1285    {
1286      TT_SBit_Metrics  metrics;
1287
1288
1289      error = sfnt->load_sbit_image( face,
1290                                     size->root.metrics.x_ppem,
1291                                     size->root.metrics.y_ppem,
1292                                     glyph_index,
1293                                     load_flags,
1294                                     stream,
1295                                     &glyph->bitmap,
1296                                     &metrics );
1297      if ( !error )
1298      {
1299        glyph->outline.n_points   = 0;
1300        glyph->outline.n_contours = 0;
1301
1302        glyph->metrics.width  = (FT_Pos)metrics.width  << 6;
1303        glyph->metrics.height = (FT_Pos)metrics.height << 6;
1304
1305        glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6;
1306        glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6;
1307        glyph->metrics.horiAdvance  = (FT_Pos)metrics.horiAdvance  << 6;
1308
1309        glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6;
1310        glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6;
1311        glyph->metrics.vertAdvance  = (FT_Pos)metrics.vertAdvance  << 6;
1312
1313        glyph->format = ft_glyph_format_bitmap;
1314        if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
1315        {
1316          glyph->bitmap_left = metrics.horiBearingX;
1317          glyph->bitmap_top  = metrics.horiBearingY;
1318        }
1319        else
1320        {
1321          glyph->bitmap_left = metrics.vertBearingX;
1322          glyph->bitmap_top  = metrics.vertBearingY;
1323        }
1324        return error;
1325      }
1326    }
1327
1328#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
1329
1330    /* seek to the beginning of the glyph table.  For Type 43 fonts      */
1331    /* the table might be accessed from a Postscript stream or something */
1332    /* else...                                                           */
1333
1334    error = face->goto_table( face, TTAG_glyf, stream, 0 );
1335    if ( error )
1336    {
1337      FT_ERROR(( "TT_Load_Glyph: Could not access glyph table\n" ));
1338      goto Exit;
1339    }
1340
1341    MEM_Set( &loader, 0, sizeof ( loader ) );
1342
1343    /* update the glyph zone bounds */
1344    {
1345      FT_GlyphLoader*  gloader = FT_FACE_DRIVER(face)->glyph_loader;
1346
1347      loader.gloader = gloader;
1348
1349      FT_GlyphLoader_Rewind( gloader );
1350
1351      tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 );
1352      tt_prepare_zone( &loader.base, &gloader->base, 0, 0 );
1353    }
1354
1355#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1356
1357    if ( size )
1358    {
1359      /* query new execution context */
1360      loader.exec = size->debug ? size->context : TT_New_Context( face );
1361      if ( !loader.exec )
1362        return TT_Err_Could_Not_Find_Context;
1363
1364      TT_Load_Context( loader.exec, face, size );
1365      loader.instructions = loader.exec->glyphIns;
1366
1367      /* load default graphics state - if needed */
1368      if ( size->GS.instruct_control & 2 )
1369        loader.exec->GS = tt_default_graphics_state;
1370    }
1371
1372#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1373
1374    /* clear all outline flags, except the `owner' one */
1375    glyph->outline.flags &= ft_outline_owner;
1376
1377    if ( size && size->root.metrics.y_ppem < 24 )
1378      glyph->outline.flags |= ft_outline_high_precision;
1379
1380    /* let's initialize the rest of our loader now */
1381
1382    loader.load_flags    = load_flags;
1383
1384    loader.face   = (FT_Face)face;
1385    loader.size   = (FT_Size)size;
1386    loader.glyph  = (FT_GlyphSlot)glyph;
1387    loader.stream = stream;
1388
1389    loader.glyf_offset  = FILE_Pos();
1390
1391#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1392
1393    /* if the cvt program has disabled hinting, the argument */
1394    /* is ignored.                                           */
1395    if ( size && ( size->GS.instruct_control & 1 ) )
1396      loader.load_flags |= FT_LOAD_NO_HINTING;
1397
1398#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */
1399
1400    /* Main loading loop */
1401    glyph->format        = ft_glyph_format_outline;
1402    glyph->num_subglyphs = 0;
1403    error = load_truetype_glyph( &loader, glyph_index );
1404    if ( !error )
1405      compute_glyph_metrics( &loader, glyph_index );
1406
1407#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER
1408    if ( !size || !size->debug )
1409      TT_Done_Context( loader.exec );
1410#endif
1411
1412  Exit:
1413    return error;
1414  }
1415
1416
1417/* END */
1418