1 /***************************************************************************/
5 /* The FreeType private base classes (body). */
7 /* Copyright 1996-2001 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
21 #include FT_INTERNAL_OBJECTS_H
22 #include FT_INTERNAL_DEBUG_H
23 #include FT_INTERNAL_STREAM_H
24 #include FT_TRUETYPE_TABLES_H
26 #include <string.h> /* for strcmp() */
29 /*************************************************************************/
30 /*************************************************************************/
31 /*************************************************************************/
34 /**** M E M O R Y ****/
37 /*************************************************************************/
38 /*************************************************************************/
39 /*************************************************************************/
41 /*************************************************************************/
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. */
48 #define FT_COMPONENT trace_memory
51 /* documentation is in ftmemory.h */
53 FT_BASE_DEF( FT_Error )
54 FT_Alloc( FT_Memory memory,
62 *P = memory->alloc( memory, size );
65 FT_ERROR(( "FT_Alloc:" ));
66 FT_ERROR(( " Out of memory? (%ld requested)\n",
69 return FT_Err_Out_Of_Memory;
71 MEM_Set( *P, 0, size );
76 FT_TRACE7(( "FT_Alloc:" ));
77 FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
84 /* documentation is in ftmemory.h */
86 FT_BASE_DEF( FT_Error )
87 FT_Realloc( FT_Memory memory,
97 /* if the original pointer is NULL, call FT_Alloc() */
99 return FT_Alloc( memory, size, P );
101 /* if the new block if zero-sized, clear the current one */
104 FT_Free( memory, P );
108 Q = memory->realloc( memory, current, size, *P );
116 FT_ERROR(( "FT_Realloc:" ));
117 FT_ERROR(( " Failed (current %ld, requested %ld)\n",
119 return FT_Err_Out_Of_Memory;
123 /* documentation is in ftmemory.h */
126 FT_Free( FT_Memory memory,
129 FT_TRACE7(( "FT_Free:" ));
130 FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
131 P, P ? *P : (void*)0 ));
135 memory->free( memory, *P );
141 /*************************************************************************/
142 /*************************************************************************/
143 /*************************************************************************/
146 /**** S T R E A M ****/
149 /*************************************************************************/
150 /*************************************************************************/
151 /*************************************************************************/
154 /*************************************************************************/
157 /* ft_new_input_stream */
160 /* Creates a new input stream object from an FT_Open_Args structure. */
163 /* The function expects a valid `astream' parameter. */
166 ft_new_input_stream( FT_Library library,
176 return FT_Err_Invalid_Library_Handle;
179 return FT_Err_Invalid_Argument;
182 memory = library->memory;
183 if ( ALLOC( stream, sizeof ( *stream ) ) )
186 stream->memory = memory;
188 /* now, look at the stream flags */
189 if ( args->flags & ft_open_memory )
192 FT_New_Memory_Stream( library,
193 (FT_Byte*)args->memory_base,
197 else if ( args->flags & ft_open_pathname )
199 error = FT_New_Stream( args->pathname, stream );
200 stream->pathname.pointer = args->pathname;
202 else if ( ( args->flags & ft_open_stream ) && args->stream )
204 /* in this case, we do not need to allocate a new stream object */
205 /* since the caller is responsible for closing it himself */
207 stream = args->stream;
210 error = FT_Err_Invalid_Argument;
222 /* documentation is in ftobjs.h */
224 FT_EXPORT_DEF( void )
225 FT_Done_Stream( FT_Stream stream )
227 if ( stream && stream->close )
229 stream->close( stream );
236 ft_done_stream( FT_Stream* astream,
239 FT_Stream stream = *astream;
243 stream->close( stream );
247 FT_Memory memory = stream->memory;
257 #define FT_COMPONENT trace_objs
260 /*************************************************************************/
261 /*************************************************************************/
262 /*************************************************************************/
265 /**** G L Y P H L O A D E R ****/
268 /*************************************************************************/
269 /*************************************************************************/
270 /*************************************************************************/
273 /*************************************************************************/
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. */
278 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
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'). */
284 /* loader.current Describes the top of the stack, on which a new */
285 /* glyph can be loaded. */
287 /* Rewind Clears the stack. */
288 /* Prepare Set up `loader.current' for addition of a new glyph */
290 /* Add Add the `current' glyph image to the `base' one, */
291 /* and prepare for another one. */
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 */
297 /*************************************************************************/
300 /* create a new glyph loader */
301 FT_BASE_DEF( FT_Error )
302 FT_GlyphLoader_New( FT_Memory memory,
303 FT_GlyphLoader* *aloader )
305 FT_GlyphLoader* loader;
309 if ( !ALLOC( loader, sizeof ( *loader ) ) )
311 loader->memory = memory;
318 /* rewind the glyph loader - reset counters to 0 */
320 FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
322 FT_GlyphLoad* base = &loader->base;
323 FT_GlyphLoad* current = &loader->current;
326 base->outline.n_points = 0;
327 base->outline.n_contours = 0;
328 base->num_subglyphs = 0;
334 /* reset the glyph loader, frees all allocated tables */
335 /* and starts from zero */
337 FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
339 FT_Memory memory = loader->memory;
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 );
348 loader->max_points = 0;
349 loader->max_contours = 0;
350 loader->max_subglyphs = 0;
352 FT_GlyphLoader_Rewind( loader );
356 /* delete a glyph loader */
358 FT_GlyphLoader_Done( FT_GlyphLoader* loader )
362 FT_Memory memory = loader->memory;
365 FT_GlyphLoader_Reset( loader );
371 /* re-adjust the `current' outline fields */
373 FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
375 FT_Outline* base = &loader->base.outline;
376 FT_Outline* current = &loader->current.outline;
379 current->points = base->points + base->n_points;
380 current->tags = base->tags + base->n_points;
381 current->contours = base->contours + base->n_contours;
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;
390 FT_BASE_DEF( FT_Error )
391 FT_GlyphLoader_Create_Extra( FT_GlyphLoader* loader )
394 FT_Memory memory = loader->memory;
397 if ( !ALLOC_ARRAY( loader->base.extra_points,
398 loader->max_points, FT_Vector ) )
400 loader->use_extra = 1;
401 FT_GlyphLoader_Adjust_Points( loader );
407 /* re-adjust the `current' subglyphs field */
409 FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
411 FT_GlyphLoad* base = &loader->base;
412 FT_GlyphLoad* current = &loader->current;
415 current->subglyphs = base->subglyphs + base->num_subglyphs;
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! */
423 FT_BASE_DEF( FT_Error )
424 FT_GlyphLoader_Check_Points( FT_GlyphLoader* loader,
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;
434 FT_UInt new_max, old_max;
437 /* check points & tags */
438 new_max = base->n_points + current->n_points + n_points;
439 old_max = loader->max_points;
441 if ( new_max > old_max )
443 new_max = ( new_max + 7 ) & -8;
445 if ( REALLOC_ARRAY( base->points, old_max, new_max, FT_Vector ) ||
446 REALLOC_ARRAY( base->tags, old_max, new_max, FT_Byte ) )
449 if ( loader->use_extra &&
450 REALLOC_ARRAY( loader->base.extra_points, old_max,
451 new_max, FT_Vector ) )
455 loader->max_points = new_max;
459 old_max = loader->max_contours;
460 new_max = base->n_contours + current->n_contours +
462 if ( new_max > old_max )
464 new_max = ( new_max + 3 ) & -4;
465 if ( REALLOC_ARRAY( base->contours, old_max, new_max, FT_Short ) )
469 loader->max_contours = new_max;
473 FT_GlyphLoader_Adjust_Points( loader );
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! */
484 FT_BASE_DEF( FT_Error )
485 FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader* loader,
488 FT_Memory memory = loader->memory;
489 FT_Error error = FT_Err_Ok;
490 FT_UInt new_max, old_max;
492 FT_GlyphLoad* base = &loader->base;
493 FT_GlyphLoad* current = &loader->current;
496 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
497 old_max = loader->max_subglyphs;
498 if ( new_max > old_max )
500 new_max = ( new_max + 1 ) & -2;
501 if ( REALLOC_ARRAY( base->subglyphs, old_max, new_max, FT_SubGlyph ) )
504 loader->max_subglyphs = new_max;
506 FT_GlyphLoader_Adjust_Subglyphs( loader );
514 /* prepare loader for the addition of a new glyph on top of the base one */
516 FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
518 FT_GlyphLoad* current = &loader->current;
521 current->outline.n_points = 0;
522 current->outline.n_contours = 0;
523 current->num_subglyphs = 0;
525 FT_GlyphLoader_Adjust_Points ( loader );
526 FT_GlyphLoader_Adjust_Subglyphs( loader );
530 /* add current glyph to the base image - and prepare for another */
532 FT_GlyphLoader_Add( FT_GlyphLoader* loader )
534 FT_GlyphLoad* base = &loader->base;
535 FT_GlyphLoad* current = &loader->current;
537 FT_UInt n_curr_contours = current->outline.n_contours;
538 FT_UInt n_base_points = base->outline.n_points;
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 );
547 base->num_subglyphs += current->num_subglyphs;
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 );
554 /* prepare for another new glyph image */
555 FT_GlyphLoader_Prepare( loader );
559 FT_BASE_DEF( FT_Error )
560 FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
561 FT_GlyphLoader* source )
564 FT_UInt num_points = source->base.outline.n_points;
565 FT_UInt num_contours = source->base.outline.n_contours;
568 error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
571 FT_Outline* out = &target->base.outline;
572 FT_Outline* in = &source->base.outline;
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 ) );
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 ) );
587 out->n_points = (short)num_points;
588 out->n_contours = (short)num_contours;
590 FT_GlyphLoader_Adjust_Points( target );
597 /*************************************************************************/
598 /*************************************************************************/
599 /*************************************************************************/
602 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
605 /*************************************************************************/
606 /*************************************************************************/
607 /*************************************************************************/
611 ft_glyphslot_init( FT_GlyphSlot slot )
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;
620 slot->library = driver->root.library;
622 if ( ALLOC( internal, sizeof ( *internal ) ) )
625 slot->internal = internal;
627 if ( FT_DRIVER_USES_OUTLINES( driver ) )
628 error = FT_GlyphLoader_New( memory, &internal->loader );
630 if ( !error && clazz->init_slot )
631 error = clazz->init_slot( slot );
639 ft_glyphslot_clear( FT_GlyphSlot slot )
641 /* free bitmap if needed */
642 if ( slot->flags & ft_glyph_own_bitmap )
644 FT_Memory memory = FT_FACE_MEMORY( slot->face );
647 FREE( slot->bitmap.buffer );
648 slot->flags &= ~ft_glyph_own_bitmap;
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 ) );
656 slot->bitmap_left = 0;
657 slot->bitmap_top = 0;
658 slot->num_subglyphs = 0;
660 slot->control_data = 0;
661 slot->control_len = 0;
663 slot->format = ft_glyph_format_none;
665 slot->linearHoriAdvance = 0;
666 slot->linearVertAdvance = 0;
671 ft_glyphslot_done( FT_GlyphSlot slot )
673 FT_Driver driver = slot->face->driver;
674 FT_Driver_Class* clazz = driver->clazz;
675 FT_Memory memory = driver->root.memory;
678 if ( clazz->done_slot )
679 clazz->done_slot( slot );
681 /* free bitmap buffer if needed */
682 if ( slot->flags & ft_glyph_own_bitmap )
683 FREE( slot->bitmap.buffer );
685 /* free glyph loader */
686 if ( FT_DRIVER_USES_OUTLINES( driver ) )
688 FT_GlyphLoader_Done( slot->internal->loader );
689 slot->internal->loader = 0;
692 FREE( slot->internal );
696 /* documentation is in ftobjs.h */
698 FT_BASE_DEF( FT_Error )
699 FT_New_GlyphSlot( FT_Face face,
700 FT_GlyphSlot *aslot )
704 FT_Driver_Class* clazz;
709 if ( !face || !aslot || !face->driver )
710 return FT_Err_Invalid_Argument;
714 driver = face->driver;
715 clazz = driver->clazz;
716 memory = driver->root.memory;
718 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
719 if ( !ALLOC( slot, clazz->slot_object_size ) )
723 error = ft_glyphslot_init( slot );
726 ft_glyphslot_done( slot );
735 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
740 /* documentation is in ftobjs.h */
743 FT_Done_GlyphSlot( FT_GlyphSlot slot )
747 FT_Driver driver = slot->face->driver;
748 FT_Memory memory = driver->root.memory;
749 FT_GlyphSlot* parent;
753 /* Remove slot from its parent face's list */
754 parent = &slot->face->glyph;
762 ft_glyphslot_done( slot );
772 /* documentation is in freetype.h */
774 FT_EXPORT_DEF( void )
775 FT_Set_Transform( FT_Face face,
779 FT_Face_Internal internal;
785 internal = face->internal;
787 internal->transform_flags = 0;
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;
798 internal->transform_matrix = *matrix;
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;
808 internal->transform_delta.x = 0;
809 internal->transform_delta.y = 0;
810 delta = &internal->transform_delta;
813 internal->transform_delta = *delta;
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;
822 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
825 /* documentation is in freetype.h */
827 FT_EXPORT_DEF( FT_Error )
828 FT_Load_Glyph( FT_Face face,
840 if ( !face || !face->size || !face->glyph )
841 return FT_Err_Invalid_Face_Handle;
843 if ( glyph_index >= (FT_UInt)face->num_glyphs )
844 return FT_Err_Invalid_Argument;
847 ft_glyphslot_clear( slot );
849 driver = face->driver;
851 /* when the flag NO_RECURSE is set, we disable hinting and scaling */
852 if ( load_flags & FT_LOAD_NO_RECURSE )
854 /* disable scaling, hinting, and transformation */
855 load_flags |= FT_LOAD_NO_SCALE |
857 FT_LOAD_IGNORE_TRANSFORM;
859 /* disable bitmap rendering */
860 load_flags &= ~FT_LOAD_RENDER;
863 /* do we need to load the glyph through the auto-hinter? */
864 library = driver->root.library;
865 hinter = library->auto_hinter;
868 !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) &&
869 FT_DRIVER_IS_SCALABLE( driver ) &&
870 FT_DRIVER_USES_OUTLINES( driver ) );
873 if ( FT_DRIVER_HAS_HINTER( driver ) &&
874 !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
880 FT_AutoHinter_Interface* hinting;
883 hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
885 error = hinting->load_glyph( (FT_AutoHinter)hinter,
887 glyph_index, load_flags );
890 error = driver->clazz->load_glyph( slot,
897 /* compute the advance */
898 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
901 slot->advance.y = slot->metrics.vertAdvance;
905 slot->advance.x = slot->metrics.horiAdvance;
909 /* compute the linear advance in 16.16 pixels */
910 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 )
912 FT_UInt EM = face->units_per_EM;
913 FT_Size_Metrics* metrics = &face->size->metrics;
915 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
916 (FT_Long)metrics->x_ppem << 16, EM );
918 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
919 (FT_Long)metrics->y_ppem << 16, EM );
922 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
924 FT_Face_Internal internal = face->internal;
927 /* now, transform the glyph image if needed */
928 if ( internal->transform_flags )
931 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
935 error = renderer->clazz->transform_glyph(
937 &internal->transform_matrix,
938 &internal->transform_delta );
939 /* transform advance */
940 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
944 /* do we need to render the image now? */
946 slot->format != ft_glyph_format_bitmap &&
947 slot->format != ft_glyph_format_composite &&
948 load_flags & FT_LOAD_RENDER )
950 error = FT_Render_Glyph( slot,
951 ( load_flags & FT_LOAD_MONOCHROME )
952 ? ft_render_mode_mono
953 : ft_render_mode_normal );
961 /* documentation is in freetype.h */
963 FT_EXPORT_DEF( FT_Error )
964 FT_Load_Char( FT_Face face,
972 return FT_Err_Invalid_Face_Handle;
974 glyph_index = (FT_UInt)char_code;
976 glyph_index = FT_Get_Char_Index( face, char_code );
978 return FT_Load_Glyph( face, glyph_index, load_flags );
982 /* destructor for sizes list */
984 destroy_size( FT_Memory memory,
988 /* finalize client-specific data */
989 if ( size->generic.finalizer )
990 size->generic.finalizer( size );
992 /* finalize format-specific stuff */
993 if ( driver->clazz->done_size )
994 driver->clazz->done_size( size );
996 FREE( size->internal );
1001 /* destructor for faces list */
1003 destroy_face( FT_Memory memory,
1007 FT_Driver_Class* clazz = driver->clazz;
1010 /* discard auto-hinting data */
1011 if ( face->autohint.finalizer )
1012 face->autohint.finalizer( face->autohint.data );
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 );
1019 /* Discard all sizes for this face */
1020 FT_List_Finalize( &face->sizes_list,
1021 (FT_List_Destructor)destroy_size,
1026 /* Now discard client data */
1027 if ( face->generic.finalizer )
1028 face->generic.finalizer( face );
1030 /* finalize format-specific stuff */
1031 if ( clazz->done_face )
1032 clazz->done_face( face );
1034 /* close the stream for this face if needed */
1037 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
1040 if ( face->internal )
1042 FREE( face->internal->postscript_name );
1043 FREE( face->internal );
1050 Destroy_Driver( FT_Driver driver )
1052 FT_List_Finalize( &driver->faces_list,
1053 (FT_List_Destructor)destroy_face,
1054 driver->root.memory,
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 );
1063 /*************************************************************************/
1069 /* This function does some work for FT_Open_Face(). */
1072 open_face( FT_Driver driver,
1076 FT_Parameter* params,
1080 FT_Driver_Class* clazz;
1083 FT_Face_Internal internal;
1086 clazz = driver->clazz;
1087 memory = driver->root.memory;
1089 /* allocate the face object and perform basic initialization */
1090 if ( ALLOC( face, clazz->face_object_size ) )
1093 if ( ALLOC( internal, sizeof ( *internal ) ) )
1096 face->internal = internal;
1098 face->driver = driver;
1099 face->memory = memory;
1100 face->stream = stream;
1102 error = clazz->init_face( stream,
1115 clazz->done_face( face );
1116 FREE( face->internal );
1125 /* there's a Mac-specific extended implementation of FT_New_Face() */
1126 /* in src/mac/ftmac.c */
1130 /* documentation is in freetype.h */
1132 FT_EXPORT_DEF( FT_Error )
1133 FT_New_Face( FT_Library library,
1134 const char* pathname,
1141 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1143 return FT_Err_Invalid_Argument;
1145 args.flags = ft_open_pathname;
1146 args.pathname = (char*)pathname;
1148 return FT_Open_Face( library, &args, face_index, aface );
1151 #endif /* !macintosh */
1154 /* documentation is in freetype.h */
1156 FT_EXPORT_DEF( FT_Error )
1157 FT_New_Memory_Face( FT_Library library,
1158 const FT_Byte* file_base,
1166 /* test for valid `library' and `face' delayed to FT_Open_Face() */
1168 return FT_Err_Invalid_Argument;
1170 args.flags = ft_open_memory;
1171 args.memory_base = file_base;
1172 args.memory_size = file_size;
1174 return FT_Open_Face( library, &args, face_index, aface );
1178 /* documentation is in freetype.h */
1180 FT_EXPORT_DEF( FT_Error )
1181 FT_Open_Face( FT_Library library,
1191 FT_ListNode node = 0;
1192 FT_Bool external_stream;
1195 /* test for valid `library' delayed to */
1196 /* ft_new_input_stream() */
1198 if ( !aface || !args )
1199 return FT_Err_Invalid_Argument;
1203 external_stream = FT_BOOL( ( args->flags & ft_open_stream ) &&
1206 /* create input stream */
1207 error = ft_new_input_stream( library, args, &stream );
1211 memory = library->memory;
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 )
1217 driver = FT_DRIVER( args->driver );
1219 /* not all modules are drivers, so check... */
1220 if ( FT_MODULE_IS_DRIVER( driver ) )
1222 FT_Int num_params = 0;
1223 FT_Parameter* params = 0;
1226 if ( args->flags & ft_open_params )
1228 num_params = args->num_params;
1229 params = args->params;
1232 error = open_face( driver, stream, face_index,
1233 num_params, params, &face );
1238 error = FT_Err_Invalid_Handle;
1240 ft_done_stream( &stream, external_stream );
1245 /* check each font driver for an appropriate format */
1246 FT_Module* cur = library->modules;
1247 FT_Module* limit = cur + library->num_modules;
1250 for ( ; cur < limit; cur++ )
1252 /* not all modules are font drivers, so check... */
1253 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
1255 FT_Int num_params = 0;
1256 FT_Parameter* params = 0;
1259 driver = FT_DRIVER( cur[0] );
1261 if ( args->flags & ft_open_params )
1263 num_params = args->num_params;
1264 params = args->params;
1267 error = open_face( driver, stream, face_index,
1268 num_params, params, &face );
1272 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
1277 /* no driver is able to handle this format */
1278 error = FT_Err_Unknown_File_Format;
1281 ft_done_stream( &stream, external_stream );
1286 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
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;
1292 /* add the face object to its driver's list */
1293 if ( ALLOC( node, sizeof ( *node ) ) )
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 );
1301 /* now allocate a glyph slot object for the face */
1306 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
1308 error = FT_New_GlyphSlot( face, &slot );
1315 /* finally, allocate a size object for the face */
1320 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1322 error = FT_New_Size( face, &size );
1329 /* initialize internal face data */
1331 FT_Face_Internal internal = face->internal;
1334 internal->transform_matrix.xx = 0x10000L;
1335 internal->transform_matrix.xy = 0;
1336 internal->transform_matrix.yx = 0;
1337 internal->transform_matrix.yy = 0x10000L;
1339 internal->transform_delta.x = 0;
1340 internal->transform_delta.y = 0;
1347 FT_Done_Face( face );
1350 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
1356 /* documentation is in freetype.h */
1358 FT_EXPORT_DEF( FT_Error )
1359 FT_Attach_File( FT_Face face,
1360 const char* filepathname )
1365 /* test for valid `face' delayed to FT_Attach_Stream() */
1367 if ( !filepathname )
1368 return FT_Err_Invalid_Argument;
1370 open.flags = ft_open_pathname;
1371 open.pathname = (char*)filepathname;
1373 return FT_Attach_Stream( face, &open );
1377 /* documentation is in freetype.h */
1379 FT_EXPORT_DEF( FT_Error )
1380 FT_Attach_Stream( FT_Face face,
1381 FT_Open_Args* parameters )
1387 FT_Driver_Class* clazz;
1390 /* test for valid `parameters' delayed to ft_new_input_stream() */
1393 return FT_Err_Invalid_Face_Handle;
1395 driver = face->driver;
1397 return FT_Err_Invalid_Driver_Handle;
1399 error = ft_new_input_stream( driver->root.library, parameters, &stream );
1403 /* we implement FT_Attach_Stream in each driver through the */
1404 /* `attach_file' interface */
1406 error = FT_Err_Unimplemented_Feature;
1407 clazz = driver->clazz;
1408 if ( clazz->attach_file )
1409 error = clazz->attach_file( face, stream );
1411 /* close the attached stream */
1412 ft_done_stream( &stream,
1413 (FT_Bool)( parameters->stream &&
1414 ( parameters->flags & ft_open_stream ) ) );
1421 /* documentation is in freetype.h */
1423 FT_EXPORT_DEF( FT_Error )
1424 FT_Done_Face( FT_Face face )
1432 error = FT_Err_Invalid_Face_Handle;
1433 if ( face && face->driver )
1435 driver = face->driver;
1436 memory = driver->root.memory;
1438 /* find face in driver's list */
1439 node = FT_List_Find( &driver->faces_list, face );
1442 /* remove face object from the driver's list */
1443 FT_List_Remove( &driver->faces_list, node );
1446 /* now destroy the object proper */
1447 destroy_face( memory, face, driver );
1455 /* documentation is in ftobjs.h */
1457 FT_EXPORT_DEF( FT_Error )
1458 FT_New_Size( FT_Face face,
1464 FT_Driver_Class* clazz;
1467 FT_ListNode node = 0;
1471 return FT_Err_Invalid_Face_Handle;
1474 return FT_Err_Invalid_Size_Handle;
1476 if ( !face->driver )
1477 return FT_Err_Invalid_Driver_Handle;
1481 driver = face->driver;
1482 clazz = driver->clazz;
1483 memory = face->memory;
1485 /* Allocate new size object and perform basic initialisation */
1486 if ( ALLOC( size, clazz->size_object_size ) ||
1487 ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
1492 /* for now, do not use any internal fields in size objects */
1495 if ( clazz->init_size )
1496 error = clazz->init_size( size );
1498 /* in case of success, add to the face's list */
1503 FT_List_Add( &face->sizes_list, node );
1517 /* documentation is in ftobjs.h */
1519 FT_EXPORT_DEF( FT_Error )
1520 FT_Done_Size( FT_Size size )
1530 return FT_Err_Invalid_Size_Handle;
1534 return FT_Err_Invalid_Face_Handle;
1536 driver = face->driver;
1538 return FT_Err_Invalid_Driver_Handle;
1540 memory = driver->root.memory;
1543 node = FT_List_Find( &face->sizes_list, size );
1546 FT_List_Remove( &face->sizes_list, node );
1549 if ( face->size == size )
1552 if ( face->sizes_list.head )
1553 face->size = (FT_Size)(face->sizes_list.head->data);
1556 destroy_size( memory, size, driver );
1559 error = FT_Err_Invalid_Size_Handle;
1566 ft_recompute_scaled_metrics( FT_Face face,
1567 FT_Size_Metrics* metrics )
1569 /* Compute root ascender, descender, test height, and max_advance */
1571 metrics->ascender = ( FT_MulFix( face->ascender,
1572 metrics->y_scale ) + 32 ) & -64;
1574 metrics->descender = ( FT_MulFix( face->descender,
1575 metrics->y_scale ) + 32 ) & -64;
1577 metrics->height = ( FT_MulFix( face->height,
1578 metrics->y_scale ) + 32 ) & -64;
1580 metrics->max_advance = ( FT_MulFix( face->max_advance_width,
1581 metrics->x_scale ) + 32 ) & -64;
1585 /* documentation is in freetype.h */
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 )
1594 FT_Error error = FT_Err_Ok;
1596 FT_Driver_Class* clazz;
1597 FT_Size_Metrics* metrics;
1598 FT_Long dim_x, dim_y;
1601 if ( !face || !face->size || !face->driver )
1602 return FT_Err_Invalid_Face_Handle;
1604 driver = face->driver;
1605 metrics = &face->size->metrics;
1608 char_width = char_height;
1610 else if ( !char_height )
1611 char_height = char_width;
1613 if ( !horz_resolution )
1614 horz_resolution = 72;
1616 if ( !vert_resolution )
1617 vert_resolution = 72;
1619 driver = face->driver;
1620 clazz = driver->clazz;
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;
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;
1632 metrics->x_ppem = (FT_UShort)( dim_x >> 6 );
1633 metrics->y_ppem = (FT_UShort)( dim_y >> 6 );
1635 metrics->x_scale = 0x10000L;
1636 metrics->y_scale = 0x10000L;
1638 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1640 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1641 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
1643 ft_recompute_scaled_metrics( face, metrics );
1646 if ( clazz->set_char_sizes )
1647 error = clazz->set_char_sizes( face->size,
1656 /* documentation is in freetype.h */
1658 FT_EXPORT_DEF( FT_Error )
1659 FT_Set_Pixel_Sizes( FT_Face face,
1660 FT_UInt pixel_width,
1661 FT_UInt pixel_height )
1663 FT_Error error = FT_Err_Ok;
1665 FT_Driver_Class* clazz;
1666 FT_Size_Metrics* metrics = &face->size->metrics;
1669 if ( !face || !face->size || !face->driver )
1670 return FT_Err_Invalid_Face_Handle;
1672 driver = face->driver;
1673 clazz = driver->clazz;
1675 /* default processing -- this can be overridden by the driver */
1676 if ( pixel_width == 0 )
1677 pixel_width = pixel_height;
1679 else if ( pixel_height == 0 )
1680 pixel_height = pixel_width;
1682 if ( pixel_width < 1 )
1684 if ( pixel_height < 1 )
1687 metrics->x_ppem = (FT_UShort)pixel_width;
1688 metrics->y_ppem = (FT_UShort)pixel_height;
1690 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1692 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
1693 face->units_per_EM );
1695 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
1696 face->units_per_EM );
1698 ft_recompute_scaled_metrics( face, metrics );
1701 if ( clazz->set_pixel_sizes )
1702 error = clazz->set_pixel_sizes( face->size,
1709 /* documentation is in freetype.h */
1711 FT_EXPORT_DEF( FT_Error )
1712 FT_Get_Kerning( FT_Face face,
1714 FT_UInt right_glyph,
1716 FT_Vector *akerning )
1718 FT_Error error = FT_Err_Ok;
1723 return FT_Err_Invalid_Face_Handle;
1726 return FT_Err_Invalid_Argument;
1728 driver = face->driver;
1733 if ( driver->clazz->get_kerning )
1735 error = driver->clazz->get_kerning( face,
1741 if ( kern_mode != ft_kerning_unscaled )
1743 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
1744 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
1746 if ( kern_mode != ft_kerning_unfitted )
1748 akerning->x = ( akerning->x + 32 ) & -64;
1749 akerning->y = ( akerning->y + 32 ) & -64;
1759 /* documentation is in freetype.h */
1761 FT_EXPORT_DEF( FT_Error )
1762 FT_Select_Charmap( FT_Face face,
1763 FT_Encoding encoding )
1770 return FT_Err_Invalid_Face_Handle;
1772 cur = face->charmaps;
1774 return FT_Err_Invalid_CharMap_Handle;
1776 limit = cur + face->num_charmaps;
1778 for ( ; cur < limit; cur++ )
1780 if ( cur[0]->encoding == encoding )
1782 face->charmap = cur[0];
1787 return FT_Err_Invalid_Argument;
1791 /* documentation is in freetype.h */
1793 FT_EXPORT_DEF( FT_Error )
1794 FT_Set_Charmap( FT_Face face,
1795 FT_CharMap charmap )
1802 return FT_Err_Invalid_Face_Handle;
1804 cur = face->charmaps;
1806 return FT_Err_Invalid_CharMap_Handle;
1808 limit = cur + face->num_charmaps;
1810 for ( ; cur < limit; cur++ )
1812 if ( cur[0] == charmap )
1814 face->charmap = cur[0];
1818 return FT_Err_Invalid_Argument;
1822 /* documentation is in freetype.h */
1824 FT_EXPORT_DEF( FT_UInt )
1825 FT_Get_Char_Index( FT_Face face,
1833 if ( face && face->charmap )
1835 driver = face->driver;
1836 result = driver->clazz->get_char_index( face->charmap, charcode );
1842 /* documentation is in freetype.h */
1844 FT_EXPORT_DEF( FT_UInt )
1845 FT_Get_Name_Index( FT_Face face,
1846 FT_String* glyph_name )
1851 if ( face && FT_HAS_GLYPH_NAMES( face ) )
1853 /* now, lookup for glyph name */
1854 FT_Driver driver = face->driver;
1855 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1858 if ( clazz->get_interface )
1860 FT_Name_Index_Requester requester;
1863 requester = (FT_Name_Index_Requester)clazz->get_interface(
1864 FT_MODULE( driver ), "name_index" );
1866 result = requester( face, glyph_name );
1873 /* documentation is in freetype.h */
1875 FT_EXPORT_DEF( FT_Error )
1876 FT_Get_Glyph_Name( FT_Face face,
1877 FT_UInt glyph_index,
1879 FT_UInt buffer_max )
1881 FT_Error error = FT_Err_Invalid_Argument;
1884 /* clean up buffer */
1885 if ( buffer && buffer_max > 0 )
1886 ((FT_Byte*)buffer)[0] = 0;
1889 glyph_index < (FT_UInt)face->num_glyphs &&
1890 FT_HAS_GLYPH_NAMES( face ) )
1892 /* now, lookup for glyph name */
1893 FT_Driver driver = face->driver;
1894 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1897 if ( clazz->get_interface )
1899 FT_Glyph_Name_Requester requester;
1902 requester = (FT_Glyph_Name_Requester)clazz->get_interface(
1903 FT_MODULE( driver ), "glyph_name" );
1905 error = requester( face, glyph_index, buffer, buffer_max );
1913 /* documentation is in freetype.h */
1915 FT_EXPORT_DEF( const char* )
1916 FT_Get_Postscript_Name( FT_Face face )
1918 const char* result = NULL;
1923 result = face->internal->postscript_name;
1926 /* now, lookup for glyph name */
1927 FT_Driver driver = face->driver;
1928 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1930 if ( clazz->get_interface )
1932 FT_PSName_Requester requester;
1934 requester = (FT_PSName_Requester)clazz->get_interface(
1935 FT_MODULE( driver ), "postscript_name" );
1937 result = requester( face );
1945 /* documentation is in tttables.h */
1947 FT_EXPORT_DEF( void* )
1948 FT_Get_Sfnt_Table( FT_Face face,
1952 FT_Get_Sfnt_Table_Func func;
1956 if ( !face || !FT_IS_SFNT( face ) )
1959 driver = face->driver;
1960 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
1961 FT_MODULE( driver ), "get_sfnt" );
1963 table = func( face, tag );
1970 FT_EXPORT_DEF( FT_Error )
1971 FT_Activate_Size( FT_Size size )
1977 return FT_Err_Bad_Argument;
1980 if ( face == NULL || face->driver == NULL )
1981 return FT_Err_Bad_Argument;
1983 /* we don't need anything more complex than that; all size objects */
1984 /* are already listed by the face */
1991 /*************************************************************************/
1992 /*************************************************************************/
1993 /*************************************************************************/
1996 /**** R E N D E R E R S ****/
1999 /*************************************************************************/
2000 /*************************************************************************/
2001 /*************************************************************************/
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,
2010 FT_Renderer result = 0;
2016 cur = library->renderers.head;
2021 cur = (*node)->next;
2027 FT_Renderer renderer = FT_RENDERER( cur->data );
2030 if ( renderer->glyph_format == format )
2047 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
2049 FT_Face face = slot->face;
2050 FT_Library library = FT_FACE_LIBRARY( face );
2051 FT_Renderer result = library->cur_renderer;
2054 if ( !result || result->glyph_format != slot->format )
2055 result = FT_Lookup_Renderer( library, slot->format, 0 );
2062 ft_set_current_renderer( FT_Library library )
2064 FT_Renderer renderer;
2067 renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
2068 library->cur_renderer = renderer;
2073 ft_add_renderer( FT_Module module )
2075 FT_Library library = module->library;
2076 FT_Memory memory = library->memory;
2081 if ( ALLOC( node, sizeof ( *node ) ) )
2085 FT_Renderer render = FT_RENDERER( module );
2086 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2089 render->clazz = clazz;
2090 render->glyph_format = clazz->glyph_format;
2092 /* allocate raster object if needed */
2093 if ( clazz->glyph_format == ft_glyph_format_outline &&
2094 clazz->raster_class->raster_new )
2096 error = clazz->raster_class->raster_new( memory, &render->raster );
2100 render->raster_render = clazz->raster_class->raster_render;
2101 render->render = clazz->render_glyph;
2105 node->data = module;
2106 FT_List_Add( &library->renderers, node );
2108 ft_set_current_renderer( library );
2121 ft_remove_renderer( FT_Module module )
2123 FT_Library library = module->library;
2124 FT_Memory memory = library->memory;
2128 node = FT_List_Find( &library->renderers, module );
2131 FT_Renderer render = FT_RENDERER( module );
2134 /* release raster object, if any */
2135 if ( render->raster )
2136 render->clazz->raster_class->raster_done( render->raster );
2138 /* remove from list */
2139 FT_List_Remove( &library->renderers, node );
2142 ft_set_current_renderer( library );
2147 /* documentation is in ftrender.h */
2149 FT_EXPORT_DEF( FT_Renderer )
2150 FT_Get_Renderer( FT_Library library,
2151 FT_Glyph_Format format )
2153 /* test for valid `library' delayed to FT_Lookup_Renderer() */
2155 return FT_Lookup_Renderer( library, format, 0 );
2159 /* documentation is in ftrender.h */
2161 FT_EXPORT_DEF( FT_Error )
2162 FT_Set_Renderer( FT_Library library,
2163 FT_Renderer renderer,
2165 FT_Parameter* parameters )
2168 FT_Error error = FT_Err_Ok;
2172 return FT_Err_Invalid_Library_Handle;
2175 return FT_Err_Invalid_Argument;
2177 node = FT_List_Find( &library->renderers, renderer );
2180 error = FT_Err_Invalid_Argument;
2184 FT_List_Up( &library->renderers, node );
2186 if ( renderer->glyph_format == ft_glyph_format_outline )
2187 library->cur_renderer = renderer;
2189 if ( num_params > 0 )
2191 FTRenderer_setMode set_mode = renderer->clazz->set_mode;
2194 for ( ; num_params > 0; num_params-- )
2196 error = set_mode( renderer, parameters->tag, parameters->data );
2207 FT_EXPORT_DEF( FT_Error )
2208 FT_Render_Glyph_Internal( FT_Library library,
2210 FT_UInt render_mode )
2212 FT_Error error = FT_Err_Ok;
2213 FT_Renderer renderer;
2216 /* if it is already a bitmap, no need to do anything */
2217 switch ( slot->format )
2219 case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
2224 FT_ListNode node = 0;
2228 /* small shortcut for the very common case */
2229 if ( slot->format == ft_glyph_format_outline )
2231 renderer = library->cur_renderer;
2232 node = library->renderers.head;
2235 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2237 error = FT_Err_Unimplemented_Feature;
2240 error = renderer->render( renderer, slot, render_mode, 0 );
2242 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
2245 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
2246 /* is unsupported by the current renderer for this glyph image */
2249 /* now, look for another renderer that supports the same */
2251 renderer = FT_Lookup_Renderer( library, slot->format, &node );
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 );
2266 /* documentation is in freetype.h */
2268 FT_EXPORT_DEF( FT_Error )
2269 FT_Render_Glyph( FT_GlyphSlot slot,
2270 FT_UInt render_mode )
2276 return FT_Err_Invalid_Argument;
2278 library = FT_FACE_LIBRARY( slot->face );
2280 return FT_Render_Glyph_Internal( library, slot, render_mode );
2284 /*************************************************************************/
2285 /*************************************************************************/
2286 /*************************************************************************/
2289 /**** M O D U L E S ****/
2292 /*************************************************************************/
2293 /*************************************************************************/
2294 /*************************************************************************/
2297 /*************************************************************************/
2300 /* Destroy_Module */
2303 /* Destroys a given module object. For drivers, this also destroys */
2304 /* all child faces. */
2307 /* module :: A handle to the target driver object. */
2310 /* The driver _must_ be LOCKED! */
2313 Destroy_Module( FT_Module module )
2315 FT_Memory memory = module->memory;
2316 FT_Module_Class* clazz = module->clazz;
2317 FT_Library library = module->library;
2320 /* finalize client-data - before anything else */
2321 if ( module->generic.finalizer )
2322 module->generic.finalizer( module );
2324 if ( library && library->auto_hinter == module )
2325 library->auto_hinter = 0;
2327 /* if the module is a renderer */
2328 if ( FT_MODULE_IS_RENDERER( module ) )
2329 ft_remove_renderer( module );
2331 /* if the module is a font driver, add some steps */
2332 if ( FT_MODULE_IS_DRIVER( module ) )
2333 Destroy_Driver( FT_DRIVER( module ) );
2335 /* finalize the module object */
2336 if ( clazz->module_done )
2337 clazz->module_done( module );
2344 /* documentation is in ftmodule.h */
2346 FT_EXPORT_DEF( FT_Error )
2347 FT_Add_Module( FT_Library library,
2348 const FT_Module_Class* clazz )
2356 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
2360 return FT_Err_Invalid_Library_Handle;
2363 return FT_Err_Invalid_Argument;
2365 /* check freetype version */
2366 if ( clazz->module_requires > FREETYPE_VER_FIXED )
2367 return FT_Err_Invalid_Version;
2369 /* look for a module with the same name in the library's table */
2370 for ( nn = 0; nn < library->num_modules; nn++ )
2372 module = library->modules[nn];
2373 if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
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;
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 );
2386 memory = library->memory;
2389 if ( library->num_modules >= FT_MAX_MODULES )
2391 error = FT_Err_Too_Many_Drivers;
2395 /* allocate module object */
2396 if ( ALLOC( module,clazz->module_size ) )
2399 /* base initialization */
2400 module->library = library;
2401 module->memory = memory;
2402 module->clazz = (FT_Module_Class*)clazz;
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 ) )
2408 /* add to the renderers list */
2409 error = ft_add_renderer( module );
2414 /* is the module a auto-hinter? */
2415 if ( FT_MODULE_IS_HINTER( module ) )
2416 library->auto_hinter = module;
2418 /* if the module is a font driver */
2419 if ( FT_MODULE_IS_DRIVER( module ) )
2421 /* allocate glyph loader if needed */
2422 FT_Driver driver = FT_DRIVER( module );
2425 driver->clazz = (FT_Driver_Class*)module->clazz;
2426 if ( FT_DRIVER_USES_OUTLINES( driver ) )
2428 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
2434 if ( clazz->module_init )
2436 error = clazz->module_init( module );
2441 /* add module to the library's table */
2442 library->modules[library->num_modules++] = module;
2448 if ( FT_MODULE_IS_DRIVER( module ) )
2450 FT_Driver driver = FT_DRIVER( module );
2453 if ( FT_DRIVER_USES_OUTLINES( driver ) )
2454 FT_GlyphLoader_Done( driver->glyph_loader );
2457 if ( FT_MODULE_IS_RENDERER( module ) )
2459 FT_Renderer renderer = FT_RENDERER( module );
2462 if ( renderer->raster )
2463 renderer->clazz->raster_class->raster_done( renderer->raster );
2471 /* documentation is in ftmodule.h */
2473 FT_EXPORT_DEF( FT_Module )
2474 FT_Get_Module( FT_Library library,
2475 const char* module_name )
2477 FT_Module result = 0;
2482 if ( !library || !module_name )
2485 cur = library->modules;
2486 limit = cur + library->num_modules;
2488 for ( ; cur < limit; cur++ )
2489 if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
2499 /* documentation is in ftobjs.h */
2501 FT_BASE_DEF( const void* )
2502 FT_Get_Module_Interface( FT_Library library,
2503 const char* mod_name )
2508 /* test for valid `library' delayed to FT_Get_Module() */
2510 module = FT_Get_Module( library, mod_name );
2512 return module ? module->clazz->module_interface : 0;
2516 /* documentation is in ftmodule.h */
2518 FT_EXPORT_DEF( FT_Error )
2519 FT_Remove_Module( FT_Library library,
2522 /* try to find the module from the table, then remove it from there */
2525 return FT_Err_Invalid_Library_Handle;
2529 FT_Module* cur = library->modules;
2530 FT_Module* limit = cur + library->num_modules;
2533 for ( ; cur < limit; cur++ )
2535 if ( cur[0] == module )
2537 /* remove it from the table */
2538 library->num_modules--;
2540 while ( cur < limit )
2547 /* destroy the module */
2548 Destroy_Module( module );
2554 return FT_Err_Invalid_Driver_Handle;
2558 /*************************************************************************/
2559 /*************************************************************************/
2560 /*************************************************************************/
2563 /**** L I B R A R Y ****/
2566 /*************************************************************************/
2567 /*************************************************************************/
2568 /*************************************************************************/
2571 /* documentation is in ftmodule.h */
2573 FT_EXPORT_DEF( FT_Error )
2574 FT_New_Library( FT_Memory memory,
2575 FT_Library *alibrary )
2577 FT_Library library = 0;
2582 return FT_Err_Invalid_Argument;
2584 /* first of all, allocate the library object */
2585 if ( ALLOC( library, sizeof ( *library ) ) )
2588 library->memory = memory;
2590 /* allocate the render pool */
2591 library->raster_pool_size = FT_RENDER_POOL_SIZE;
2592 if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
2596 *alibrary = library;
2606 /* documentation is in ftmodule.h */
2608 FT_EXPORT_DEF( FT_Error )
2609 FT_Done_Library( FT_Library library )
2616 return FT_Err_Invalid_Library_Handle;
2618 memory = library->memory;
2620 /* Discard client-data */
2621 if ( library->generic.finalizer )
2622 library->generic.finalizer( library );
2624 /* Close all modules in the library */
2625 for ( n = 0; n < library->num_modules; n++ )
2627 FT_Module module = library->modules[n];
2632 Destroy_Module( module );
2633 library->modules[n] = 0;
2637 /* Destroy raster objects */
2638 FREE( library->raster_pool );
2639 library->raster_pool_size = 0;
2646 /* documentation is in ftmodule.h */
2648 FT_EXPORT_DEF( void )
2649 FT_Set_Debug_Hook( FT_Library library,
2651 FT_DebugHook_Func debug_hook )
2653 if ( library && debug_hook &&
2655 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
2656 library->debug_hooks[hook_index] = debug_hook;