xref: /inferno-os/libfreetype/ftobjs.c (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsyth /***************************************************************************/
2*37da2899SCharles.Forsyth /*                                                                         */
3*37da2899SCharles.Forsyth /*  ftobjs.c                                                               */
4*37da2899SCharles.Forsyth /*                                                                         */
5*37da2899SCharles.Forsyth /*    The FreeType private base classes (body).                            */
6*37da2899SCharles.Forsyth /*                                                                         */
7*37da2899SCharles.Forsyth /*  Copyright 1996-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_LIST_H
21*37da2899SCharles.Forsyth #include FT_OUTLINE_H
22*37da2899SCharles.Forsyth #include FT_INTERNAL_OBJECTS_H
23*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H
24*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H
25*37da2899SCharles.Forsyth #include FT_TRUETYPE_TABLES_H
26*37da2899SCharles.Forsyth #include FT_OUTLINE_H
27*37da2899SCharles.Forsyth 
28*37da2899SCharles.Forsyth 
29*37da2899SCharles.Forsyth   FT_BASE_DEF( void )
ft_validator_init(FT_Validator valid,const FT_Byte * base,const FT_Byte * limit,FT_ValidationLevel level)30*37da2899SCharles.Forsyth   ft_validator_init( FT_Validator        valid,
31*37da2899SCharles.Forsyth                      const FT_Byte*      base,
32*37da2899SCharles.Forsyth                      const FT_Byte*      limit,
33*37da2899SCharles.Forsyth                      FT_ValidationLevel  level )
34*37da2899SCharles.Forsyth   {
35*37da2899SCharles.Forsyth     valid->base  = base;
36*37da2899SCharles.Forsyth     valid->limit = limit;
37*37da2899SCharles.Forsyth     valid->level = level;
38*37da2899SCharles.Forsyth     valid->error = 0;
39*37da2899SCharles.Forsyth   }
40*37da2899SCharles.Forsyth 
41*37da2899SCharles.Forsyth 
42*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Int )
ft_validator_run(FT_Validator valid)43*37da2899SCharles.Forsyth   ft_validator_run( FT_Validator  valid )
44*37da2899SCharles.Forsyth   {
45*37da2899SCharles.Forsyth     int  result;
46*37da2899SCharles.Forsyth 
47*37da2899SCharles.Forsyth 
48*37da2899SCharles.Forsyth     result = ft_setjmp( valid->jump_buffer );
49*37da2899SCharles.Forsyth     return result;
50*37da2899SCharles.Forsyth   }
51*37da2899SCharles.Forsyth 
52*37da2899SCharles.Forsyth 
53*37da2899SCharles.Forsyth   FT_BASE_DEF( void )
ft_validator_error(FT_Validator valid,FT_Error error)54*37da2899SCharles.Forsyth   ft_validator_error( FT_Validator  valid,
55*37da2899SCharles.Forsyth                       FT_Error      error )
56*37da2899SCharles.Forsyth   {
57*37da2899SCharles.Forsyth     valid->error = error;
58*37da2899SCharles.Forsyth     ft_longjmp( valid->jump_buffer, 1 );
59*37da2899SCharles.Forsyth   }
60*37da2899SCharles.Forsyth 
61*37da2899SCharles.Forsyth 
62*37da2899SCharles.Forsyth   /*************************************************************************/
63*37da2899SCharles.Forsyth   /*************************************************************************/
64*37da2899SCharles.Forsyth   /*************************************************************************/
65*37da2899SCharles.Forsyth   /****                                                                 ****/
66*37da2899SCharles.Forsyth   /****                                                                 ****/
67*37da2899SCharles.Forsyth   /****                           S T R E A M                           ****/
68*37da2899SCharles.Forsyth   /****                                                                 ****/
69*37da2899SCharles.Forsyth   /****                                                                 ****/
70*37da2899SCharles.Forsyth   /*************************************************************************/
71*37da2899SCharles.Forsyth   /*************************************************************************/
72*37da2899SCharles.Forsyth   /*************************************************************************/
73*37da2899SCharles.Forsyth 
74*37da2899SCharles.Forsyth 
75*37da2899SCharles.Forsyth   /* create a new input stream from a FT_Open_Args structure */
76*37da2899SCharles.Forsyth   /*                                                         */
77*37da2899SCharles.Forsyth   static FT_Error
ft_input_stream_new(FT_Library library,const FT_Open_Args * args,FT_Stream * astream)78*37da2899SCharles.Forsyth   ft_input_stream_new( FT_Library           library,
79*37da2899SCharles.Forsyth                        const FT_Open_Args*  args,
80*37da2899SCharles.Forsyth                        FT_Stream*           astream )
81*37da2899SCharles.Forsyth   {
82*37da2899SCharles.Forsyth     FT_Error   error;
83*37da2899SCharles.Forsyth     FT_Memory  memory;
84*37da2899SCharles.Forsyth     FT_Stream  stream;
85*37da2899SCharles.Forsyth 
86*37da2899SCharles.Forsyth 
87*37da2899SCharles.Forsyth     if ( !library )
88*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
89*37da2899SCharles.Forsyth 
90*37da2899SCharles.Forsyth     if ( !args )
91*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
92*37da2899SCharles.Forsyth 
93*37da2899SCharles.Forsyth     *astream = 0;
94*37da2899SCharles.Forsyth     memory   = library->memory;
95*37da2899SCharles.Forsyth 
96*37da2899SCharles.Forsyth     if ( FT_NEW( stream ) )
97*37da2899SCharles.Forsyth       goto Exit;
98*37da2899SCharles.Forsyth 
99*37da2899SCharles.Forsyth     stream->memory = memory;
100*37da2899SCharles.Forsyth 
101*37da2899SCharles.Forsyth     if ( args->flags & FT_OPEN_MEMORY )
102*37da2899SCharles.Forsyth     {
103*37da2899SCharles.Forsyth       /* create a memory-based stream */
104*37da2899SCharles.Forsyth       FT_Stream_OpenMemory( stream,
105*37da2899SCharles.Forsyth                             (const FT_Byte*)args->memory_base,
106*37da2899SCharles.Forsyth                             args->memory_size );
107*37da2899SCharles.Forsyth     }
108*37da2899SCharles.Forsyth     else if ( args->flags & FT_OPEN_PATHNAME )
109*37da2899SCharles.Forsyth     {
110*37da2899SCharles.Forsyth       /* create a normal system stream */
111*37da2899SCharles.Forsyth       error = FT_Stream_Open( stream, args->pathname );
112*37da2899SCharles.Forsyth       stream->pathname.pointer = args->pathname;
113*37da2899SCharles.Forsyth     }
114*37da2899SCharles.Forsyth     else if ( ( args->flags & FT_OPEN_STREAM ) && args->stream )
115*37da2899SCharles.Forsyth     {
116*37da2899SCharles.Forsyth       /* use an existing, user-provided stream */
117*37da2899SCharles.Forsyth 
118*37da2899SCharles.Forsyth       /* in this case, we do not need to allocate a new stream object */
119*37da2899SCharles.Forsyth       /* since the caller is responsible for closing it himself       */
120*37da2899SCharles.Forsyth       FT_FREE( stream );
121*37da2899SCharles.Forsyth       stream = args->stream;
122*37da2899SCharles.Forsyth     }
123*37da2899SCharles.Forsyth     else
124*37da2899SCharles.Forsyth       error = FT_Err_Invalid_Argument;
125*37da2899SCharles.Forsyth 
126*37da2899SCharles.Forsyth     if ( error )
127*37da2899SCharles.Forsyth       FT_FREE( stream );
128*37da2899SCharles.Forsyth     else
129*37da2899SCharles.Forsyth       stream->memory = memory;  /* just to be certain */
130*37da2899SCharles.Forsyth 
131*37da2899SCharles.Forsyth     *astream = stream;
132*37da2899SCharles.Forsyth 
133*37da2899SCharles.Forsyth   Exit:
134*37da2899SCharles.Forsyth     return error;
135*37da2899SCharles.Forsyth   }
136*37da2899SCharles.Forsyth 
137*37da2899SCharles.Forsyth 
138*37da2899SCharles.Forsyth   static void
ft_input_stream_free(FT_Stream stream,FT_Int external)139*37da2899SCharles.Forsyth   ft_input_stream_free( FT_Stream  stream,
140*37da2899SCharles.Forsyth                         FT_Int     external )
141*37da2899SCharles.Forsyth   {
142*37da2899SCharles.Forsyth     if ( stream )
143*37da2899SCharles.Forsyth     {
144*37da2899SCharles.Forsyth       FT_Memory  memory = stream->memory;
145*37da2899SCharles.Forsyth 
146*37da2899SCharles.Forsyth 
147*37da2899SCharles.Forsyth       FT_Stream_Close( stream );
148*37da2899SCharles.Forsyth 
149*37da2899SCharles.Forsyth       if ( !external )
150*37da2899SCharles.Forsyth         FT_FREE( stream );
151*37da2899SCharles.Forsyth     }
152*37da2899SCharles.Forsyth   }
153*37da2899SCharles.Forsyth 
154*37da2899SCharles.Forsyth 
155*37da2899SCharles.Forsyth #undef  FT_COMPONENT
156*37da2899SCharles.Forsyth #define FT_COMPONENT  trace_objs
157*37da2899SCharles.Forsyth 
158*37da2899SCharles.Forsyth 
159*37da2899SCharles.Forsyth   /*************************************************************************/
160*37da2899SCharles.Forsyth   /*************************************************************************/
161*37da2899SCharles.Forsyth   /*************************************************************************/
162*37da2899SCharles.Forsyth   /****                                                                 ****/
163*37da2899SCharles.Forsyth   /****                                                                 ****/
164*37da2899SCharles.Forsyth   /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
165*37da2899SCharles.Forsyth   /****                                                                 ****/
166*37da2899SCharles.Forsyth   /****                                                                 ****/
167*37da2899SCharles.Forsyth   /*************************************************************************/
168*37da2899SCharles.Forsyth   /*************************************************************************/
169*37da2899SCharles.Forsyth   /*************************************************************************/
170*37da2899SCharles.Forsyth 
171*37da2899SCharles.Forsyth 
172*37da2899SCharles.Forsyth   static FT_Error
ft_glyphslot_init(FT_GlyphSlot slot)173*37da2899SCharles.Forsyth   ft_glyphslot_init( FT_GlyphSlot  slot )
174*37da2899SCharles.Forsyth   {
175*37da2899SCharles.Forsyth     FT_Driver         driver = slot->face->driver;
176*37da2899SCharles.Forsyth     FT_Driver_Class   clazz  = driver->clazz;
177*37da2899SCharles.Forsyth     FT_Memory         memory = driver->root.memory;
178*37da2899SCharles.Forsyth     FT_Error          error  = FT_Err_Ok;
179*37da2899SCharles.Forsyth     FT_Slot_Internal  internal;
180*37da2899SCharles.Forsyth 
181*37da2899SCharles.Forsyth 
182*37da2899SCharles.Forsyth     slot->library = driver->root.library;
183*37da2899SCharles.Forsyth 
184*37da2899SCharles.Forsyth     if ( FT_NEW( internal ) )
185*37da2899SCharles.Forsyth       goto Exit;
186*37da2899SCharles.Forsyth 
187*37da2899SCharles.Forsyth     slot->internal = internal;
188*37da2899SCharles.Forsyth 
189*37da2899SCharles.Forsyth     if ( FT_DRIVER_USES_OUTLINES( driver ) )
190*37da2899SCharles.Forsyth       error = FT_GlyphLoader_New( memory, &internal->loader );
191*37da2899SCharles.Forsyth 
192*37da2899SCharles.Forsyth     if ( !error && clazz->init_slot )
193*37da2899SCharles.Forsyth       error = clazz->init_slot( slot );
194*37da2899SCharles.Forsyth 
195*37da2899SCharles.Forsyth   Exit:
196*37da2899SCharles.Forsyth     return error;
197*37da2899SCharles.Forsyth   }
198*37da2899SCharles.Forsyth 
199*37da2899SCharles.Forsyth 
200*37da2899SCharles.Forsyth   static void
ft_glyphslot_clear(FT_GlyphSlot slot)201*37da2899SCharles.Forsyth   ft_glyphslot_clear( FT_GlyphSlot  slot )
202*37da2899SCharles.Forsyth   {
203*37da2899SCharles.Forsyth     /* free bitmap if needed */
204*37da2899SCharles.Forsyth     if ( slot->flags & FT_GLYPH_OWN_BITMAP )
205*37da2899SCharles.Forsyth     {
206*37da2899SCharles.Forsyth       FT_Memory  memory = FT_FACE_MEMORY( slot->face );
207*37da2899SCharles.Forsyth 
208*37da2899SCharles.Forsyth 
209*37da2899SCharles.Forsyth       FT_FREE( slot->bitmap.buffer );
210*37da2899SCharles.Forsyth       slot->flags &= ~FT_GLYPH_OWN_BITMAP;
211*37da2899SCharles.Forsyth     }
212*37da2899SCharles.Forsyth 
213*37da2899SCharles.Forsyth     /* clear all public fields in the glyph slot */
214*37da2899SCharles.Forsyth     FT_ZERO( &slot->metrics );
215*37da2899SCharles.Forsyth     FT_ZERO( &slot->outline );
216*37da2899SCharles.Forsyth 
217*37da2899SCharles.Forsyth     slot->bitmap.width = 0;
218*37da2899SCharles.Forsyth     slot->bitmap.rows  = 0;
219*37da2899SCharles.Forsyth     slot->bitmap.pitch = 0;
220*37da2899SCharles.Forsyth     slot->bitmap.pixel_mode = 0;
221*37da2899SCharles.Forsyth     /* don't touch 'slot->bitmap.buffer' !! */
222*37da2899SCharles.Forsyth 
223*37da2899SCharles.Forsyth     slot->bitmap_left   = 0;
224*37da2899SCharles.Forsyth     slot->bitmap_top    = 0;
225*37da2899SCharles.Forsyth     slot->num_subglyphs = 0;
226*37da2899SCharles.Forsyth     slot->subglyphs     = 0;
227*37da2899SCharles.Forsyth     slot->control_data  = 0;
228*37da2899SCharles.Forsyth     slot->control_len   = 0;
229*37da2899SCharles.Forsyth     slot->other         = 0;
230*37da2899SCharles.Forsyth     slot->format        = FT_GLYPH_FORMAT_NONE;
231*37da2899SCharles.Forsyth 
232*37da2899SCharles.Forsyth     slot->linearHoriAdvance = 0;
233*37da2899SCharles.Forsyth     slot->linearVertAdvance = 0;
234*37da2899SCharles.Forsyth   }
235*37da2899SCharles.Forsyth 
236*37da2899SCharles.Forsyth 
237*37da2899SCharles.Forsyth   static void
ft_glyphslot_done(FT_GlyphSlot slot)238*37da2899SCharles.Forsyth   ft_glyphslot_done( FT_GlyphSlot  slot )
239*37da2899SCharles.Forsyth   {
240*37da2899SCharles.Forsyth     FT_Driver         driver = slot->face->driver;
241*37da2899SCharles.Forsyth     FT_Driver_Class   clazz  = driver->clazz;
242*37da2899SCharles.Forsyth     FT_Memory         memory = driver->root.memory;
243*37da2899SCharles.Forsyth 
244*37da2899SCharles.Forsyth 
245*37da2899SCharles.Forsyth     if ( clazz->done_slot )
246*37da2899SCharles.Forsyth       clazz->done_slot( slot );
247*37da2899SCharles.Forsyth 
248*37da2899SCharles.Forsyth     /* free bitmap buffer if needed */
249*37da2899SCharles.Forsyth     if ( slot->flags & FT_GLYPH_OWN_BITMAP )
250*37da2899SCharles.Forsyth       FT_FREE( slot->bitmap.buffer );
251*37da2899SCharles.Forsyth 
252*37da2899SCharles.Forsyth     /* free glyph loader */
253*37da2899SCharles.Forsyth     if ( FT_DRIVER_USES_OUTLINES( driver ) )
254*37da2899SCharles.Forsyth     {
255*37da2899SCharles.Forsyth       FT_GlyphLoader_Done( slot->internal->loader );
256*37da2899SCharles.Forsyth       slot->internal->loader = 0;
257*37da2899SCharles.Forsyth     }
258*37da2899SCharles.Forsyth 
259*37da2899SCharles.Forsyth     FT_FREE( slot->internal );
260*37da2899SCharles.Forsyth   }
261*37da2899SCharles.Forsyth 
262*37da2899SCharles.Forsyth 
263*37da2899SCharles.Forsyth   /* documentation is in ftobjs.h */
264*37da2899SCharles.Forsyth 
265*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Error )
FT_New_GlyphSlot(FT_Face face,FT_GlyphSlot * aslot)266*37da2899SCharles.Forsyth   FT_New_GlyphSlot( FT_Face        face,
267*37da2899SCharles.Forsyth                     FT_GlyphSlot  *aslot )
268*37da2899SCharles.Forsyth   {
269*37da2899SCharles.Forsyth     FT_Error          error;
270*37da2899SCharles.Forsyth     FT_Driver         driver;
271*37da2899SCharles.Forsyth     FT_Driver_Class   clazz;
272*37da2899SCharles.Forsyth     FT_Memory         memory;
273*37da2899SCharles.Forsyth     FT_GlyphSlot      slot;
274*37da2899SCharles.Forsyth 
275*37da2899SCharles.Forsyth 
276*37da2899SCharles.Forsyth     if ( !face || !aslot || !face->driver )
277*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
278*37da2899SCharles.Forsyth 
279*37da2899SCharles.Forsyth     *aslot = 0;
280*37da2899SCharles.Forsyth 
281*37da2899SCharles.Forsyth     driver = face->driver;
282*37da2899SCharles.Forsyth     clazz  = driver->clazz;
283*37da2899SCharles.Forsyth     memory = driver->root.memory;
284*37da2899SCharles.Forsyth 
285*37da2899SCharles.Forsyth     FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
286*37da2899SCharles.Forsyth     if ( !FT_ALLOC( slot, clazz->slot_object_size ) )
287*37da2899SCharles.Forsyth     {
288*37da2899SCharles.Forsyth       slot->face = face;
289*37da2899SCharles.Forsyth 
290*37da2899SCharles.Forsyth       error = ft_glyphslot_init( slot );
291*37da2899SCharles.Forsyth       if ( error )
292*37da2899SCharles.Forsyth       {
293*37da2899SCharles.Forsyth         ft_glyphslot_done( slot );
294*37da2899SCharles.Forsyth         FT_FREE( slot );
295*37da2899SCharles.Forsyth         goto Exit;
296*37da2899SCharles.Forsyth       }
297*37da2899SCharles.Forsyth 
298*37da2899SCharles.Forsyth       *aslot = slot;
299*37da2899SCharles.Forsyth     }
300*37da2899SCharles.Forsyth 
301*37da2899SCharles.Forsyth   Exit:
302*37da2899SCharles.Forsyth     FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
303*37da2899SCharles.Forsyth     return error;
304*37da2899SCharles.Forsyth   }
305*37da2899SCharles.Forsyth 
306*37da2899SCharles.Forsyth 
307*37da2899SCharles.Forsyth   /* documentation is in ftobjs.h */
308*37da2899SCharles.Forsyth 
309*37da2899SCharles.Forsyth   FT_BASE_DEF( void )
FT_Done_GlyphSlot(FT_GlyphSlot slot)310*37da2899SCharles.Forsyth   FT_Done_GlyphSlot( FT_GlyphSlot  slot )
311*37da2899SCharles.Forsyth   {
312*37da2899SCharles.Forsyth     if ( slot )
313*37da2899SCharles.Forsyth     {
314*37da2899SCharles.Forsyth       FT_Driver      driver = slot->face->driver;
315*37da2899SCharles.Forsyth       FT_Memory      memory = driver->root.memory;
316*37da2899SCharles.Forsyth       FT_GlyphSlot*  parent;
317*37da2899SCharles.Forsyth       FT_GlyphSlot   cur;
318*37da2899SCharles.Forsyth 
319*37da2899SCharles.Forsyth 
320*37da2899SCharles.Forsyth       /* Remove slot from its parent face's list */
321*37da2899SCharles.Forsyth       parent = &slot->face->glyph;
322*37da2899SCharles.Forsyth       cur    = *parent;
323*37da2899SCharles.Forsyth 
324*37da2899SCharles.Forsyth       while ( cur )
325*37da2899SCharles.Forsyth       {
326*37da2899SCharles.Forsyth         if ( cur == slot )
327*37da2899SCharles.Forsyth         {
328*37da2899SCharles.Forsyth           *parent = cur->next;
329*37da2899SCharles.Forsyth           ft_glyphslot_done( slot );
330*37da2899SCharles.Forsyth           FT_FREE( slot );
331*37da2899SCharles.Forsyth           break;
332*37da2899SCharles.Forsyth         }
333*37da2899SCharles.Forsyth         cur = cur->next;
334*37da2899SCharles.Forsyth       }
335*37da2899SCharles.Forsyth     }
336*37da2899SCharles.Forsyth   }
337*37da2899SCharles.Forsyth 
338*37da2899SCharles.Forsyth 
339*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
340*37da2899SCharles.Forsyth 
341*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Set_Transform(FT_Face face,FT_Matrix * matrix,FT_Vector * delta)342*37da2899SCharles.Forsyth   FT_Set_Transform( FT_Face     face,
343*37da2899SCharles.Forsyth                     FT_Matrix*  matrix,
344*37da2899SCharles.Forsyth                     FT_Vector*  delta )
345*37da2899SCharles.Forsyth   {
346*37da2899SCharles.Forsyth     FT_Face_Internal  internal;
347*37da2899SCharles.Forsyth 
348*37da2899SCharles.Forsyth 
349*37da2899SCharles.Forsyth     if ( !face )
350*37da2899SCharles.Forsyth       return;
351*37da2899SCharles.Forsyth 
352*37da2899SCharles.Forsyth     internal = face->internal;
353*37da2899SCharles.Forsyth 
354*37da2899SCharles.Forsyth     internal->transform_flags = 0;
355*37da2899SCharles.Forsyth 
356*37da2899SCharles.Forsyth     if ( !matrix )
357*37da2899SCharles.Forsyth     {
358*37da2899SCharles.Forsyth       internal->transform_matrix.xx = 0x10000L;
359*37da2899SCharles.Forsyth       internal->transform_matrix.xy = 0;
360*37da2899SCharles.Forsyth       internal->transform_matrix.yx = 0;
361*37da2899SCharles.Forsyth       internal->transform_matrix.yy = 0x10000L;
362*37da2899SCharles.Forsyth       matrix = &internal->transform_matrix;
363*37da2899SCharles.Forsyth     }
364*37da2899SCharles.Forsyth     else
365*37da2899SCharles.Forsyth       internal->transform_matrix = *matrix;
366*37da2899SCharles.Forsyth 
367*37da2899SCharles.Forsyth     /* set transform_flags bit flag 0 if `matrix' isn't the identity */
368*37da2899SCharles.Forsyth     if ( ( matrix->xy | matrix->yx ) ||
369*37da2899SCharles.Forsyth          matrix->xx != 0x10000L      ||
370*37da2899SCharles.Forsyth          matrix->yy != 0x10000L      )
371*37da2899SCharles.Forsyth       internal->transform_flags |= 1;
372*37da2899SCharles.Forsyth 
373*37da2899SCharles.Forsyth     if ( !delta )
374*37da2899SCharles.Forsyth     {
375*37da2899SCharles.Forsyth       internal->transform_delta.x = 0;
376*37da2899SCharles.Forsyth       internal->transform_delta.y = 0;
377*37da2899SCharles.Forsyth       delta = &internal->transform_delta;
378*37da2899SCharles.Forsyth     }
379*37da2899SCharles.Forsyth     else
380*37da2899SCharles.Forsyth       internal->transform_delta = *delta;
381*37da2899SCharles.Forsyth 
382*37da2899SCharles.Forsyth     /* set transform_flags bit flag 1 if `delta' isn't the null vector */
383*37da2899SCharles.Forsyth     if ( delta->x | delta->y )
384*37da2899SCharles.Forsyth       internal->transform_flags |= 2;
385*37da2899SCharles.Forsyth   }
386*37da2899SCharles.Forsyth 
387*37da2899SCharles.Forsyth 
388*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
389*37da2899SCharles.Forsyth 
390*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Set_Hint_Flags(FT_Face face,FT_ULong flags)391*37da2899SCharles.Forsyth   FT_Set_Hint_Flags( FT_Face     face,
392*37da2899SCharles.Forsyth                      FT_ULong    flags )
393*37da2899SCharles.Forsyth   {
394*37da2899SCharles.Forsyth     FT_Face_Internal  internal;
395*37da2899SCharles.Forsyth 
396*37da2899SCharles.Forsyth     if ( !face )
397*37da2899SCharles.Forsyth       return;
398*37da2899SCharles.Forsyth 
399*37da2899SCharles.Forsyth     internal = face->internal;
400*37da2899SCharles.Forsyth 
401*37da2899SCharles.Forsyth     internal->hint_flags = (FT_UInt)flags;
402*37da2899SCharles.Forsyth   }
403*37da2899SCharles.Forsyth 
404*37da2899SCharles.Forsyth 
405*37da2899SCharles.Forsyth   static FT_Renderer
406*37da2899SCharles.Forsyth   ft_lookup_glyph_renderer( FT_GlyphSlot  slot );
407*37da2899SCharles.Forsyth 
408*37da2899SCharles.Forsyth 
409*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
410*37da2899SCharles.Forsyth 
411*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Load_Glyph(FT_Face face,FT_UInt glyph_index,FT_Int32 load_flags)412*37da2899SCharles.Forsyth   FT_Load_Glyph( FT_Face   face,
413*37da2899SCharles.Forsyth                  FT_UInt   glyph_index,
414*37da2899SCharles.Forsyth                  FT_Int32  load_flags )
415*37da2899SCharles.Forsyth   {
416*37da2899SCharles.Forsyth     FT_Error      error;
417*37da2899SCharles.Forsyth     FT_Driver     driver;
418*37da2899SCharles.Forsyth     FT_GlyphSlot  slot;
419*37da2899SCharles.Forsyth     FT_Library    library;
420*37da2899SCharles.Forsyth     FT_Bool       autohint;
421*37da2899SCharles.Forsyth     FT_Module     hinter;
422*37da2899SCharles.Forsyth 
423*37da2899SCharles.Forsyth 
424*37da2899SCharles.Forsyth     if ( !face || !face->size || !face->glyph )
425*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
426*37da2899SCharles.Forsyth 
427*37da2899SCharles.Forsyth     if ( glyph_index > (FT_UInt)face->num_glyphs )
428*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
429*37da2899SCharles.Forsyth 
430*37da2899SCharles.Forsyth     slot = face->glyph;
431*37da2899SCharles.Forsyth     ft_glyphslot_clear( slot );
432*37da2899SCharles.Forsyth 
433*37da2899SCharles.Forsyth     driver = face->driver;
434*37da2899SCharles.Forsyth 
435*37da2899SCharles.Forsyth     /* if the flag NO_RECURSE is set, we disable hinting and scaling */
436*37da2899SCharles.Forsyth     if ( load_flags & FT_LOAD_NO_RECURSE )
437*37da2899SCharles.Forsyth     {
438*37da2899SCharles.Forsyth       /* disable scaling, hinting, and transformation */
439*37da2899SCharles.Forsyth       load_flags |= FT_LOAD_NO_SCALE         |
440*37da2899SCharles.Forsyth                     FT_LOAD_NO_HINTING       |
441*37da2899SCharles.Forsyth                     FT_LOAD_NO_BITMAP        |
442*37da2899SCharles.Forsyth                     FT_LOAD_IGNORE_TRANSFORM;
443*37da2899SCharles.Forsyth 
444*37da2899SCharles.Forsyth       /* disable bitmap rendering */
445*37da2899SCharles.Forsyth       load_flags &= ~FT_LOAD_RENDER;
446*37da2899SCharles.Forsyth     }
447*37da2899SCharles.Forsyth 
448*37da2899SCharles.Forsyth     /* do we need to load the glyph through the auto-hinter? */
449*37da2899SCharles.Forsyth     library  = driver->root.library;
450*37da2899SCharles.Forsyth     hinter   = library->auto_hinter;
451*37da2899SCharles.Forsyth     autohint =
452*37da2899SCharles.Forsyth       FT_BOOL( hinter                                      &&
453*37da2899SCharles.Forsyth                !( load_flags & ( FT_LOAD_NO_SCALE    |
454*37da2899SCharles.Forsyth                                  FT_LOAD_NO_HINTING  |
455*37da2899SCharles.Forsyth                                  FT_LOAD_NO_AUTOHINT ) )   &&
456*37da2899SCharles.Forsyth                FT_DRIVER_IS_SCALABLE( driver )             &&
457*37da2899SCharles.Forsyth                FT_DRIVER_USES_OUTLINES( driver )           );
458*37da2899SCharles.Forsyth     if ( autohint )
459*37da2899SCharles.Forsyth     {
460*37da2899SCharles.Forsyth       if ( FT_DRIVER_HAS_HINTER( driver ) &&
461*37da2899SCharles.Forsyth            !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
462*37da2899SCharles.Forsyth         autohint = 0;
463*37da2899SCharles.Forsyth     }
464*37da2899SCharles.Forsyth 
465*37da2899SCharles.Forsyth     if ( autohint )
466*37da2899SCharles.Forsyth     {
467*37da2899SCharles.Forsyth       FT_AutoHinter_Service  hinting;
468*37da2899SCharles.Forsyth 
469*37da2899SCharles.Forsyth 
470*37da2899SCharles.Forsyth       /* try to load embedded bitmaps first if available            */
471*37da2899SCharles.Forsyth       /*                                                            */
472*37da2899SCharles.Forsyth       /* XXX: This is really a temporary hack that should disappear */
473*37da2899SCharles.Forsyth       /*      promptly with FreeType 2.1!                           */
474*37da2899SCharles.Forsyth       /*                                                            */
475*37da2899SCharles.Forsyth       if ( FT_HAS_FIXED_SIZES( face )             &&
476*37da2899SCharles.Forsyth           ( load_flags & FT_LOAD_NO_BITMAP ) == 0 )
477*37da2899SCharles.Forsyth       {
478*37da2899SCharles.Forsyth         error = driver->clazz->load_glyph( slot, face->size,
479*37da2899SCharles.Forsyth                                            glyph_index,
480*37da2899SCharles.Forsyth                                            load_flags | FT_LOAD_SBITS_ONLY );
481*37da2899SCharles.Forsyth 
482*37da2899SCharles.Forsyth         if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
483*37da2899SCharles.Forsyth           goto Load_Ok;
484*37da2899SCharles.Forsyth       }
485*37da2899SCharles.Forsyth 
486*37da2899SCharles.Forsyth       /* load auto-hinted outline */
487*37da2899SCharles.Forsyth       hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
488*37da2899SCharles.Forsyth 
489*37da2899SCharles.Forsyth       error   = hinting->load_glyph( (FT_AutoHinter)hinter,
490*37da2899SCharles.Forsyth                                      slot, face->size,
491*37da2899SCharles.Forsyth                                      glyph_index, load_flags );
492*37da2899SCharles.Forsyth     }
493*37da2899SCharles.Forsyth     else
494*37da2899SCharles.Forsyth     {
495*37da2899SCharles.Forsyth       error = driver->clazz->load_glyph( slot,
496*37da2899SCharles.Forsyth                                          face->size,
497*37da2899SCharles.Forsyth                                          glyph_index,
498*37da2899SCharles.Forsyth                                          load_flags );
499*37da2899SCharles.Forsyth       if ( error )
500*37da2899SCharles.Forsyth         goto Exit;
501*37da2899SCharles.Forsyth 
502*37da2899SCharles.Forsyth       /* check that the loaded outline is correct */
503*37da2899SCharles.Forsyth       error = FT_Outline_Check( &slot->outline );
504*37da2899SCharles.Forsyth       if ( error )
505*37da2899SCharles.Forsyth         goto Exit;
506*37da2899SCharles.Forsyth     }
507*37da2899SCharles.Forsyth 
508*37da2899SCharles.Forsyth   Load_Ok:
509*37da2899SCharles.Forsyth     /* compute the advance */
510*37da2899SCharles.Forsyth     if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
511*37da2899SCharles.Forsyth     {
512*37da2899SCharles.Forsyth       slot->advance.x = 0;
513*37da2899SCharles.Forsyth       slot->advance.y = slot->metrics.vertAdvance;
514*37da2899SCharles.Forsyth     }
515*37da2899SCharles.Forsyth     else
516*37da2899SCharles.Forsyth     {
517*37da2899SCharles.Forsyth       slot->advance.x = slot->metrics.horiAdvance;
518*37da2899SCharles.Forsyth       slot->advance.y = 0;
519*37da2899SCharles.Forsyth     }
520*37da2899SCharles.Forsyth 
521*37da2899SCharles.Forsyth     /* compute the linear advance in 16.16 pixels */
522*37da2899SCharles.Forsyth     if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 )
523*37da2899SCharles.Forsyth     {
524*37da2899SCharles.Forsyth       FT_UInt           EM      = face->units_per_EM;
525*37da2899SCharles.Forsyth       FT_Size_Metrics*  metrics = &face->size->metrics;
526*37da2899SCharles.Forsyth 
527*37da2899SCharles.Forsyth 
528*37da2899SCharles.Forsyth       slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
529*37da2899SCharles.Forsyth                                            (FT_Long)metrics->x_ppem << 16, EM );
530*37da2899SCharles.Forsyth 
531*37da2899SCharles.Forsyth       slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
532*37da2899SCharles.Forsyth                                            (FT_Long)metrics->y_ppem << 16, EM );
533*37da2899SCharles.Forsyth     }
534*37da2899SCharles.Forsyth 
535*37da2899SCharles.Forsyth     if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
536*37da2899SCharles.Forsyth     {
537*37da2899SCharles.Forsyth       FT_Face_Internal  internal = face->internal;
538*37da2899SCharles.Forsyth 
539*37da2899SCharles.Forsyth 
540*37da2899SCharles.Forsyth       /* now, transform the glyph image if needed */
541*37da2899SCharles.Forsyth       if ( internal->transform_flags )
542*37da2899SCharles.Forsyth       {
543*37da2899SCharles.Forsyth         /* get renderer */
544*37da2899SCharles.Forsyth         FT_Renderer  renderer = ft_lookup_glyph_renderer( slot );
545*37da2899SCharles.Forsyth 
546*37da2899SCharles.Forsyth 
547*37da2899SCharles.Forsyth         if ( renderer )
548*37da2899SCharles.Forsyth           error = renderer->clazz->transform_glyph(
549*37da2899SCharles.Forsyth                                      renderer, slot,
550*37da2899SCharles.Forsyth                                      &internal->transform_matrix,
551*37da2899SCharles.Forsyth                                      &internal->transform_delta );
552*37da2899SCharles.Forsyth         /* transform advance */
553*37da2899SCharles.Forsyth         FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
554*37da2899SCharles.Forsyth       }
555*37da2899SCharles.Forsyth     }
556*37da2899SCharles.Forsyth 
557*37da2899SCharles.Forsyth     /* do we need to render the image now? */
558*37da2899SCharles.Forsyth     if ( !error                                    &&
559*37da2899SCharles.Forsyth          slot->format != FT_GLYPH_FORMAT_BITMAP    &&
560*37da2899SCharles.Forsyth          slot->format != FT_GLYPH_FORMAT_COMPOSITE &&
561*37da2899SCharles.Forsyth          load_flags & FT_LOAD_RENDER )
562*37da2899SCharles.Forsyth     {
563*37da2899SCharles.Forsyth       FT_Render_Mode  mode = FT_LOAD_TARGET_MODE( load_flags );
564*37da2899SCharles.Forsyth 
565*37da2899SCharles.Forsyth 
566*37da2899SCharles.Forsyth       if ( mode == FT_RENDER_MODE_NORMAL      &&
567*37da2899SCharles.Forsyth            (load_flags & FT_LOAD_MONOCHROME ) )
568*37da2899SCharles.Forsyth         mode = FT_RENDER_MODE_MONO;
569*37da2899SCharles.Forsyth 
570*37da2899SCharles.Forsyth       error = FT_Render_Glyph( slot, mode );
571*37da2899SCharles.Forsyth     }
572*37da2899SCharles.Forsyth 
573*37da2899SCharles.Forsyth   Exit:
574*37da2899SCharles.Forsyth     return error;
575*37da2899SCharles.Forsyth   }
576*37da2899SCharles.Forsyth 
577*37da2899SCharles.Forsyth 
578*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
579*37da2899SCharles.Forsyth 
580*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Load_Char(FT_Face face,FT_ULong char_code,FT_Int32 load_flags)581*37da2899SCharles.Forsyth   FT_Load_Char( FT_Face   face,
582*37da2899SCharles.Forsyth                 FT_ULong  char_code,
583*37da2899SCharles.Forsyth                 FT_Int32  load_flags )
584*37da2899SCharles.Forsyth   {
585*37da2899SCharles.Forsyth     FT_UInt  glyph_index;
586*37da2899SCharles.Forsyth 
587*37da2899SCharles.Forsyth 
588*37da2899SCharles.Forsyth     if ( !face )
589*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
590*37da2899SCharles.Forsyth 
591*37da2899SCharles.Forsyth     glyph_index = (FT_UInt)char_code;
592*37da2899SCharles.Forsyth     if ( face->charmap )
593*37da2899SCharles.Forsyth       glyph_index = FT_Get_Char_Index( face, char_code );
594*37da2899SCharles.Forsyth 
595*37da2899SCharles.Forsyth     return FT_Load_Glyph( face, glyph_index, load_flags );
596*37da2899SCharles.Forsyth   }
597*37da2899SCharles.Forsyth 
598*37da2899SCharles.Forsyth 
599*37da2899SCharles.Forsyth   /* destructor for sizes list */
600*37da2899SCharles.Forsyth   static void
destroy_size(FT_Memory memory,FT_Size size,FT_Driver driver)601*37da2899SCharles.Forsyth   destroy_size( FT_Memory  memory,
602*37da2899SCharles.Forsyth                 FT_Size    size,
603*37da2899SCharles.Forsyth                 FT_Driver  driver )
604*37da2899SCharles.Forsyth   {
605*37da2899SCharles.Forsyth     /* finalize client-specific data */
606*37da2899SCharles.Forsyth     if ( size->generic.finalizer )
607*37da2899SCharles.Forsyth       size->generic.finalizer( size );
608*37da2899SCharles.Forsyth 
609*37da2899SCharles.Forsyth     /* finalize format-specific stuff */
610*37da2899SCharles.Forsyth     if ( driver->clazz->done_size )
611*37da2899SCharles.Forsyth       driver->clazz->done_size( size );
612*37da2899SCharles.Forsyth 
613*37da2899SCharles.Forsyth     FT_FREE( size->internal );
614*37da2899SCharles.Forsyth     FT_FREE( size );
615*37da2899SCharles.Forsyth   }
616*37da2899SCharles.Forsyth 
617*37da2899SCharles.Forsyth 
618*37da2899SCharles.Forsyth   /* destructor for faces list */
619*37da2899SCharles.Forsyth   static void
destroy_face(FT_Memory memory,FT_Face face,FT_Driver driver)620*37da2899SCharles.Forsyth   destroy_face( FT_Memory  memory,
621*37da2899SCharles.Forsyth                 FT_Face    face,
622*37da2899SCharles.Forsyth                 FT_Driver  driver )
623*37da2899SCharles.Forsyth   {
624*37da2899SCharles.Forsyth     FT_Driver_Class  clazz = driver->clazz;
625*37da2899SCharles.Forsyth 
626*37da2899SCharles.Forsyth 
627*37da2899SCharles.Forsyth     /* discard auto-hinting data */
628*37da2899SCharles.Forsyth     if ( face->autohint.finalizer )
629*37da2899SCharles.Forsyth       face->autohint.finalizer( face->autohint.data );
630*37da2899SCharles.Forsyth 
631*37da2899SCharles.Forsyth     /* Discard glyph slots for this face.                           */
632*37da2899SCharles.Forsyth     /* Beware!  FT_Done_GlyphSlot() changes the field `face->glyph' */
633*37da2899SCharles.Forsyth     while ( face->glyph )
634*37da2899SCharles.Forsyth       FT_Done_GlyphSlot( face->glyph );
635*37da2899SCharles.Forsyth 
636*37da2899SCharles.Forsyth     /* discard all sizes for this face */
637*37da2899SCharles.Forsyth     FT_List_Finalize( &face->sizes_list,
638*37da2899SCharles.Forsyth                      (FT_List_Destructor)destroy_size,
639*37da2899SCharles.Forsyth                      memory,
640*37da2899SCharles.Forsyth                      driver );
641*37da2899SCharles.Forsyth     face->size = 0;
642*37da2899SCharles.Forsyth 
643*37da2899SCharles.Forsyth     /* now discard client data */
644*37da2899SCharles.Forsyth     if ( face->generic.finalizer )
645*37da2899SCharles.Forsyth       face->generic.finalizer( face );
646*37da2899SCharles.Forsyth 
647*37da2899SCharles.Forsyth     /* discard charmaps */
648*37da2899SCharles.Forsyth     {
649*37da2899SCharles.Forsyth       FT_Int  n;
650*37da2899SCharles.Forsyth 
651*37da2899SCharles.Forsyth 
652*37da2899SCharles.Forsyth       for ( n = 0; n < face->num_charmaps; n++ )
653*37da2899SCharles.Forsyth       {
654*37da2899SCharles.Forsyth         FT_CMap  cmap = FT_CMAP( face->charmaps[n] );
655*37da2899SCharles.Forsyth 
656*37da2899SCharles.Forsyth 
657*37da2899SCharles.Forsyth         FT_CMap_Done( cmap );
658*37da2899SCharles.Forsyth 
659*37da2899SCharles.Forsyth         face->charmaps[n] = NULL;
660*37da2899SCharles.Forsyth       }
661*37da2899SCharles.Forsyth 
662*37da2899SCharles.Forsyth       FT_FREE( face->charmaps );
663*37da2899SCharles.Forsyth       face->num_charmaps = 0;
664*37da2899SCharles.Forsyth     }
665*37da2899SCharles.Forsyth 
666*37da2899SCharles.Forsyth 
667*37da2899SCharles.Forsyth     /* finalize format-specific stuff */
668*37da2899SCharles.Forsyth     if ( clazz->done_face )
669*37da2899SCharles.Forsyth       clazz->done_face( face );
670*37da2899SCharles.Forsyth 
671*37da2899SCharles.Forsyth     /* close the stream for this face if needed */
672*37da2899SCharles.Forsyth     ft_input_stream_free(
673*37da2899SCharles.Forsyth       face->stream,
674*37da2899SCharles.Forsyth       ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
675*37da2899SCharles.Forsyth 
676*37da2899SCharles.Forsyth     face->stream = 0;
677*37da2899SCharles.Forsyth 
678*37da2899SCharles.Forsyth     /* get rid of it */
679*37da2899SCharles.Forsyth     if ( face->internal )
680*37da2899SCharles.Forsyth     {
681*37da2899SCharles.Forsyth       FT_FREE( face->internal->postscript_name );
682*37da2899SCharles.Forsyth       FT_FREE( face->internal );
683*37da2899SCharles.Forsyth     }
684*37da2899SCharles.Forsyth     FT_FREE( face );
685*37da2899SCharles.Forsyth   }
686*37da2899SCharles.Forsyth 
687*37da2899SCharles.Forsyth 
688*37da2899SCharles.Forsyth   static void
Destroy_Driver(FT_Driver driver)689*37da2899SCharles.Forsyth   Destroy_Driver( FT_Driver  driver )
690*37da2899SCharles.Forsyth   {
691*37da2899SCharles.Forsyth     FT_List_Finalize( &driver->faces_list,
692*37da2899SCharles.Forsyth                       (FT_List_Destructor)destroy_face,
693*37da2899SCharles.Forsyth                       driver->root.memory,
694*37da2899SCharles.Forsyth                       driver );
695*37da2899SCharles.Forsyth 
696*37da2899SCharles.Forsyth     /* check whether we need to drop the driver's glyph loader */
697*37da2899SCharles.Forsyth     if ( FT_DRIVER_USES_OUTLINES( driver ) )
698*37da2899SCharles.Forsyth       FT_GlyphLoader_Done( driver->glyph_loader );
699*37da2899SCharles.Forsyth   }
700*37da2899SCharles.Forsyth 
701*37da2899SCharles.Forsyth 
702*37da2899SCharles.Forsyth   /*************************************************************************/
703*37da2899SCharles.Forsyth   /*                                                                       */
704*37da2899SCharles.Forsyth   /* <Function>                                                            */
705*37da2899SCharles.Forsyth   /*    open_face                                                          */
706*37da2899SCharles.Forsyth   /*                                                                       */
707*37da2899SCharles.Forsyth   /* <Description>                                                         */
708*37da2899SCharles.Forsyth   /*    This function does some work for FT_Open_Face().                   */
709*37da2899SCharles.Forsyth   /*                                                                       */
710*37da2899SCharles.Forsyth   static FT_Error
open_face(FT_Driver driver,FT_Stream stream,FT_Long face_index,FT_Int num_params,FT_Parameter * params,FT_Face * aface)711*37da2899SCharles.Forsyth   open_face( FT_Driver      driver,
712*37da2899SCharles.Forsyth              FT_Stream      stream,
713*37da2899SCharles.Forsyth              FT_Long        face_index,
714*37da2899SCharles.Forsyth              FT_Int         num_params,
715*37da2899SCharles.Forsyth              FT_Parameter*  params,
716*37da2899SCharles.Forsyth              FT_Face*       aface )
717*37da2899SCharles.Forsyth   {
718*37da2899SCharles.Forsyth     FT_Memory         memory;
719*37da2899SCharles.Forsyth     FT_Driver_Class  clazz;
720*37da2899SCharles.Forsyth     FT_Face           face = 0;
721*37da2899SCharles.Forsyth     FT_Error          error;
722*37da2899SCharles.Forsyth     FT_Face_Internal  internal;
723*37da2899SCharles.Forsyth 
724*37da2899SCharles.Forsyth 
725*37da2899SCharles.Forsyth     clazz  = driver->clazz;
726*37da2899SCharles.Forsyth     memory = driver->root.memory;
727*37da2899SCharles.Forsyth 
728*37da2899SCharles.Forsyth     /* allocate the face object and perform basic initialization */
729*37da2899SCharles.Forsyth     if ( FT_ALLOC( face, clazz->face_object_size ) )
730*37da2899SCharles.Forsyth       goto Fail;
731*37da2899SCharles.Forsyth 
732*37da2899SCharles.Forsyth     if ( FT_NEW( internal ) )
733*37da2899SCharles.Forsyth       goto Fail;
734*37da2899SCharles.Forsyth 
735*37da2899SCharles.Forsyth     face->internal = internal;
736*37da2899SCharles.Forsyth 
737*37da2899SCharles.Forsyth     face->driver   = driver;
738*37da2899SCharles.Forsyth     face->memory   = memory;
739*37da2899SCharles.Forsyth     face->stream   = stream;
740*37da2899SCharles.Forsyth 
741*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL
742*37da2899SCharles.Forsyth     {
743*37da2899SCharles.Forsyth       int  i;
744*37da2899SCharles.Forsyth 
745*37da2899SCharles.Forsyth 
746*37da2899SCharles.Forsyth       face->internal->incremental_interface = 0;
747*37da2899SCharles.Forsyth       for ( i = 0; i < num_params && !face->internal->incremental_interface;
748*37da2899SCharles.Forsyth             i++ )
749*37da2899SCharles.Forsyth         if ( params[i].tag == FT_PARAM_TAG_INCREMENTAL )
750*37da2899SCharles.Forsyth           face->internal->incremental_interface = params[i].data;
751*37da2899SCharles.Forsyth 	}
752*37da2899SCharles.Forsyth #endif
753*37da2899SCharles.Forsyth 
754*37da2899SCharles.Forsyth     error = clazz->init_face( stream,
755*37da2899SCharles.Forsyth                               face,
756*37da2899SCharles.Forsyth                               (FT_Int)face_index,
757*37da2899SCharles.Forsyth                               num_params,
758*37da2899SCharles.Forsyth                               params );
759*37da2899SCharles.Forsyth     if ( error )
760*37da2899SCharles.Forsyth       goto Fail;
761*37da2899SCharles.Forsyth 
762*37da2899SCharles.Forsyth     /* select Unicode charmap by default */
763*37da2899SCharles.Forsyth     {
764*37da2899SCharles.Forsyth       FT_Int      nn;
765*37da2899SCharles.Forsyth       FT_CharMap  unicmap = NULL, cmap;
766*37da2899SCharles.Forsyth 
767*37da2899SCharles.Forsyth 
768*37da2899SCharles.Forsyth       for ( nn = 0; nn < face->num_charmaps; nn++ )
769*37da2899SCharles.Forsyth       {
770*37da2899SCharles.Forsyth         cmap = face->charmaps[nn];
771*37da2899SCharles.Forsyth 
772*37da2899SCharles.Forsyth         if ( cmap->encoding == FT_ENCODING_UNICODE )
773*37da2899SCharles.Forsyth         {
774*37da2899SCharles.Forsyth           unicmap = cmap;
775*37da2899SCharles.Forsyth           break;
776*37da2899SCharles.Forsyth         }
777*37da2899SCharles.Forsyth       }
778*37da2899SCharles.Forsyth 
779*37da2899SCharles.Forsyth       if ( unicmap != NULL )
780*37da2899SCharles.Forsyth         face->charmap = unicmap;
781*37da2899SCharles.Forsyth     }
782*37da2899SCharles.Forsyth 
783*37da2899SCharles.Forsyth     *aface = face;
784*37da2899SCharles.Forsyth 
785*37da2899SCharles.Forsyth   Fail:
786*37da2899SCharles.Forsyth     if ( error )
787*37da2899SCharles.Forsyth     {
788*37da2899SCharles.Forsyth       clazz->done_face( face );
789*37da2899SCharles.Forsyth       FT_FREE( face->internal );
790*37da2899SCharles.Forsyth       FT_FREE( face );
791*37da2899SCharles.Forsyth       *aface = 0;
792*37da2899SCharles.Forsyth     }
793*37da2899SCharles.Forsyth 
794*37da2899SCharles.Forsyth     return error;
795*37da2899SCharles.Forsyth   }
796*37da2899SCharles.Forsyth 
797*37da2899SCharles.Forsyth 
798*37da2899SCharles.Forsyth   /* there's a Mac-specific extended implementation of FT_New_Face() */
799*37da2899SCharles.Forsyth   /* in src/base/ftmac.c                                             */
800*37da2899SCharles.Forsyth 
801*37da2899SCharles.Forsyth #ifndef FT_MACINTOSH
802*37da2899SCharles.Forsyth 
803*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
804*37da2899SCharles.Forsyth 
805*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_New_Face(FT_Library library,const char * pathname,FT_Long face_index,FT_Face * aface)806*37da2899SCharles.Forsyth   FT_New_Face( FT_Library   library,
807*37da2899SCharles.Forsyth                const char*  pathname,
808*37da2899SCharles.Forsyth                FT_Long      face_index,
809*37da2899SCharles.Forsyth                FT_Face     *aface )
810*37da2899SCharles.Forsyth   {
811*37da2899SCharles.Forsyth     FT_Open_Args  args;
812*37da2899SCharles.Forsyth 
813*37da2899SCharles.Forsyth 
814*37da2899SCharles.Forsyth     /* test for valid `library' and `aface' delayed to FT_Open_Face() */
815*37da2899SCharles.Forsyth     if ( !pathname )
816*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
817*37da2899SCharles.Forsyth 
818*37da2899SCharles.Forsyth     args.flags    = FT_OPEN_PATHNAME;
819*37da2899SCharles.Forsyth     args.pathname = (char*)pathname;
820*37da2899SCharles.Forsyth 
821*37da2899SCharles.Forsyth     return FT_Open_Face( library, &args, face_index, aface );
822*37da2899SCharles.Forsyth   }
823*37da2899SCharles.Forsyth 
824*37da2899SCharles.Forsyth #endif  /* !FT_MACINTOSH */
825*37da2899SCharles.Forsyth 
826*37da2899SCharles.Forsyth 
827*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
828*37da2899SCharles.Forsyth 
829*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_New_Memory_Face(FT_Library library,const FT_Byte * file_base,FT_Long file_size,FT_Long face_index,FT_Face * aface)830*37da2899SCharles.Forsyth   FT_New_Memory_Face( FT_Library      library,
831*37da2899SCharles.Forsyth                       const FT_Byte*  file_base,
832*37da2899SCharles.Forsyth                       FT_Long         file_size,
833*37da2899SCharles.Forsyth                       FT_Long         face_index,
834*37da2899SCharles.Forsyth                       FT_Face        *aface )
835*37da2899SCharles.Forsyth   {
836*37da2899SCharles.Forsyth     FT_Open_Args  args;
837*37da2899SCharles.Forsyth 
838*37da2899SCharles.Forsyth 
839*37da2899SCharles.Forsyth     /* test for valid `library' and `face' delayed to FT_Open_Face() */
840*37da2899SCharles.Forsyth     if ( !file_base )
841*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
842*37da2899SCharles.Forsyth 
843*37da2899SCharles.Forsyth     args.flags       = FT_OPEN_MEMORY;
844*37da2899SCharles.Forsyth     args.memory_base = file_base;
845*37da2899SCharles.Forsyth     args.memory_size = file_size;
846*37da2899SCharles.Forsyth 
847*37da2899SCharles.Forsyth     return FT_Open_Face( library, &args, face_index, aface );
848*37da2899SCharles.Forsyth   }
849*37da2899SCharles.Forsyth 
850*37da2899SCharles.Forsyth 
851*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
852*37da2899SCharles.Forsyth 
853*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Open_Face(FT_Library library,const FT_Open_Args * args,FT_Long face_index,FT_Face * aface)854*37da2899SCharles.Forsyth   FT_Open_Face( FT_Library           library,
855*37da2899SCharles.Forsyth                 const FT_Open_Args*  args,
856*37da2899SCharles.Forsyth                 FT_Long              face_index,
857*37da2899SCharles.Forsyth                 FT_Face             *aface )
858*37da2899SCharles.Forsyth   {
859*37da2899SCharles.Forsyth     FT_Error     error;
860*37da2899SCharles.Forsyth     FT_Driver    driver;
861*37da2899SCharles.Forsyth     FT_Memory    memory;
862*37da2899SCharles.Forsyth     FT_Stream    stream;
863*37da2899SCharles.Forsyth     FT_Face      face = 0;
864*37da2899SCharles.Forsyth     FT_ListNode  node = 0;
865*37da2899SCharles.Forsyth     FT_Bool      external_stream;
866*37da2899SCharles.Forsyth 
867*37da2899SCharles.Forsyth 
868*37da2899SCharles.Forsyth     /* test for valid `library' delayed to */
869*37da2899SCharles.Forsyth     /* ft_input_stream_new()               */
870*37da2899SCharles.Forsyth 
871*37da2899SCharles.Forsyth     if ( !aface || !args )
872*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
873*37da2899SCharles.Forsyth 
874*37da2899SCharles.Forsyth     *aface = 0;
875*37da2899SCharles.Forsyth 
876*37da2899SCharles.Forsyth     external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
877*37da2899SCharles.Forsyth                                args->stream                     );
878*37da2899SCharles.Forsyth 
879*37da2899SCharles.Forsyth     /* create input stream */
880*37da2899SCharles.Forsyth     error = ft_input_stream_new( library, args, &stream );
881*37da2899SCharles.Forsyth     if ( error )
882*37da2899SCharles.Forsyth       goto Exit;
883*37da2899SCharles.Forsyth 
884*37da2899SCharles.Forsyth     memory = library->memory;
885*37da2899SCharles.Forsyth 
886*37da2899SCharles.Forsyth     /* If the font driver is specified in the `args' structure, use */
887*37da2899SCharles.Forsyth     /* it.  Otherwise, we scan the list of registered drivers.      */
888*37da2899SCharles.Forsyth     if ( ( args->flags & FT_OPEN_DRIVER ) && args->driver )
889*37da2899SCharles.Forsyth     {
890*37da2899SCharles.Forsyth       driver = FT_DRIVER( args->driver );
891*37da2899SCharles.Forsyth 
892*37da2899SCharles.Forsyth       /* not all modules are drivers, so check... */
893*37da2899SCharles.Forsyth       if ( FT_MODULE_IS_DRIVER( driver ) )
894*37da2899SCharles.Forsyth       {
895*37da2899SCharles.Forsyth         FT_Int         num_params = 0;
896*37da2899SCharles.Forsyth         FT_Parameter*  params     = 0;
897*37da2899SCharles.Forsyth 
898*37da2899SCharles.Forsyth 
899*37da2899SCharles.Forsyth         if ( args->flags & FT_OPEN_PARAMS )
900*37da2899SCharles.Forsyth         {
901*37da2899SCharles.Forsyth           num_params = args->num_params;
902*37da2899SCharles.Forsyth           params     = args->params;
903*37da2899SCharles.Forsyth         }
904*37da2899SCharles.Forsyth 
905*37da2899SCharles.Forsyth         error = open_face( driver, stream, face_index,
906*37da2899SCharles.Forsyth                            num_params, params, &face );
907*37da2899SCharles.Forsyth         if ( !error )
908*37da2899SCharles.Forsyth           goto Success;
909*37da2899SCharles.Forsyth       }
910*37da2899SCharles.Forsyth       else
911*37da2899SCharles.Forsyth         error = FT_Err_Invalid_Handle;
912*37da2899SCharles.Forsyth 
913*37da2899SCharles.Forsyth       ft_input_stream_free( stream, external_stream );
914*37da2899SCharles.Forsyth       goto Fail;
915*37da2899SCharles.Forsyth     }
916*37da2899SCharles.Forsyth     else
917*37da2899SCharles.Forsyth     {
918*37da2899SCharles.Forsyth       /* check each font driver for an appropriate format */
919*37da2899SCharles.Forsyth       FT_Module*  cur   = library->modules;
920*37da2899SCharles.Forsyth       FT_Module*  limit = cur + library->num_modules;
921*37da2899SCharles.Forsyth 
922*37da2899SCharles.Forsyth 
923*37da2899SCharles.Forsyth       for ( ; cur < limit; cur++ )
924*37da2899SCharles.Forsyth       {
925*37da2899SCharles.Forsyth         /* not all modules are font drivers, so check... */
926*37da2899SCharles.Forsyth         if ( FT_MODULE_IS_DRIVER( cur[0] ) )
927*37da2899SCharles.Forsyth         {
928*37da2899SCharles.Forsyth           FT_Int         num_params = 0;
929*37da2899SCharles.Forsyth           FT_Parameter*  params     = 0;
930*37da2899SCharles.Forsyth 
931*37da2899SCharles.Forsyth 
932*37da2899SCharles.Forsyth           driver = FT_DRIVER( cur[0] );
933*37da2899SCharles.Forsyth 
934*37da2899SCharles.Forsyth           if ( args->flags & FT_OPEN_PARAMS )
935*37da2899SCharles.Forsyth           {
936*37da2899SCharles.Forsyth             num_params = args->num_params;
937*37da2899SCharles.Forsyth             params     = args->params;
938*37da2899SCharles.Forsyth           }
939*37da2899SCharles.Forsyth 
940*37da2899SCharles.Forsyth           error = open_face( driver, stream, face_index,
941*37da2899SCharles.Forsyth                             num_params, params, &face );
942*37da2899SCharles.Forsyth           if ( !error )
943*37da2899SCharles.Forsyth             goto Success;
944*37da2899SCharles.Forsyth 
945*37da2899SCharles.Forsyth           if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
946*37da2899SCharles.Forsyth             goto Fail2;
947*37da2899SCharles.Forsyth         }
948*37da2899SCharles.Forsyth       }
949*37da2899SCharles.Forsyth 
950*37da2899SCharles.Forsyth       /* no driver is able to handle this format */
951*37da2899SCharles.Forsyth       error = FT_Err_Unknown_File_Format;
952*37da2899SCharles.Forsyth 
953*37da2899SCharles.Forsyth   Fail2:
954*37da2899SCharles.Forsyth       ft_input_stream_free( stream, external_stream );
955*37da2899SCharles.Forsyth       goto Fail;
956*37da2899SCharles.Forsyth     }
957*37da2899SCharles.Forsyth 
958*37da2899SCharles.Forsyth   Success:
959*37da2899SCharles.Forsyth     FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
960*37da2899SCharles.Forsyth 
961*37da2899SCharles.Forsyth     /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
962*37da2899SCharles.Forsyth     if ( external_stream )
963*37da2899SCharles.Forsyth       face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
964*37da2899SCharles.Forsyth 
965*37da2899SCharles.Forsyth     /* add the face object to its driver's list */
966*37da2899SCharles.Forsyth     if ( FT_NEW( node ) )
967*37da2899SCharles.Forsyth       goto Fail;
968*37da2899SCharles.Forsyth 
969*37da2899SCharles.Forsyth     node->data = face;
970*37da2899SCharles.Forsyth     /* don't assume driver is the same as face->driver, so use */
971*37da2899SCharles.Forsyth     /* face->driver instead.                                   */
972*37da2899SCharles.Forsyth     FT_List_Add( &face->driver->faces_list, node );
973*37da2899SCharles.Forsyth 
974*37da2899SCharles.Forsyth     /* now allocate a glyph slot object for the face */
975*37da2899SCharles.Forsyth     {
976*37da2899SCharles.Forsyth       FT_GlyphSlot  slot;
977*37da2899SCharles.Forsyth 
978*37da2899SCharles.Forsyth 
979*37da2899SCharles.Forsyth       FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
980*37da2899SCharles.Forsyth 
981*37da2899SCharles.Forsyth       error = FT_New_GlyphSlot( face, &slot );
982*37da2899SCharles.Forsyth       if ( error )
983*37da2899SCharles.Forsyth         goto Fail;
984*37da2899SCharles.Forsyth 
985*37da2899SCharles.Forsyth       face->glyph = slot;
986*37da2899SCharles.Forsyth     }
987*37da2899SCharles.Forsyth 
988*37da2899SCharles.Forsyth     /* finally, allocate a size object for the face */
989*37da2899SCharles.Forsyth     {
990*37da2899SCharles.Forsyth       FT_Size  size;
991*37da2899SCharles.Forsyth 
992*37da2899SCharles.Forsyth 
993*37da2899SCharles.Forsyth       FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
994*37da2899SCharles.Forsyth 
995*37da2899SCharles.Forsyth       error = FT_New_Size( face, &size );
996*37da2899SCharles.Forsyth       if ( error )
997*37da2899SCharles.Forsyth         goto Fail;
998*37da2899SCharles.Forsyth 
999*37da2899SCharles.Forsyth       face->size = size;
1000*37da2899SCharles.Forsyth     }
1001*37da2899SCharles.Forsyth 
1002*37da2899SCharles.Forsyth     /* initialize internal face data */
1003*37da2899SCharles.Forsyth     {
1004*37da2899SCharles.Forsyth       FT_Face_Internal  internal = face->internal;
1005*37da2899SCharles.Forsyth 
1006*37da2899SCharles.Forsyth 
1007*37da2899SCharles.Forsyth       internal->transform_matrix.xx = 0x10000L;
1008*37da2899SCharles.Forsyth       internal->transform_matrix.xy = 0;
1009*37da2899SCharles.Forsyth       internal->transform_matrix.yx = 0;
1010*37da2899SCharles.Forsyth       internal->transform_matrix.yy = 0x10000L;
1011*37da2899SCharles.Forsyth 
1012*37da2899SCharles.Forsyth       internal->transform_delta.x = 0;
1013*37da2899SCharles.Forsyth       internal->transform_delta.y = 0;
1014*37da2899SCharles.Forsyth     }
1015*37da2899SCharles.Forsyth 
1016*37da2899SCharles.Forsyth     *aface = face;
1017*37da2899SCharles.Forsyth     goto Exit;
1018*37da2899SCharles.Forsyth 
1019*37da2899SCharles.Forsyth   Fail:
1020*37da2899SCharles.Forsyth     FT_Done_Face( face );
1021*37da2899SCharles.Forsyth 
1022*37da2899SCharles.Forsyth   Exit:
1023*37da2899SCharles.Forsyth     FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
1024*37da2899SCharles.Forsyth 
1025*37da2899SCharles.Forsyth     return error;
1026*37da2899SCharles.Forsyth   }
1027*37da2899SCharles.Forsyth 
1028*37da2899SCharles.Forsyth 
1029*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1030*37da2899SCharles.Forsyth 
1031*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Attach_File(FT_Face face,const char * filepathname)1032*37da2899SCharles.Forsyth   FT_Attach_File( FT_Face      face,
1033*37da2899SCharles.Forsyth                   const char*  filepathname )
1034*37da2899SCharles.Forsyth   {
1035*37da2899SCharles.Forsyth     FT_Open_Args  open;
1036*37da2899SCharles.Forsyth 
1037*37da2899SCharles.Forsyth 
1038*37da2899SCharles.Forsyth     /* test for valid `face' delayed to FT_Attach_Stream() */
1039*37da2899SCharles.Forsyth 
1040*37da2899SCharles.Forsyth     if ( !filepathname )
1041*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
1042*37da2899SCharles.Forsyth 
1043*37da2899SCharles.Forsyth     open.flags    = FT_OPEN_PATHNAME;
1044*37da2899SCharles.Forsyth     open.pathname = (char*)filepathname;
1045*37da2899SCharles.Forsyth 
1046*37da2899SCharles.Forsyth     return FT_Attach_Stream( face, &open );
1047*37da2899SCharles.Forsyth   }
1048*37da2899SCharles.Forsyth 
1049*37da2899SCharles.Forsyth 
1050*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1051*37da2899SCharles.Forsyth 
1052*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Attach_Stream(FT_Face face,FT_Open_Args * parameters)1053*37da2899SCharles.Forsyth   FT_Attach_Stream( FT_Face        face,
1054*37da2899SCharles.Forsyth                     FT_Open_Args*  parameters )
1055*37da2899SCharles.Forsyth   {
1056*37da2899SCharles.Forsyth     FT_Stream  stream;
1057*37da2899SCharles.Forsyth     FT_Error   error;
1058*37da2899SCharles.Forsyth     FT_Driver  driver;
1059*37da2899SCharles.Forsyth 
1060*37da2899SCharles.Forsyth     FT_Driver_Class  clazz;
1061*37da2899SCharles.Forsyth 
1062*37da2899SCharles.Forsyth 
1063*37da2899SCharles.Forsyth     /* test for valid `parameters' delayed to ft_input_stream_new() */
1064*37da2899SCharles.Forsyth 
1065*37da2899SCharles.Forsyth     if ( !face )
1066*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1067*37da2899SCharles.Forsyth 
1068*37da2899SCharles.Forsyth     driver = face->driver;
1069*37da2899SCharles.Forsyth     if ( !driver )
1070*37da2899SCharles.Forsyth       return FT_Err_Invalid_Driver_Handle;
1071*37da2899SCharles.Forsyth 
1072*37da2899SCharles.Forsyth     error = ft_input_stream_new( driver->root.library, parameters, &stream );
1073*37da2899SCharles.Forsyth     if ( error )
1074*37da2899SCharles.Forsyth       goto Exit;
1075*37da2899SCharles.Forsyth 
1076*37da2899SCharles.Forsyth     /* we implement FT_Attach_Stream in each driver through the */
1077*37da2899SCharles.Forsyth     /* `attach_file' interface                                  */
1078*37da2899SCharles.Forsyth 
1079*37da2899SCharles.Forsyth     error = FT_Err_Unimplemented_Feature;
1080*37da2899SCharles.Forsyth     clazz = driver->clazz;
1081*37da2899SCharles.Forsyth     if ( clazz->attach_file )
1082*37da2899SCharles.Forsyth       error = clazz->attach_file( face, stream );
1083*37da2899SCharles.Forsyth 
1084*37da2899SCharles.Forsyth     /* close the attached stream */
1085*37da2899SCharles.Forsyth     ft_input_stream_free( stream,
1086*37da2899SCharles.Forsyth                     (FT_Bool)( parameters->stream &&
1087*37da2899SCharles.Forsyth                                ( parameters->flags & FT_OPEN_STREAM ) ) );
1088*37da2899SCharles.Forsyth 
1089*37da2899SCharles.Forsyth   Exit:
1090*37da2899SCharles.Forsyth     return error;
1091*37da2899SCharles.Forsyth   }
1092*37da2899SCharles.Forsyth 
1093*37da2899SCharles.Forsyth 
1094*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1095*37da2899SCharles.Forsyth 
1096*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Done_Face(FT_Face face)1097*37da2899SCharles.Forsyth   FT_Done_Face( FT_Face  face )
1098*37da2899SCharles.Forsyth   {
1099*37da2899SCharles.Forsyth     FT_Error     error;
1100*37da2899SCharles.Forsyth     FT_Driver    driver;
1101*37da2899SCharles.Forsyth     FT_Memory    memory;
1102*37da2899SCharles.Forsyth     FT_ListNode  node;
1103*37da2899SCharles.Forsyth 
1104*37da2899SCharles.Forsyth 
1105*37da2899SCharles.Forsyth     error = FT_Err_Invalid_Face_Handle;
1106*37da2899SCharles.Forsyth     if ( face && face->driver )
1107*37da2899SCharles.Forsyth     {
1108*37da2899SCharles.Forsyth       driver = face->driver;
1109*37da2899SCharles.Forsyth       memory = driver->root.memory;
1110*37da2899SCharles.Forsyth 
1111*37da2899SCharles.Forsyth       /* find face in driver's list */
1112*37da2899SCharles.Forsyth       node = FT_List_Find( &driver->faces_list, face );
1113*37da2899SCharles.Forsyth       if ( node )
1114*37da2899SCharles.Forsyth       {
1115*37da2899SCharles.Forsyth         /* remove face object from the driver's list */
1116*37da2899SCharles.Forsyth         FT_List_Remove( &driver->faces_list, node );
1117*37da2899SCharles.Forsyth         FT_FREE( node );
1118*37da2899SCharles.Forsyth 
1119*37da2899SCharles.Forsyth         /* now destroy the object proper */
1120*37da2899SCharles.Forsyth         destroy_face( memory, face, driver );
1121*37da2899SCharles.Forsyth         error = FT_Err_Ok;
1122*37da2899SCharles.Forsyth       }
1123*37da2899SCharles.Forsyth     }
1124*37da2899SCharles.Forsyth     return error;
1125*37da2899SCharles.Forsyth   }
1126*37da2899SCharles.Forsyth 
1127*37da2899SCharles.Forsyth 
1128*37da2899SCharles.Forsyth   /* documentation is in ftobjs.h */
1129*37da2899SCharles.Forsyth 
1130*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_New_Size(FT_Face face,FT_Size * asize)1131*37da2899SCharles.Forsyth   FT_New_Size( FT_Face   face,
1132*37da2899SCharles.Forsyth                FT_Size  *asize )
1133*37da2899SCharles.Forsyth   {
1134*37da2899SCharles.Forsyth     FT_Error         error;
1135*37da2899SCharles.Forsyth     FT_Memory        memory;
1136*37da2899SCharles.Forsyth     FT_Driver        driver;
1137*37da2899SCharles.Forsyth     FT_Driver_Class  clazz;
1138*37da2899SCharles.Forsyth 
1139*37da2899SCharles.Forsyth     FT_Size          size = 0;
1140*37da2899SCharles.Forsyth     FT_ListNode      node = 0;
1141*37da2899SCharles.Forsyth 
1142*37da2899SCharles.Forsyth 
1143*37da2899SCharles.Forsyth     if ( !face )
1144*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1145*37da2899SCharles.Forsyth 
1146*37da2899SCharles.Forsyth     if ( !asize )
1147*37da2899SCharles.Forsyth       return FT_Err_Invalid_Size_Handle;
1148*37da2899SCharles.Forsyth 
1149*37da2899SCharles.Forsyth     if ( !face->driver )
1150*37da2899SCharles.Forsyth       return FT_Err_Invalid_Driver_Handle;
1151*37da2899SCharles.Forsyth 
1152*37da2899SCharles.Forsyth     *asize = 0;
1153*37da2899SCharles.Forsyth 
1154*37da2899SCharles.Forsyth     driver = face->driver;
1155*37da2899SCharles.Forsyth     clazz  = driver->clazz;
1156*37da2899SCharles.Forsyth     memory = face->memory;
1157*37da2899SCharles.Forsyth 
1158*37da2899SCharles.Forsyth     /* Allocate new size object and perform basic initialisation */
1159*37da2899SCharles.Forsyth     if ( FT_ALLOC( size, clazz->size_object_size ) || FT_NEW( node ) )
1160*37da2899SCharles.Forsyth       goto Exit;
1161*37da2899SCharles.Forsyth 
1162*37da2899SCharles.Forsyth     size->face = face;
1163*37da2899SCharles.Forsyth 
1164*37da2899SCharles.Forsyth     /* for now, do not use any internal fields in size objects */
1165*37da2899SCharles.Forsyth     size->internal = 0;
1166*37da2899SCharles.Forsyth 
1167*37da2899SCharles.Forsyth     if ( clazz->init_size )
1168*37da2899SCharles.Forsyth       error = clazz->init_size( size );
1169*37da2899SCharles.Forsyth 
1170*37da2899SCharles.Forsyth     /* in case of success, add to the face's list */
1171*37da2899SCharles.Forsyth     if ( !error )
1172*37da2899SCharles.Forsyth     {
1173*37da2899SCharles.Forsyth       *asize     = size;
1174*37da2899SCharles.Forsyth       node->data = size;
1175*37da2899SCharles.Forsyth       FT_List_Add( &face->sizes_list, node );
1176*37da2899SCharles.Forsyth     }
1177*37da2899SCharles.Forsyth 
1178*37da2899SCharles.Forsyth   Exit:
1179*37da2899SCharles.Forsyth     if ( error )
1180*37da2899SCharles.Forsyth     {
1181*37da2899SCharles.Forsyth       FT_FREE( node );
1182*37da2899SCharles.Forsyth       FT_FREE( size );
1183*37da2899SCharles.Forsyth     }
1184*37da2899SCharles.Forsyth 
1185*37da2899SCharles.Forsyth     return error;
1186*37da2899SCharles.Forsyth   }
1187*37da2899SCharles.Forsyth 
1188*37da2899SCharles.Forsyth 
1189*37da2899SCharles.Forsyth   /* documentation is in ftobjs.h */
1190*37da2899SCharles.Forsyth 
1191*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Done_Size(FT_Size size)1192*37da2899SCharles.Forsyth   FT_Done_Size( FT_Size  size )
1193*37da2899SCharles.Forsyth   {
1194*37da2899SCharles.Forsyth     FT_Error     error;
1195*37da2899SCharles.Forsyth     FT_Driver    driver;
1196*37da2899SCharles.Forsyth     FT_Memory    memory;
1197*37da2899SCharles.Forsyth     FT_Face      face;
1198*37da2899SCharles.Forsyth     FT_ListNode  node;
1199*37da2899SCharles.Forsyth 
1200*37da2899SCharles.Forsyth 
1201*37da2899SCharles.Forsyth     if ( !size )
1202*37da2899SCharles.Forsyth       return FT_Err_Invalid_Size_Handle;
1203*37da2899SCharles.Forsyth 
1204*37da2899SCharles.Forsyth     face = size->face;
1205*37da2899SCharles.Forsyth     if ( !face )
1206*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1207*37da2899SCharles.Forsyth 
1208*37da2899SCharles.Forsyth     driver = face->driver;
1209*37da2899SCharles.Forsyth     if ( !driver )
1210*37da2899SCharles.Forsyth       return FT_Err_Invalid_Driver_Handle;
1211*37da2899SCharles.Forsyth 
1212*37da2899SCharles.Forsyth     memory = driver->root.memory;
1213*37da2899SCharles.Forsyth 
1214*37da2899SCharles.Forsyth     error = FT_Err_Ok;
1215*37da2899SCharles.Forsyth     node  = FT_List_Find( &face->sizes_list, size );
1216*37da2899SCharles.Forsyth     if ( node )
1217*37da2899SCharles.Forsyth     {
1218*37da2899SCharles.Forsyth       FT_List_Remove( &face->sizes_list, node );
1219*37da2899SCharles.Forsyth       FT_FREE( node );
1220*37da2899SCharles.Forsyth 
1221*37da2899SCharles.Forsyth       if ( face->size == size )
1222*37da2899SCharles.Forsyth       {
1223*37da2899SCharles.Forsyth         face->size = 0;
1224*37da2899SCharles.Forsyth         if ( face->sizes_list.head )
1225*37da2899SCharles.Forsyth           face->size = (FT_Size)(face->sizes_list.head->data);
1226*37da2899SCharles.Forsyth       }
1227*37da2899SCharles.Forsyth 
1228*37da2899SCharles.Forsyth       destroy_size( memory, size, driver );
1229*37da2899SCharles.Forsyth     }
1230*37da2899SCharles.Forsyth     else
1231*37da2899SCharles.Forsyth       error = FT_Err_Invalid_Size_Handle;
1232*37da2899SCharles.Forsyth 
1233*37da2899SCharles.Forsyth     return error;
1234*37da2899SCharles.Forsyth   }
1235*37da2899SCharles.Forsyth 
1236*37da2899SCharles.Forsyth 
1237*37da2899SCharles.Forsyth   static void
ft_recompute_scaled_metrics(FT_Face face,FT_Size_Metrics * metrics)1238*37da2899SCharles.Forsyth   ft_recompute_scaled_metrics( FT_Face           face,
1239*37da2899SCharles.Forsyth                                FT_Size_Metrics*  metrics )
1240*37da2899SCharles.Forsyth   {
1241*37da2899SCharles.Forsyth     /* Compute root ascender, descender, test height, and max_advance */
1242*37da2899SCharles.Forsyth 
1243*37da2899SCharles.Forsyth     metrics->ascender    = ( FT_MulFix( face->ascender,
1244*37da2899SCharles.Forsyth                                         metrics->y_scale ) + 32 ) & -64;
1245*37da2899SCharles.Forsyth 
1246*37da2899SCharles.Forsyth     metrics->descender   = ( FT_MulFix( face->descender,
1247*37da2899SCharles.Forsyth                                         metrics->y_scale ) + 32 ) & -64;
1248*37da2899SCharles.Forsyth 
1249*37da2899SCharles.Forsyth     metrics->height      = ( FT_MulFix( face->height,
1250*37da2899SCharles.Forsyth                                         metrics->y_scale ) + 32 ) & -64;
1251*37da2899SCharles.Forsyth 
1252*37da2899SCharles.Forsyth     metrics->max_advance = ( FT_MulFix( face->max_advance_width,
1253*37da2899SCharles.Forsyth                                         metrics->x_scale ) + 32 ) & -64;
1254*37da2899SCharles.Forsyth   }
1255*37da2899SCharles.Forsyth 
1256*37da2899SCharles.Forsyth 
1257*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1258*37da2899SCharles.Forsyth 
1259*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Set_Char_Size(FT_Face face,FT_F26Dot6 char_width,FT_F26Dot6 char_height,FT_UInt horz_resolution,FT_UInt vert_resolution)1260*37da2899SCharles.Forsyth   FT_Set_Char_Size( FT_Face     face,
1261*37da2899SCharles.Forsyth                     FT_F26Dot6  char_width,
1262*37da2899SCharles.Forsyth                     FT_F26Dot6  char_height,
1263*37da2899SCharles.Forsyth                     FT_UInt     horz_resolution,
1264*37da2899SCharles.Forsyth                     FT_UInt     vert_resolution )
1265*37da2899SCharles.Forsyth   {
1266*37da2899SCharles.Forsyth     FT_Error          error = FT_Err_Ok;
1267*37da2899SCharles.Forsyth     FT_Driver         driver;
1268*37da2899SCharles.Forsyth     FT_Driver_Class   clazz;
1269*37da2899SCharles.Forsyth     FT_Size_Metrics*  metrics;
1270*37da2899SCharles.Forsyth     FT_Long           dim_x, dim_y;
1271*37da2899SCharles.Forsyth 
1272*37da2899SCharles.Forsyth 
1273*37da2899SCharles.Forsyth     if ( !face || !face->size || !face->driver )
1274*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1275*37da2899SCharles.Forsyth 
1276*37da2899SCharles.Forsyth     driver  = face->driver;
1277*37da2899SCharles.Forsyth     metrics = &face->size->metrics;
1278*37da2899SCharles.Forsyth 
1279*37da2899SCharles.Forsyth     if ( !char_width )
1280*37da2899SCharles.Forsyth       char_width = char_height;
1281*37da2899SCharles.Forsyth 
1282*37da2899SCharles.Forsyth     else if ( !char_height )
1283*37da2899SCharles.Forsyth       char_height = char_width;
1284*37da2899SCharles.Forsyth 
1285*37da2899SCharles.Forsyth     if ( !horz_resolution )
1286*37da2899SCharles.Forsyth       horz_resolution = 72;
1287*37da2899SCharles.Forsyth 
1288*37da2899SCharles.Forsyth     if ( !vert_resolution )
1289*37da2899SCharles.Forsyth       vert_resolution = 72;
1290*37da2899SCharles.Forsyth 
1291*37da2899SCharles.Forsyth     driver = face->driver;
1292*37da2899SCharles.Forsyth     clazz  = driver->clazz;
1293*37da2899SCharles.Forsyth 
1294*37da2899SCharles.Forsyth     /* default processing -- this can be overridden by the driver */
1295*37da2899SCharles.Forsyth     if ( char_width  < 1 * 64 )
1296*37da2899SCharles.Forsyth       char_width  = 1 * 64;
1297*37da2899SCharles.Forsyth     if ( char_height < 1 * 64 )
1298*37da2899SCharles.Forsyth       char_height = 1 * 64;
1299*37da2899SCharles.Forsyth 
1300*37da2899SCharles.Forsyth     /* Compute pixel sizes in 26.6 units */
1301*37da2899SCharles.Forsyth     dim_x = ( ( ( char_width  * horz_resolution ) / 72 ) + 32 ) & -64;
1302*37da2899SCharles.Forsyth     dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
1303*37da2899SCharles.Forsyth 
1304*37da2899SCharles.Forsyth     metrics->x_ppem  = (FT_UShort)( dim_x >> 6 );
1305*37da2899SCharles.Forsyth     metrics->y_ppem  = (FT_UShort)( dim_y >> 6 );
1306*37da2899SCharles.Forsyth 
1307*37da2899SCharles.Forsyth     metrics->x_scale = 0x10000L;
1308*37da2899SCharles.Forsyth     metrics->y_scale = 0x10000L;
1309*37da2899SCharles.Forsyth 
1310*37da2899SCharles.Forsyth     if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1311*37da2899SCharles.Forsyth     {
1312*37da2899SCharles.Forsyth       metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1313*37da2899SCharles.Forsyth       metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
1314*37da2899SCharles.Forsyth 
1315*37da2899SCharles.Forsyth       ft_recompute_scaled_metrics( face, metrics );
1316*37da2899SCharles.Forsyth     }
1317*37da2899SCharles.Forsyth 
1318*37da2899SCharles.Forsyth     if ( clazz->set_char_sizes )
1319*37da2899SCharles.Forsyth       error = clazz->set_char_sizes( face->size,
1320*37da2899SCharles.Forsyth                                      char_width,
1321*37da2899SCharles.Forsyth                                      char_height,
1322*37da2899SCharles.Forsyth                                      horz_resolution,
1323*37da2899SCharles.Forsyth                                      vert_resolution );
1324*37da2899SCharles.Forsyth     return error;
1325*37da2899SCharles.Forsyth   }
1326*37da2899SCharles.Forsyth 
1327*37da2899SCharles.Forsyth 
1328*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1329*37da2899SCharles.Forsyth 
1330*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Set_Pixel_Sizes(FT_Face face,FT_UInt pixel_width,FT_UInt pixel_height)1331*37da2899SCharles.Forsyth   FT_Set_Pixel_Sizes( FT_Face  face,
1332*37da2899SCharles.Forsyth                       FT_UInt  pixel_width,
1333*37da2899SCharles.Forsyth                       FT_UInt  pixel_height )
1334*37da2899SCharles.Forsyth   {
1335*37da2899SCharles.Forsyth     FT_Error          error = FT_Err_Ok;
1336*37da2899SCharles.Forsyth     FT_Driver         driver;
1337*37da2899SCharles.Forsyth     FT_Driver_Class   clazz;
1338*37da2899SCharles.Forsyth     FT_Size_Metrics*  metrics = &face->size->metrics;
1339*37da2899SCharles.Forsyth 
1340*37da2899SCharles.Forsyth 
1341*37da2899SCharles.Forsyth     if ( !face || !face->size || !face->driver )
1342*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1343*37da2899SCharles.Forsyth 
1344*37da2899SCharles.Forsyth     driver = face->driver;
1345*37da2899SCharles.Forsyth     clazz  = driver->clazz;
1346*37da2899SCharles.Forsyth 
1347*37da2899SCharles.Forsyth     /* default processing -- this can be overridden by the driver */
1348*37da2899SCharles.Forsyth     if ( pixel_width == 0 )
1349*37da2899SCharles.Forsyth       pixel_width = pixel_height;
1350*37da2899SCharles.Forsyth 
1351*37da2899SCharles.Forsyth     else if ( pixel_height == 0 )
1352*37da2899SCharles.Forsyth       pixel_height = pixel_width;
1353*37da2899SCharles.Forsyth 
1354*37da2899SCharles.Forsyth     if ( pixel_width  < 1 )
1355*37da2899SCharles.Forsyth       pixel_width  = 1;
1356*37da2899SCharles.Forsyth     if ( pixel_height < 1 )
1357*37da2899SCharles.Forsyth       pixel_height = 1;
1358*37da2899SCharles.Forsyth 
1359*37da2899SCharles.Forsyth     metrics->x_ppem = (FT_UShort)pixel_width;
1360*37da2899SCharles.Forsyth     metrics->y_ppem = (FT_UShort)pixel_height;
1361*37da2899SCharles.Forsyth 
1362*37da2899SCharles.Forsyth     if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1363*37da2899SCharles.Forsyth     {
1364*37da2899SCharles.Forsyth       metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
1365*37da2899SCharles.Forsyth                                     face->units_per_EM );
1366*37da2899SCharles.Forsyth 
1367*37da2899SCharles.Forsyth       metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
1368*37da2899SCharles.Forsyth                                     face->units_per_EM );
1369*37da2899SCharles.Forsyth 
1370*37da2899SCharles.Forsyth       ft_recompute_scaled_metrics( face, metrics );
1371*37da2899SCharles.Forsyth     }
1372*37da2899SCharles.Forsyth 
1373*37da2899SCharles.Forsyth     if ( clazz->set_pixel_sizes )
1374*37da2899SCharles.Forsyth       error = clazz->set_pixel_sizes( face->size,
1375*37da2899SCharles.Forsyth                                       pixel_width,
1376*37da2899SCharles.Forsyth                                       pixel_height );
1377*37da2899SCharles.Forsyth     return error;
1378*37da2899SCharles.Forsyth   }
1379*37da2899SCharles.Forsyth 
1380*37da2899SCharles.Forsyth 
1381*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1382*37da2899SCharles.Forsyth 
1383*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Get_Kerning(FT_Face face,FT_UInt left_glyph,FT_UInt right_glyph,FT_UInt kern_mode,FT_Vector * akerning)1384*37da2899SCharles.Forsyth   FT_Get_Kerning( FT_Face     face,
1385*37da2899SCharles.Forsyth                   FT_UInt     left_glyph,
1386*37da2899SCharles.Forsyth                   FT_UInt     right_glyph,
1387*37da2899SCharles.Forsyth                   FT_UInt     kern_mode,
1388*37da2899SCharles.Forsyth                   FT_Vector  *akerning )
1389*37da2899SCharles.Forsyth   {
1390*37da2899SCharles.Forsyth     FT_Error   error = FT_Err_Ok;
1391*37da2899SCharles.Forsyth     FT_Driver  driver;
1392*37da2899SCharles.Forsyth 
1393*37da2899SCharles.Forsyth 
1394*37da2899SCharles.Forsyth     if ( !face )
1395*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1396*37da2899SCharles.Forsyth 
1397*37da2899SCharles.Forsyth     if ( !akerning )
1398*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
1399*37da2899SCharles.Forsyth 
1400*37da2899SCharles.Forsyth     driver = face->driver;
1401*37da2899SCharles.Forsyth 
1402*37da2899SCharles.Forsyth     akerning->x = 0;
1403*37da2899SCharles.Forsyth     akerning->y = 0;
1404*37da2899SCharles.Forsyth 
1405*37da2899SCharles.Forsyth     if ( driver->clazz->get_kerning )
1406*37da2899SCharles.Forsyth     {
1407*37da2899SCharles.Forsyth       error = driver->clazz->get_kerning( face,
1408*37da2899SCharles.Forsyth                                           left_glyph,
1409*37da2899SCharles.Forsyth                                           right_glyph,
1410*37da2899SCharles.Forsyth                                           akerning );
1411*37da2899SCharles.Forsyth       if ( !error )
1412*37da2899SCharles.Forsyth       {
1413*37da2899SCharles.Forsyth         if ( kern_mode != FT_KERNING_UNSCALED )
1414*37da2899SCharles.Forsyth         {
1415*37da2899SCharles.Forsyth           akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
1416*37da2899SCharles.Forsyth           akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
1417*37da2899SCharles.Forsyth 
1418*37da2899SCharles.Forsyth           if ( kern_mode != FT_KERNING_UNFITTED )
1419*37da2899SCharles.Forsyth           {
1420*37da2899SCharles.Forsyth             akerning->x = ( akerning->x + 32 ) & -64;
1421*37da2899SCharles.Forsyth             akerning->y = ( akerning->y + 32 ) & -64;
1422*37da2899SCharles.Forsyth           }
1423*37da2899SCharles.Forsyth         }
1424*37da2899SCharles.Forsyth       }
1425*37da2899SCharles.Forsyth     }
1426*37da2899SCharles.Forsyth 
1427*37da2899SCharles.Forsyth     return error;
1428*37da2899SCharles.Forsyth   }
1429*37da2899SCharles.Forsyth 
1430*37da2899SCharles.Forsyth 
1431*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1432*37da2899SCharles.Forsyth 
1433*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Select_Charmap(FT_Face face,FT_Encoding encoding)1434*37da2899SCharles.Forsyth   FT_Select_Charmap( FT_Face      face,
1435*37da2899SCharles.Forsyth                      FT_Encoding  encoding )
1436*37da2899SCharles.Forsyth   {
1437*37da2899SCharles.Forsyth     FT_CharMap*  cur;
1438*37da2899SCharles.Forsyth     FT_CharMap*  limit;
1439*37da2899SCharles.Forsyth 
1440*37da2899SCharles.Forsyth 
1441*37da2899SCharles.Forsyth     if ( !face )
1442*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1443*37da2899SCharles.Forsyth 
1444*37da2899SCharles.Forsyth     cur = face->charmaps;
1445*37da2899SCharles.Forsyth     if ( !cur )
1446*37da2899SCharles.Forsyth       return FT_Err_Invalid_CharMap_Handle;
1447*37da2899SCharles.Forsyth 
1448*37da2899SCharles.Forsyth     limit = cur + face->num_charmaps;
1449*37da2899SCharles.Forsyth 
1450*37da2899SCharles.Forsyth     for ( ; cur < limit; cur++ )
1451*37da2899SCharles.Forsyth     {
1452*37da2899SCharles.Forsyth       if ( cur[0]->encoding == encoding )
1453*37da2899SCharles.Forsyth       {
1454*37da2899SCharles.Forsyth         face->charmap = cur[0];
1455*37da2899SCharles.Forsyth         return 0;
1456*37da2899SCharles.Forsyth       }
1457*37da2899SCharles.Forsyth     }
1458*37da2899SCharles.Forsyth 
1459*37da2899SCharles.Forsyth     return FT_Err_Invalid_Argument;
1460*37da2899SCharles.Forsyth   }
1461*37da2899SCharles.Forsyth 
1462*37da2899SCharles.Forsyth 
1463*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1464*37da2899SCharles.Forsyth 
1465*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Set_Charmap(FT_Face face,FT_CharMap charmap)1466*37da2899SCharles.Forsyth   FT_Set_Charmap( FT_Face     face,
1467*37da2899SCharles.Forsyth                   FT_CharMap  charmap )
1468*37da2899SCharles.Forsyth   {
1469*37da2899SCharles.Forsyth     FT_CharMap*  cur;
1470*37da2899SCharles.Forsyth     FT_CharMap*  limit;
1471*37da2899SCharles.Forsyth 
1472*37da2899SCharles.Forsyth 
1473*37da2899SCharles.Forsyth     if ( !face )
1474*37da2899SCharles.Forsyth       return FT_Err_Invalid_Face_Handle;
1475*37da2899SCharles.Forsyth 
1476*37da2899SCharles.Forsyth     cur = face->charmaps;
1477*37da2899SCharles.Forsyth     if ( !cur )
1478*37da2899SCharles.Forsyth       return FT_Err_Invalid_CharMap_Handle;
1479*37da2899SCharles.Forsyth 
1480*37da2899SCharles.Forsyth     limit = cur + face->num_charmaps;
1481*37da2899SCharles.Forsyth 
1482*37da2899SCharles.Forsyth     for ( ; cur < limit; cur++ )
1483*37da2899SCharles.Forsyth     {
1484*37da2899SCharles.Forsyth       if ( cur[0] == charmap )
1485*37da2899SCharles.Forsyth       {
1486*37da2899SCharles.Forsyth         face->charmap = cur[0];
1487*37da2899SCharles.Forsyth         return 0;
1488*37da2899SCharles.Forsyth       }
1489*37da2899SCharles.Forsyth     }
1490*37da2899SCharles.Forsyth     return FT_Err_Invalid_Argument;
1491*37da2899SCharles.Forsyth   }
1492*37da2899SCharles.Forsyth 
1493*37da2899SCharles.Forsyth 
1494*37da2899SCharles.Forsyth   FT_BASE_DEF( void )
FT_CMap_Done(FT_CMap cmap)1495*37da2899SCharles.Forsyth   FT_CMap_Done( FT_CMap  cmap )
1496*37da2899SCharles.Forsyth   {
1497*37da2899SCharles.Forsyth     if ( cmap )
1498*37da2899SCharles.Forsyth     {
1499*37da2899SCharles.Forsyth       FT_CMap_Class  clazz  = cmap->clazz;
1500*37da2899SCharles.Forsyth       FT_Face        face   = cmap->charmap.face;
1501*37da2899SCharles.Forsyth       FT_Memory      memory = FT_FACE_MEMORY(face);
1502*37da2899SCharles.Forsyth 
1503*37da2899SCharles.Forsyth 
1504*37da2899SCharles.Forsyth       if ( clazz->done )
1505*37da2899SCharles.Forsyth         clazz->done( cmap );
1506*37da2899SCharles.Forsyth 
1507*37da2899SCharles.Forsyth       FT_FREE( cmap );
1508*37da2899SCharles.Forsyth     }
1509*37da2899SCharles.Forsyth   }
1510*37da2899SCharles.Forsyth 
1511*37da2899SCharles.Forsyth 
1512*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Error )
FT_CMap_New(FT_CMap_Class clazz,FT_Pointer init_data,FT_CharMap charmap,FT_CMap * acmap)1513*37da2899SCharles.Forsyth   FT_CMap_New( FT_CMap_Class   clazz,
1514*37da2899SCharles.Forsyth                FT_Pointer      init_data,
1515*37da2899SCharles.Forsyth                FT_CharMap      charmap,
1516*37da2899SCharles.Forsyth                FT_CMap        *acmap )
1517*37da2899SCharles.Forsyth   {
1518*37da2899SCharles.Forsyth     FT_Error   error = 0;
1519*37da2899SCharles.Forsyth     FT_Face    face;
1520*37da2899SCharles.Forsyth     FT_Memory  memory;
1521*37da2899SCharles.Forsyth     FT_CMap    cmap;
1522*37da2899SCharles.Forsyth 
1523*37da2899SCharles.Forsyth 
1524*37da2899SCharles.Forsyth     if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
1525*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
1526*37da2899SCharles.Forsyth 
1527*37da2899SCharles.Forsyth     face   = charmap->face;
1528*37da2899SCharles.Forsyth     memory = FT_FACE_MEMORY(face);
1529*37da2899SCharles.Forsyth 
1530*37da2899SCharles.Forsyth     if ( !FT_ALLOC( cmap, clazz->size ) )
1531*37da2899SCharles.Forsyth     {
1532*37da2899SCharles.Forsyth       cmap->charmap = *charmap;
1533*37da2899SCharles.Forsyth       cmap->clazz   = clazz;
1534*37da2899SCharles.Forsyth 
1535*37da2899SCharles.Forsyth       if ( clazz->init )
1536*37da2899SCharles.Forsyth       {
1537*37da2899SCharles.Forsyth         error = clazz->init( cmap, init_data );
1538*37da2899SCharles.Forsyth         if ( error )
1539*37da2899SCharles.Forsyth           goto Fail;
1540*37da2899SCharles.Forsyth       }
1541*37da2899SCharles.Forsyth 
1542*37da2899SCharles.Forsyth       /* add it to our list of charmaps */
1543*37da2899SCharles.Forsyth       if ( FT_RENEW_ARRAY( face->charmaps,
1544*37da2899SCharles.Forsyth                            face->num_charmaps,
1545*37da2899SCharles.Forsyth                            face->num_charmaps+1 ) )
1546*37da2899SCharles.Forsyth         goto Fail;
1547*37da2899SCharles.Forsyth 
1548*37da2899SCharles.Forsyth       face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
1549*37da2899SCharles.Forsyth     }
1550*37da2899SCharles.Forsyth 
1551*37da2899SCharles.Forsyth   Exit:
1552*37da2899SCharles.Forsyth     if ( acmap )
1553*37da2899SCharles.Forsyth       *acmap = cmap;
1554*37da2899SCharles.Forsyth 
1555*37da2899SCharles.Forsyth     return error;
1556*37da2899SCharles.Forsyth 
1557*37da2899SCharles.Forsyth   Fail:
1558*37da2899SCharles.Forsyth     FT_CMap_Done( cmap );
1559*37da2899SCharles.Forsyth     cmap = NULL;
1560*37da2899SCharles.Forsyth     goto Exit;
1561*37da2899SCharles.Forsyth   }
1562*37da2899SCharles.Forsyth 
1563*37da2899SCharles.Forsyth 
1564*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1565*37da2899SCharles.Forsyth 
1566*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_UInt )
FT_Get_Char_Index(FT_Face face,FT_ULong charcode)1567*37da2899SCharles.Forsyth   FT_Get_Char_Index( FT_Face   face,
1568*37da2899SCharles.Forsyth                      FT_ULong  charcode )
1569*37da2899SCharles.Forsyth   {
1570*37da2899SCharles.Forsyth     FT_UInt  result = 0;
1571*37da2899SCharles.Forsyth 
1572*37da2899SCharles.Forsyth 
1573*37da2899SCharles.Forsyth     if ( face && face->charmap )
1574*37da2899SCharles.Forsyth     {
1575*37da2899SCharles.Forsyth       FT_CMap  cmap = FT_CMAP( face->charmap );
1576*37da2899SCharles.Forsyth 
1577*37da2899SCharles.Forsyth 
1578*37da2899SCharles.Forsyth       result = cmap->clazz->char_index( cmap, charcode );
1579*37da2899SCharles.Forsyth     }
1580*37da2899SCharles.Forsyth     return  result;
1581*37da2899SCharles.Forsyth   }
1582*37da2899SCharles.Forsyth 
1583*37da2899SCharles.Forsyth 
1584*37da2899SCharles.Forsyth 
1585*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1586*37da2899SCharles.Forsyth 
1587*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_ULong )
FT_Get_First_Char(FT_Face face,FT_UInt * agindex)1588*37da2899SCharles.Forsyth   FT_Get_First_Char( FT_Face   face,
1589*37da2899SCharles.Forsyth                      FT_UInt  *agindex )
1590*37da2899SCharles.Forsyth   {
1591*37da2899SCharles.Forsyth     FT_ULong  result = 0;
1592*37da2899SCharles.Forsyth     FT_UInt   gindex = 0;
1593*37da2899SCharles.Forsyth 
1594*37da2899SCharles.Forsyth 
1595*37da2899SCharles.Forsyth     if ( face && face->charmap )
1596*37da2899SCharles.Forsyth     {
1597*37da2899SCharles.Forsyth       gindex = FT_Get_Char_Index( face, 0 );
1598*37da2899SCharles.Forsyth       if ( gindex == 0 )
1599*37da2899SCharles.Forsyth         result = FT_Get_Next_Char( face, 0, &gindex );
1600*37da2899SCharles.Forsyth     }
1601*37da2899SCharles.Forsyth 
1602*37da2899SCharles.Forsyth     if ( agindex  )
1603*37da2899SCharles.Forsyth       *agindex = gindex;
1604*37da2899SCharles.Forsyth 
1605*37da2899SCharles.Forsyth     return result;
1606*37da2899SCharles.Forsyth   }
1607*37da2899SCharles.Forsyth 
1608*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1609*37da2899SCharles.Forsyth 
1610*37da2899SCharles.Forsyth 
1611*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_ULong )
FT_Get_Next_Char(FT_Face face,FT_ULong charcode,FT_UInt * agindex)1612*37da2899SCharles.Forsyth   FT_Get_Next_Char( FT_Face   face,
1613*37da2899SCharles.Forsyth                     FT_ULong  charcode,
1614*37da2899SCharles.Forsyth                     FT_UInt  *agindex )
1615*37da2899SCharles.Forsyth   {
1616*37da2899SCharles.Forsyth     FT_ULong  result = 0;
1617*37da2899SCharles.Forsyth     FT_UInt   gindex = 0;
1618*37da2899SCharles.Forsyth 
1619*37da2899SCharles.Forsyth 
1620*37da2899SCharles.Forsyth     if ( face && face->charmap )
1621*37da2899SCharles.Forsyth     {
1622*37da2899SCharles.Forsyth       FT_UInt32  code = (FT_UInt32)charcode;
1623*37da2899SCharles.Forsyth       FT_CMap    cmap = FT_CMAP( face->charmap );
1624*37da2899SCharles.Forsyth 
1625*37da2899SCharles.Forsyth 
1626*37da2899SCharles.Forsyth       gindex = cmap->clazz->char_next( cmap, &code );
1627*37da2899SCharles.Forsyth       result = ( gindex == 0 ) ? 0 : code;
1628*37da2899SCharles.Forsyth     }
1629*37da2899SCharles.Forsyth 
1630*37da2899SCharles.Forsyth     if ( agindex )
1631*37da2899SCharles.Forsyth       *agindex = gindex;
1632*37da2899SCharles.Forsyth 
1633*37da2899SCharles.Forsyth     return result;
1634*37da2899SCharles.Forsyth   }
1635*37da2899SCharles.Forsyth 
1636*37da2899SCharles.Forsyth 
1637*37da2899SCharles.Forsyth 
1638*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1639*37da2899SCharles.Forsyth 
1640*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_UInt )
FT_Get_Name_Index(FT_Face face,FT_String * glyph_name)1641*37da2899SCharles.Forsyth   FT_Get_Name_Index( FT_Face     face,
1642*37da2899SCharles.Forsyth                      FT_String*  glyph_name )
1643*37da2899SCharles.Forsyth   {
1644*37da2899SCharles.Forsyth     FT_UInt  result = 0;
1645*37da2899SCharles.Forsyth 
1646*37da2899SCharles.Forsyth 
1647*37da2899SCharles.Forsyth     if ( face && FT_HAS_GLYPH_NAMES( face ) )
1648*37da2899SCharles.Forsyth     {
1649*37da2899SCharles.Forsyth       /* now, lookup for glyph name */
1650*37da2899SCharles.Forsyth       FT_Driver         driver = face->driver;
1651*37da2899SCharles.Forsyth       FT_Module_Class*  clazz  = FT_MODULE_CLASS( driver );
1652*37da2899SCharles.Forsyth 
1653*37da2899SCharles.Forsyth 
1654*37da2899SCharles.Forsyth       if ( clazz->get_interface )
1655*37da2899SCharles.Forsyth       {
1656*37da2899SCharles.Forsyth         FT_Face_GetGlyphNameIndexFunc  requester;
1657*37da2899SCharles.Forsyth 
1658*37da2899SCharles.Forsyth 
1659*37da2899SCharles.Forsyth         requester = (FT_Face_GetGlyphNameIndexFunc)clazz->get_interface(
1660*37da2899SCharles.Forsyth                       FT_MODULE( driver ), "name_index" );
1661*37da2899SCharles.Forsyth         if ( requester )
1662*37da2899SCharles.Forsyth           result = requester( face, glyph_name );
1663*37da2899SCharles.Forsyth       }
1664*37da2899SCharles.Forsyth     }
1665*37da2899SCharles.Forsyth 
1666*37da2899SCharles.Forsyth     return result;
1667*37da2899SCharles.Forsyth   }
1668*37da2899SCharles.Forsyth 
1669*37da2899SCharles.Forsyth 
1670*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1671*37da2899SCharles.Forsyth 
1672*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Get_Glyph_Name(FT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)1673*37da2899SCharles.Forsyth   FT_Get_Glyph_Name( FT_Face     face,
1674*37da2899SCharles.Forsyth                      FT_UInt     glyph_index,
1675*37da2899SCharles.Forsyth                      FT_Pointer  buffer,
1676*37da2899SCharles.Forsyth                      FT_UInt     buffer_max )
1677*37da2899SCharles.Forsyth   {
1678*37da2899SCharles.Forsyth     FT_Error  error = FT_Err_Invalid_Argument;
1679*37da2899SCharles.Forsyth 
1680*37da2899SCharles.Forsyth 
1681*37da2899SCharles.Forsyth     /* clean up buffer */
1682*37da2899SCharles.Forsyth     if ( buffer && buffer_max > 0 )
1683*37da2899SCharles.Forsyth       ((FT_Byte*)buffer)[0] = 0;
1684*37da2899SCharles.Forsyth 
1685*37da2899SCharles.Forsyth     if ( face                                     &&
1686*37da2899SCharles.Forsyth          glyph_index <= (FT_UInt)face->num_glyphs &&
1687*37da2899SCharles.Forsyth          FT_HAS_GLYPH_NAMES( face )               )
1688*37da2899SCharles.Forsyth     {
1689*37da2899SCharles.Forsyth       /* now, lookup for glyph name */
1690*37da2899SCharles.Forsyth       FT_Driver         driver = face->driver;
1691*37da2899SCharles.Forsyth       FT_Module_Class*  clazz  = FT_MODULE_CLASS( driver );
1692*37da2899SCharles.Forsyth 
1693*37da2899SCharles.Forsyth 
1694*37da2899SCharles.Forsyth       if ( clazz->get_interface )
1695*37da2899SCharles.Forsyth       {
1696*37da2899SCharles.Forsyth         FT_Face_GetGlyphNameFunc  requester;
1697*37da2899SCharles.Forsyth 
1698*37da2899SCharles.Forsyth 
1699*37da2899SCharles.Forsyth         requester = (FT_Face_GetGlyphNameFunc)clazz->get_interface(
1700*37da2899SCharles.Forsyth                       FT_MODULE( driver ), "glyph_name" );
1701*37da2899SCharles.Forsyth         if ( requester )
1702*37da2899SCharles.Forsyth           error = requester( face, glyph_index, buffer, buffer_max );
1703*37da2899SCharles.Forsyth       }
1704*37da2899SCharles.Forsyth     }
1705*37da2899SCharles.Forsyth 
1706*37da2899SCharles.Forsyth     return error;
1707*37da2899SCharles.Forsyth   }
1708*37da2899SCharles.Forsyth 
1709*37da2899SCharles.Forsyth 
1710*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
1711*37da2899SCharles.Forsyth 
1712*37da2899SCharles.Forsyth   FT_EXPORT_DEF( const char* )
FT_Get_Postscript_Name(FT_Face face)1713*37da2899SCharles.Forsyth   FT_Get_Postscript_Name( FT_Face  face )
1714*37da2899SCharles.Forsyth   {
1715*37da2899SCharles.Forsyth     const char*  result = NULL;
1716*37da2899SCharles.Forsyth 
1717*37da2899SCharles.Forsyth 
1718*37da2899SCharles.Forsyth     if ( !face )
1719*37da2899SCharles.Forsyth       goto Exit;
1720*37da2899SCharles.Forsyth 
1721*37da2899SCharles.Forsyth     result = face->internal->postscript_name;
1722*37da2899SCharles.Forsyth     if ( !result )
1723*37da2899SCharles.Forsyth     {
1724*37da2899SCharles.Forsyth       /* now, look up glyph name */
1725*37da2899SCharles.Forsyth       FT_Driver         driver = face->driver;
1726*37da2899SCharles.Forsyth       FT_Module_Class*  clazz  = FT_MODULE_CLASS( driver );
1727*37da2899SCharles.Forsyth 
1728*37da2899SCharles.Forsyth 
1729*37da2899SCharles.Forsyth       if ( clazz->get_interface )
1730*37da2899SCharles.Forsyth       {
1731*37da2899SCharles.Forsyth         FT_Face_GetPostscriptNameFunc  requester;
1732*37da2899SCharles.Forsyth 
1733*37da2899SCharles.Forsyth 
1734*37da2899SCharles.Forsyth         requester = (FT_Face_GetPostscriptNameFunc)clazz->get_interface(
1735*37da2899SCharles.Forsyth                       FT_MODULE( driver ), "postscript_name" );
1736*37da2899SCharles.Forsyth         if ( requester )
1737*37da2899SCharles.Forsyth           result = requester( face );
1738*37da2899SCharles.Forsyth       }
1739*37da2899SCharles.Forsyth     }
1740*37da2899SCharles.Forsyth   Exit:
1741*37da2899SCharles.Forsyth     return result;
1742*37da2899SCharles.Forsyth   }
1743*37da2899SCharles.Forsyth 
1744*37da2899SCharles.Forsyth 
1745*37da2899SCharles.Forsyth   /* documentation is in tttables.h */
1746*37da2899SCharles.Forsyth 
1747*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void* )
FT_Get_Sfnt_Table(FT_Face face,FT_Sfnt_Tag tag)1748*37da2899SCharles.Forsyth   FT_Get_Sfnt_Table( FT_Face      face,
1749*37da2899SCharles.Forsyth                      FT_Sfnt_Tag  tag )
1750*37da2899SCharles.Forsyth   {
1751*37da2899SCharles.Forsyth     void*                   table = 0;
1752*37da2899SCharles.Forsyth     FT_Get_Sfnt_Table_Func  func;
1753*37da2899SCharles.Forsyth     FT_Driver               driver;
1754*37da2899SCharles.Forsyth 
1755*37da2899SCharles.Forsyth 
1756*37da2899SCharles.Forsyth     if ( !face || !FT_IS_SFNT( face ) )
1757*37da2899SCharles.Forsyth       goto Exit;
1758*37da2899SCharles.Forsyth 
1759*37da2899SCharles.Forsyth     driver = face->driver;
1760*37da2899SCharles.Forsyth     func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
1761*37da2899SCharles.Forsyth                                      FT_MODULE( driver ), "get_sfnt" );
1762*37da2899SCharles.Forsyth     if ( func )
1763*37da2899SCharles.Forsyth       table = func( face, tag );
1764*37da2899SCharles.Forsyth 
1765*37da2899SCharles.Forsyth   Exit:
1766*37da2899SCharles.Forsyth     return table;
1767*37da2899SCharles.Forsyth   }
1768*37da2899SCharles.Forsyth 
1769*37da2899SCharles.Forsyth 
1770*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Activate_Size(FT_Size size)1771*37da2899SCharles.Forsyth   FT_Activate_Size( FT_Size  size )
1772*37da2899SCharles.Forsyth   {
1773*37da2899SCharles.Forsyth     FT_Face  face;
1774*37da2899SCharles.Forsyth 
1775*37da2899SCharles.Forsyth 
1776*37da2899SCharles.Forsyth     if ( size == NULL )
1777*37da2899SCharles.Forsyth       return FT_Err_Bad_Argument;
1778*37da2899SCharles.Forsyth 
1779*37da2899SCharles.Forsyth     face = size->face;
1780*37da2899SCharles.Forsyth     if ( face == NULL || face->driver == NULL )
1781*37da2899SCharles.Forsyth       return FT_Err_Bad_Argument;
1782*37da2899SCharles.Forsyth 
1783*37da2899SCharles.Forsyth     /* we don't need anything more complex than that; all size objects */
1784*37da2899SCharles.Forsyth     /* are already listed by the face                                  */
1785*37da2899SCharles.Forsyth     face->size = size;
1786*37da2899SCharles.Forsyth 
1787*37da2899SCharles.Forsyth     return FT_Err_Ok;
1788*37da2899SCharles.Forsyth   }
1789*37da2899SCharles.Forsyth 
1790*37da2899SCharles.Forsyth 
1791*37da2899SCharles.Forsyth   /*************************************************************************/
1792*37da2899SCharles.Forsyth   /*************************************************************************/
1793*37da2899SCharles.Forsyth   /*************************************************************************/
1794*37da2899SCharles.Forsyth   /****                                                                 ****/
1795*37da2899SCharles.Forsyth   /****                                                                 ****/
1796*37da2899SCharles.Forsyth   /****                        R E N D E R E R S                        ****/
1797*37da2899SCharles.Forsyth   /****                                                                 ****/
1798*37da2899SCharles.Forsyth   /****                                                                 ****/
1799*37da2899SCharles.Forsyth   /*************************************************************************/
1800*37da2899SCharles.Forsyth   /*************************************************************************/
1801*37da2899SCharles.Forsyth   /*************************************************************************/
1802*37da2899SCharles.Forsyth 
1803*37da2899SCharles.Forsyth   /* lookup a renderer by glyph format in the library's list */
1804*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Renderer )
FT_Lookup_Renderer(FT_Library library,FT_Glyph_Format format,FT_ListNode * node)1805*37da2899SCharles.Forsyth   FT_Lookup_Renderer( FT_Library       library,
1806*37da2899SCharles.Forsyth                       FT_Glyph_Format  format,
1807*37da2899SCharles.Forsyth                       FT_ListNode*     node )
1808*37da2899SCharles.Forsyth   {
1809*37da2899SCharles.Forsyth     FT_ListNode  cur;
1810*37da2899SCharles.Forsyth     FT_Renderer  result = 0;
1811*37da2899SCharles.Forsyth 
1812*37da2899SCharles.Forsyth 
1813*37da2899SCharles.Forsyth     if ( !library )
1814*37da2899SCharles.Forsyth       goto Exit;
1815*37da2899SCharles.Forsyth 
1816*37da2899SCharles.Forsyth     cur = library->renderers.head;
1817*37da2899SCharles.Forsyth 
1818*37da2899SCharles.Forsyth     if ( node )
1819*37da2899SCharles.Forsyth     {
1820*37da2899SCharles.Forsyth       if ( *node )
1821*37da2899SCharles.Forsyth         cur = (*node)->next;
1822*37da2899SCharles.Forsyth       *node = 0;
1823*37da2899SCharles.Forsyth     }
1824*37da2899SCharles.Forsyth 
1825*37da2899SCharles.Forsyth     while ( cur )
1826*37da2899SCharles.Forsyth     {
1827*37da2899SCharles.Forsyth       FT_Renderer  renderer = FT_RENDERER( cur->data );
1828*37da2899SCharles.Forsyth 
1829*37da2899SCharles.Forsyth 
1830*37da2899SCharles.Forsyth       if ( renderer->glyph_format == format )
1831*37da2899SCharles.Forsyth       {
1832*37da2899SCharles.Forsyth         if ( node )
1833*37da2899SCharles.Forsyth           *node = cur;
1834*37da2899SCharles.Forsyth 
1835*37da2899SCharles.Forsyth         result = renderer;
1836*37da2899SCharles.Forsyth         break;
1837*37da2899SCharles.Forsyth       }
1838*37da2899SCharles.Forsyth       cur = cur->next;
1839*37da2899SCharles.Forsyth     }
1840*37da2899SCharles.Forsyth 
1841*37da2899SCharles.Forsyth   Exit:
1842*37da2899SCharles.Forsyth     return result;
1843*37da2899SCharles.Forsyth   }
1844*37da2899SCharles.Forsyth 
1845*37da2899SCharles.Forsyth 
1846*37da2899SCharles.Forsyth   static FT_Renderer
ft_lookup_glyph_renderer(FT_GlyphSlot slot)1847*37da2899SCharles.Forsyth   ft_lookup_glyph_renderer( FT_GlyphSlot  slot )
1848*37da2899SCharles.Forsyth   {
1849*37da2899SCharles.Forsyth     FT_Face      face    = slot->face;
1850*37da2899SCharles.Forsyth     FT_Library   library = FT_FACE_LIBRARY( face );
1851*37da2899SCharles.Forsyth     FT_Renderer  result  = library->cur_renderer;
1852*37da2899SCharles.Forsyth 
1853*37da2899SCharles.Forsyth 
1854*37da2899SCharles.Forsyth     if ( !result || result->glyph_format != slot->format )
1855*37da2899SCharles.Forsyth       result = FT_Lookup_Renderer( library, slot->format, 0 );
1856*37da2899SCharles.Forsyth 
1857*37da2899SCharles.Forsyth     return result;
1858*37da2899SCharles.Forsyth   }
1859*37da2899SCharles.Forsyth 
1860*37da2899SCharles.Forsyth 
1861*37da2899SCharles.Forsyth   static void
ft_set_current_renderer(FT_Library library)1862*37da2899SCharles.Forsyth   ft_set_current_renderer( FT_Library  library )
1863*37da2899SCharles.Forsyth   {
1864*37da2899SCharles.Forsyth     FT_Renderer  renderer;
1865*37da2899SCharles.Forsyth 
1866*37da2899SCharles.Forsyth 
1867*37da2899SCharles.Forsyth     renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
1868*37da2899SCharles.Forsyth     library->cur_renderer = renderer;
1869*37da2899SCharles.Forsyth   }
1870*37da2899SCharles.Forsyth 
1871*37da2899SCharles.Forsyth 
1872*37da2899SCharles.Forsyth   static FT_Error
ft_add_renderer(FT_Module module)1873*37da2899SCharles.Forsyth   ft_add_renderer( FT_Module  module )
1874*37da2899SCharles.Forsyth   {
1875*37da2899SCharles.Forsyth     FT_Library   library = module->library;
1876*37da2899SCharles.Forsyth     FT_Memory    memory  = library->memory;
1877*37da2899SCharles.Forsyth     FT_Error     error;
1878*37da2899SCharles.Forsyth     FT_ListNode  node;
1879*37da2899SCharles.Forsyth 
1880*37da2899SCharles.Forsyth 
1881*37da2899SCharles.Forsyth     if ( FT_NEW( node ) )
1882*37da2899SCharles.Forsyth       goto Exit;
1883*37da2899SCharles.Forsyth 
1884*37da2899SCharles.Forsyth     {
1885*37da2899SCharles.Forsyth       FT_Renderer         render = FT_RENDERER( module );
1886*37da2899SCharles.Forsyth       FT_Renderer_Class*  clazz  = (FT_Renderer_Class*)module->clazz;
1887*37da2899SCharles.Forsyth 
1888*37da2899SCharles.Forsyth 
1889*37da2899SCharles.Forsyth       render->clazz        = clazz;
1890*37da2899SCharles.Forsyth       render->glyph_format = clazz->glyph_format;
1891*37da2899SCharles.Forsyth 
1892*37da2899SCharles.Forsyth       /* allocate raster object if needed */
1893*37da2899SCharles.Forsyth       if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
1894*37da2899SCharles.Forsyth            clazz->raster_class->raster_new )
1895*37da2899SCharles.Forsyth       {
1896*37da2899SCharles.Forsyth         error = clazz->raster_class->raster_new( memory, &render->raster );
1897*37da2899SCharles.Forsyth         if ( error )
1898*37da2899SCharles.Forsyth           goto Fail;
1899*37da2899SCharles.Forsyth 
1900*37da2899SCharles.Forsyth         render->raster_render = clazz->raster_class->raster_render;
1901*37da2899SCharles.Forsyth         render->render        = clazz->render_glyph;
1902*37da2899SCharles.Forsyth       }
1903*37da2899SCharles.Forsyth 
1904*37da2899SCharles.Forsyth       /* add to list */
1905*37da2899SCharles.Forsyth       node->data = module;
1906*37da2899SCharles.Forsyth       FT_List_Add( &library->renderers, node );
1907*37da2899SCharles.Forsyth 
1908*37da2899SCharles.Forsyth       ft_set_current_renderer( library );
1909*37da2899SCharles.Forsyth     }
1910*37da2899SCharles.Forsyth 
1911*37da2899SCharles.Forsyth   Fail:
1912*37da2899SCharles.Forsyth     if ( error )
1913*37da2899SCharles.Forsyth       FT_FREE( node );
1914*37da2899SCharles.Forsyth 
1915*37da2899SCharles.Forsyth   Exit:
1916*37da2899SCharles.Forsyth     return error;
1917*37da2899SCharles.Forsyth   }
1918*37da2899SCharles.Forsyth 
1919*37da2899SCharles.Forsyth 
1920*37da2899SCharles.Forsyth   static void
ft_remove_renderer(FT_Module module)1921*37da2899SCharles.Forsyth   ft_remove_renderer( FT_Module  module )
1922*37da2899SCharles.Forsyth   {
1923*37da2899SCharles.Forsyth     FT_Library   library = module->library;
1924*37da2899SCharles.Forsyth     FT_Memory    memory  = library->memory;
1925*37da2899SCharles.Forsyth     FT_ListNode  node;
1926*37da2899SCharles.Forsyth 
1927*37da2899SCharles.Forsyth 
1928*37da2899SCharles.Forsyth     node = FT_List_Find( &library->renderers, module );
1929*37da2899SCharles.Forsyth     if ( node )
1930*37da2899SCharles.Forsyth     {
1931*37da2899SCharles.Forsyth       FT_Renderer  render = FT_RENDERER( module );
1932*37da2899SCharles.Forsyth 
1933*37da2899SCharles.Forsyth 
1934*37da2899SCharles.Forsyth       /* release raster object, if any */
1935*37da2899SCharles.Forsyth       if ( render->raster )
1936*37da2899SCharles.Forsyth         render->clazz->raster_class->raster_done( render->raster );
1937*37da2899SCharles.Forsyth 
1938*37da2899SCharles.Forsyth       /* remove from list */
1939*37da2899SCharles.Forsyth       FT_List_Remove( &library->renderers, node );
1940*37da2899SCharles.Forsyth       FT_FREE( node );
1941*37da2899SCharles.Forsyth 
1942*37da2899SCharles.Forsyth       ft_set_current_renderer( library );
1943*37da2899SCharles.Forsyth     }
1944*37da2899SCharles.Forsyth   }
1945*37da2899SCharles.Forsyth 
1946*37da2899SCharles.Forsyth 
1947*37da2899SCharles.Forsyth   /* documentation is in ftrender.h */
1948*37da2899SCharles.Forsyth 
1949*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Renderer )
FT_Get_Renderer(FT_Library library,FT_Glyph_Format format)1950*37da2899SCharles.Forsyth   FT_Get_Renderer( FT_Library       library,
1951*37da2899SCharles.Forsyth                    FT_Glyph_Format  format )
1952*37da2899SCharles.Forsyth   {
1953*37da2899SCharles.Forsyth     /* test for valid `library' delayed to FT_Lookup_Renderer() */
1954*37da2899SCharles.Forsyth 
1955*37da2899SCharles.Forsyth     return FT_Lookup_Renderer( library, format, 0 );
1956*37da2899SCharles.Forsyth   }
1957*37da2899SCharles.Forsyth 
1958*37da2899SCharles.Forsyth 
1959*37da2899SCharles.Forsyth   /* documentation is in ftrender.h */
1960*37da2899SCharles.Forsyth 
1961*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Set_Renderer(FT_Library library,FT_Renderer renderer,FT_UInt num_params,FT_Parameter * parameters)1962*37da2899SCharles.Forsyth   FT_Set_Renderer( FT_Library     library,
1963*37da2899SCharles.Forsyth                    FT_Renderer    renderer,
1964*37da2899SCharles.Forsyth                    FT_UInt        num_params,
1965*37da2899SCharles.Forsyth                    FT_Parameter*  parameters )
1966*37da2899SCharles.Forsyth   {
1967*37da2899SCharles.Forsyth     FT_ListNode  node;
1968*37da2899SCharles.Forsyth     FT_Error     error = FT_Err_Ok;
1969*37da2899SCharles.Forsyth 
1970*37da2899SCharles.Forsyth 
1971*37da2899SCharles.Forsyth     if ( !library )
1972*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
1973*37da2899SCharles.Forsyth 
1974*37da2899SCharles.Forsyth     if ( !renderer )
1975*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
1976*37da2899SCharles.Forsyth 
1977*37da2899SCharles.Forsyth     node = FT_List_Find( &library->renderers, renderer );
1978*37da2899SCharles.Forsyth     if ( !node )
1979*37da2899SCharles.Forsyth     {
1980*37da2899SCharles.Forsyth       error = FT_Err_Invalid_Argument;
1981*37da2899SCharles.Forsyth       goto Exit;
1982*37da2899SCharles.Forsyth     }
1983*37da2899SCharles.Forsyth 
1984*37da2899SCharles.Forsyth     FT_List_Up( &library->renderers, node );
1985*37da2899SCharles.Forsyth 
1986*37da2899SCharles.Forsyth     if ( renderer->glyph_format == FT_GLYPH_FORMAT_OUTLINE )
1987*37da2899SCharles.Forsyth       library->cur_renderer = renderer;
1988*37da2899SCharles.Forsyth 
1989*37da2899SCharles.Forsyth     if ( num_params > 0 )
1990*37da2899SCharles.Forsyth     {
1991*37da2899SCharles.Forsyth       FT_Renderer_SetModeFunc  set_mode = renderer->clazz->set_mode;
1992*37da2899SCharles.Forsyth 
1993*37da2899SCharles.Forsyth 
1994*37da2899SCharles.Forsyth       for ( ; num_params > 0; num_params-- )
1995*37da2899SCharles.Forsyth       {
1996*37da2899SCharles.Forsyth         error = set_mode( renderer, parameters->tag, parameters->data );
1997*37da2899SCharles.Forsyth         if ( error )
1998*37da2899SCharles.Forsyth           break;
1999*37da2899SCharles.Forsyth       }
2000*37da2899SCharles.Forsyth     }
2001*37da2899SCharles.Forsyth 
2002*37da2899SCharles.Forsyth   Exit:
2003*37da2899SCharles.Forsyth     return error;
2004*37da2899SCharles.Forsyth   }
2005*37da2899SCharles.Forsyth 
2006*37da2899SCharles.Forsyth 
2007*37da2899SCharles.Forsyth   FT_BASE_DEF( FT_Error )
FT_Render_Glyph_Internal(FT_Library library,FT_GlyphSlot slot,FT_Render_Mode render_mode)2008*37da2899SCharles.Forsyth   FT_Render_Glyph_Internal( FT_Library      library,
2009*37da2899SCharles.Forsyth                             FT_GlyphSlot    slot,
2010*37da2899SCharles.Forsyth                             FT_Render_Mode  render_mode )
2011*37da2899SCharles.Forsyth   {
2012*37da2899SCharles.Forsyth     FT_Error     error = FT_Err_Ok;
2013*37da2899SCharles.Forsyth     FT_Renderer  renderer;
2014*37da2899SCharles.Forsyth 
2015*37da2899SCharles.Forsyth 
2016*37da2899SCharles.Forsyth     /* if it is already a bitmap, no need to do anything */
2017*37da2899SCharles.Forsyth     switch ( slot->format )
2018*37da2899SCharles.Forsyth     {
2019*37da2899SCharles.Forsyth     case FT_GLYPH_FORMAT_BITMAP:   /* already a bitmap, don't do anything */
2020*37da2899SCharles.Forsyth       break;
2021*37da2899SCharles.Forsyth 
2022*37da2899SCharles.Forsyth     default:
2023*37da2899SCharles.Forsyth       {
2024*37da2899SCharles.Forsyth         FT_ListNode  node   = 0;
2025*37da2899SCharles.Forsyth         FT_Bool      update = 0;
2026*37da2899SCharles.Forsyth 
2027*37da2899SCharles.Forsyth 
2028*37da2899SCharles.Forsyth         /* small shortcut for the very common case */
2029*37da2899SCharles.Forsyth         if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
2030*37da2899SCharles.Forsyth         {
2031*37da2899SCharles.Forsyth           renderer = library->cur_renderer;
2032*37da2899SCharles.Forsyth           node     = library->renderers.head;
2033*37da2899SCharles.Forsyth         }
2034*37da2899SCharles.Forsyth         else
2035*37da2899SCharles.Forsyth           renderer = FT_Lookup_Renderer( library, slot->format, &node );
2036*37da2899SCharles.Forsyth 
2037*37da2899SCharles.Forsyth         error = FT_Err_Unimplemented_Feature;
2038*37da2899SCharles.Forsyth         while ( renderer )
2039*37da2899SCharles.Forsyth         {
2040*37da2899SCharles.Forsyth           error = renderer->render( renderer, slot, render_mode, NULL );
2041*37da2899SCharles.Forsyth           if ( !error ||
2042*37da2899SCharles.Forsyth                FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
2043*37da2899SCharles.Forsyth             break;
2044*37da2899SCharles.Forsyth 
2045*37da2899SCharles.Forsyth           /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
2046*37da2899SCharles.Forsyth           /* is unsupported by the current renderer for this glyph image */
2047*37da2899SCharles.Forsyth           /* format.                                                     */
2048*37da2899SCharles.Forsyth 
2049*37da2899SCharles.Forsyth           /* now, look for another renderer that supports the same */
2050*37da2899SCharles.Forsyth           /* format.                                               */
2051*37da2899SCharles.Forsyth           renderer = FT_Lookup_Renderer( library, slot->format, &node );
2052*37da2899SCharles.Forsyth           update   = 1;
2053*37da2899SCharles.Forsyth         }
2054*37da2899SCharles.Forsyth 
2055*37da2899SCharles.Forsyth         /* if we changed the current renderer for the glyph image format */
2056*37da2899SCharles.Forsyth         /* we need to select it as the next current one                  */
2057*37da2899SCharles.Forsyth         if ( !error && update && renderer )
2058*37da2899SCharles.Forsyth           FT_Set_Renderer( library, renderer, 0, 0 );
2059*37da2899SCharles.Forsyth       }
2060*37da2899SCharles.Forsyth     }
2061*37da2899SCharles.Forsyth 
2062*37da2899SCharles.Forsyth     return error;
2063*37da2899SCharles.Forsyth   }
2064*37da2899SCharles.Forsyth 
2065*37da2899SCharles.Forsyth 
2066*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
2067*37da2899SCharles.Forsyth 
2068*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Render_Glyph(FT_GlyphSlot slot,FT_Render_Mode render_mode)2069*37da2899SCharles.Forsyth   FT_Render_Glyph( FT_GlyphSlot    slot,
2070*37da2899SCharles.Forsyth                    FT_Render_Mode  render_mode )
2071*37da2899SCharles.Forsyth   {
2072*37da2899SCharles.Forsyth     FT_Library  library;
2073*37da2899SCharles.Forsyth 
2074*37da2899SCharles.Forsyth 
2075*37da2899SCharles.Forsyth     if ( !slot )
2076*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
2077*37da2899SCharles.Forsyth 
2078*37da2899SCharles.Forsyth     library = FT_FACE_LIBRARY( slot->face );
2079*37da2899SCharles.Forsyth 
2080*37da2899SCharles.Forsyth     return FT_Render_Glyph_Internal( library, slot, render_mode );
2081*37da2899SCharles.Forsyth   }
2082*37da2899SCharles.Forsyth 
2083*37da2899SCharles.Forsyth 
2084*37da2899SCharles.Forsyth   /*************************************************************************/
2085*37da2899SCharles.Forsyth   /*************************************************************************/
2086*37da2899SCharles.Forsyth   /*************************************************************************/
2087*37da2899SCharles.Forsyth   /****                                                                 ****/
2088*37da2899SCharles.Forsyth   /****                                                                 ****/
2089*37da2899SCharles.Forsyth   /****                         M O D U L E S                           ****/
2090*37da2899SCharles.Forsyth   /****                                                                 ****/
2091*37da2899SCharles.Forsyth   /****                                                                 ****/
2092*37da2899SCharles.Forsyth   /*************************************************************************/
2093*37da2899SCharles.Forsyth   /*************************************************************************/
2094*37da2899SCharles.Forsyth   /*************************************************************************/
2095*37da2899SCharles.Forsyth 
2096*37da2899SCharles.Forsyth 
2097*37da2899SCharles.Forsyth   /*************************************************************************/
2098*37da2899SCharles.Forsyth   /*                                                                       */
2099*37da2899SCharles.Forsyth   /* <Function>                                                            */
2100*37da2899SCharles.Forsyth   /*    Destroy_Module                                                     */
2101*37da2899SCharles.Forsyth   /*                                                                       */
2102*37da2899SCharles.Forsyth   /* <Description>                                                         */
2103*37da2899SCharles.Forsyth   /*    Destroys a given module object.  For drivers, this also destroys   */
2104*37da2899SCharles.Forsyth   /*    all child faces.                                                   */
2105*37da2899SCharles.Forsyth   /*                                                                       */
2106*37da2899SCharles.Forsyth   /* <InOut>                                                               */
2107*37da2899SCharles.Forsyth   /*     module :: A handle to the target driver object.                   */
2108*37da2899SCharles.Forsyth   /*                                                                       */
2109*37da2899SCharles.Forsyth   /* <Note>                                                                */
2110*37da2899SCharles.Forsyth   /*     The driver _must_ be LOCKED!                                      */
2111*37da2899SCharles.Forsyth   /*                                                                       */
2112*37da2899SCharles.Forsyth   static void
Destroy_Module(FT_Module module)2113*37da2899SCharles.Forsyth   Destroy_Module( FT_Module  module )
2114*37da2899SCharles.Forsyth   {
2115*37da2899SCharles.Forsyth     FT_Memory         memory  = module->memory;
2116*37da2899SCharles.Forsyth     FT_Module_Class*  clazz   = module->clazz;
2117*37da2899SCharles.Forsyth     FT_Library        library = module->library;
2118*37da2899SCharles.Forsyth 
2119*37da2899SCharles.Forsyth 
2120*37da2899SCharles.Forsyth     /* finalize client-data - before anything else */
2121*37da2899SCharles.Forsyth     if ( module->generic.finalizer )
2122*37da2899SCharles.Forsyth       module->generic.finalizer( module );
2123*37da2899SCharles.Forsyth 
2124*37da2899SCharles.Forsyth     if ( library && library->auto_hinter == module )
2125*37da2899SCharles.Forsyth       library->auto_hinter = 0;
2126*37da2899SCharles.Forsyth 
2127*37da2899SCharles.Forsyth     /* if the module is a renderer */
2128*37da2899SCharles.Forsyth     if ( FT_MODULE_IS_RENDERER( module ) )
2129*37da2899SCharles.Forsyth       ft_remove_renderer( module );
2130*37da2899SCharles.Forsyth 
2131*37da2899SCharles.Forsyth     /* if the module is a font driver, add some steps */
2132*37da2899SCharles.Forsyth     if ( FT_MODULE_IS_DRIVER( module ) )
2133*37da2899SCharles.Forsyth       Destroy_Driver( FT_DRIVER( module ) );
2134*37da2899SCharles.Forsyth 
2135*37da2899SCharles.Forsyth     /* finalize the module object */
2136*37da2899SCharles.Forsyth     if ( clazz->module_done )
2137*37da2899SCharles.Forsyth       clazz->module_done( module );
2138*37da2899SCharles.Forsyth 
2139*37da2899SCharles.Forsyth     /* discard it */
2140*37da2899SCharles.Forsyth     FT_FREE( module );
2141*37da2899SCharles.Forsyth   }
2142*37da2899SCharles.Forsyth 
2143*37da2899SCharles.Forsyth 
2144*37da2899SCharles.Forsyth   /* documentation is in ftmodule.h */
2145*37da2899SCharles.Forsyth 
2146*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Add_Module(FT_Library library,const FT_Module_Class * clazz)2147*37da2899SCharles.Forsyth   FT_Add_Module( FT_Library              library,
2148*37da2899SCharles.Forsyth                  const FT_Module_Class*  clazz )
2149*37da2899SCharles.Forsyth   {
2150*37da2899SCharles.Forsyth     FT_Error   error;
2151*37da2899SCharles.Forsyth     FT_Memory  memory;
2152*37da2899SCharles.Forsyth     FT_Module  module;
2153*37da2899SCharles.Forsyth     FT_UInt    nn;
2154*37da2899SCharles.Forsyth 
2155*37da2899SCharles.Forsyth 
2156*37da2899SCharles.Forsyth #define FREETYPE_VER_FIXED  ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
2157*37da2899SCharles.Forsyth                                 FREETYPE_MINOR                  )
2158*37da2899SCharles.Forsyth 
2159*37da2899SCharles.Forsyth     if ( !library )
2160*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
2161*37da2899SCharles.Forsyth 
2162*37da2899SCharles.Forsyth     if ( !clazz )
2163*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
2164*37da2899SCharles.Forsyth 
2165*37da2899SCharles.Forsyth     /* check freetype version */
2166*37da2899SCharles.Forsyth     if ( clazz->module_requires > FREETYPE_VER_FIXED )
2167*37da2899SCharles.Forsyth       return FT_Err_Invalid_Version;
2168*37da2899SCharles.Forsyth 
2169*37da2899SCharles.Forsyth     /* look for a module with the same name in the library's table */
2170*37da2899SCharles.Forsyth     for ( nn = 0; nn < library->num_modules; nn++ )
2171*37da2899SCharles.Forsyth     {
2172*37da2899SCharles.Forsyth       module = library->modules[nn];
2173*37da2899SCharles.Forsyth       if ( ft_strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
2174*37da2899SCharles.Forsyth       {
2175*37da2899SCharles.Forsyth         /* this installed module has the same name, compare their versions */
2176*37da2899SCharles.Forsyth         if ( clazz->module_version <= module->clazz->module_version )
2177*37da2899SCharles.Forsyth           return FT_Err_Lower_Module_Version;
2178*37da2899SCharles.Forsyth 
2179*37da2899SCharles.Forsyth         /* remove the module from our list, then exit the loop to replace */
2180*37da2899SCharles.Forsyth         /* it by our new version..                                        */
2181*37da2899SCharles.Forsyth         FT_Remove_Module( library, module );
2182*37da2899SCharles.Forsyth         break;
2183*37da2899SCharles.Forsyth       }
2184*37da2899SCharles.Forsyth     }
2185*37da2899SCharles.Forsyth 
2186*37da2899SCharles.Forsyth     memory = library->memory;
2187*37da2899SCharles.Forsyth     error  = FT_Err_Ok;
2188*37da2899SCharles.Forsyth 
2189*37da2899SCharles.Forsyth     if ( library->num_modules >= FT_MAX_MODULES )
2190*37da2899SCharles.Forsyth     {
2191*37da2899SCharles.Forsyth       error = FT_Err_Too_Many_Drivers;
2192*37da2899SCharles.Forsyth       goto Exit;
2193*37da2899SCharles.Forsyth     }
2194*37da2899SCharles.Forsyth 
2195*37da2899SCharles.Forsyth     /* allocate module object */
2196*37da2899SCharles.Forsyth     if ( FT_ALLOC( module, clazz->module_size ) )
2197*37da2899SCharles.Forsyth       goto Exit;
2198*37da2899SCharles.Forsyth 
2199*37da2899SCharles.Forsyth     /* base initialization */
2200*37da2899SCharles.Forsyth     module->library = library;
2201*37da2899SCharles.Forsyth     module->memory  = memory;
2202*37da2899SCharles.Forsyth     module->clazz   = (FT_Module_Class*)clazz;
2203*37da2899SCharles.Forsyth 
2204*37da2899SCharles.Forsyth     /* check whether the module is a renderer - this must be performed */
2205*37da2899SCharles.Forsyth     /* before the normal module initialization                         */
2206*37da2899SCharles.Forsyth     if ( FT_MODULE_IS_RENDERER( module ) )
2207*37da2899SCharles.Forsyth     {
2208*37da2899SCharles.Forsyth       /* add to the renderers list */
2209*37da2899SCharles.Forsyth       error = ft_add_renderer( module );
2210*37da2899SCharles.Forsyth       if ( error )
2211*37da2899SCharles.Forsyth         goto Fail;
2212*37da2899SCharles.Forsyth     }
2213*37da2899SCharles.Forsyth 
2214*37da2899SCharles.Forsyth     /* is the module a auto-hinter? */
2215*37da2899SCharles.Forsyth     if ( FT_MODULE_IS_HINTER( module ) )
2216*37da2899SCharles.Forsyth       library->auto_hinter = module;
2217*37da2899SCharles.Forsyth 
2218*37da2899SCharles.Forsyth     /* if the module is a font driver */
2219*37da2899SCharles.Forsyth     if ( FT_MODULE_IS_DRIVER( module ) )
2220*37da2899SCharles.Forsyth     {
2221*37da2899SCharles.Forsyth       /* allocate glyph loader if needed */
2222*37da2899SCharles.Forsyth       FT_Driver  driver = FT_DRIVER( module );
2223*37da2899SCharles.Forsyth 
2224*37da2899SCharles.Forsyth 
2225*37da2899SCharles.Forsyth       driver->clazz = (FT_Driver_Class)module->clazz;
2226*37da2899SCharles.Forsyth       if ( FT_DRIVER_USES_OUTLINES( driver ) )
2227*37da2899SCharles.Forsyth       {
2228*37da2899SCharles.Forsyth         error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
2229*37da2899SCharles.Forsyth         if ( error )
2230*37da2899SCharles.Forsyth           goto Fail;
2231*37da2899SCharles.Forsyth       }
2232*37da2899SCharles.Forsyth     }
2233*37da2899SCharles.Forsyth 
2234*37da2899SCharles.Forsyth     if ( clazz->module_init )
2235*37da2899SCharles.Forsyth     {
2236*37da2899SCharles.Forsyth       error = clazz->module_init( module );
2237*37da2899SCharles.Forsyth       if ( error )
2238*37da2899SCharles.Forsyth         goto Fail;
2239*37da2899SCharles.Forsyth     }
2240*37da2899SCharles.Forsyth 
2241*37da2899SCharles.Forsyth     /* add module to the library's table */
2242*37da2899SCharles.Forsyth     library->modules[library->num_modules++] = module;
2243*37da2899SCharles.Forsyth 
2244*37da2899SCharles.Forsyth   Exit:
2245*37da2899SCharles.Forsyth     return error;
2246*37da2899SCharles.Forsyth 
2247*37da2899SCharles.Forsyth   Fail:
2248*37da2899SCharles.Forsyth     if ( FT_MODULE_IS_DRIVER( module ) )
2249*37da2899SCharles.Forsyth     {
2250*37da2899SCharles.Forsyth       FT_Driver  driver = FT_DRIVER( module );
2251*37da2899SCharles.Forsyth 
2252*37da2899SCharles.Forsyth 
2253*37da2899SCharles.Forsyth       if ( FT_DRIVER_USES_OUTLINES( driver ) )
2254*37da2899SCharles.Forsyth         FT_GlyphLoader_Done( driver->glyph_loader );
2255*37da2899SCharles.Forsyth     }
2256*37da2899SCharles.Forsyth 
2257*37da2899SCharles.Forsyth     if ( FT_MODULE_IS_RENDERER( module ) )
2258*37da2899SCharles.Forsyth     {
2259*37da2899SCharles.Forsyth       FT_Renderer  renderer = FT_RENDERER( module );
2260*37da2899SCharles.Forsyth 
2261*37da2899SCharles.Forsyth 
2262*37da2899SCharles.Forsyth       if ( renderer->raster )
2263*37da2899SCharles.Forsyth         renderer->clazz->raster_class->raster_done( renderer->raster );
2264*37da2899SCharles.Forsyth     }
2265*37da2899SCharles.Forsyth 
2266*37da2899SCharles.Forsyth     FT_FREE( module );
2267*37da2899SCharles.Forsyth     goto Exit;
2268*37da2899SCharles.Forsyth   }
2269*37da2899SCharles.Forsyth 
2270*37da2899SCharles.Forsyth 
2271*37da2899SCharles.Forsyth   /* documentation is in ftmodule.h */
2272*37da2899SCharles.Forsyth 
2273*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Module )
FT_Get_Module(FT_Library library,const char * module_name)2274*37da2899SCharles.Forsyth   FT_Get_Module( FT_Library   library,
2275*37da2899SCharles.Forsyth                  const char*  module_name )
2276*37da2899SCharles.Forsyth   {
2277*37da2899SCharles.Forsyth     FT_Module   result = 0;
2278*37da2899SCharles.Forsyth     FT_Module*  cur;
2279*37da2899SCharles.Forsyth     FT_Module*  limit;
2280*37da2899SCharles.Forsyth 
2281*37da2899SCharles.Forsyth 
2282*37da2899SCharles.Forsyth     if ( !library || !module_name )
2283*37da2899SCharles.Forsyth       return result;
2284*37da2899SCharles.Forsyth 
2285*37da2899SCharles.Forsyth     cur   = library->modules;
2286*37da2899SCharles.Forsyth     limit = cur + library->num_modules;
2287*37da2899SCharles.Forsyth 
2288*37da2899SCharles.Forsyth     for ( ; cur < limit; cur++ )
2289*37da2899SCharles.Forsyth       if ( ft_strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
2290*37da2899SCharles.Forsyth       {
2291*37da2899SCharles.Forsyth         result = cur[0];
2292*37da2899SCharles.Forsyth         break;
2293*37da2899SCharles.Forsyth       }
2294*37da2899SCharles.Forsyth 
2295*37da2899SCharles.Forsyth     return result;
2296*37da2899SCharles.Forsyth   }
2297*37da2899SCharles.Forsyth 
2298*37da2899SCharles.Forsyth 
2299*37da2899SCharles.Forsyth   /* documentation is in ftobjs.h */
2300*37da2899SCharles.Forsyth 
2301*37da2899SCharles.Forsyth   FT_BASE_DEF( const void* )
FT_Get_Module_Interface(FT_Library library,const char * mod_name)2302*37da2899SCharles.Forsyth   FT_Get_Module_Interface( FT_Library   library,
2303*37da2899SCharles.Forsyth                            const char*  mod_name )
2304*37da2899SCharles.Forsyth   {
2305*37da2899SCharles.Forsyth     FT_Module  module;
2306*37da2899SCharles.Forsyth 
2307*37da2899SCharles.Forsyth 
2308*37da2899SCharles.Forsyth     /* test for valid `library' delayed to FT_Get_Module() */
2309*37da2899SCharles.Forsyth 
2310*37da2899SCharles.Forsyth     module = FT_Get_Module( library, mod_name );
2311*37da2899SCharles.Forsyth 
2312*37da2899SCharles.Forsyth     return module ? module->clazz->module_interface : 0;
2313*37da2899SCharles.Forsyth   }
2314*37da2899SCharles.Forsyth 
2315*37da2899SCharles.Forsyth 
2316*37da2899SCharles.Forsyth   /* documentation is in ftmodule.h */
2317*37da2899SCharles.Forsyth 
2318*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Remove_Module(FT_Library library,FT_Module module)2319*37da2899SCharles.Forsyth   FT_Remove_Module( FT_Library  library,
2320*37da2899SCharles.Forsyth                     FT_Module   module )
2321*37da2899SCharles.Forsyth   {
2322*37da2899SCharles.Forsyth     /* try to find the module from the table, then remove it from there */
2323*37da2899SCharles.Forsyth 
2324*37da2899SCharles.Forsyth     if ( !library )
2325*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
2326*37da2899SCharles.Forsyth 
2327*37da2899SCharles.Forsyth     if ( module )
2328*37da2899SCharles.Forsyth     {
2329*37da2899SCharles.Forsyth       FT_Module*  cur   = library->modules;
2330*37da2899SCharles.Forsyth       FT_Module*  limit = cur + library->num_modules;
2331*37da2899SCharles.Forsyth 
2332*37da2899SCharles.Forsyth 
2333*37da2899SCharles.Forsyth       for ( ; cur < limit; cur++ )
2334*37da2899SCharles.Forsyth       {
2335*37da2899SCharles.Forsyth         if ( cur[0] == module )
2336*37da2899SCharles.Forsyth         {
2337*37da2899SCharles.Forsyth           /* remove it from the table */
2338*37da2899SCharles.Forsyth           library->num_modules--;
2339*37da2899SCharles.Forsyth           limit--;
2340*37da2899SCharles.Forsyth           while ( cur < limit )
2341*37da2899SCharles.Forsyth           {
2342*37da2899SCharles.Forsyth             cur[0] = cur[1];
2343*37da2899SCharles.Forsyth             cur++;
2344*37da2899SCharles.Forsyth           }
2345*37da2899SCharles.Forsyth           limit[0] = 0;
2346*37da2899SCharles.Forsyth 
2347*37da2899SCharles.Forsyth           /* destroy the module */
2348*37da2899SCharles.Forsyth           Destroy_Module( module );
2349*37da2899SCharles.Forsyth 
2350*37da2899SCharles.Forsyth           return FT_Err_Ok;
2351*37da2899SCharles.Forsyth         }
2352*37da2899SCharles.Forsyth       }
2353*37da2899SCharles.Forsyth     }
2354*37da2899SCharles.Forsyth     return FT_Err_Invalid_Driver_Handle;
2355*37da2899SCharles.Forsyth   }
2356*37da2899SCharles.Forsyth 
2357*37da2899SCharles.Forsyth 
2358*37da2899SCharles.Forsyth   /*************************************************************************/
2359*37da2899SCharles.Forsyth   /*************************************************************************/
2360*37da2899SCharles.Forsyth   /*************************************************************************/
2361*37da2899SCharles.Forsyth   /****                                                                 ****/
2362*37da2899SCharles.Forsyth   /****                                                                 ****/
2363*37da2899SCharles.Forsyth   /****                         L I B R A R Y                           ****/
2364*37da2899SCharles.Forsyth   /****                                                                 ****/
2365*37da2899SCharles.Forsyth   /****                                                                 ****/
2366*37da2899SCharles.Forsyth   /*************************************************************************/
2367*37da2899SCharles.Forsyth   /*************************************************************************/
2368*37da2899SCharles.Forsyth   /*************************************************************************/
2369*37da2899SCharles.Forsyth 
2370*37da2899SCharles.Forsyth 
2371*37da2899SCharles.Forsyth   /* documentation is in ftmodule.h */
2372*37da2899SCharles.Forsyth 
2373*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_New_Library(FT_Memory memory,FT_Library * alibrary)2374*37da2899SCharles.Forsyth   FT_New_Library( FT_Memory    memory,
2375*37da2899SCharles.Forsyth                   FT_Library  *alibrary )
2376*37da2899SCharles.Forsyth   {
2377*37da2899SCharles.Forsyth     FT_Library  library = 0;
2378*37da2899SCharles.Forsyth     FT_Error    error;
2379*37da2899SCharles.Forsyth 
2380*37da2899SCharles.Forsyth 
2381*37da2899SCharles.Forsyth     if ( !memory )
2382*37da2899SCharles.Forsyth       return FT_Err_Invalid_Argument;
2383*37da2899SCharles.Forsyth 
2384*37da2899SCharles.Forsyth #ifdef FT_DEBUG_LEVEL_ERROR
2385*37da2899SCharles.Forsyth     /* init debugging support */
2386*37da2899SCharles.Forsyth     ft_debug_init();
2387*37da2899SCharles.Forsyth #endif
2388*37da2899SCharles.Forsyth 
2389*37da2899SCharles.Forsyth     /* first of all, allocate the library object */
2390*37da2899SCharles.Forsyth     if ( FT_NEW( library ) )
2391*37da2899SCharles.Forsyth       return error;
2392*37da2899SCharles.Forsyth 
2393*37da2899SCharles.Forsyth     library->memory = memory;
2394*37da2899SCharles.Forsyth 
2395*37da2899SCharles.Forsyth     /* allocate the render pool */
2396*37da2899SCharles.Forsyth     library->raster_pool_size = FT_RENDER_POOL_SIZE;
2397*37da2899SCharles.Forsyth     if ( FT_ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
2398*37da2899SCharles.Forsyth       goto Fail;
2399*37da2899SCharles.Forsyth 
2400*37da2899SCharles.Forsyth     /* That's ok now */
2401*37da2899SCharles.Forsyth     *alibrary = library;
2402*37da2899SCharles.Forsyth 
2403*37da2899SCharles.Forsyth     return FT_Err_Ok;
2404*37da2899SCharles.Forsyth 
2405*37da2899SCharles.Forsyth   Fail:
2406*37da2899SCharles.Forsyth     FT_FREE( library );
2407*37da2899SCharles.Forsyth     return error;
2408*37da2899SCharles.Forsyth   }
2409*37da2899SCharles.Forsyth 
2410*37da2899SCharles.Forsyth 
2411*37da2899SCharles.Forsyth   /* documentation is in freetype.h */
2412*37da2899SCharles.Forsyth 
2413*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Library_Version(FT_Library library,FT_Int * amajor,FT_Int * aminor,FT_Int * apatch)2414*37da2899SCharles.Forsyth   FT_Library_Version( FT_Library   library,
2415*37da2899SCharles.Forsyth                       FT_Int      *amajor,
2416*37da2899SCharles.Forsyth                       FT_Int      *aminor,
2417*37da2899SCharles.Forsyth                       FT_Int      *apatch )
2418*37da2899SCharles.Forsyth   {
2419*37da2899SCharles.Forsyth     FT_Int  major = 0;
2420*37da2899SCharles.Forsyth     FT_Int  minor = 0;
2421*37da2899SCharles.Forsyth     FT_Int  patch = 0;
2422*37da2899SCharles.Forsyth 
2423*37da2899SCharles.Forsyth 
2424*37da2899SCharles.Forsyth     if ( library )
2425*37da2899SCharles.Forsyth     {
2426*37da2899SCharles.Forsyth       major = library->version_major;
2427*37da2899SCharles.Forsyth       minor = library->version_minor;
2428*37da2899SCharles.Forsyth       patch = library->version_patch;
2429*37da2899SCharles.Forsyth     }
2430*37da2899SCharles.Forsyth 
2431*37da2899SCharles.Forsyth     if ( amajor )
2432*37da2899SCharles.Forsyth       *amajor = major;
2433*37da2899SCharles.Forsyth 
2434*37da2899SCharles.Forsyth     if ( aminor )
2435*37da2899SCharles.Forsyth       *aminor = minor;
2436*37da2899SCharles.Forsyth 
2437*37da2899SCharles.Forsyth     if ( apatch )
2438*37da2899SCharles.Forsyth       *apatch = patch;
2439*37da2899SCharles.Forsyth   }
2440*37da2899SCharles.Forsyth 
2441*37da2899SCharles.Forsyth 
2442*37da2899SCharles.Forsyth   /* documentation is in ftmodule.h */
2443*37da2899SCharles.Forsyth 
2444*37da2899SCharles.Forsyth   FT_EXPORT_DEF( FT_Error )
FT_Done_Library(FT_Library library)2445*37da2899SCharles.Forsyth   FT_Done_Library( FT_Library  library )
2446*37da2899SCharles.Forsyth   {
2447*37da2899SCharles.Forsyth     FT_Memory  memory;
2448*37da2899SCharles.Forsyth 
2449*37da2899SCharles.Forsyth 
2450*37da2899SCharles.Forsyth     if ( !library )
2451*37da2899SCharles.Forsyth       return FT_Err_Invalid_Library_Handle;
2452*37da2899SCharles.Forsyth 
2453*37da2899SCharles.Forsyth     memory = library->memory;
2454*37da2899SCharles.Forsyth 
2455*37da2899SCharles.Forsyth     /* Discard client-data */
2456*37da2899SCharles.Forsyth     if ( library->generic.finalizer )
2457*37da2899SCharles.Forsyth       library->generic.finalizer( library );
2458*37da2899SCharles.Forsyth 
2459*37da2899SCharles.Forsyth     /* Close all modules in the library */
2460*37da2899SCharles.Forsyth #if 1
2461*37da2899SCharles.Forsyth     while ( library->num_modules > 0 )
2462*37da2899SCharles.Forsyth       FT_Remove_Module( library, library->modules[0] );
2463*37da2899SCharles.Forsyth #else
2464*37da2899SCharles.Forsyth     {
2465*37da2899SCharles.Forsyth       FT_UInt  n;
2466*37da2899SCharles.Forsyth 
2467*37da2899SCharles.Forsyth 
2468*37da2899SCharles.Forsyth       for ( n = 0; n < library->num_modules; n++ )
2469*37da2899SCharles.Forsyth       {
2470*37da2899SCharles.Forsyth         FT_Module  module = library->modules[n];
2471*37da2899SCharles.Forsyth 
2472*37da2899SCharles.Forsyth 
2473*37da2899SCharles.Forsyth         if ( module )
2474*37da2899SCharles.Forsyth         {
2475*37da2899SCharles.Forsyth           Destroy_Module( module );
2476*37da2899SCharles.Forsyth           library->modules[n] = 0;
2477*37da2899SCharles.Forsyth         }
2478*37da2899SCharles.Forsyth       }
2479*37da2899SCharles.Forsyth     }
2480*37da2899SCharles.Forsyth #endif
2481*37da2899SCharles.Forsyth 
2482*37da2899SCharles.Forsyth     /* Destroy raster objects */
2483*37da2899SCharles.Forsyth     FT_FREE( library->raster_pool );
2484*37da2899SCharles.Forsyth     library->raster_pool_size = 0;
2485*37da2899SCharles.Forsyth 
2486*37da2899SCharles.Forsyth     FT_FREE( library );
2487*37da2899SCharles.Forsyth     return FT_Err_Ok;
2488*37da2899SCharles.Forsyth   }
2489*37da2899SCharles.Forsyth 
2490*37da2899SCharles.Forsyth 
2491*37da2899SCharles.Forsyth   /* documentation is in ftmodule.h */
2492*37da2899SCharles.Forsyth 
2493*37da2899SCharles.Forsyth   FT_EXPORT_DEF( void )
FT_Set_Debug_Hook(FT_Library library,FT_UInt hook_index,FT_DebugHook_Func debug_hook)2494*37da2899SCharles.Forsyth   FT_Set_Debug_Hook( FT_Library         library,
2495*37da2899SCharles.Forsyth                      FT_UInt            hook_index,
2496*37da2899SCharles.Forsyth                      FT_DebugHook_Func  debug_hook )
2497*37da2899SCharles.Forsyth   {
2498*37da2899SCharles.Forsyth     if ( library && debug_hook &&
2499*37da2899SCharles.Forsyth          hook_index <
2500*37da2899SCharles.Forsyth            ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
2501*37da2899SCharles.Forsyth       library->debug_hooks[hook_index] = debug_hook;
2502*37da2899SCharles.Forsyth   }
2503*37da2899SCharles.Forsyth 
2504*37da2899SCharles.Forsyth 
2505*37da2899SCharles.Forsyth /* END */
2506