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