xref: /inferno-os/libfreetype/pfrgload.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  pfrgload.c                                                             */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType PFR glyph loader (body).                                    */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2002 by                                                      */
8*37da2899SCharles.Forsyth /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9*37da2899SCharles.Forsyth /*                                                                         */
10*37da2899SCharles.Forsyth /*  This file is part of the FreeType project, and may only be used,       */
11*37da2899SCharles.Forsyth /*  modified, and distributed under the terms of the FreeType project      */
12*37da2899SCharles.Forsyth /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13*37da2899SCharles.Forsyth /*  this file you indicate that you have read the license and              */
14*37da2899SCharles.Forsyth /*  understand and accept it fully.                                        */
15*37da2899SCharles.Forsyth /*                                                                         */
16*37da2899SCharles.Forsyth /***************************************************************************/
17*37da2899SCharles.Forsyth 
18*37da2899SCharles.Forsyth 
19*37da2899SCharles.Forsyth #include "pfrgload.h"
20*37da2899SCharles.Forsyth #include "pfrsbit.h"
21*37da2899SCharles.Forsyth #include "pfrload.h"            /* for macro definitions */
22*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
23*37da2899SCharles.Forsyth 
24*37da2899SCharles.Forsyth #include "pfrerror.h"
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth #undef  FT_COMPONENT
27*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_pfr
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth 
30*37da2899SCharles.Forsyth   /*************************************************************************/
31*37da2899SCharles.Forsyth   /*************************************************************************/
32*37da2899SCharles.Forsyth   /*****                                                               *****/
33*37da2899SCharles.Forsyth   /*****                      PFR GLYPH BUILDER                        *****/
34*37da2899SCharles.Forsyth   /*****                                                               *****/
35*37da2899SCharles.Forsyth   /*************************************************************************/
36*37da2899SCharles.Forsyth   /*************************************************************************/
37*37da2899SCharles.Forsyth 
38*37da2899SCharles.Forsyth 
39*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
pfr_glyph_init(PFR_Glyph glyph,FT_GlyphLoader loader)40*37da2899SCharles.Forsyth   pfr_glyph_init( PFR_Glyph       glyph,
41*37da2899SCharles.Forsyth                   FT_GlyphLoader  loader )
42*37da2899SCharles.Forsyth   {
43*37da2899SCharles.Forsyth     FT_ZERO( glyph );
44*37da2899SCharles.Forsyth 
45*37da2899SCharles.Forsyth     glyph->loader     = loader;
46*37da2899SCharles.Forsyth     glyph->path_begun = 0;
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth     FT_GlyphLoader_Rewind( loader );
49*37da2899SCharles.Forsyth   }
50*37da2899SCharles.Forsyth 
51*37da2899SCharles.Forsyth 
52*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
pfr_glyph_done(PFR_Glyph glyph)53*37da2899SCharles.Forsyth   pfr_glyph_done( PFR_Glyph  glyph )
54*37da2899SCharles.Forsyth   {
55*37da2899SCharles.Forsyth     FT_Memory  memory = glyph->loader->memory;
56*37da2899SCharles.Forsyth 
57*37da2899SCharles.Forsyth 
58*37da2899SCharles.Forsyth     FT_FREE( glyph->x_control );
59*37da2899SCharles.Forsyth     glyph->y_control = NULL;
60*37da2899SCharles.Forsyth 
61*37da2899SCharles.Forsyth     glyph->max_xy_control = 0;
62*37da2899SCharles.Forsyth     glyph->num_x_control  = 0;
63*37da2899SCharles.Forsyth     glyph->num_y_control  = 0;
64*37da2899SCharles.Forsyth 
65*37da2899SCharles.Forsyth     FT_FREE( glyph->subs );
66*37da2899SCharles.Forsyth 
67*37da2899SCharles.Forsyth     glyph->max_subs = 0;
68*37da2899SCharles.Forsyth     glyph->num_subs = 0;
69*37da2899SCharles.Forsyth 
70*37da2899SCharles.Forsyth     glyph->loader     = NULL;
71*37da2899SCharles.Forsyth     glyph->path_begun = 0;
72*37da2899SCharles.Forsyth   }
73*37da2899SCharles.Forsyth 
74*37da2899SCharles.Forsyth 
75*37da2899SCharles.Forsyth   /* close current contour, if any */
76*37da2899SCharles.Forsyth   static void
pfr_glyph_close_contour(PFR_Glyph glyph)77*37da2899SCharles.Forsyth   pfr_glyph_close_contour( PFR_Glyph  glyph )
78*37da2899SCharles.Forsyth   {
79*37da2899SCharles.Forsyth     FT_GlyphLoader  loader  = glyph->loader;
80*37da2899SCharles.Forsyth     FT_Outline*     outline = &loader->current.outline;
81*37da2899SCharles.Forsyth     FT_Int          last, first;
82*37da2899SCharles.Forsyth 
83*37da2899SCharles.Forsyth 
84*37da2899SCharles.Forsyth     if ( !glyph->path_begun )
85*37da2899SCharles.Forsyth       return;
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth     /* compute first and last point indices in current glyph outline */
88*37da2899SCharles.Forsyth     last  = outline->n_points - 1;
89*37da2899SCharles.Forsyth     first = 0;
90*37da2899SCharles.Forsyth     if ( outline->n_contours > 0 )
91*37da2899SCharles.Forsyth       first = outline->contours[outline->n_contours - 1];
92*37da2899SCharles.Forsyth 
93*37da2899SCharles.Forsyth     /* if the last point falls on the same location than the first one */
94*37da2899SCharles.Forsyth     /* we need to delete it                                            */
95*37da2899SCharles.Forsyth     if ( last > first )
96*37da2899SCharles.Forsyth     {
97*37da2899SCharles.Forsyth       FT_Vector*  p1 = outline->points + first;
98*37da2899SCharles.Forsyth       FT_Vector*  p2 = outline->points + last;
99*37da2899SCharles.Forsyth 
100*37da2899SCharles.Forsyth 
101*37da2899SCharles.Forsyth       if ( p1->x == p2->x && p1->y == p2->y )
102*37da2899SCharles.Forsyth       {
103*37da2899SCharles.Forsyth         outline->n_points--;
104*37da2899SCharles.Forsyth         last--;
105*37da2899SCharles.Forsyth       }
106*37da2899SCharles.Forsyth     }
107*37da2899SCharles.Forsyth 
108*37da2899SCharles.Forsyth     /* don't add empty contours */
109*37da2899SCharles.Forsyth     if ( last >= first )
110*37da2899SCharles.Forsyth       outline->contours[outline->n_contours++] = (short)last;
111*37da2899SCharles.Forsyth 
112*37da2899SCharles.Forsyth     glyph->path_begun = 0;
113*37da2899SCharles.Forsyth   }
114*37da2899SCharles.Forsyth 
115*37da2899SCharles.Forsyth 
116*37da2899SCharles.Forsyth   /* reset glyph to start the loading of a new glyph */
117*37da2899SCharles.Forsyth   static void
pfr_glyph_start(PFR_Glyph glyph)118*37da2899SCharles.Forsyth   pfr_glyph_start( PFR_Glyph  glyph )
119*37da2899SCharles.Forsyth   {
120*37da2899SCharles.Forsyth     glyph->path_begun = 0;
121*37da2899SCharles.Forsyth   }
122*37da2899SCharles.Forsyth 
123*37da2899SCharles.Forsyth 
124*37da2899SCharles.Forsyth   static FT_Error
pfr_glyph_line_to(PFR_Glyph glyph,FT_Vector * to)125*37da2899SCharles.Forsyth   pfr_glyph_line_to( PFR_Glyph   glyph,
126*37da2899SCharles.Forsyth                      FT_Vector*  to )
127*37da2899SCharles.Forsyth   {
128*37da2899SCharles.Forsyth     FT_GlyphLoader  loader  = glyph->loader;
129*37da2899SCharles.Forsyth     FT_Outline*     outline = &loader->current.outline;
130*37da2899SCharles.Forsyth     FT_Error        error;
131*37da2899SCharles.Forsyth 
132*37da2899SCharles.Forsyth 
133*37da2899SCharles.Forsyth     /* check that we have begun a new path */
134*37da2899SCharles.Forsyth     FT_ASSERT( glyph->path_begun != 0 );
135*37da2899SCharles.Forsyth 
136*37da2899SCharles.Forsyth     error = FT_GlyphLoader_CheckPoints( loader, 1, 0 );
137*37da2899SCharles.Forsyth     if ( !error )
138*37da2899SCharles.Forsyth     {
139*37da2899SCharles.Forsyth       FT_UInt  n = outline->n_points;
140*37da2899SCharles.Forsyth 
141*37da2899SCharles.Forsyth 
142*37da2899SCharles.Forsyth       outline->points[n] = *to;
143*37da2899SCharles.Forsyth       outline->tags  [n] = FT_CURVE_TAG_ON;
144*37da2899SCharles.Forsyth 
145*37da2899SCharles.Forsyth       outline->n_points++;
146*37da2899SCharles.Forsyth     }
147*37da2899SCharles.Forsyth 
148*37da2899SCharles.Forsyth     return error;
149*37da2899SCharles.Forsyth   }
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth 
152*37da2899SCharles.Forsyth   static FT_Error
pfr_glyph_curve_to(PFR_Glyph glyph,FT_Vector * control1,FT_Vector * control2,FT_Vector * to)153*37da2899SCharles.Forsyth   pfr_glyph_curve_to( PFR_Glyph   glyph,
154*37da2899SCharles.Forsyth                       FT_Vector*  control1,
155*37da2899SCharles.Forsyth                       FT_Vector*  control2,
156*37da2899SCharles.Forsyth                       FT_Vector*  to )
157*37da2899SCharles.Forsyth   {
158*37da2899SCharles.Forsyth     FT_GlyphLoader  loader  = glyph->loader;
159*37da2899SCharles.Forsyth     FT_Outline*     outline = &loader->current.outline;
160*37da2899SCharles.Forsyth     FT_Error        error;
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth 
163*37da2899SCharles.Forsyth     /* check that we have begun a new path */
164*37da2899SCharles.Forsyth     FT_ASSERT( glyph->path_begun != 0 );
165*37da2899SCharles.Forsyth 
166*37da2899SCharles.Forsyth     error = FT_GlyphLoader_CheckPoints( loader, 3, 0 );
167*37da2899SCharles.Forsyth     if ( !error )
168*37da2899SCharles.Forsyth     {
169*37da2899SCharles.Forsyth       FT_Vector*  vec = outline->points         + outline->n_points;
170*37da2899SCharles.Forsyth       FT_Byte*    tag = (FT_Byte*)outline->tags + outline->n_points;
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth 
173*37da2899SCharles.Forsyth       vec[0] = *control1;
174*37da2899SCharles.Forsyth       vec[1] = *control2;
175*37da2899SCharles.Forsyth       vec[2] = *to;
176*37da2899SCharles.Forsyth       tag[0] = FT_CURVE_TAG_CUBIC;
177*37da2899SCharles.Forsyth       tag[1] = FT_CURVE_TAG_CUBIC;
178*37da2899SCharles.Forsyth       tag[2] = FT_CURVE_TAG_ON;
179*37da2899SCharles.Forsyth 
180*37da2899SCharles.Forsyth       outline->n_points = (FT_Short)( outline->n_points + 3 );
181*37da2899SCharles.Forsyth     }
182*37da2899SCharles.Forsyth 
183*37da2899SCharles.Forsyth     return error;
184*37da2899SCharles.Forsyth   }
185*37da2899SCharles.Forsyth 
186*37da2899SCharles.Forsyth 
187*37da2899SCharles.Forsyth   static FT_Error
pfr_glyph_move_to(PFR_Glyph glyph,FT_Vector * to)188*37da2899SCharles.Forsyth   pfr_glyph_move_to( PFR_Glyph   glyph,
189*37da2899SCharles.Forsyth                      FT_Vector*  to )
190*37da2899SCharles.Forsyth   {
191*37da2899SCharles.Forsyth     FT_GlyphLoader  loader  = glyph->loader;
192*37da2899SCharles.Forsyth     FT_Error        error;
193*37da2899SCharles.Forsyth 
194*37da2899SCharles.Forsyth 
195*37da2899SCharles.Forsyth     /* close current contour if any */
196*37da2899SCharles.Forsyth     pfr_glyph_close_contour( glyph );
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth     /* indicate that a new contour has started */
199*37da2899SCharles.Forsyth     glyph->path_begun = 1;
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth     /* check that there is room for a new contour and a new point */
202*37da2899SCharles.Forsyth     error = FT_GlyphLoader_CheckPoints( loader, 1, 1 );
203*37da2899SCharles.Forsyth     if ( !error )
204*37da2899SCharles.Forsyth       /* add new start point */
205*37da2899SCharles.Forsyth       error = pfr_glyph_line_to( glyph, to );
206*37da2899SCharles.Forsyth 
207*37da2899SCharles.Forsyth     return error;
208*37da2899SCharles.Forsyth   }
209*37da2899SCharles.Forsyth 
210*37da2899SCharles.Forsyth 
211*37da2899SCharles.Forsyth   static void
pfr_glyph_end(PFR_Glyph glyph)212*37da2899SCharles.Forsyth   pfr_glyph_end( PFR_Glyph  glyph )
213*37da2899SCharles.Forsyth   {
214*37da2899SCharles.Forsyth     /* close current contour if any */
215*37da2899SCharles.Forsyth     pfr_glyph_close_contour( glyph );
216*37da2899SCharles.Forsyth 
217*37da2899SCharles.Forsyth     /* merge the current glyph into the stack */
218*37da2899SCharles.Forsyth     FT_GlyphLoader_Add( glyph->loader );
219*37da2899SCharles.Forsyth   }
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth 
222*37da2899SCharles.Forsyth   /*************************************************************************/
223*37da2899SCharles.Forsyth   /*************************************************************************/
224*37da2899SCharles.Forsyth   /*****                                                               *****/
225*37da2899SCharles.Forsyth   /*****                      PFR GLYPH LOADER                         *****/
226*37da2899SCharles.Forsyth   /*****                                                               *****/
227*37da2899SCharles.Forsyth   /*************************************************************************/
228*37da2899SCharles.Forsyth   /*************************************************************************/
229*37da2899SCharles.Forsyth 
230*37da2899SCharles.Forsyth 
231*37da2899SCharles.Forsyth   /* load a simple glyph */
232*37da2899SCharles.Forsyth   static FT_Error
pfr_glyph_load_simple(PFR_Glyph glyph,FT_Byte * p,FT_Byte * limit)233*37da2899SCharles.Forsyth   pfr_glyph_load_simple( PFR_Glyph  glyph,
234*37da2899SCharles.Forsyth                          FT_Byte*   p,
235*37da2899SCharles.Forsyth                          FT_Byte*   limit )
236*37da2899SCharles.Forsyth   {
237*37da2899SCharles.Forsyth     FT_Error   error  = 0;
238*37da2899SCharles.Forsyth     FT_Memory  memory = glyph->loader->memory;
239*37da2899SCharles.Forsyth     FT_UInt    flags, x_count, y_count, i, count, mask;
240*37da2899SCharles.Forsyth     FT_Int     x;
241*37da2899SCharles.Forsyth 
242*37da2899SCharles.Forsyth 
243*37da2899SCharles.Forsyth     PFR_CHECK( 1 );
244*37da2899SCharles.Forsyth     flags = PFR_NEXT_BYTE( p );
245*37da2899SCharles.Forsyth 
246*37da2899SCharles.Forsyth     /* test for composite glyphs */
247*37da2899SCharles.Forsyth     FT_ASSERT( ( flags & PFR_GLYPH_IS_COMPOUND ) == 0 );
248*37da2899SCharles.Forsyth 
249*37da2899SCharles.Forsyth     x_count = 0;
250*37da2899SCharles.Forsyth     y_count = 0;
251*37da2899SCharles.Forsyth 
252*37da2899SCharles.Forsyth     if ( flags & PFR_GLYPH_1BYTE_XYCOUNT )
253*37da2899SCharles.Forsyth     {
254*37da2899SCharles.Forsyth       PFR_CHECK( 1 );
255*37da2899SCharles.Forsyth       count   = PFR_NEXT_BYTE( p );
256*37da2899SCharles.Forsyth       x_count = ( count & 15 );
257*37da2899SCharles.Forsyth       y_count = ( count >> 4 );
258*37da2899SCharles.Forsyth     }
259*37da2899SCharles.Forsyth     else
260*37da2899SCharles.Forsyth     {
261*37da2899SCharles.Forsyth       if ( flags & PFR_GLYPH_XCOUNT )
262*37da2899SCharles.Forsyth       {
263*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
264*37da2899SCharles.Forsyth         x_count = PFR_NEXT_BYTE( p );
265*37da2899SCharles.Forsyth       }
266*37da2899SCharles.Forsyth 
267*37da2899SCharles.Forsyth       if ( flags & PFR_GLYPH_YCOUNT )
268*37da2899SCharles.Forsyth       {
269*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
270*37da2899SCharles.Forsyth         y_count = PFR_NEXT_BYTE( p );
271*37da2899SCharles.Forsyth       }
272*37da2899SCharles.Forsyth     }
273*37da2899SCharles.Forsyth 
274*37da2899SCharles.Forsyth     count = x_count + y_count;
275*37da2899SCharles.Forsyth 
276*37da2899SCharles.Forsyth     /* re-allocate array when necessary */
277*37da2899SCharles.Forsyth     if ( count > glyph->max_xy_control )
278*37da2899SCharles.Forsyth     {
279*37da2899SCharles.Forsyth       FT_UInt  new_max = ( count + 7 ) & -8;
280*37da2899SCharles.Forsyth 
281*37da2899SCharles.Forsyth 
282*37da2899SCharles.Forsyth       if ( FT_RENEW_ARRAY( glyph->x_control,
283*37da2899SCharles.Forsyth                            glyph->max_xy_control,
284*37da2899SCharles.Forsyth                            new_max ) )
285*37da2899SCharles.Forsyth         goto Exit;
286*37da2899SCharles.Forsyth 
287*37da2899SCharles.Forsyth       glyph->max_xy_control = new_max;
288*37da2899SCharles.Forsyth     }
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth     glyph->y_control = glyph->x_control + x_count;
291*37da2899SCharles.Forsyth 
292*37da2899SCharles.Forsyth     mask  = 0;
293*37da2899SCharles.Forsyth     x     = 0;
294*37da2899SCharles.Forsyth 
295*37da2899SCharles.Forsyth     for ( i = 0; i < count; i++ )
296*37da2899SCharles.Forsyth     {
297*37da2899SCharles.Forsyth       if ( ( i & 7 ) == 0 )
298*37da2899SCharles.Forsyth       {
299*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
300*37da2899SCharles.Forsyth         mask = PFR_NEXT_BYTE( p );
301*37da2899SCharles.Forsyth       }
302*37da2899SCharles.Forsyth 
303*37da2899SCharles.Forsyth       if ( mask & 1 )
304*37da2899SCharles.Forsyth       {
305*37da2899SCharles.Forsyth         PFR_CHECK( 2 );
306*37da2899SCharles.Forsyth         x = PFR_NEXT_SHORT( p );
307*37da2899SCharles.Forsyth       }
308*37da2899SCharles.Forsyth       else
309*37da2899SCharles.Forsyth       {
310*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
311*37da2899SCharles.Forsyth         x += PFR_NEXT_BYTE( p );
312*37da2899SCharles.Forsyth       }
313*37da2899SCharles.Forsyth 
314*37da2899SCharles.Forsyth       glyph->x_control[i] = x;
315*37da2899SCharles.Forsyth 
316*37da2899SCharles.Forsyth       mask >>= 1;
317*37da2899SCharles.Forsyth     }
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth     /* XXX: for now we ignore the secondary stroke and edge definitions */
320*37da2899SCharles.Forsyth     /*      since we don't want to support native PFR hinting           */
321*37da2899SCharles.Forsyth     /*                                                                  */
322*37da2899SCharles.Forsyth     if ( flags & PFR_GLYPH_EXTRA_ITEMS )
323*37da2899SCharles.Forsyth     {
324*37da2899SCharles.Forsyth       error = pfr_extra_items_skip( &p, limit );
325*37da2899SCharles.Forsyth       if ( error )
326*37da2899SCharles.Forsyth         goto Exit;
327*37da2899SCharles.Forsyth     }
328*37da2899SCharles.Forsyth 
329*37da2899SCharles.Forsyth     pfr_glyph_start( glyph );
330*37da2899SCharles.Forsyth 
331*37da2899SCharles.Forsyth     /* now load a simple glyph */
332*37da2899SCharles.Forsyth     {
333*37da2899SCharles.Forsyth       FT_Vector   pos[4];
334*37da2899SCharles.Forsyth       FT_Vector*  cur;
335*37da2899SCharles.Forsyth 
336*37da2899SCharles.Forsyth 
337*37da2899SCharles.Forsyth       pos[0].x = pos[0].y = 0;
338*37da2899SCharles.Forsyth       pos[3]   = pos[0];
339*37da2899SCharles.Forsyth 
340*37da2899SCharles.Forsyth       for (;;)
341*37da2899SCharles.Forsyth       {
342*37da2899SCharles.Forsyth         FT_Int  format, args_format = 0, args_count, n;
343*37da2899SCharles.Forsyth 
344*37da2899SCharles.Forsyth 
345*37da2899SCharles.Forsyth         /***************************************************************/
346*37da2899SCharles.Forsyth         /*  read instruction                                           */
347*37da2899SCharles.Forsyth         /*                                                             */
348*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
349*37da2899SCharles.Forsyth         format = PFR_NEXT_BYTE( p );
350*37da2899SCharles.Forsyth 
351*37da2899SCharles.Forsyth         switch ( format >> 4 )
352*37da2899SCharles.Forsyth         {
353*37da2899SCharles.Forsyth         case 0:                             /* end glyph */
354*37da2899SCharles.Forsyth           FT_TRACE6(( "- end glyph" ));
355*37da2899SCharles.Forsyth           args_count = 0;
356*37da2899SCharles.Forsyth           break;
357*37da2899SCharles.Forsyth 
358*37da2899SCharles.Forsyth         case 1:                             /* general line operation */
359*37da2899SCharles.Forsyth           FT_TRACE6(( "- general line" ));
360*37da2899SCharles.Forsyth           goto Line1;
361*37da2899SCharles.Forsyth 
362*37da2899SCharles.Forsyth         case 4:                             /* move to inside contour  */
363*37da2899SCharles.Forsyth           FT_TRACE6(( "- move to inside" ));
364*37da2899SCharles.Forsyth           goto Line1;
365*37da2899SCharles.Forsyth 
366*37da2899SCharles.Forsyth         case 5:                             /* move to outside contour */
367*37da2899SCharles.Forsyth           FT_TRACE6(( "- move to outside" ));
368*37da2899SCharles.Forsyth         Line1:
369*37da2899SCharles.Forsyth           args_format = format & 15;
370*37da2899SCharles.Forsyth           args_count  = 1;
371*37da2899SCharles.Forsyth           break;
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth         case 2:                             /* horizontal line to */
374*37da2899SCharles.Forsyth           FT_TRACE6(( "- horizontal line to cx.%d", format & 15 ));
375*37da2899SCharles.Forsyth           pos[0].y   = pos[3].y;
376*37da2899SCharles.Forsyth           pos[0].x   = glyph->x_control[format & 15];
377*37da2899SCharles.Forsyth           pos[3]     = pos[0];
378*37da2899SCharles.Forsyth           args_count = 0;
379*37da2899SCharles.Forsyth           break;
380*37da2899SCharles.Forsyth 
381*37da2899SCharles.Forsyth         case 3:                             /* vertical line to */
382*37da2899SCharles.Forsyth           FT_TRACE6(( "- vertical line to cy.%d", format & 15 ));
383*37da2899SCharles.Forsyth           pos[0].x   = pos[3].x;
384*37da2899SCharles.Forsyth           pos[0].y   = glyph->y_control[format & 15];
385*37da2899SCharles.Forsyth           pos[3] = pos[0];
386*37da2899SCharles.Forsyth           args_count = 0;
387*37da2899SCharles.Forsyth           break;
388*37da2899SCharles.Forsyth 
389*37da2899SCharles.Forsyth         case 6:                             /* horizontal to vertical curve */
390*37da2899SCharles.Forsyth           FT_TRACE6(( "- hv curve " ));
391*37da2899SCharles.Forsyth           args_format  = 0xB8E;
392*37da2899SCharles.Forsyth           args_count   = 3;
393*37da2899SCharles.Forsyth           break;
394*37da2899SCharles.Forsyth 
395*37da2899SCharles.Forsyth         case 7:                             /* vertical to horizontal curve */
396*37da2899SCharles.Forsyth           FT_TRACE6(( "- vh curve" ));
397*37da2899SCharles.Forsyth           args_format = 0xE2B;
398*37da2899SCharles.Forsyth           args_count  = 3;
399*37da2899SCharles.Forsyth           break;
400*37da2899SCharles.Forsyth 
401*37da2899SCharles.Forsyth         default:                            /* general curve to */
402*37da2899SCharles.Forsyth           FT_TRACE6(( "- general curve" ));
403*37da2899SCharles.Forsyth           args_count  = 4;
404*37da2899SCharles.Forsyth           args_format = format & 15;
405*37da2899SCharles.Forsyth         }
406*37da2899SCharles.Forsyth 
407*37da2899SCharles.Forsyth         /***********************************************************/
408*37da2899SCharles.Forsyth         /*  now read arguments                                     */
409*37da2899SCharles.Forsyth         /*                                                         */
410*37da2899SCharles.Forsyth         cur = pos;
411*37da2899SCharles.Forsyth         for ( n = 0; n < args_count; n++ )
412*37da2899SCharles.Forsyth         {
413*37da2899SCharles.Forsyth           FT_Int  idx, delta;
414*37da2899SCharles.Forsyth 
415*37da2899SCharles.Forsyth 
416*37da2899SCharles.Forsyth           /* read the X argument */
417*37da2899SCharles.Forsyth           switch ( args_format & 3 )
418*37da2899SCharles.Forsyth           {
419*37da2899SCharles.Forsyth           case 0:                           /* 8-bit index */
420*37da2899SCharles.Forsyth             PFR_CHECK( 1 );
421*37da2899SCharles.Forsyth             idx  = PFR_NEXT_BYTE( p );
422*37da2899SCharles.Forsyth             cur->x = glyph->x_control[idx];
423*37da2899SCharles.Forsyth             FT_TRACE7(( " cx#%d", idx ));
424*37da2899SCharles.Forsyth             break;
425*37da2899SCharles.Forsyth 
426*37da2899SCharles.Forsyth           case 1:                           /* 16-bit value */
427*37da2899SCharles.Forsyth             PFR_CHECK( 2 );
428*37da2899SCharles.Forsyth             cur->x = PFR_NEXT_SHORT( p );
429*37da2899SCharles.Forsyth             FT_TRACE7(( " x.%d", cur->x ));
430*37da2899SCharles.Forsyth             break;
431*37da2899SCharles.Forsyth 
432*37da2899SCharles.Forsyth           case 2:                           /* 8-bit delta */
433*37da2899SCharles.Forsyth             PFR_CHECK( 1 );
434*37da2899SCharles.Forsyth             delta  = PFR_NEXT_INT8( p );
435*37da2899SCharles.Forsyth             cur->x = pos[3].x + delta;
436*37da2899SCharles.Forsyth             FT_TRACE7(( " dx.%d", delta ));
437*37da2899SCharles.Forsyth             break;
438*37da2899SCharles.Forsyth 
439*37da2899SCharles.Forsyth           default:
440*37da2899SCharles.Forsyth             FT_TRACE7(( " |" ));
441*37da2899SCharles.Forsyth             cur->x = pos[3].x;
442*37da2899SCharles.Forsyth           }
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth           /* read the Y argument */
445*37da2899SCharles.Forsyth           switch ( ( args_format >> 2 ) & 3 )
446*37da2899SCharles.Forsyth           {
447*37da2899SCharles.Forsyth           case 0:                           /* 8-bit index */
448*37da2899SCharles.Forsyth             PFR_CHECK( 1 );
449*37da2899SCharles.Forsyth             idx  = PFR_NEXT_BYTE( p );
450*37da2899SCharles.Forsyth             cur->y = glyph->y_control[idx];
451*37da2899SCharles.Forsyth             FT_TRACE7(( " cy#%d", idx ));
452*37da2899SCharles.Forsyth             break;
453*37da2899SCharles.Forsyth 
454*37da2899SCharles.Forsyth           case 1:                           /* 16-bit absolute value */
455*37da2899SCharles.Forsyth             PFR_CHECK( 2 );
456*37da2899SCharles.Forsyth             cur->y = PFR_NEXT_SHORT( p );
457*37da2899SCharles.Forsyth             FT_TRACE7(( " y.%d", cur->y ));
458*37da2899SCharles.Forsyth             break;
459*37da2899SCharles.Forsyth 
460*37da2899SCharles.Forsyth           case 2:                           /* 8-bit delta */
461*37da2899SCharles.Forsyth             PFR_CHECK( 1 );
462*37da2899SCharles.Forsyth             delta  = PFR_NEXT_INT8( p );
463*37da2899SCharles.Forsyth             cur->y = pos[3].y + delta;
464*37da2899SCharles.Forsyth             FT_TRACE7(( " dy.%d", delta ));
465*37da2899SCharles.Forsyth             break;
466*37da2899SCharles.Forsyth 
467*37da2899SCharles.Forsyth           default:
468*37da2899SCharles.Forsyth             FT_TRACE7(( " -" ));
469*37da2899SCharles.Forsyth             cur->y = pos[3].y;
470*37da2899SCharles.Forsyth           }
471*37da2899SCharles.Forsyth 
472*37da2899SCharles.Forsyth           /* read the additional format flag for the general curve */
473*37da2899SCharles.Forsyth           if ( n == 0 && args_count == 4 )
474*37da2899SCharles.Forsyth           {
475*37da2899SCharles.Forsyth             PFR_CHECK( 1 );
476*37da2899SCharles.Forsyth             args_format = PFR_NEXT_BYTE( p );
477*37da2899SCharles.Forsyth             args_count--;
478*37da2899SCharles.Forsyth           }
479*37da2899SCharles.Forsyth           else
480*37da2899SCharles.Forsyth             args_format >>= 4;
481*37da2899SCharles.Forsyth 
482*37da2899SCharles.Forsyth           /* save the previous point */
483*37da2899SCharles.Forsyth           pos[3] = cur[0];
484*37da2899SCharles.Forsyth           cur++;
485*37da2899SCharles.Forsyth         }
486*37da2899SCharles.Forsyth 
487*37da2899SCharles.Forsyth         FT_TRACE7(( "\n" ));
488*37da2899SCharles.Forsyth 
489*37da2899SCharles.Forsyth         /***********************************************************/
490*37da2899SCharles.Forsyth         /*  finally, execute instruction                           */
491*37da2899SCharles.Forsyth         /*                                                         */
492*37da2899SCharles.Forsyth         switch ( format >> 4 )
493*37da2899SCharles.Forsyth         {
494*37da2899SCharles.Forsyth         case 0:                             /* end glyph => EXIT */
495*37da2899SCharles.Forsyth           pfr_glyph_end( glyph );
496*37da2899SCharles.Forsyth           goto Exit;
497*37da2899SCharles.Forsyth 
498*37da2899SCharles.Forsyth         case 1:                             /* line operations */
499*37da2899SCharles.Forsyth         case 2:
500*37da2899SCharles.Forsyth         case 3:
501*37da2899SCharles.Forsyth           error = pfr_glyph_line_to( glyph, pos );
502*37da2899SCharles.Forsyth           goto Test_Error;
503*37da2899SCharles.Forsyth 
504*37da2899SCharles.Forsyth         case 4:                             /* move to inside contour  */
505*37da2899SCharles.Forsyth         case 5:                             /* move to outside contour */
506*37da2899SCharles.Forsyth           error = pfr_glyph_move_to( glyph, pos );
507*37da2899SCharles.Forsyth           goto Test_Error;
508*37da2899SCharles.Forsyth 
509*37da2899SCharles.Forsyth         default:                            /* curve operations */
510*37da2899SCharles.Forsyth           error = pfr_glyph_curve_to( glyph, pos, pos + 1, pos + 2 );
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth         Test_Error:  /* test error condition */
513*37da2899SCharles.Forsyth           if ( error )
514*37da2899SCharles.Forsyth             goto Exit;
515*37da2899SCharles.Forsyth         }
516*37da2899SCharles.Forsyth       } /* for (;;) */
517*37da2899SCharles.Forsyth     }
518*37da2899SCharles.Forsyth 
519*37da2899SCharles.Forsyth   Exit:
520*37da2899SCharles.Forsyth     return error;
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth   Too_Short:
523*37da2899SCharles.Forsyth     error = PFR_Err_Invalid_Table;
524*37da2899SCharles.Forsyth     FT_ERROR(( "pfr_glyph_load_simple: invalid glyph data\n" ));
525*37da2899SCharles.Forsyth     goto Exit;
526*37da2899SCharles.Forsyth   }
527*37da2899SCharles.Forsyth 
528*37da2899SCharles.Forsyth 
529*37da2899SCharles.Forsyth   /* load a composite/compound glyph */
530*37da2899SCharles.Forsyth   static FT_Error
pfr_glyph_load_compound(PFR_Glyph glyph,FT_Byte * p,FT_Byte * limit)531*37da2899SCharles.Forsyth   pfr_glyph_load_compound( PFR_Glyph  glyph,
532*37da2899SCharles.Forsyth                            FT_Byte*   p,
533*37da2899SCharles.Forsyth                            FT_Byte*   limit )
534*37da2899SCharles.Forsyth   {
535*37da2899SCharles.Forsyth     FT_Error        error  = 0;
536*37da2899SCharles.Forsyth     FT_GlyphLoader  loader = glyph->loader;
537*37da2899SCharles.Forsyth     FT_Memory       memory = loader->memory;
538*37da2899SCharles.Forsyth     PFR_SubGlyph    subglyph;
539*37da2899SCharles.Forsyth     FT_UInt         flags, i, count, org_count;
540*37da2899SCharles.Forsyth     FT_Int          x_pos, y_pos;
541*37da2899SCharles.Forsyth 
542*37da2899SCharles.Forsyth 
543*37da2899SCharles.Forsyth     PFR_CHECK( 1 );
544*37da2899SCharles.Forsyth     flags = PFR_NEXT_BYTE( p );
545*37da2899SCharles.Forsyth 
546*37da2899SCharles.Forsyth     /* test for composite glyphs */
547*37da2899SCharles.Forsyth     FT_ASSERT( ( flags & PFR_GLYPH_IS_COMPOUND ) != 0 );
548*37da2899SCharles.Forsyth 
549*37da2899SCharles.Forsyth     count = flags & 0x3F;
550*37da2899SCharles.Forsyth 
551*37da2899SCharles.Forsyth     /* ignore extra items when present */
552*37da2899SCharles.Forsyth     /*                                 */
553*37da2899SCharles.Forsyth     if ( flags & PFR_GLYPH_EXTRA_ITEMS )
554*37da2899SCharles.Forsyth     {
555*37da2899SCharles.Forsyth       error = pfr_extra_items_skip( &p, limit );
556*37da2899SCharles.Forsyth       if (error) goto Exit;
557*37da2899SCharles.Forsyth     }
558*37da2899SCharles.Forsyth 
559*37da2899SCharles.Forsyth     /* we can't rely on the FT_GlyphLoader to load sub-glyphs, because   */
560*37da2899SCharles.Forsyth     /* the PFR format is dumb, using direct file offsets to point to the */
561*37da2899SCharles.Forsyth     /* sub-glyphs (instead of glyph indices).  Sigh.                     */
562*37da2899SCharles.Forsyth     /*                                                                   */
563*37da2899SCharles.Forsyth     /* For now, we load the list of sub-glyphs into a different array    */
564*37da2899SCharles.Forsyth     /* but this will prevent us from using the auto-hinter at its best   */
565*37da2899SCharles.Forsyth     /* quality.                                                          */
566*37da2899SCharles.Forsyth     /*                                                                   */
567*37da2899SCharles.Forsyth     org_count = glyph->num_subs;
568*37da2899SCharles.Forsyth 
569*37da2899SCharles.Forsyth     if ( org_count + count > glyph->max_subs )
570*37da2899SCharles.Forsyth     {
571*37da2899SCharles.Forsyth       FT_UInt  new_max = ( org_count + count + 3 ) & -4;
572*37da2899SCharles.Forsyth 
573*37da2899SCharles.Forsyth 
574*37da2899SCharles.Forsyth       if ( FT_RENEW_ARRAY( glyph->subs, glyph->max_subs, new_max ) )
575*37da2899SCharles.Forsyth         goto Exit;
576*37da2899SCharles.Forsyth 
577*37da2899SCharles.Forsyth       glyph->max_subs = new_max;
578*37da2899SCharles.Forsyth     }
579*37da2899SCharles.Forsyth 
580*37da2899SCharles.Forsyth     subglyph = glyph->subs + org_count;
581*37da2899SCharles.Forsyth 
582*37da2899SCharles.Forsyth     for ( i = 0; i < count; i++, subglyph++ )
583*37da2899SCharles.Forsyth     {
584*37da2899SCharles.Forsyth       FT_UInt  format;
585*37da2899SCharles.Forsyth 
586*37da2899SCharles.Forsyth 
587*37da2899SCharles.Forsyth       x_pos = 0;
588*37da2899SCharles.Forsyth       y_pos = 0;
589*37da2899SCharles.Forsyth 
590*37da2899SCharles.Forsyth       PFR_CHECK( 1 );
591*37da2899SCharles.Forsyth       format = PFR_NEXT_BYTE( p );
592*37da2899SCharles.Forsyth 
593*37da2899SCharles.Forsyth       /* read scale when available */
594*37da2899SCharles.Forsyth       subglyph->x_scale = 0x10000L;
595*37da2899SCharles.Forsyth       if ( format & PFR_SUBGLYPH_XSCALE )
596*37da2899SCharles.Forsyth       {
597*37da2899SCharles.Forsyth         PFR_CHECK( 2 );
598*37da2899SCharles.Forsyth         subglyph->x_scale = PFR_NEXT_SHORT( p ) << 4;
599*37da2899SCharles.Forsyth       }
600*37da2899SCharles.Forsyth 
601*37da2899SCharles.Forsyth       subglyph->y_scale = 0x10000L;
602*37da2899SCharles.Forsyth       if ( format & PFR_SUBGLYPH_YSCALE )
603*37da2899SCharles.Forsyth       {
604*37da2899SCharles.Forsyth         PFR_CHECK( 2 );
605*37da2899SCharles.Forsyth         subglyph->y_scale = PFR_NEXT_SHORT( p ) << 4;
606*37da2899SCharles.Forsyth       }
607*37da2899SCharles.Forsyth 
608*37da2899SCharles.Forsyth       /* read offset */
609*37da2899SCharles.Forsyth       switch ( format & 3 )
610*37da2899SCharles.Forsyth       {
611*37da2899SCharles.Forsyth       case 1:
612*37da2899SCharles.Forsyth         PFR_CHECK( 2 );
613*37da2899SCharles.Forsyth         x_pos = PFR_NEXT_SHORT( p );
614*37da2899SCharles.Forsyth         break;
615*37da2899SCharles.Forsyth 
616*37da2899SCharles.Forsyth       case 2:
617*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
618*37da2899SCharles.Forsyth         x_pos += PFR_NEXT_INT8( p );
619*37da2899SCharles.Forsyth         break;
620*37da2899SCharles.Forsyth 
621*37da2899SCharles.Forsyth       default:
622*37da2899SCharles.Forsyth         ;
623*37da2899SCharles.Forsyth       }
624*37da2899SCharles.Forsyth 
625*37da2899SCharles.Forsyth       switch ( ( format >> 2 ) & 3 )
626*37da2899SCharles.Forsyth       {
627*37da2899SCharles.Forsyth       case 1:
628*37da2899SCharles.Forsyth         PFR_CHECK( 2 );
629*37da2899SCharles.Forsyth         y_pos = PFR_NEXT_SHORT( p );
630*37da2899SCharles.Forsyth         break;
631*37da2899SCharles.Forsyth 
632*37da2899SCharles.Forsyth       case 2:
633*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
634*37da2899SCharles.Forsyth         y_pos += PFR_NEXT_INT8( p );
635*37da2899SCharles.Forsyth         break;
636*37da2899SCharles.Forsyth 
637*37da2899SCharles.Forsyth       default:
638*37da2899SCharles.Forsyth         ;
639*37da2899SCharles.Forsyth       }
640*37da2899SCharles.Forsyth 
641*37da2899SCharles.Forsyth       subglyph->x_delta = x_pos;
642*37da2899SCharles.Forsyth       subglyph->y_delta = y_pos;
643*37da2899SCharles.Forsyth 
644*37da2899SCharles.Forsyth       /* read glyph position and size now */
645*37da2899SCharles.Forsyth       if ( format & PFR_SUBGLYPH_2BYTE_SIZE )
646*37da2899SCharles.Forsyth       {
647*37da2899SCharles.Forsyth         PFR_CHECK( 2 );
648*37da2899SCharles.Forsyth         subglyph->gps_size = PFR_NEXT_USHORT( p );
649*37da2899SCharles.Forsyth       }
650*37da2899SCharles.Forsyth       else
651*37da2899SCharles.Forsyth       {
652*37da2899SCharles.Forsyth         PFR_CHECK( 1 );
653*37da2899SCharles.Forsyth         subglyph->gps_size = PFR_NEXT_BYTE( p );
654*37da2899SCharles.Forsyth       }
655*37da2899SCharles.Forsyth 
656*37da2899SCharles.Forsyth       if ( format & PFR_SUBGLYPH_3BYTE_OFFSET )
657*37da2899SCharles.Forsyth       {
658*37da2899SCharles.Forsyth         PFR_CHECK( 3 );
659*37da2899SCharles.Forsyth         subglyph->gps_offset = PFR_NEXT_LONG( p );
660*37da2899SCharles.Forsyth       }
661*37da2899SCharles.Forsyth       else
662*37da2899SCharles.Forsyth       {
663*37da2899SCharles.Forsyth         PFR_CHECK( 2 );
664*37da2899SCharles.Forsyth         subglyph->gps_offset = PFR_NEXT_USHORT( p );
665*37da2899SCharles.Forsyth       }
666*37da2899SCharles.Forsyth 
667*37da2899SCharles.Forsyth       glyph->num_subs++;
668*37da2899SCharles.Forsyth     }
669*37da2899SCharles.Forsyth 
670*37da2899SCharles.Forsyth   Exit:
671*37da2899SCharles.Forsyth     return error;
672*37da2899SCharles.Forsyth 
673*37da2899SCharles.Forsyth   Too_Short:
674*37da2899SCharles.Forsyth     error = PFR_Err_Invalid_Table;
675*37da2899SCharles.Forsyth     FT_ERROR(( "pfr_glyph_load_compound: invalid glyph data\n" ));
676*37da2899SCharles.Forsyth     goto Exit;
677*37da2899SCharles.Forsyth   }
678*37da2899SCharles.Forsyth 
679*37da2899SCharles.Forsyth 
680*37da2899SCharles.Forsyth 
681*37da2899SCharles.Forsyth 
682*37da2899SCharles.Forsyth 
683*37da2899SCharles.Forsyth   static FT_Error
pfr_glyph_load_rec(PFR_Glyph glyph,FT_Stream stream,FT_ULong gps_offset,FT_ULong offset,FT_ULong size)684*37da2899SCharles.Forsyth   pfr_glyph_load_rec( PFR_Glyph  glyph,
685*37da2899SCharles.Forsyth                       FT_Stream  stream,
686*37da2899SCharles.Forsyth                       FT_ULong   gps_offset,
687*37da2899SCharles.Forsyth                       FT_ULong   offset,
688*37da2899SCharles.Forsyth                       FT_ULong   size )
689*37da2899SCharles.Forsyth   {
690*37da2899SCharles.Forsyth     FT_Error  error;
691*37da2899SCharles.Forsyth     FT_Byte*  p;
692*37da2899SCharles.Forsyth     FT_Byte*  limit;
693*37da2899SCharles.Forsyth 
694*37da2899SCharles.Forsyth 
695*37da2899SCharles.Forsyth     if ( FT_STREAM_SEEK( gps_offset + offset ) ||
696*37da2899SCharles.Forsyth          FT_FRAME_ENTER( size )                )
697*37da2899SCharles.Forsyth       goto Exit;
698*37da2899SCharles.Forsyth 
699*37da2899SCharles.Forsyth     p     = (FT_Byte*)stream->cursor;
700*37da2899SCharles.Forsyth     limit = p + size;
701*37da2899SCharles.Forsyth 
702*37da2899SCharles.Forsyth     if ( size > 0 && *p & PFR_GLYPH_IS_COMPOUND )
703*37da2899SCharles.Forsyth     {
704*37da2899SCharles.Forsyth       FT_Int          n, old_count, count;
705*37da2899SCharles.Forsyth       FT_GlyphLoader  loader = glyph->loader;
706*37da2899SCharles.Forsyth       FT_Outline*     base   = &loader->base.outline;
707*37da2899SCharles.Forsyth 
708*37da2899SCharles.Forsyth 
709*37da2899SCharles.Forsyth       old_count = glyph->num_subs;
710*37da2899SCharles.Forsyth 
711*37da2899SCharles.Forsyth       /* this is a compound glyph - load it */
712*37da2899SCharles.Forsyth       error = pfr_glyph_load_compound( glyph, p, limit );
713*37da2899SCharles.Forsyth 
714*37da2899SCharles.Forsyth       FT_FRAME_EXIT();
715*37da2899SCharles.Forsyth 
716*37da2899SCharles.Forsyth       if ( error )
717*37da2899SCharles.Forsyth         goto Exit;
718*37da2899SCharles.Forsyth 
719*37da2899SCharles.Forsyth       count = glyph->num_subs - old_count;
720*37da2899SCharles.Forsyth 
721*37da2899SCharles.Forsyth       /* now, load each individual glyph */
722*37da2899SCharles.Forsyth       for ( n = 0; n < count; n++ )
723*37da2899SCharles.Forsyth       {
724*37da2899SCharles.Forsyth         FT_Int        i, old_points, num_points;
725*37da2899SCharles.Forsyth         PFR_SubGlyph  subglyph;
726*37da2899SCharles.Forsyth 
727*37da2899SCharles.Forsyth 
728*37da2899SCharles.Forsyth         subglyph   = glyph->subs + old_count + n;
729*37da2899SCharles.Forsyth         old_points = base->n_points;
730*37da2899SCharles.Forsyth 
731*37da2899SCharles.Forsyth         error = pfr_glyph_load_rec( glyph, stream, gps_offset,
732*37da2899SCharles.Forsyth                                     subglyph->gps_offset,
733*37da2899SCharles.Forsyth                                     subglyph->gps_size );
734*37da2899SCharles.Forsyth         if ( error )
735*37da2899SCharles.Forsyth           goto Exit;
736*37da2899SCharles.Forsyth 
737*37da2899SCharles.Forsyth         /* note that `glyph->subs' might have been re-allocated */
738*37da2899SCharles.Forsyth         subglyph   = glyph->subs + old_count + n;
739*37da2899SCharles.Forsyth         num_points = base->n_points - old_points;
740*37da2899SCharles.Forsyth 
741*37da2899SCharles.Forsyth         /* translate and eventually scale the new glyph points */
742*37da2899SCharles.Forsyth         if ( subglyph->x_scale != 0x10000L || subglyph->y_scale != 0x10000L )
743*37da2899SCharles.Forsyth         {
744*37da2899SCharles.Forsyth           FT_Vector*  vec = base->points + old_points;
745*37da2899SCharles.Forsyth 
746*37da2899SCharles.Forsyth 
747*37da2899SCharles.Forsyth           for ( i = 0; i < num_points; i++, vec++ )
748*37da2899SCharles.Forsyth           {
749*37da2899SCharles.Forsyth             vec->x = FT_MulFix( vec->x, subglyph->x_scale ) +
750*37da2899SCharles.Forsyth                        subglyph->x_delta;
751*37da2899SCharles.Forsyth             vec->y = FT_MulFix( vec->y, subglyph->y_scale ) +
752*37da2899SCharles.Forsyth                        subglyph->y_delta;
753*37da2899SCharles.Forsyth           }
754*37da2899SCharles.Forsyth         }
755*37da2899SCharles.Forsyth         else
756*37da2899SCharles.Forsyth         {
757*37da2899SCharles.Forsyth           FT_Vector*  vec = loader->base.outline.points + old_points;
758*37da2899SCharles.Forsyth 
759*37da2899SCharles.Forsyth 
760*37da2899SCharles.Forsyth           for ( i = 0; i < num_points; i++, vec++ )
761*37da2899SCharles.Forsyth           {
762*37da2899SCharles.Forsyth             vec->x += subglyph->x_delta;
763*37da2899SCharles.Forsyth             vec->y += subglyph->y_delta;
764*37da2899SCharles.Forsyth           }
765*37da2899SCharles.Forsyth         }
766*37da2899SCharles.Forsyth 
767*37da2899SCharles.Forsyth         /* proceed to next sub-glyph */
768*37da2899SCharles.Forsyth       }
769*37da2899SCharles.Forsyth     }
770*37da2899SCharles.Forsyth     else
771*37da2899SCharles.Forsyth     {
772*37da2899SCharles.Forsyth       /* load a simple glyph */
773*37da2899SCharles.Forsyth       error = pfr_glyph_load_simple( glyph, p, limit );
774*37da2899SCharles.Forsyth 
775*37da2899SCharles.Forsyth       FT_FRAME_EXIT();
776*37da2899SCharles.Forsyth     }
777*37da2899SCharles.Forsyth 
778*37da2899SCharles.Forsyth   Exit:
779*37da2899SCharles.Forsyth     return error;
780*37da2899SCharles.Forsyth   }
781*37da2899SCharles.Forsyth 
782*37da2899SCharles.Forsyth 
783*37da2899SCharles.Forsyth 
784*37da2899SCharles.Forsyth 
785*37da2899SCharles.Forsyth 
786*37da2899SCharles.Forsyth   FT_LOCAL_DEF( FT_Error )
pfr_glyph_load(PFR_Glyph glyph,FT_Stream stream,FT_ULong gps_offset,FT_ULong offset,FT_ULong size)787*37da2899SCharles.Forsyth   pfr_glyph_load( PFR_Glyph  glyph,
788*37da2899SCharles.Forsyth                   FT_Stream  stream,
789*37da2899SCharles.Forsyth                   FT_ULong   gps_offset,
790*37da2899SCharles.Forsyth                   FT_ULong   offset,
791*37da2899SCharles.Forsyth                   FT_ULong   size )
792*37da2899SCharles.Forsyth   {
793*37da2899SCharles.Forsyth     /* initialize glyph loader */
794*37da2899SCharles.Forsyth     FT_GlyphLoader_Rewind( glyph->loader );
795*37da2899SCharles.Forsyth 
796*37da2899SCharles.Forsyth     /* load the glyph, recursively when needed */
797*37da2899SCharles.Forsyth     return pfr_glyph_load_rec( glyph, stream, gps_offset, offset, size );
798*37da2899SCharles.Forsyth   }
799*37da2899SCharles.Forsyth 
800*37da2899SCharles.Forsyth 
801*37da2899SCharles.Forsyth /* END */
802