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