xref: /inferno-os/libfreetype/pshrec.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  pshrec.c                                                               */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    FreeType PostScript hints recorder (body).                           */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 2001, 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 <ft2build.h>
20*37da2899SCharles.Forsyth #include FT_FREETYPE_H
21*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
22*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
23*37da2899SCharles.Forsyth #include "pshrec.h"
24*37da2899SCharles.Forsyth #include "pshalgo.h"
25*37da2899SCharles.Forsyth 
26*37da2899SCharles.Forsyth #undef  FT_COMPONENT
27*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_pshrec
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth #ifdef DEBUG_HINTER
30*37da2899SCharles.Forsyth   PS_Hints  ps_debug_hints         = 0;
31*37da2899SCharles.Forsyth   int       ps_debug_no_horz_hints = 0;
32*37da2899SCharles.Forsyth   int       ps_debug_no_vert_hints = 0;
33*37da2899SCharles.Forsyth #endif
34*37da2899SCharles.Forsyth 
35*37da2899SCharles.Forsyth 
36*37da2899SCharles.Forsyth   /*************************************************************************/
37*37da2899SCharles.Forsyth   /*************************************************************************/
38*37da2899SCharles.Forsyth   /*****                                                               *****/
39*37da2899SCharles.Forsyth   /*****                      PS_HINT MANAGEMENT                       *****/
40*37da2899SCharles.Forsyth   /*****                                                               *****/
41*37da2899SCharles.Forsyth   /*************************************************************************/
42*37da2899SCharles.Forsyth   /*************************************************************************/
43*37da2899SCharles.Forsyth 
44*37da2899SCharles.Forsyth   /* destroy hints table */
45*37da2899SCharles.Forsyth   static void
ps_hint_table_done(PS_Hint_Table table,FT_Memory memory)46*37da2899SCharles.Forsyth   ps_hint_table_done( PS_Hint_Table  table,
47*37da2899SCharles.Forsyth                       FT_Memory      memory )
48*37da2899SCharles.Forsyth   {
49*37da2899SCharles.Forsyth     FT_FREE( table->hints );
50*37da2899SCharles.Forsyth     table->num_hints = 0;
51*37da2899SCharles.Forsyth     table->max_hints = 0;
52*37da2899SCharles.Forsyth   }
53*37da2899SCharles.Forsyth 
54*37da2899SCharles.Forsyth 
55*37da2899SCharles.Forsyth   /* ensure that a table can contain "count" elements */
56*37da2899SCharles.Forsyth   static FT_Error
ps_hint_table_ensure(PS_Hint_Table table,FT_UInt count,FT_Memory memory)57*37da2899SCharles.Forsyth   ps_hint_table_ensure( PS_Hint_Table  table,
58*37da2899SCharles.Forsyth                         FT_UInt        count,
59*37da2899SCharles.Forsyth                         FT_Memory      memory )
60*37da2899SCharles.Forsyth   {
61*37da2899SCharles.Forsyth     FT_UInt   old_max = table->max_hints;
62*37da2899SCharles.Forsyth     FT_UInt   new_max = count;
63*37da2899SCharles.Forsyth     FT_Error  error   = 0;
64*37da2899SCharles.Forsyth 
65*37da2899SCharles.Forsyth 
66*37da2899SCharles.Forsyth     if ( new_max > old_max )
67*37da2899SCharles.Forsyth     {
68*37da2899SCharles.Forsyth       /* try to grow the table */
69*37da2899SCharles.Forsyth       new_max = ( new_max + 7 ) & -8;
70*37da2899SCharles.Forsyth       if ( !FT_RENEW_ARRAY( table->hints, old_max, new_max ) )
71*37da2899SCharles.Forsyth         table->max_hints = new_max;
72*37da2899SCharles.Forsyth     }
73*37da2899SCharles.Forsyth     return error;
74*37da2899SCharles.Forsyth   }
75*37da2899SCharles.Forsyth 
76*37da2899SCharles.Forsyth 
77*37da2899SCharles.Forsyth   static FT_Error
ps_hint_table_alloc(PS_Hint_Table table,FT_Memory memory,PS_Hint * ahint)78*37da2899SCharles.Forsyth   ps_hint_table_alloc( PS_Hint_Table  table,
79*37da2899SCharles.Forsyth                        FT_Memory      memory,
80*37da2899SCharles.Forsyth                        PS_Hint       *ahint )
81*37da2899SCharles.Forsyth   {
82*37da2899SCharles.Forsyth     FT_Error  error = 0;
83*37da2899SCharles.Forsyth     FT_UInt   count;
84*37da2899SCharles.Forsyth     PS_Hint   hint = 0;
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth     count = table->num_hints;
88*37da2899SCharles.Forsyth     count++;
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth     if ( count >= table->max_hints )
91*37da2899SCharles.Forsyth     {
92*37da2899SCharles.Forsyth       error = ps_hint_table_ensure( table, count, memory );
93*37da2899SCharles.Forsyth       if ( error )
94*37da2899SCharles.Forsyth         goto Exit;
95*37da2899SCharles.Forsyth     }
96*37da2899SCharles.Forsyth 
97*37da2899SCharles.Forsyth     hint        = table->hints + count - 1;
98*37da2899SCharles.Forsyth     hint->pos   = 0;
99*37da2899SCharles.Forsyth     hint->len   = 0;
100*37da2899SCharles.Forsyth     hint->flags = 0;
101*37da2899SCharles.Forsyth 
102*37da2899SCharles.Forsyth     table->num_hints = count;
103*37da2899SCharles.Forsyth 
104*37da2899SCharles.Forsyth   Exit:
105*37da2899SCharles.Forsyth     *ahint = hint;
106*37da2899SCharles.Forsyth     return error;
107*37da2899SCharles.Forsyth   }
108*37da2899SCharles.Forsyth 
109*37da2899SCharles.Forsyth 
110*37da2899SCharles.Forsyth   /*************************************************************************/
111*37da2899SCharles.Forsyth   /*************************************************************************/
112*37da2899SCharles.Forsyth   /*****                                                               *****/
113*37da2899SCharles.Forsyth   /*****                      PS_MASK MANAGEMENT                       *****/
114*37da2899SCharles.Forsyth   /*****                                                               *****/
115*37da2899SCharles.Forsyth   /*************************************************************************/
116*37da2899SCharles.Forsyth   /*************************************************************************/
117*37da2899SCharles.Forsyth 
118*37da2899SCharles.Forsyth   /* destroy mask */
119*37da2899SCharles.Forsyth   static void
ps_mask_done(PS_Mask mask,FT_Memory memory)120*37da2899SCharles.Forsyth   ps_mask_done( PS_Mask    mask,
121*37da2899SCharles.Forsyth                 FT_Memory  memory )
122*37da2899SCharles.Forsyth   {
123*37da2899SCharles.Forsyth     FT_FREE( mask->bytes );
124*37da2899SCharles.Forsyth     mask->num_bits  = 0;
125*37da2899SCharles.Forsyth     mask->max_bits  = 0;
126*37da2899SCharles.Forsyth     mask->end_point = 0;
127*37da2899SCharles.Forsyth   }
128*37da2899SCharles.Forsyth 
129*37da2899SCharles.Forsyth 
130*37da2899SCharles.Forsyth   /* ensure that a mask can contain "count" bits */
131*37da2899SCharles.Forsyth   static FT_Error
ps_mask_ensure(PS_Mask mask,FT_UInt count,FT_Memory memory)132*37da2899SCharles.Forsyth   ps_mask_ensure( PS_Mask    mask,
133*37da2899SCharles.Forsyth                   FT_UInt    count,
134*37da2899SCharles.Forsyth                   FT_Memory  memory )
135*37da2899SCharles.Forsyth   {
136*37da2899SCharles.Forsyth     FT_UInt   old_max = ( mask->max_bits + 7 ) >> 3;
137*37da2899SCharles.Forsyth     FT_UInt   new_max = ( count          + 7 ) >> 3;
138*37da2899SCharles.Forsyth     FT_Error  error   = 0;
139*37da2899SCharles.Forsyth 
140*37da2899SCharles.Forsyth 
141*37da2899SCharles.Forsyth     if ( new_max > old_max )
142*37da2899SCharles.Forsyth     {
143*37da2899SCharles.Forsyth       new_max = ( new_max + 7 ) & -8;
144*37da2899SCharles.Forsyth       if ( !FT_RENEW_ARRAY( mask->bytes, old_max, new_max ) )
145*37da2899SCharles.Forsyth         mask->max_bits = new_max * 8;
146*37da2899SCharles.Forsyth     }
147*37da2899SCharles.Forsyth     return error;
148*37da2899SCharles.Forsyth   }
149*37da2899SCharles.Forsyth 
150*37da2899SCharles.Forsyth 
151*37da2899SCharles.Forsyth   /* test a bit value in a given mask */
152*37da2899SCharles.Forsyth   static FT_Int
ps_mask_test_bit(PS_Mask mask,FT_Int idx)153*37da2899SCharles.Forsyth   ps_mask_test_bit( PS_Mask  mask,
154*37da2899SCharles.Forsyth                     FT_Int   idx )
155*37da2899SCharles.Forsyth   {
156*37da2899SCharles.Forsyth     if ( (FT_UInt)idx >= mask->num_bits )
157*37da2899SCharles.Forsyth       return 0;
158*37da2899SCharles.Forsyth 
159*37da2899SCharles.Forsyth     return mask->bytes[idx >> 3] & ( 0x80 >> ( idx & 7 ) );
160*37da2899SCharles.Forsyth   }
161*37da2899SCharles.Forsyth 
162*37da2899SCharles.Forsyth 
163*37da2899SCharles.Forsyth   /* clear a given bit */
164*37da2899SCharles.Forsyth   static void
ps_mask_clear_bit(PS_Mask mask,FT_Int idx)165*37da2899SCharles.Forsyth   ps_mask_clear_bit( PS_Mask  mask,
166*37da2899SCharles.Forsyth                      FT_Int   idx )
167*37da2899SCharles.Forsyth   {
168*37da2899SCharles.Forsyth     FT_Byte*  p;
169*37da2899SCharles.Forsyth 
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth     if ( (FT_UInt)idx >= mask->num_bits )
172*37da2899SCharles.Forsyth       return;
173*37da2899SCharles.Forsyth 
174*37da2899SCharles.Forsyth     p    = mask->bytes + ( idx >> 3 );
175*37da2899SCharles.Forsyth     p[0] = (FT_Byte)( p[0] & ~( 0x80 >> ( idx & 7 ) ) );
176*37da2899SCharles.Forsyth   }
177*37da2899SCharles.Forsyth 
178*37da2899SCharles.Forsyth 
179*37da2899SCharles.Forsyth   /* set a given bit, possibly grow the mask */
180*37da2899SCharles.Forsyth   static FT_Error
ps_mask_set_bit(PS_Mask mask,FT_Int idx,FT_Memory memory)181*37da2899SCharles.Forsyth   ps_mask_set_bit( PS_Mask    mask,
182*37da2899SCharles.Forsyth                    FT_Int     idx,
183*37da2899SCharles.Forsyth                    FT_Memory  memory )
184*37da2899SCharles.Forsyth   {
185*37da2899SCharles.Forsyth     FT_Error  error = 0;
186*37da2899SCharles.Forsyth     FT_Byte*  p;
187*37da2899SCharles.Forsyth 
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth     if ( idx < 0 )
190*37da2899SCharles.Forsyth       goto Exit;
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth     if ( (FT_UInt)idx >= mask->num_bits )
193*37da2899SCharles.Forsyth     {
194*37da2899SCharles.Forsyth       error = ps_mask_ensure( mask, idx + 1, memory );
195*37da2899SCharles.Forsyth       if ( error )
196*37da2899SCharles.Forsyth         goto Exit;
197*37da2899SCharles.Forsyth 
198*37da2899SCharles.Forsyth       mask->num_bits = idx + 1;
199*37da2899SCharles.Forsyth     }
200*37da2899SCharles.Forsyth 
201*37da2899SCharles.Forsyth     p    = mask->bytes + ( idx >> 3 );
202*37da2899SCharles.Forsyth     p[0] = (FT_Byte)( p[0] | ( 0x80 >> ( idx & 7 ) ) );
203*37da2899SCharles.Forsyth 
204*37da2899SCharles.Forsyth   Exit:
205*37da2899SCharles.Forsyth     return error;
206*37da2899SCharles.Forsyth   }
207*37da2899SCharles.Forsyth 
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth   /* destroy mask table */
210*37da2899SCharles.Forsyth   static void
ps_mask_table_done(PS_Mask_Table table,FT_Memory memory)211*37da2899SCharles.Forsyth   ps_mask_table_done( PS_Mask_Table  table,
212*37da2899SCharles.Forsyth                       FT_Memory      memory )
213*37da2899SCharles.Forsyth   {
214*37da2899SCharles.Forsyth     FT_UInt  count = table->max_masks;
215*37da2899SCharles.Forsyth     PS_Mask  mask  = table->masks;
216*37da2899SCharles.Forsyth 
217*37da2899SCharles.Forsyth 
218*37da2899SCharles.Forsyth     for ( ; count > 0; count--, mask++ )
219*37da2899SCharles.Forsyth       ps_mask_done( mask, memory );
220*37da2899SCharles.Forsyth 
221*37da2899SCharles.Forsyth     FT_FREE( table->masks );
222*37da2899SCharles.Forsyth     table->num_masks = 0;
223*37da2899SCharles.Forsyth     table->max_masks = 0;
224*37da2899SCharles.Forsyth   }
225*37da2899SCharles.Forsyth 
226*37da2899SCharles.Forsyth 
227*37da2899SCharles.Forsyth   /* ensure that a mask table can contain "count" masks */
228*37da2899SCharles.Forsyth   static FT_Error
ps_mask_table_ensure(PS_Mask_Table table,FT_UInt count,FT_Memory memory)229*37da2899SCharles.Forsyth   ps_mask_table_ensure( PS_Mask_Table  table,
230*37da2899SCharles.Forsyth                         FT_UInt        count,
231*37da2899SCharles.Forsyth                         FT_Memory      memory )
232*37da2899SCharles.Forsyth   {
233*37da2899SCharles.Forsyth     FT_UInt   old_max = table->max_masks;
234*37da2899SCharles.Forsyth     FT_UInt   new_max = count;
235*37da2899SCharles.Forsyth     FT_Error  error   = 0;
236*37da2899SCharles.Forsyth 
237*37da2899SCharles.Forsyth 
238*37da2899SCharles.Forsyth     if ( new_max > old_max )
239*37da2899SCharles.Forsyth     {
240*37da2899SCharles.Forsyth       new_max = ( new_max + 7 ) & -8;
241*37da2899SCharles.Forsyth       if ( !FT_RENEW_ARRAY( table->masks, old_max, new_max ) )
242*37da2899SCharles.Forsyth         table->max_masks = new_max;
243*37da2899SCharles.Forsyth     }
244*37da2899SCharles.Forsyth     return error;
245*37da2899SCharles.Forsyth   }
246*37da2899SCharles.Forsyth 
247*37da2899SCharles.Forsyth 
248*37da2899SCharles.Forsyth   /* allocate a new mask in a table */
249*37da2899SCharles.Forsyth   static FT_Error
ps_mask_table_alloc(PS_Mask_Table table,FT_Memory memory,PS_Mask * amask)250*37da2899SCharles.Forsyth   ps_mask_table_alloc( PS_Mask_Table  table,
251*37da2899SCharles.Forsyth                        FT_Memory      memory,
252*37da2899SCharles.Forsyth                        PS_Mask       *amask )
253*37da2899SCharles.Forsyth   {
254*37da2899SCharles.Forsyth     FT_UInt   count;
255*37da2899SCharles.Forsyth     FT_Error  error = 0;
256*37da2899SCharles.Forsyth     PS_Mask   mask  = 0;
257*37da2899SCharles.Forsyth 
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth     count = table->num_masks;
260*37da2899SCharles.Forsyth     count++;
261*37da2899SCharles.Forsyth 
262*37da2899SCharles.Forsyth     if ( count > table->max_masks )
263*37da2899SCharles.Forsyth     {
264*37da2899SCharles.Forsyth       error = ps_mask_table_ensure( table, count, memory );
265*37da2899SCharles.Forsyth       if ( error )
266*37da2899SCharles.Forsyth         goto Exit;
267*37da2899SCharles.Forsyth     }
268*37da2899SCharles.Forsyth 
269*37da2899SCharles.Forsyth     mask             = table->masks + count - 1;
270*37da2899SCharles.Forsyth     mask->num_bits   = 0;
271*37da2899SCharles.Forsyth     mask->end_point  = 0;
272*37da2899SCharles.Forsyth     table->num_masks = count;
273*37da2899SCharles.Forsyth 
274*37da2899SCharles.Forsyth   Exit:
275*37da2899SCharles.Forsyth     *amask = mask;
276*37da2899SCharles.Forsyth     return error;
277*37da2899SCharles.Forsyth   }
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth 
280*37da2899SCharles.Forsyth   /* return last hint mask in a table, create one if the table is empty */
281*37da2899SCharles.Forsyth   static FT_Error
ps_mask_table_last(PS_Mask_Table table,FT_Memory memory,PS_Mask * amask)282*37da2899SCharles.Forsyth   ps_mask_table_last( PS_Mask_Table  table,
283*37da2899SCharles.Forsyth                       FT_Memory      memory,
284*37da2899SCharles.Forsyth                       PS_Mask       *amask )
285*37da2899SCharles.Forsyth   {
286*37da2899SCharles.Forsyth     FT_Error  error = 0;
287*37da2899SCharles.Forsyth     FT_UInt   count;
288*37da2899SCharles.Forsyth     PS_Mask   mask;
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth 
291*37da2899SCharles.Forsyth     count = table->num_masks;
292*37da2899SCharles.Forsyth     if ( count == 0 )
293*37da2899SCharles.Forsyth     {
294*37da2899SCharles.Forsyth       error = ps_mask_table_alloc( table, memory, &mask );
295*37da2899SCharles.Forsyth       if ( error )
296*37da2899SCharles.Forsyth         goto Exit;
297*37da2899SCharles.Forsyth     }
298*37da2899SCharles.Forsyth     else
299*37da2899SCharles.Forsyth       mask = table->masks + count - 1;
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth   Exit:
302*37da2899SCharles.Forsyth     *amask = mask;
303*37da2899SCharles.Forsyth     return error;
304*37da2899SCharles.Forsyth   }
305*37da2899SCharles.Forsyth 
306*37da2899SCharles.Forsyth 
307*37da2899SCharles.Forsyth   /* set a new mask to a given bit range */
308*37da2899SCharles.Forsyth   static FT_Error
ps_mask_table_set_bits(PS_Mask_Table table,FT_Byte * source,FT_UInt bit_pos,FT_UInt bit_count,FT_Memory memory)309*37da2899SCharles.Forsyth   ps_mask_table_set_bits( PS_Mask_Table  table,
310*37da2899SCharles.Forsyth                           FT_Byte*       source,
311*37da2899SCharles.Forsyth                           FT_UInt        bit_pos,
312*37da2899SCharles.Forsyth                           FT_UInt        bit_count,
313*37da2899SCharles.Forsyth                           FT_Memory      memory )
314*37da2899SCharles.Forsyth   {
315*37da2899SCharles.Forsyth     FT_Error  error = 0;
316*37da2899SCharles.Forsyth     PS_Mask   mask;
317*37da2899SCharles.Forsyth 
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth     /* allocate new mask, and grow it to "bit_count" bits */
320*37da2899SCharles.Forsyth     error = ps_mask_table_alloc( table, memory, &mask );
321*37da2899SCharles.Forsyth     if ( error )
322*37da2899SCharles.Forsyth       goto Exit;
323*37da2899SCharles.Forsyth 
324*37da2899SCharles.Forsyth     error = ps_mask_ensure( mask, bit_count, memory );
325*37da2899SCharles.Forsyth     if ( error )
326*37da2899SCharles.Forsyth       goto Exit;
327*37da2899SCharles.Forsyth 
328*37da2899SCharles.Forsyth     mask->num_bits = bit_count;
329*37da2899SCharles.Forsyth 
330*37da2899SCharles.Forsyth     /* now, copy bits */
331*37da2899SCharles.Forsyth     {
332*37da2899SCharles.Forsyth       FT_Byte*  read  = source + ( bit_pos >> 3 );
333*37da2899SCharles.Forsyth       FT_Int    rmask = 0x80 >> ( bit_pos & 7 );
334*37da2899SCharles.Forsyth       FT_Byte*  write = mask->bytes;
335*37da2899SCharles.Forsyth       FT_Int    wmask = 0x80;
336*37da2899SCharles.Forsyth       FT_Int    val;
337*37da2899SCharles.Forsyth 
338*37da2899SCharles.Forsyth 
339*37da2899SCharles.Forsyth       for ( ; bit_count > 0; bit_count-- )
340*37da2899SCharles.Forsyth       {
341*37da2899SCharles.Forsyth         val = write[0] & ~wmask;
342*37da2899SCharles.Forsyth 
343*37da2899SCharles.Forsyth         if ( read[0] & rmask )
344*37da2899SCharles.Forsyth           val |= wmask;
345*37da2899SCharles.Forsyth 
346*37da2899SCharles.Forsyth         write[0] = (FT_Byte)val;
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth         rmask >>= 1;
349*37da2899SCharles.Forsyth         if ( rmask == 0 )
350*37da2899SCharles.Forsyth         {
351*37da2899SCharles.Forsyth           read++;
352*37da2899SCharles.Forsyth           rmask = 0x80;
353*37da2899SCharles.Forsyth         }
354*37da2899SCharles.Forsyth 
355*37da2899SCharles.Forsyth         wmask >>= 1;
356*37da2899SCharles.Forsyth         if ( wmask == 0 )
357*37da2899SCharles.Forsyth         {
358*37da2899SCharles.Forsyth           write++;
359*37da2899SCharles.Forsyth           wmask = 0x80;
360*37da2899SCharles.Forsyth         }
361*37da2899SCharles.Forsyth       }
362*37da2899SCharles.Forsyth     }
363*37da2899SCharles.Forsyth 
364*37da2899SCharles.Forsyth   Exit:
365*37da2899SCharles.Forsyth     return error;
366*37da2899SCharles.Forsyth   }
367*37da2899SCharles.Forsyth 
368*37da2899SCharles.Forsyth 
369*37da2899SCharles.Forsyth   /* test whether two masks in a table intersect */
370*37da2899SCharles.Forsyth   static FT_Int
ps_mask_table_test_intersect(PS_Mask_Table table,FT_Int index1,FT_Int index2)371*37da2899SCharles.Forsyth   ps_mask_table_test_intersect( PS_Mask_Table  table,
372*37da2899SCharles.Forsyth                                 FT_Int         index1,
373*37da2899SCharles.Forsyth                                 FT_Int         index2 )
374*37da2899SCharles.Forsyth   {
375*37da2899SCharles.Forsyth     PS_Mask   mask1  = table->masks + index1;
376*37da2899SCharles.Forsyth     PS_Mask   mask2  = table->masks + index2;
377*37da2899SCharles.Forsyth     FT_Byte*  p1     = mask1->bytes;
378*37da2899SCharles.Forsyth     FT_Byte*  p2     = mask2->bytes;
379*37da2899SCharles.Forsyth     FT_UInt   count1 = mask1->num_bits;
380*37da2899SCharles.Forsyth     FT_UInt   count2 = mask2->num_bits;
381*37da2899SCharles.Forsyth     FT_UInt   count;
382*37da2899SCharles.Forsyth 
383*37da2899SCharles.Forsyth 
384*37da2899SCharles.Forsyth     count = ( count1 <= count2 ) ? count1 : count2;
385*37da2899SCharles.Forsyth     for ( ; count >= 8; count -= 8 )
386*37da2899SCharles.Forsyth     {
387*37da2899SCharles.Forsyth       if ( p1[0] & p2[0] )
388*37da2899SCharles.Forsyth         return 1;
389*37da2899SCharles.Forsyth 
390*37da2899SCharles.Forsyth       p1++;
391*37da2899SCharles.Forsyth       p2++;
392*37da2899SCharles.Forsyth     }
393*37da2899SCharles.Forsyth 
394*37da2899SCharles.Forsyth     if ( count == 0 )
395*37da2899SCharles.Forsyth       return 0;
396*37da2899SCharles.Forsyth 
397*37da2899SCharles.Forsyth     return ( p1[0] & p2[0] ) & ~( 0xFF >> count );
398*37da2899SCharles.Forsyth   }
399*37da2899SCharles.Forsyth 
400*37da2899SCharles.Forsyth 
401*37da2899SCharles.Forsyth   /* merge two masks, used by ps_mask_table_merge_all */
402*37da2899SCharles.Forsyth   static FT_Error
ps_mask_table_merge(PS_Mask_Table table,FT_Int index1,FT_Int index2,FT_Memory memory)403*37da2899SCharles.Forsyth   ps_mask_table_merge( PS_Mask_Table  table,
404*37da2899SCharles.Forsyth                        FT_Int         index1,
405*37da2899SCharles.Forsyth                        FT_Int         index2,
406*37da2899SCharles.Forsyth                        FT_Memory      memory )
407*37da2899SCharles.Forsyth   {
408*37da2899SCharles.Forsyth     FT_UInt   temp;
409*37da2899SCharles.Forsyth     FT_Error  error = 0;
410*37da2899SCharles.Forsyth 
411*37da2899SCharles.Forsyth 
412*37da2899SCharles.Forsyth     /* swap index1 and index2 so that index1 < index2 */
413*37da2899SCharles.Forsyth     if ( index1 > index2 )
414*37da2899SCharles.Forsyth     {
415*37da2899SCharles.Forsyth       temp   = index1;
416*37da2899SCharles.Forsyth       index1 = index2;
417*37da2899SCharles.Forsyth       index2 = temp;
418*37da2899SCharles.Forsyth     }
419*37da2899SCharles.Forsyth 
420*37da2899SCharles.Forsyth     if ( index1 < index2 && index1 >= 0 && index2 < (FT_Int)table->num_masks )
421*37da2899SCharles.Forsyth     {
422*37da2899SCharles.Forsyth       /* we need to merge the bitsets of index1 and index2 with a */
423*37da2899SCharles.Forsyth       /* simple union                                             */
424*37da2899SCharles.Forsyth       PS_Mask  mask1  = table->masks + index1;
425*37da2899SCharles.Forsyth       PS_Mask  mask2  = table->masks + index2;
426*37da2899SCharles.Forsyth       FT_UInt  count1 = mask1->num_bits;
427*37da2899SCharles.Forsyth       FT_UInt  count2 = mask2->num_bits;
428*37da2899SCharles.Forsyth       FT_Int   delta;
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth 
431*37da2899SCharles.Forsyth       if ( count2 > 0 )
432*37da2899SCharles.Forsyth       {
433*37da2899SCharles.Forsyth         FT_UInt   pos;
434*37da2899SCharles.Forsyth         FT_Byte*  read;
435*37da2899SCharles.Forsyth         FT_Byte*  write;
436*37da2899SCharles.Forsyth 
437*37da2899SCharles.Forsyth 
438*37da2899SCharles.Forsyth         /* if "count2" is greater than "count1", we need to grow the */
439*37da2899SCharles.Forsyth         /* first bitset, and clear the highest bits                  */
440*37da2899SCharles.Forsyth         if ( count2 > count1 )
441*37da2899SCharles.Forsyth         {
442*37da2899SCharles.Forsyth           error = ps_mask_ensure( mask1, count2, memory );
443*37da2899SCharles.Forsyth           if ( error )
444*37da2899SCharles.Forsyth             goto Exit;
445*37da2899SCharles.Forsyth 
446*37da2899SCharles.Forsyth           for ( pos = count1; pos < count2; pos++ )
447*37da2899SCharles.Forsyth             ps_mask_clear_bit( mask1, pos );
448*37da2899SCharles.Forsyth         }
449*37da2899SCharles.Forsyth 
450*37da2899SCharles.Forsyth         /* merge (unite) the bitsets */
451*37da2899SCharles.Forsyth         read  = mask2->bytes;
452*37da2899SCharles.Forsyth         write = mask1->bytes;
453*37da2899SCharles.Forsyth         pos   = (FT_UInt)( ( count2 + 7 ) >> 3 );
454*37da2899SCharles.Forsyth 
455*37da2899SCharles.Forsyth         for ( ; pos > 0; pos-- )
456*37da2899SCharles.Forsyth         {
457*37da2899SCharles.Forsyth           write[0] = (FT_Byte)( write[0] | read[0] );
458*37da2899SCharles.Forsyth           write++;
459*37da2899SCharles.Forsyth           read++;
460*37da2899SCharles.Forsyth         }
461*37da2899SCharles.Forsyth       }
462*37da2899SCharles.Forsyth 
463*37da2899SCharles.Forsyth       /* Now, remove "mask2" from the list.  We need to keep the masks */
464*37da2899SCharles.Forsyth       /* sorted in order of importance, so move table elements.        */
465*37da2899SCharles.Forsyth       mask2->num_bits  = 0;
466*37da2899SCharles.Forsyth       mask2->end_point = 0;
467*37da2899SCharles.Forsyth 
468*37da2899SCharles.Forsyth       delta = table->num_masks - 1 - index2; /* number of masks to move */
469*37da2899SCharles.Forsyth       if ( delta > 0 )
470*37da2899SCharles.Forsyth       {
471*37da2899SCharles.Forsyth         /* move to end of table for reuse */
472*37da2899SCharles.Forsyth         PS_MaskRec  dummy = *mask2;
473*37da2899SCharles.Forsyth 
474*37da2899SCharles.Forsyth 
475*37da2899SCharles.Forsyth         ft_memmove( mask2, mask2 + 1, delta * sizeof ( PS_MaskRec ) );
476*37da2899SCharles.Forsyth 
477*37da2899SCharles.Forsyth         mask2[delta] = dummy;
478*37da2899SCharles.Forsyth       }
479*37da2899SCharles.Forsyth 
480*37da2899SCharles.Forsyth       table->num_masks--;
481*37da2899SCharles.Forsyth     }
482*37da2899SCharles.Forsyth     else
483*37da2899SCharles.Forsyth       FT_ERROR(( "ps_mask_table_merge: ignoring invalid indices (%d,%d)\n",
484*37da2899SCharles.Forsyth                  index1, index2 ));
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth   Exit:
487*37da2899SCharles.Forsyth     return error;
488*37da2899SCharles.Forsyth   }
489*37da2899SCharles.Forsyth 
490*37da2899SCharles.Forsyth 
491*37da2899SCharles.Forsyth   /* Try to merge all masks in a given table.  This is used to merge */
492*37da2899SCharles.Forsyth   /* all counter masks into independent counter "paths".             */
493*37da2899SCharles.Forsyth   /*                                                                 */
494*37da2899SCharles.Forsyth   static FT_Error
ps_mask_table_merge_all(PS_Mask_Table table,FT_Memory memory)495*37da2899SCharles.Forsyth   ps_mask_table_merge_all( PS_Mask_Table  table,
496*37da2899SCharles.Forsyth                            FT_Memory      memory )
497*37da2899SCharles.Forsyth   {
498*37da2899SCharles.Forsyth     FT_Int    index1, index2;
499*37da2899SCharles.Forsyth     FT_Error  error = 0;
500*37da2899SCharles.Forsyth 
501*37da2899SCharles.Forsyth 
502*37da2899SCharles.Forsyth     for ( index1 = table->num_masks - 1; index1 > 0; index1-- )
503*37da2899SCharles.Forsyth     {
504*37da2899SCharles.Forsyth       for ( index2 = index1 - 1; index2 >= 0; index2-- )
505*37da2899SCharles.Forsyth       {
506*37da2899SCharles.Forsyth         if ( ps_mask_table_test_intersect( table, index1, index2 ) )
507*37da2899SCharles.Forsyth         {
508*37da2899SCharles.Forsyth           error = ps_mask_table_merge( table, index2, index1, memory );
509*37da2899SCharles.Forsyth           if ( error )
510*37da2899SCharles.Forsyth             goto Exit;
511*37da2899SCharles.Forsyth 
512*37da2899SCharles.Forsyth           break;
513*37da2899SCharles.Forsyth         }
514*37da2899SCharles.Forsyth       }
515*37da2899SCharles.Forsyth     }
516*37da2899SCharles.Forsyth 
517*37da2899SCharles.Forsyth   Exit:
518*37da2899SCharles.Forsyth     return error;
519*37da2899SCharles.Forsyth   }
520*37da2899SCharles.Forsyth 
521*37da2899SCharles.Forsyth 
522*37da2899SCharles.Forsyth   /*************************************************************************/
523*37da2899SCharles.Forsyth   /*************************************************************************/
524*37da2899SCharles.Forsyth   /*****                                                               *****/
525*37da2899SCharles.Forsyth   /*****                    PS_DIMENSION MANAGEMENT                    *****/
526*37da2899SCharles.Forsyth   /*****                                                               *****/
527*37da2899SCharles.Forsyth   /*************************************************************************/
528*37da2899SCharles.Forsyth   /*************************************************************************/
529*37da2899SCharles.Forsyth 
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth   /* finalize a given dimension */
532*37da2899SCharles.Forsyth   static void
ps_dimension_done(PS_Dimension dimension,FT_Memory memory)533*37da2899SCharles.Forsyth   ps_dimension_done( PS_Dimension  dimension,
534*37da2899SCharles.Forsyth                      FT_Memory     memory )
535*37da2899SCharles.Forsyth   {
536*37da2899SCharles.Forsyth     ps_mask_table_done( &dimension->counters, memory );
537*37da2899SCharles.Forsyth     ps_mask_table_done( &dimension->masks,    memory );
538*37da2899SCharles.Forsyth     ps_hint_table_done( &dimension->hints,    memory );
539*37da2899SCharles.Forsyth   }
540*37da2899SCharles.Forsyth 
541*37da2899SCharles.Forsyth 
542*37da2899SCharles.Forsyth   /* initialize a given dimension */
543*37da2899SCharles.Forsyth   static void
ps_dimension_init(PS_Dimension dimension)544*37da2899SCharles.Forsyth   ps_dimension_init( PS_Dimension  dimension )
545*37da2899SCharles.Forsyth   {
546*37da2899SCharles.Forsyth     dimension->hints.num_hints    = 0;
547*37da2899SCharles.Forsyth     dimension->masks.num_masks    = 0;
548*37da2899SCharles.Forsyth     dimension->counters.num_masks = 0;
549*37da2899SCharles.Forsyth   }
550*37da2899SCharles.Forsyth 
551*37da2899SCharles.Forsyth 
552*37da2899SCharles.Forsyth #if 0
553*37da2899SCharles.Forsyth 
554*37da2899SCharles.Forsyth   /* set a bit at a given index in the current hint mask */
555*37da2899SCharles.Forsyth   static FT_Error
556*37da2899SCharles.Forsyth   ps_dimension_set_mask_bit( PS_Dimension  dim,
557*37da2899SCharles.Forsyth                              FT_UInt       idx,
558*37da2899SCharles.Forsyth                              FT_Memory     memory )
559*37da2899SCharles.Forsyth   {
560*37da2899SCharles.Forsyth     PS_Mask  mask;
561*37da2899SCharles.Forsyth     FT_Error  error = 0;
562*37da2899SCharles.Forsyth 
563*37da2899SCharles.Forsyth 
564*37da2899SCharles.Forsyth     /* get last hint mask */
565*37da2899SCharles.Forsyth     error = ps_mask_table_last( &dim->masks, memory, &mask );
566*37da2899SCharles.Forsyth     if ( error )
567*37da2899SCharles.Forsyth       goto Exit;
568*37da2899SCharles.Forsyth 
569*37da2899SCharles.Forsyth     error = ps_mask_set_bit( mask, idx, memory );
570*37da2899SCharles.Forsyth 
571*37da2899SCharles.Forsyth   Exit:
572*37da2899SCharles.Forsyth     return error;
573*37da2899SCharles.Forsyth   }
574*37da2899SCharles.Forsyth 
575*37da2899SCharles.Forsyth #endif
576*37da2899SCharles.Forsyth 
577*37da2899SCharles.Forsyth   /* set the end point in a mask, called from "End" & "Reset" methods */
578*37da2899SCharles.Forsyth   static void
ps_dimension_end_mask(PS_Dimension dim,FT_UInt end_point)579*37da2899SCharles.Forsyth   ps_dimension_end_mask( PS_Dimension  dim,
580*37da2899SCharles.Forsyth                          FT_UInt       end_point )
581*37da2899SCharles.Forsyth   {
582*37da2899SCharles.Forsyth     FT_UInt  count = dim->masks.num_masks;
583*37da2899SCharles.Forsyth     PS_Mask  mask;
584*37da2899SCharles.Forsyth 
585*37da2899SCharles.Forsyth 
586*37da2899SCharles.Forsyth     if ( count > 0 )
587*37da2899SCharles.Forsyth     {
588*37da2899SCharles.Forsyth       mask            = dim->masks.masks + count - 1;
589*37da2899SCharles.Forsyth       mask->end_point = end_point;
590*37da2899SCharles.Forsyth     }
591*37da2899SCharles.Forsyth   }
592*37da2899SCharles.Forsyth 
593*37da2899SCharles.Forsyth 
594*37da2899SCharles.Forsyth   /* set the end point in the current mask, then create a new empty one */
595*37da2899SCharles.Forsyth   /* (called by "Reset" method)                                         */
596*37da2899SCharles.Forsyth   static FT_Error
ps_dimension_reset_mask(PS_Dimension dim,FT_UInt end_point,FT_Memory memory)597*37da2899SCharles.Forsyth   ps_dimension_reset_mask( PS_Dimension  dim,
598*37da2899SCharles.Forsyth                            FT_UInt       end_point,
599*37da2899SCharles.Forsyth                            FT_Memory     memory )
600*37da2899SCharles.Forsyth   {
601*37da2899SCharles.Forsyth     PS_Mask  mask;
602*37da2899SCharles.Forsyth 
603*37da2899SCharles.Forsyth 
604*37da2899SCharles.Forsyth     /* end current mask */
605*37da2899SCharles.Forsyth     ps_dimension_end_mask( dim, end_point );
606*37da2899SCharles.Forsyth 
607*37da2899SCharles.Forsyth     /* allocate new one */
608*37da2899SCharles.Forsyth     return ps_mask_table_alloc( &dim->masks, memory, &mask );
609*37da2899SCharles.Forsyth   }
610*37da2899SCharles.Forsyth 
611*37da2899SCharles.Forsyth 
612*37da2899SCharles.Forsyth   /* set a new mask, called from the "T2Stem" method */
613*37da2899SCharles.Forsyth   static FT_Error
ps_dimension_set_mask_bits(PS_Dimension dim,const FT_Byte * source,FT_UInt source_pos,FT_UInt source_bits,FT_UInt end_point,FT_Memory memory)614*37da2899SCharles.Forsyth   ps_dimension_set_mask_bits( PS_Dimension    dim,
615*37da2899SCharles.Forsyth                               const FT_Byte*  source,
616*37da2899SCharles.Forsyth                               FT_UInt         source_pos,
617*37da2899SCharles.Forsyth                               FT_UInt         source_bits,
618*37da2899SCharles.Forsyth                               FT_UInt         end_point,
619*37da2899SCharles.Forsyth                               FT_Memory       memory )
620*37da2899SCharles.Forsyth   {
621*37da2899SCharles.Forsyth     FT_Error  error = 0;
622*37da2899SCharles.Forsyth 
623*37da2899SCharles.Forsyth 
624*37da2899SCharles.Forsyth     /* reset current mask, if any */
625*37da2899SCharles.Forsyth     error = ps_dimension_reset_mask( dim, end_point, memory );
626*37da2899SCharles.Forsyth     if ( error )
627*37da2899SCharles.Forsyth       goto Exit;
628*37da2899SCharles.Forsyth 
629*37da2899SCharles.Forsyth     /* set bits in new mask */
630*37da2899SCharles.Forsyth     error = ps_mask_table_set_bits( &dim->masks, (FT_Byte*)source,
631*37da2899SCharles.Forsyth                                     source_pos, source_bits, memory );
632*37da2899SCharles.Forsyth 
633*37da2899SCharles.Forsyth   Exit:
634*37da2899SCharles.Forsyth     return error;
635*37da2899SCharles.Forsyth   }
636*37da2899SCharles.Forsyth 
637*37da2899SCharles.Forsyth 
638*37da2899SCharles.Forsyth   /* add a new single stem (called from "T1Stem" method) */
639*37da2899SCharles.Forsyth   static FT_Error
ps_dimension_add_t1stem(PS_Dimension dim,FT_Int pos,FT_Int len,FT_Memory memory,FT_Int * aindex)640*37da2899SCharles.Forsyth   ps_dimension_add_t1stem( PS_Dimension  dim,
641*37da2899SCharles.Forsyth                            FT_Int        pos,
642*37da2899SCharles.Forsyth                            FT_Int        len,
643*37da2899SCharles.Forsyth                            FT_Memory     memory,
644*37da2899SCharles.Forsyth                            FT_Int       *aindex )
645*37da2899SCharles.Forsyth   {
646*37da2899SCharles.Forsyth     FT_Error  error = 0;
647*37da2899SCharles.Forsyth     FT_UInt   flags = 0;
648*37da2899SCharles.Forsyth 
649*37da2899SCharles.Forsyth 
650*37da2899SCharles.Forsyth     /* detect ghost stem */
651*37da2899SCharles.Forsyth     if ( len < 0 )
652*37da2899SCharles.Forsyth     {
653*37da2899SCharles.Forsyth       flags |= PS_HINT_FLAG_GHOST;
654*37da2899SCharles.Forsyth       if ( len == -21 )
655*37da2899SCharles.Forsyth       {
656*37da2899SCharles.Forsyth         flags |= PS_HINT_FLAG_BOTTOM;
657*37da2899SCharles.Forsyth         pos   += len;
658*37da2899SCharles.Forsyth       }
659*37da2899SCharles.Forsyth       len = 0;
660*37da2899SCharles.Forsyth     }
661*37da2899SCharles.Forsyth 
662*37da2899SCharles.Forsyth     if ( aindex )
663*37da2899SCharles.Forsyth       *aindex = -1;
664*37da2899SCharles.Forsyth 
665*37da2899SCharles.Forsyth     /* now, lookup stem in the current hints table */
666*37da2899SCharles.Forsyth     {
667*37da2899SCharles.Forsyth       PS_Mask  mask;
668*37da2899SCharles.Forsyth       FT_UInt  idx;
669*37da2899SCharles.Forsyth       FT_UInt  max   = dim->hints.num_hints;
670*37da2899SCharles.Forsyth       PS_Hint  hint  = dim->hints.hints;
671*37da2899SCharles.Forsyth 
672*37da2899SCharles.Forsyth 
673*37da2899SCharles.Forsyth       for ( idx = 0; idx < max; idx++, hint++ )
674*37da2899SCharles.Forsyth       {
675*37da2899SCharles.Forsyth         if ( hint->pos == pos && hint->len == len )
676*37da2899SCharles.Forsyth           break;
677*37da2899SCharles.Forsyth       }
678*37da2899SCharles.Forsyth 
679*37da2899SCharles.Forsyth       /* we need to create a new hint in the table */
680*37da2899SCharles.Forsyth       if ( idx >= max )
681*37da2899SCharles.Forsyth       {
682*37da2899SCharles.Forsyth         error = ps_hint_table_alloc( &dim->hints, memory, &hint );
683*37da2899SCharles.Forsyth         if ( error )
684*37da2899SCharles.Forsyth           goto Exit;
685*37da2899SCharles.Forsyth 
686*37da2899SCharles.Forsyth         hint->pos   = pos;
687*37da2899SCharles.Forsyth         hint->len   = len;
688*37da2899SCharles.Forsyth         hint->flags = flags;
689*37da2899SCharles.Forsyth       }
690*37da2899SCharles.Forsyth 
691*37da2899SCharles.Forsyth       /* now, store the hint in the current mask */
692*37da2899SCharles.Forsyth       error = ps_mask_table_last( &dim->masks, memory, &mask );
693*37da2899SCharles.Forsyth       if ( error )
694*37da2899SCharles.Forsyth         goto Exit;
695*37da2899SCharles.Forsyth 
696*37da2899SCharles.Forsyth       error = ps_mask_set_bit( mask, idx, memory );
697*37da2899SCharles.Forsyth       if ( error )
698*37da2899SCharles.Forsyth         goto Exit;
699*37da2899SCharles.Forsyth 
700*37da2899SCharles.Forsyth       if ( aindex )
701*37da2899SCharles.Forsyth         *aindex = (FT_Int)idx;
702*37da2899SCharles.Forsyth     }
703*37da2899SCharles.Forsyth 
704*37da2899SCharles.Forsyth   Exit:
705*37da2899SCharles.Forsyth     return error;
706*37da2899SCharles.Forsyth   }
707*37da2899SCharles.Forsyth 
708*37da2899SCharles.Forsyth 
709*37da2899SCharles.Forsyth   /* add a "hstem3/vstem3" counter to our dimension table */
710*37da2899SCharles.Forsyth   static FT_Error
ps_dimension_add_counter(PS_Dimension dim,FT_Int hint1,FT_Int hint2,FT_Int hint3,FT_Memory memory)711*37da2899SCharles.Forsyth   ps_dimension_add_counter( PS_Dimension  dim,
712*37da2899SCharles.Forsyth                             FT_Int        hint1,
713*37da2899SCharles.Forsyth                             FT_Int        hint2,
714*37da2899SCharles.Forsyth                             FT_Int        hint3,
715*37da2899SCharles.Forsyth                             FT_Memory     memory )
716*37da2899SCharles.Forsyth   {
717*37da2899SCharles.Forsyth     FT_Error  error   = 0;
718*37da2899SCharles.Forsyth     FT_UInt   count   = dim->counters.num_masks;
719*37da2899SCharles.Forsyth     PS_Mask   counter = dim->counters.masks;
720*37da2899SCharles.Forsyth 
721*37da2899SCharles.Forsyth 
722*37da2899SCharles.Forsyth     /* try to find an existing counter mask that already uses */
723*37da2899SCharles.Forsyth     /* one of these stems here                                */
724*37da2899SCharles.Forsyth     for ( ; count > 0; count--, counter++ )
725*37da2899SCharles.Forsyth     {
726*37da2899SCharles.Forsyth       if ( ps_mask_test_bit( counter, hint1 ) ||
727*37da2899SCharles.Forsyth            ps_mask_test_bit( counter, hint2 ) ||
728*37da2899SCharles.Forsyth            ps_mask_test_bit( counter, hint3 ) )
729*37da2899SCharles.Forsyth         break;
730*37da2899SCharles.Forsyth     }
731*37da2899SCharles.Forsyth 
732*37da2899SCharles.Forsyth     /* creat a new counter when needed */
733*37da2899SCharles.Forsyth     if ( count == 0 )
734*37da2899SCharles.Forsyth     {
735*37da2899SCharles.Forsyth       error = ps_mask_table_alloc( &dim->counters, memory, &counter );
736*37da2899SCharles.Forsyth       if ( error )
737*37da2899SCharles.Forsyth         goto Exit;
738*37da2899SCharles.Forsyth     }
739*37da2899SCharles.Forsyth 
740*37da2899SCharles.Forsyth     /* now, set the bits for our hints in the counter mask */
741*37da2899SCharles.Forsyth     error = ps_mask_set_bit( counter, hint1, memory );
742*37da2899SCharles.Forsyth     if ( error )
743*37da2899SCharles.Forsyth       goto Exit;
744*37da2899SCharles.Forsyth 
745*37da2899SCharles.Forsyth     error = ps_mask_set_bit( counter, hint2, memory );
746*37da2899SCharles.Forsyth     if ( error )
747*37da2899SCharles.Forsyth       goto Exit;
748*37da2899SCharles.Forsyth 
749*37da2899SCharles.Forsyth     error = ps_mask_set_bit( counter, hint3, memory );
750*37da2899SCharles.Forsyth     if ( error )
751*37da2899SCharles.Forsyth       goto Exit;
752*37da2899SCharles.Forsyth 
753*37da2899SCharles.Forsyth   Exit:
754*37da2899SCharles.Forsyth     return error;
755*37da2899SCharles.Forsyth   }
756*37da2899SCharles.Forsyth 
757*37da2899SCharles.Forsyth 
758*37da2899SCharles.Forsyth   /* end of recording session for a given dimension */
759*37da2899SCharles.Forsyth   static FT_Error
ps_dimension_end(PS_Dimension dim,FT_UInt end_point,FT_Memory memory)760*37da2899SCharles.Forsyth   ps_dimension_end( PS_Dimension  dim,
761*37da2899SCharles.Forsyth                     FT_UInt       end_point,
762*37da2899SCharles.Forsyth                     FT_Memory     memory )
763*37da2899SCharles.Forsyth   {
764*37da2899SCharles.Forsyth     /* end hint mask table */
765*37da2899SCharles.Forsyth     ps_dimension_end_mask( dim, end_point );
766*37da2899SCharles.Forsyth 
767*37da2899SCharles.Forsyth     /* merge all counter masks into independent "paths" */
768*37da2899SCharles.Forsyth     return ps_mask_table_merge_all( &dim->counters, memory );
769*37da2899SCharles.Forsyth   }
770*37da2899SCharles.Forsyth 
771*37da2899SCharles.Forsyth 
772*37da2899SCharles.Forsyth   /*************************************************************************/
773*37da2899SCharles.Forsyth   /*************************************************************************/
774*37da2899SCharles.Forsyth   /*****                                                               *****/
775*37da2899SCharles.Forsyth   /*****                    PS_RECORDER MANAGEMENT                     *****/
776*37da2899SCharles.Forsyth   /*****                                                               *****/
777*37da2899SCharles.Forsyth   /*************************************************************************/
778*37da2899SCharles.Forsyth   /*************************************************************************/
779*37da2899SCharles.Forsyth 
780*37da2899SCharles.Forsyth 
781*37da2899SCharles.Forsyth   /* destroy hints */
782*37da2899SCharles.Forsyth   FT_LOCAL( void )
ps_hints_done(PS_Hints hints)783*37da2899SCharles.Forsyth   ps_hints_done( PS_Hints  hints )
784*37da2899SCharles.Forsyth   {
785*37da2899SCharles.Forsyth     FT_Memory  memory = hints->memory;
786*37da2899SCharles.Forsyth 
787*37da2899SCharles.Forsyth 
788*37da2899SCharles.Forsyth     ps_dimension_done( &hints->dimension[0], memory );
789*37da2899SCharles.Forsyth     ps_dimension_done( &hints->dimension[1], memory );
790*37da2899SCharles.Forsyth 
791*37da2899SCharles.Forsyth     hints->error  = 0;
792*37da2899SCharles.Forsyth     hints->memory = 0;
793*37da2899SCharles.Forsyth   }
794*37da2899SCharles.Forsyth 
795*37da2899SCharles.Forsyth 
796*37da2899SCharles.Forsyth   FT_LOCAL( FT_Error )
ps_hints_init(PS_Hints hints,FT_Memory memory)797*37da2899SCharles.Forsyth   ps_hints_init( PS_Hints   hints,
798*37da2899SCharles.Forsyth                  FT_Memory  memory )
799*37da2899SCharles.Forsyth   {
800*37da2899SCharles.Forsyth     FT_MEM_ZERO( hints, sizeof ( *hints ) );
801*37da2899SCharles.Forsyth     hints->memory = memory;
802*37da2899SCharles.Forsyth     return 0;
803*37da2899SCharles.Forsyth   }
804*37da2899SCharles.Forsyth 
805*37da2899SCharles.Forsyth 
806*37da2899SCharles.Forsyth   /* initialize a hints for a new session */
807*37da2899SCharles.Forsyth   static void
ps_hints_open(PS_Hints hints,PS_Hint_Type hint_type)808*37da2899SCharles.Forsyth   ps_hints_open( PS_Hints      hints,
809*37da2899SCharles.Forsyth                  PS_Hint_Type  hint_type )
810*37da2899SCharles.Forsyth   {
811*37da2899SCharles.Forsyth     switch ( hint_type )
812*37da2899SCharles.Forsyth     {
813*37da2899SCharles.Forsyth     case PS_HINT_TYPE_1:
814*37da2899SCharles.Forsyth     case PS_HINT_TYPE_2:
815*37da2899SCharles.Forsyth       hints->error     = 0;
816*37da2899SCharles.Forsyth       hints->hint_type = hint_type;
817*37da2899SCharles.Forsyth 
818*37da2899SCharles.Forsyth       ps_dimension_init( &hints->dimension[0] );
819*37da2899SCharles.Forsyth       ps_dimension_init( &hints->dimension[1] );
820*37da2899SCharles.Forsyth       break;
821*37da2899SCharles.Forsyth 
822*37da2899SCharles.Forsyth     default:
823*37da2899SCharles.Forsyth       hints->error     = FT_Err_Invalid_Argument;
824*37da2899SCharles.Forsyth       hints->hint_type = hint_type;
825*37da2899SCharles.Forsyth 
826*37da2899SCharles.Forsyth       FT_ERROR(( "ps_hints_open: invalid charstring type!\n" ));
827*37da2899SCharles.Forsyth       break;
828*37da2899SCharles.Forsyth     }
829*37da2899SCharles.Forsyth   }
830*37da2899SCharles.Forsyth 
831*37da2899SCharles.Forsyth 
832*37da2899SCharles.Forsyth   /* add one or more stems to the current hints table */
833*37da2899SCharles.Forsyth   static void
ps_hints_stem(PS_Hints hints,FT_Int dimension,FT_UInt count,FT_Long * stems)834*37da2899SCharles.Forsyth   ps_hints_stem( PS_Hints  hints,
835*37da2899SCharles.Forsyth                  FT_Int    dimension,
836*37da2899SCharles.Forsyth                  FT_UInt   count,
837*37da2899SCharles.Forsyth                  FT_Long*  stems )
838*37da2899SCharles.Forsyth   {
839*37da2899SCharles.Forsyth     if ( !hints->error )
840*37da2899SCharles.Forsyth     {
841*37da2899SCharles.Forsyth       /* limit "dimension" to 0..1 */
842*37da2899SCharles.Forsyth       if ( dimension < 0 || dimension > 1 )
843*37da2899SCharles.Forsyth       {
844*37da2899SCharles.Forsyth         FT_ERROR(( "ps_hints_stem: invalid dimension (%d) used\n",
845*37da2899SCharles.Forsyth                    dimension ));
846*37da2899SCharles.Forsyth         dimension = ( dimension != 0 );
847*37da2899SCharles.Forsyth       }
848*37da2899SCharles.Forsyth 
849*37da2899SCharles.Forsyth       /* record the stems in the current hints/masks table */
850*37da2899SCharles.Forsyth       switch ( hints->hint_type )
851*37da2899SCharles.Forsyth       {
852*37da2899SCharles.Forsyth       case PS_HINT_TYPE_1:  /* Type 1 "hstem" or "vstem" operator */
853*37da2899SCharles.Forsyth       case PS_HINT_TYPE_2:  /* Type 2 "hstem" or "vstem" operator */
854*37da2899SCharles.Forsyth         {
855*37da2899SCharles.Forsyth           PS_Dimension  dim = &hints->dimension[dimension];
856*37da2899SCharles.Forsyth 
857*37da2899SCharles.Forsyth 
858*37da2899SCharles.Forsyth           for ( ; count > 0; count--, stems += 2 )
859*37da2899SCharles.Forsyth           {
860*37da2899SCharles.Forsyth             FT_Error   error;
861*37da2899SCharles.Forsyth             FT_Memory  memory = hints->memory;
862*37da2899SCharles.Forsyth 
863*37da2899SCharles.Forsyth 
864*37da2899SCharles.Forsyth             error = ps_dimension_add_t1stem( dim, stems[0], stems[1],
865*37da2899SCharles.Forsyth                                              memory, NULL );
866*37da2899SCharles.Forsyth             if ( error )
867*37da2899SCharles.Forsyth             {
868*37da2899SCharles.Forsyth               FT_ERROR(( "ps_hints_stem: could not add stem"
869*37da2899SCharles.Forsyth                          " (%d,%d) to hints table\n", stems[0], stems[1] ));
870*37da2899SCharles.Forsyth 
871*37da2899SCharles.Forsyth               hints->error = error;
872*37da2899SCharles.Forsyth               return;
873*37da2899SCharles.Forsyth             }
874*37da2899SCharles.Forsyth           }
875*37da2899SCharles.Forsyth           break;
876*37da2899SCharles.Forsyth         }
877*37da2899SCharles.Forsyth 
878*37da2899SCharles.Forsyth       default:
879*37da2899SCharles.Forsyth         FT_ERROR(( "ps_hints_stem: called with invalid hint type (%d)\n",
880*37da2899SCharles.Forsyth                    hints->hint_type ));
881*37da2899SCharles.Forsyth         break;
882*37da2899SCharles.Forsyth       }
883*37da2899SCharles.Forsyth     }
884*37da2899SCharles.Forsyth   }
885*37da2899SCharles.Forsyth 
886*37da2899SCharles.Forsyth 
887*37da2899SCharles.Forsyth   /* add one Type1 counter stem to the current hints table */
888*37da2899SCharles.Forsyth   static void
ps_hints_t1stem3(PS_Hints hints,FT_Int dimension,FT_Long * stems)889*37da2899SCharles.Forsyth   ps_hints_t1stem3( PS_Hints  hints,
890*37da2899SCharles.Forsyth                     FT_Int    dimension,
891*37da2899SCharles.Forsyth                     FT_Long*  stems )
892*37da2899SCharles.Forsyth   {
893*37da2899SCharles.Forsyth     FT_Error  error = 0;
894*37da2899SCharles.Forsyth 
895*37da2899SCharles.Forsyth 
896*37da2899SCharles.Forsyth     if ( !hints->error )
897*37da2899SCharles.Forsyth     {
898*37da2899SCharles.Forsyth       PS_Dimension  dim;
899*37da2899SCharles.Forsyth       FT_Memory     memory = hints->memory;
900*37da2899SCharles.Forsyth       FT_Int        count;
901*37da2899SCharles.Forsyth       FT_Int        idx[3];
902*37da2899SCharles.Forsyth 
903*37da2899SCharles.Forsyth 
904*37da2899SCharles.Forsyth       /* limit "dimension" to 0..1 */
905*37da2899SCharles.Forsyth       if ( dimension < 0 || dimension > 1 )
906*37da2899SCharles.Forsyth       {
907*37da2899SCharles.Forsyth         FT_ERROR(( "ps_hints_t1stem3: invalid dimension (%d) used\n",
908*37da2899SCharles.Forsyth                    dimension ));
909*37da2899SCharles.Forsyth         dimension = ( dimension != 0 );
910*37da2899SCharles.Forsyth       }
911*37da2899SCharles.Forsyth 
912*37da2899SCharles.Forsyth       dim = &hints->dimension[dimension];
913*37da2899SCharles.Forsyth 
914*37da2899SCharles.Forsyth       /* there must be 6 elements in the 'stem' array */
915*37da2899SCharles.Forsyth       if ( hints->hint_type == PS_HINT_TYPE_1 )
916*37da2899SCharles.Forsyth       {
917*37da2899SCharles.Forsyth         /* add the three stems to our hints/masks table */
918*37da2899SCharles.Forsyth         for ( count = 0; count < 3; count++, stems += 2 )
919*37da2899SCharles.Forsyth         {
920*37da2899SCharles.Forsyth           error = ps_dimension_add_t1stem( dim, stems[0], stems[1],
921*37da2899SCharles.Forsyth                                            memory, &idx[count] );
922*37da2899SCharles.Forsyth           if ( error )
923*37da2899SCharles.Forsyth             goto Fail;
924*37da2899SCharles.Forsyth         }
925*37da2899SCharles.Forsyth 
926*37da2899SCharles.Forsyth         /* now, add the hints to the counters table */
927*37da2899SCharles.Forsyth         error = ps_dimension_add_counter( dim, idx[0], idx[1], idx[2],
928*37da2899SCharles.Forsyth                                           memory );
929*37da2899SCharles.Forsyth         if ( error )
930*37da2899SCharles.Forsyth           goto Fail;
931*37da2899SCharles.Forsyth       }
932*37da2899SCharles.Forsyth       else
933*37da2899SCharles.Forsyth       {
934*37da2899SCharles.Forsyth         FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type!\n" ));
935*37da2899SCharles.Forsyth         error = FT_Err_Invalid_Argument;
936*37da2899SCharles.Forsyth         goto Fail;
937*37da2899SCharles.Forsyth       }
938*37da2899SCharles.Forsyth     }
939*37da2899SCharles.Forsyth 
940*37da2899SCharles.Forsyth     return;
941*37da2899SCharles.Forsyth 
942*37da2899SCharles.Forsyth   Fail:
943*37da2899SCharles.Forsyth     FT_ERROR(( "ps_hints_t1stem3: could not add counter stems to table\n" ));
944*37da2899SCharles.Forsyth     hints->error = error;
945*37da2899SCharles.Forsyth   }
946*37da2899SCharles.Forsyth 
947*37da2899SCharles.Forsyth 
948*37da2899SCharles.Forsyth   /* reset hints (only with Type 1 hints) */
949*37da2899SCharles.Forsyth   static void
ps_hints_t1reset(PS_Hints hints,FT_UInt end_point)950*37da2899SCharles.Forsyth   ps_hints_t1reset( PS_Hints  hints,
951*37da2899SCharles.Forsyth                     FT_UInt   end_point )
952*37da2899SCharles.Forsyth   {
953*37da2899SCharles.Forsyth     FT_Error  error = 0;
954*37da2899SCharles.Forsyth 
955*37da2899SCharles.Forsyth 
956*37da2899SCharles.Forsyth     if ( !hints->error )
957*37da2899SCharles.Forsyth     {
958*37da2899SCharles.Forsyth       FT_Memory  memory = hints->memory;
959*37da2899SCharles.Forsyth 
960*37da2899SCharles.Forsyth 
961*37da2899SCharles.Forsyth       if ( hints->hint_type == PS_HINT_TYPE_1 )
962*37da2899SCharles.Forsyth       {
963*37da2899SCharles.Forsyth         error = ps_dimension_reset_mask( &hints->dimension[0],
964*37da2899SCharles.Forsyth                                          end_point, memory );
965*37da2899SCharles.Forsyth         if ( error )
966*37da2899SCharles.Forsyth           goto Fail;
967*37da2899SCharles.Forsyth 
968*37da2899SCharles.Forsyth         error = ps_dimension_reset_mask( &hints->dimension[1],
969*37da2899SCharles.Forsyth                                          end_point, memory );
970*37da2899SCharles.Forsyth         if ( error )
971*37da2899SCharles.Forsyth           goto Fail;
972*37da2899SCharles.Forsyth       }
973*37da2899SCharles.Forsyth       else
974*37da2899SCharles.Forsyth       {
975*37da2899SCharles.Forsyth         /* invalid hint type */
976*37da2899SCharles.Forsyth         error = FT_Err_Invalid_Argument;
977*37da2899SCharles.Forsyth         goto Fail;
978*37da2899SCharles.Forsyth       }
979*37da2899SCharles.Forsyth     }
980*37da2899SCharles.Forsyth     return;
981*37da2899SCharles.Forsyth 
982*37da2899SCharles.Forsyth   Fail:
983*37da2899SCharles.Forsyth     hints->error = error;
984*37da2899SCharles.Forsyth   }
985*37da2899SCharles.Forsyth 
986*37da2899SCharles.Forsyth 
987*37da2899SCharles.Forsyth   /* Type2 "hintmask" operator, add a new hintmask to each direction */
988*37da2899SCharles.Forsyth   static void
ps_hints_t2mask(PS_Hints hints,FT_UInt end_point,FT_UInt bit_count,const FT_Byte * bytes)989*37da2899SCharles.Forsyth   ps_hints_t2mask( PS_Hints        hints,
990*37da2899SCharles.Forsyth                    FT_UInt         end_point,
991*37da2899SCharles.Forsyth                    FT_UInt         bit_count,
992*37da2899SCharles.Forsyth                    const FT_Byte*  bytes )
993*37da2899SCharles.Forsyth   {
994*37da2899SCharles.Forsyth     FT_Error  error;
995*37da2899SCharles.Forsyth 
996*37da2899SCharles.Forsyth 
997*37da2899SCharles.Forsyth     if ( !hints->error )
998*37da2899SCharles.Forsyth     {
999*37da2899SCharles.Forsyth       PS_Dimension  dim    = hints->dimension;
1000*37da2899SCharles.Forsyth       FT_Memory     memory = hints->memory;
1001*37da2899SCharles.Forsyth       FT_UInt       count1 = dim[0].hints.num_hints;
1002*37da2899SCharles.Forsyth       FT_UInt       count2 = dim[1].hints.num_hints;
1003*37da2899SCharles.Forsyth 
1004*37da2899SCharles.Forsyth 
1005*37da2899SCharles.Forsyth       /* check bit count; must be equal to current total hint count */
1006*37da2899SCharles.Forsyth       if ( bit_count !=  count1 + count2 )
1007*37da2899SCharles.Forsyth       {
1008*37da2899SCharles.Forsyth         FT_ERROR(( "ps_hints_t2mask: "
1009*37da2899SCharles.Forsyth                    "called with invalid bitcount %d (instead of %d)\n",
1010*37da2899SCharles.Forsyth                    bit_count, count1 + count2 ));
1011*37da2899SCharles.Forsyth 
1012*37da2899SCharles.Forsyth         /* simply ignore the operator */
1013*37da2899SCharles.Forsyth         return;
1014*37da2899SCharles.Forsyth       }
1015*37da2899SCharles.Forsyth 
1016*37da2899SCharles.Forsyth       /* set-up new horizontal and vertical hint mask now */
1017*37da2899SCharles.Forsyth       error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1,
1018*37da2899SCharles.Forsyth                                           end_point, memory );
1019*37da2899SCharles.Forsyth       if ( error )
1020*37da2899SCharles.Forsyth         goto Fail;
1021*37da2899SCharles.Forsyth 
1022*37da2899SCharles.Forsyth       error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2,
1023*37da2899SCharles.Forsyth                                           end_point, memory );
1024*37da2899SCharles.Forsyth       if ( error )
1025*37da2899SCharles.Forsyth         goto Fail;
1026*37da2899SCharles.Forsyth     }
1027*37da2899SCharles.Forsyth     return;
1028*37da2899SCharles.Forsyth 
1029*37da2899SCharles.Forsyth   Fail:
1030*37da2899SCharles.Forsyth     hints->error = error;
1031*37da2899SCharles.Forsyth   }
1032*37da2899SCharles.Forsyth 
1033*37da2899SCharles.Forsyth 
1034*37da2899SCharles.Forsyth   static void
ps_hints_t2counter(PS_Hints hints,FT_UInt bit_count,const FT_Byte * bytes)1035*37da2899SCharles.Forsyth   ps_hints_t2counter( PS_Hints        hints,
1036*37da2899SCharles.Forsyth                       FT_UInt         bit_count,
1037*37da2899SCharles.Forsyth                       const FT_Byte*  bytes )
1038*37da2899SCharles.Forsyth   {
1039*37da2899SCharles.Forsyth     FT_Error  error;
1040*37da2899SCharles.Forsyth 
1041*37da2899SCharles.Forsyth 
1042*37da2899SCharles.Forsyth     if ( !hints->error )
1043*37da2899SCharles.Forsyth     {
1044*37da2899SCharles.Forsyth       PS_Dimension  dim    = hints->dimension;
1045*37da2899SCharles.Forsyth       FT_Memory     memory = hints->memory;
1046*37da2899SCharles.Forsyth       FT_UInt       count1 = dim[0].hints.num_hints;
1047*37da2899SCharles.Forsyth       FT_UInt       count2 = dim[1].hints.num_hints;
1048*37da2899SCharles.Forsyth 
1049*37da2899SCharles.Forsyth 
1050*37da2899SCharles.Forsyth       /* check bit count, must be equal to current total hint count */
1051*37da2899SCharles.Forsyth       if ( bit_count !=  count1 + count2 )
1052*37da2899SCharles.Forsyth       {
1053*37da2899SCharles.Forsyth         FT_ERROR(( "ps_hints_t2counter: "
1054*37da2899SCharles.Forsyth                    "called with invalid bitcount %d (instead of %d)\n",
1055*37da2899SCharles.Forsyth                    bit_count, count1 + count2 ));
1056*37da2899SCharles.Forsyth 
1057*37da2899SCharles.Forsyth         /* simply ignore the operator */
1058*37da2899SCharles.Forsyth         return;
1059*37da2899SCharles.Forsyth       }
1060*37da2899SCharles.Forsyth 
1061*37da2899SCharles.Forsyth       /* set-up new horizontal and vertical hint mask now */
1062*37da2899SCharles.Forsyth       error = ps_dimension_set_mask_bits( &dim[0], bytes, 0, count1,
1063*37da2899SCharles.Forsyth                                           0, memory );
1064*37da2899SCharles.Forsyth       if ( error )
1065*37da2899SCharles.Forsyth         goto Fail;
1066*37da2899SCharles.Forsyth 
1067*37da2899SCharles.Forsyth       error = ps_dimension_set_mask_bits( &dim[1], bytes, count1, count2,
1068*37da2899SCharles.Forsyth                                           0, memory );
1069*37da2899SCharles.Forsyth       if ( error )
1070*37da2899SCharles.Forsyth         goto Fail;
1071*37da2899SCharles.Forsyth     }
1072*37da2899SCharles.Forsyth     return;
1073*37da2899SCharles.Forsyth 
1074*37da2899SCharles.Forsyth   Fail:
1075*37da2899SCharles.Forsyth     hints->error = error;
1076*37da2899SCharles.Forsyth   }
1077*37da2899SCharles.Forsyth 
1078*37da2899SCharles.Forsyth 
1079*37da2899SCharles.Forsyth   /* end recording session */
1080*37da2899SCharles.Forsyth   static FT_Error
ps_hints_close(PS_Hints hints,FT_UInt end_point)1081*37da2899SCharles.Forsyth   ps_hints_close( PS_Hints  hints,
1082*37da2899SCharles.Forsyth                   FT_UInt   end_point )
1083*37da2899SCharles.Forsyth   {
1084*37da2899SCharles.Forsyth     FT_Error  error;
1085*37da2899SCharles.Forsyth 
1086*37da2899SCharles.Forsyth 
1087*37da2899SCharles.Forsyth     error = hints->error;
1088*37da2899SCharles.Forsyth     if ( !error )
1089*37da2899SCharles.Forsyth     {
1090*37da2899SCharles.Forsyth       FT_Memory     memory = hints->memory;
1091*37da2899SCharles.Forsyth       PS_Dimension  dim    = hints->dimension;
1092*37da2899SCharles.Forsyth 
1093*37da2899SCharles.Forsyth 
1094*37da2899SCharles.Forsyth       error = ps_dimension_end( &dim[0], end_point, memory );
1095*37da2899SCharles.Forsyth       if ( !error )
1096*37da2899SCharles.Forsyth       {
1097*37da2899SCharles.Forsyth         error = ps_dimension_end( &dim[1], end_point, memory );
1098*37da2899SCharles.Forsyth       }
1099*37da2899SCharles.Forsyth     }
1100*37da2899SCharles.Forsyth 
1101*37da2899SCharles.Forsyth #ifdef DEBUG_HINTER
1102*37da2899SCharles.Forsyth     if ( !error )
1103*37da2899SCharles.Forsyth       ps_debug_hints = hints;
1104*37da2899SCharles.Forsyth #endif
1105*37da2899SCharles.Forsyth     return error;
1106*37da2899SCharles.Forsyth   }
1107*37da2899SCharles.Forsyth 
1108*37da2899SCharles.Forsyth 
1109*37da2899SCharles.Forsyth   /*************************************************************************/
1110*37da2899SCharles.Forsyth   /*************************************************************************/
1111*37da2899SCharles.Forsyth   /*****                                                               *****/
1112*37da2899SCharles.Forsyth   /*****                TYPE 1 HINTS RECORDING INTERFACE               *****/
1113*37da2899SCharles.Forsyth   /*****                                                               *****/
1114*37da2899SCharles.Forsyth   /*************************************************************************/
1115*37da2899SCharles.Forsyth   /*************************************************************************/
1116*37da2899SCharles.Forsyth 
1117*37da2899SCharles.Forsyth   static void
t1_hints_open(T1_Hints hints)1118*37da2899SCharles.Forsyth   t1_hints_open( T1_Hints  hints )
1119*37da2899SCharles.Forsyth   {
1120*37da2899SCharles.Forsyth     ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_1 );
1121*37da2899SCharles.Forsyth   }
1122*37da2899SCharles.Forsyth 
1123*37da2899SCharles.Forsyth   static void
t1_hints_stem(T1_Hints hints,FT_Int dimension,FT_Long * coords)1124*37da2899SCharles.Forsyth   t1_hints_stem( T1_Hints  hints,
1125*37da2899SCharles.Forsyth                  FT_Int    dimension,
1126*37da2899SCharles.Forsyth                  FT_Long*  coords )
1127*37da2899SCharles.Forsyth   {
1128*37da2899SCharles.Forsyth     ps_hints_stem( (PS_Hints)hints, dimension, 1, coords );
1129*37da2899SCharles.Forsyth   }
1130*37da2899SCharles.Forsyth 
1131*37da2899SCharles.Forsyth 
1132*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
t1_hints_funcs_init(T1_Hints_FuncsRec * funcs)1133*37da2899SCharles.Forsyth   t1_hints_funcs_init( T1_Hints_FuncsRec*  funcs )
1134*37da2899SCharles.Forsyth   {
1135*37da2899SCharles.Forsyth     FT_MEM_ZERO( (char*)funcs, sizeof ( *funcs ) );
1136*37da2899SCharles.Forsyth 
1137*37da2899SCharles.Forsyth     funcs->open  = (T1_Hints_OpenFunc)    t1_hints_open;
1138*37da2899SCharles.Forsyth     funcs->close = (T1_Hints_CloseFunc)   ps_hints_close;
1139*37da2899SCharles.Forsyth     funcs->stem  = (T1_Hints_SetStemFunc) t1_hints_stem;
1140*37da2899SCharles.Forsyth     funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3;
1141*37da2899SCharles.Forsyth     funcs->reset = (T1_Hints_ResetFunc)   ps_hints_t1reset;
1142*37da2899SCharles.Forsyth     funcs->apply = (T1_Hints_ApplyFunc)   PS_HINTS_APPLY_FUNC;
1143*37da2899SCharles.Forsyth   }
1144*37da2899SCharles.Forsyth 
1145*37da2899SCharles.Forsyth 
1146*37da2899SCharles.Forsyth   /*************************************************************************/
1147*37da2899SCharles.Forsyth   /*************************************************************************/
1148*37da2899SCharles.Forsyth   /*****                                                               *****/
1149*37da2899SCharles.Forsyth   /*****                TYPE 2 HINTS RECORDING INTERFACE               *****/
1150*37da2899SCharles.Forsyth   /*****                                                               *****/
1151*37da2899SCharles.Forsyth   /*************************************************************************/
1152*37da2899SCharles.Forsyth   /*************************************************************************/
1153*37da2899SCharles.Forsyth 
1154*37da2899SCharles.Forsyth   static void
t2_hints_open(T2_Hints hints)1155*37da2899SCharles.Forsyth   t2_hints_open( T2_Hints  hints )
1156*37da2899SCharles.Forsyth   {
1157*37da2899SCharles.Forsyth     ps_hints_open( (PS_Hints)hints, PS_HINT_TYPE_2 );
1158*37da2899SCharles.Forsyth   }
1159*37da2899SCharles.Forsyth 
1160*37da2899SCharles.Forsyth 
1161*37da2899SCharles.Forsyth   static void
t2_hints_stems(T2_Hints hints,FT_Int dimension,FT_Int count,FT_Fixed * coords)1162*37da2899SCharles.Forsyth   t2_hints_stems( T2_Hints   hints,
1163*37da2899SCharles.Forsyth                   FT_Int     dimension,
1164*37da2899SCharles.Forsyth                   FT_Int     count,
1165*37da2899SCharles.Forsyth                   FT_Fixed*  coords )
1166*37da2899SCharles.Forsyth   {
1167*37da2899SCharles.Forsyth     FT_Pos  stems[32], y, n, total = count;
1168*37da2899SCharles.Forsyth 
1169*37da2899SCharles.Forsyth 
1170*37da2899SCharles.Forsyth     y = 0;
1171*37da2899SCharles.Forsyth     while ( total > 0 )
1172*37da2899SCharles.Forsyth     {
1173*37da2899SCharles.Forsyth       /* determine number of stems to write */
1174*37da2899SCharles.Forsyth       count = total;
1175*37da2899SCharles.Forsyth       if ( count > 16 )
1176*37da2899SCharles.Forsyth         count = 16;
1177*37da2899SCharles.Forsyth 
1178*37da2899SCharles.Forsyth       /* compute integer stem positions in font units */
1179*37da2899SCharles.Forsyth       for ( n = 0; n < count * 2; n++ )
1180*37da2899SCharles.Forsyth       {
1181*37da2899SCharles.Forsyth         y       += coords[n];
1182*37da2899SCharles.Forsyth         stems[n] = ( y + 0x8000 ) >> 16;
1183*37da2899SCharles.Forsyth       }
1184*37da2899SCharles.Forsyth 
1185*37da2899SCharles.Forsyth       /* compute lengths */
1186*37da2899SCharles.Forsyth       for ( n = 0; n < count * 2; n += 2 )
1187*37da2899SCharles.Forsyth         stems[n + 1] = stems[n + 1] - stems[n];
1188*37da2899SCharles.Forsyth 
1189*37da2899SCharles.Forsyth       /* add them to the current dimension */
1190*37da2899SCharles.Forsyth       ps_hints_stem( (PS_Hints)hints, dimension, count, stems );
1191*37da2899SCharles.Forsyth 
1192*37da2899SCharles.Forsyth       total -= count;
1193*37da2899SCharles.Forsyth     }
1194*37da2899SCharles.Forsyth   }
1195*37da2899SCharles.Forsyth 
1196*37da2899SCharles.Forsyth 
1197*37da2899SCharles.Forsyth   FT_LOCAL_DEF( void )
t2_hints_funcs_init(T2_Hints_FuncsRec * funcs)1198*37da2899SCharles.Forsyth   t2_hints_funcs_init( T2_Hints_FuncsRec*  funcs )
1199*37da2899SCharles.Forsyth   {
1200*37da2899SCharles.Forsyth     FT_MEM_ZERO( funcs, sizeof ( *funcs ) );
1201*37da2899SCharles.Forsyth 
1202*37da2899SCharles.Forsyth     funcs->open    = (T2_Hints_OpenFunc)   t2_hints_open;
1203*37da2899SCharles.Forsyth     funcs->close   = (T2_Hints_CloseFunc)  ps_hints_close;
1204*37da2899SCharles.Forsyth     funcs->stems   = (T2_Hints_StemsFunc)  t2_hints_stems;
1205*37da2899SCharles.Forsyth     funcs->hintmask= (T2_Hints_MaskFunc)   ps_hints_t2mask;
1206*37da2899SCharles.Forsyth     funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter;
1207*37da2899SCharles.Forsyth     funcs->apply   = (T2_Hints_ApplyFunc)  PS_HINTS_APPLY_FUNC;
1208*37da2899SCharles.Forsyth   }
1209*37da2899SCharles.Forsyth 
1210*37da2899SCharles.Forsyth 
1211*37da2899SCharles.Forsyth /* END */
1212