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