1 /***************************************************************************/
5 /* The FreeType private base classes (body). */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
11 /* This file is part of the FreeType project, and may only be used, */
12 /* modified, and distributed under the terms of the FreeType project */
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
14 /* this file you indicate that you have read the license and */
15 /* understand and accept it fully. */
17 /***************************************************************************/
23 #include FT_INTERNAL_VALIDATE_H
24 #include FT_INTERNAL_OBJECTS_H
25 #include FT_INTERNAL_DEBUG_H
26 #include FT_INTERNAL_RFORK_H
27 #include FT_INTERNAL_STREAM_H
28 #include FT_INTERNAL_SFNT_H /* for SFNT_Load_Table_Func */
29 #include FT_TRUETYPE_TABLES_H
30 #include FT_TRUETYPE_TAGS_H
31 #include FT_TRUETYPE_IDS_H
34 #include FT_SERVICE_SFNT_H
35 #include FT_SERVICE_POSTSCRIPT_NAME_H
36 #include FT_SERVICE_GLYPH_DICT_H
37 #include FT_SERVICE_TT_CMAP_H
38 #include FT_SERVICE_KERNING_H
39 #include FT_SERVICE_TRUETYPE_ENGINE_H
41 #ifdef FT_CONFIG_OPTION_MAC_FONTS
45 #define GRID_FIT_METRICS
48 FT_BASE_DEF( FT_Pointer
)
49 ft_service_list_lookup( FT_ServiceDesc service_descriptors
,
50 const char* service_id
)
52 FT_Pointer result
= NULL
;
53 FT_ServiceDesc desc
= service_descriptors
;
56 if ( desc
&& service_id
)
58 for ( ; desc
->serv_id
!= NULL
; desc
++ )
60 if ( ft_strcmp( desc
->serv_id
, service_id
) == 0 )
62 result
= (FT_Pointer
)desc
->serv_data
;
73 ft_validator_init( FT_Validator valid
,
76 FT_ValidationLevel level
)
81 valid
->error
= FT_Err_Ok
;
86 ft_validator_run( FT_Validator valid
)
88 /* This function doesn't work! None should call it. */
96 ft_validator_error( FT_Validator valid
,
99 /* since the cast below also disables the compiler's */
100 /* type check, we introduce a dummy variable, which */
101 /* will be optimized away */
102 volatile ft_jmp_buf
* jump_buffer
= &valid
->jump_buffer
;
105 valid
->error
= error
;
107 /* throw away volatileness; use `jump_buffer' or the */
108 /* compiler may warn about an unused local variable */
109 ft_longjmp( *(ft_jmp_buf
*) jump_buffer
, 1 );
113 /*************************************************************************/
114 /*************************************************************************/
115 /*************************************************************************/
118 /**** S T R E A M ****/
121 /*************************************************************************/
122 /*************************************************************************/
123 /*************************************************************************/
126 /* create a new input stream from an FT_Open_Args structure */
128 FT_BASE_DEF( FT_Error
)
129 FT_Stream_New( FT_Library library
,
130 const FT_Open_Args
* args
,
141 return FT_Err_Invalid_Library_Handle
;
144 return FT_Err_Invalid_Argument
;
146 memory
= library
->memory
;
148 if ( FT_NEW( stream
) )
151 stream
->memory
= memory
;
153 if ( args
->flags
& FT_OPEN_MEMORY
)
155 /* create a memory-based stream */
156 FT_Stream_OpenMemory( stream
,
157 (const FT_Byte
*)args
->memory_base
,
160 else if ( args
->flags
& FT_OPEN_PATHNAME
)
162 /* create a normal system stream */
163 error
= FT_Stream_Open( stream
, args
->pathname
);
164 stream
->pathname
.pointer
= args
->pathname
;
166 else if ( ( args
->flags
& FT_OPEN_STREAM
) && args
->stream
)
168 /* use an existing, user-provided stream */
170 /* in this case, we do not need to allocate a new stream object */
171 /* since the caller is responsible for closing it himself */
173 stream
= args
->stream
;
176 error
= FT_Err_Invalid_Argument
;
181 stream
->memory
= memory
; /* just to be certain */
191 FT_Stream_Free( FT_Stream stream
,
196 FT_Memory memory
= stream
->memory
;
199 FT_Stream_Close( stream
);
207 /*************************************************************************/
209 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
210 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
211 /* messages during execution. */
214 #define FT_COMPONENT trace_objs
217 /*************************************************************************/
218 /*************************************************************************/
219 /*************************************************************************/
222 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
225 /*************************************************************************/
226 /*************************************************************************/
227 /*************************************************************************/
231 ft_glyphslot_init( FT_GlyphSlot slot
)
233 FT_Driver driver
= slot
->face
->driver
;
234 FT_Driver_Class clazz
= driver
->clazz
;
235 FT_Memory memory
= driver
->root
.memory
;
236 FT_Error error
= FT_Err_Ok
;
237 FT_Slot_Internal internal
;
240 slot
->library
= driver
->root
.library
;
242 if ( FT_NEW( internal
) )
245 slot
->internal
= internal
;
247 if ( FT_DRIVER_USES_OUTLINES( driver
) )
248 error
= FT_GlyphLoader_New( memory
, &internal
->loader
);
250 if ( !error
&& clazz
->init_slot
)
251 error
= clazz
->init_slot( slot
);
259 ft_glyphslot_free_bitmap( FT_GlyphSlot slot
)
261 if ( slot
->internal
&& ( slot
->internal
->flags
& FT_GLYPH_OWN_BITMAP
) )
263 FT_Memory memory
= FT_FACE_MEMORY( slot
->face
);
266 FT_FREE( slot
->bitmap
.buffer
);
267 slot
->internal
->flags
&= ~FT_GLYPH_OWN_BITMAP
;
271 /* assume that the bitmap buffer was stolen or not */
272 /* allocated from the heap */
273 slot
->bitmap
.buffer
= NULL
;
279 ft_glyphslot_set_bitmap( FT_GlyphSlot slot
,
282 ft_glyphslot_free_bitmap( slot
);
284 slot
->bitmap
.buffer
= buffer
;
286 FT_ASSERT( (slot
->internal
->flags
& FT_GLYPH_OWN_BITMAP
) == 0 );
290 FT_BASE_DEF( FT_Error
)
291 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot
,
294 FT_Memory memory
= FT_FACE_MEMORY( slot
->face
);
298 if ( slot
->internal
->flags
& FT_GLYPH_OWN_BITMAP
)
299 FT_FREE( slot
->bitmap
.buffer
);
301 slot
->internal
->flags
|= FT_GLYPH_OWN_BITMAP
;
303 (void)FT_ALLOC( slot
->bitmap
.buffer
, size
);
309 ft_glyphslot_clear( FT_GlyphSlot slot
)
311 /* free bitmap if needed */
312 ft_glyphslot_free_bitmap( slot
);
314 /* clear all public fields in the glyph slot */
315 FT_ZERO( &slot
->metrics
);
316 FT_ZERO( &slot
->outline
);
318 slot
->bitmap
.width
= 0;
319 slot
->bitmap
.rows
= 0;
320 slot
->bitmap
.pitch
= 0;
321 slot
->bitmap
.pixel_mode
= 0;
322 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
324 slot
->bitmap_left
= 0;
325 slot
->bitmap_top
= 0;
326 slot
->num_subglyphs
= 0;
328 slot
->control_data
= 0;
329 slot
->control_len
= 0;
331 slot
->format
= FT_GLYPH_FORMAT_NONE
;
333 slot
->linearHoriAdvance
= 0;
334 slot
->linearVertAdvance
= 0;
341 ft_glyphslot_done( FT_GlyphSlot slot
)
343 FT_Driver driver
= slot
->face
->driver
;
344 FT_Driver_Class clazz
= driver
->clazz
;
345 FT_Memory memory
= driver
->root
.memory
;
348 if ( clazz
->done_slot
)
349 clazz
->done_slot( slot
);
351 /* free bitmap buffer if needed */
352 ft_glyphslot_free_bitmap( slot
);
354 /* slot->internal might be NULL in out-of-memory situations */
355 if ( slot
->internal
)
357 /* free glyph loader */
358 if ( FT_DRIVER_USES_OUTLINES( driver
) )
360 FT_GlyphLoader_Done( slot
->internal
->loader
);
361 slot
->internal
->loader
= 0;
364 FT_FREE( slot
->internal
);
369 /* documentation is in ftobjs.h */
371 FT_BASE_DEF( FT_Error
)
372 FT_New_GlyphSlot( FT_Face face
,
373 FT_GlyphSlot
*aslot
)
377 FT_Driver_Class clazz
;
382 if ( !face
|| !face
->driver
)
383 return FT_Err_Invalid_Argument
;
385 driver
= face
->driver
;
386 clazz
= driver
->clazz
;
387 memory
= driver
->root
.memory
;
389 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
390 if ( !FT_ALLOC( slot
, clazz
->slot_object_size
) )
394 error
= ft_glyphslot_init( slot
);
397 ft_glyphslot_done( slot
);
402 slot
->next
= face
->glyph
;
413 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error
));
418 /* documentation is in ftobjs.h */
421 FT_Done_GlyphSlot( FT_GlyphSlot slot
)
425 FT_Driver driver
= slot
->face
->driver
;
426 FT_Memory memory
= driver
->root
.memory
;
431 /* Remove slot from its parent face's list */
433 cur
= slot
->face
->glyph
;
440 slot
->face
->glyph
= cur
->next
;
442 prev
->next
= cur
->next
;
444 ft_glyphslot_done( slot
);
455 /* documentation is in freetype.h */
457 FT_EXPORT_DEF( void )
458 FT_Set_Transform( FT_Face face
,
462 FT_Face_Internal internal
;
468 internal
= face
->internal
;
470 internal
->transform_flags
= 0;
474 internal
->transform_matrix
.xx
= 0x10000L
;
475 internal
->transform_matrix
.xy
= 0;
476 internal
->transform_matrix
.yx
= 0;
477 internal
->transform_matrix
.yy
= 0x10000L
;
478 matrix
= &internal
->transform_matrix
;
481 internal
->transform_matrix
= *matrix
;
483 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
484 if ( ( matrix
->xy
| matrix
->yx
) ||
485 matrix
->xx
!= 0x10000L
||
486 matrix
->yy
!= 0x10000L
)
487 internal
->transform_flags
|= 1;
491 internal
->transform_delta
.x
= 0;
492 internal
->transform_delta
.y
= 0;
493 delta
= &internal
->transform_delta
;
496 internal
->transform_delta
= *delta
;
498 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
499 if ( delta
->x
| delta
->y
)
500 internal
->transform_flags
|= 2;
505 ft_lookup_glyph_renderer( FT_GlyphSlot slot
);
508 #ifdef GRID_FIT_METRICS
510 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot
,
513 FT_Glyph_Metrics
* metrics
= &slot
->metrics
;
514 FT_Pos right
, bottom
;
519 metrics
->horiBearingX
= FT_PIX_FLOOR( metrics
->horiBearingX
);
520 metrics
->horiBearingY
= FT_PIX_CEIL ( metrics
->horiBearingY
);
522 right
= FT_PIX_CEIL( metrics
->vertBearingX
+ metrics
->width
);
523 bottom
= FT_PIX_CEIL( metrics
->vertBearingY
+ metrics
->height
);
525 metrics
->vertBearingX
= FT_PIX_FLOOR( metrics
->vertBearingX
);
526 metrics
->vertBearingY
= FT_PIX_FLOOR( metrics
->vertBearingY
);
528 metrics
->width
= right
- metrics
->vertBearingX
;
529 metrics
->height
= bottom
- metrics
->vertBearingY
;
533 metrics
->vertBearingX
= FT_PIX_FLOOR( metrics
->vertBearingX
);
534 metrics
->vertBearingY
= FT_PIX_FLOOR( metrics
->vertBearingY
);
536 right
= FT_PIX_CEIL ( metrics
->horiBearingX
+ metrics
->width
);
537 bottom
= FT_PIX_FLOOR( metrics
->horiBearingY
- metrics
->height
);
539 metrics
->horiBearingX
= FT_PIX_FLOOR( metrics
->horiBearingX
);
540 metrics
->horiBearingY
= FT_PIX_CEIL ( metrics
->horiBearingY
);
542 metrics
->width
= right
- metrics
->horiBearingX
;
543 metrics
->height
= metrics
->horiBearingY
- bottom
;
546 metrics
->horiAdvance
= FT_PIX_ROUND( metrics
->horiAdvance
);
547 metrics
->vertAdvance
= FT_PIX_ROUND( metrics
->vertAdvance
);
549 #endif /* GRID_FIT_METRICS */
552 /* documentation is in freetype.h */
554 FT_EXPORT_DEF( FT_Error
)
555 FT_Load_Glyph( FT_Face face
,
557 FT_Int32 load_flags
)
563 FT_Bool autohint
= FALSE
;
567 if ( !face
|| !face
->size
|| !face
->glyph
)
568 return FT_Err_Invalid_Face_Handle
;
570 /* The validity test for `glyph_index' is performed by the */
574 ft_glyphslot_clear( slot
);
576 driver
= face
->driver
;
577 library
= driver
->root
.library
;
578 hinter
= library
->auto_hinter
;
580 /* resolve load flags dependencies */
582 if ( load_flags
& FT_LOAD_NO_RECURSE
)
583 load_flags
|= FT_LOAD_NO_SCALE
|
584 FT_LOAD_IGNORE_TRANSFORM
;
586 if ( load_flags
& FT_LOAD_NO_SCALE
)
588 load_flags
|= FT_LOAD_NO_HINTING
|
591 load_flags
&= ~FT_LOAD_RENDER
;
595 * Determine whether we need to auto-hint or not.
596 * The general rules are:
598 * - Do only auto-hinting if we have a hinter module, a scalable font
599 * format dealing with outlines, and no transforms except simple
600 * slants and/or rotations by integer multiples of 90 degrees.
602 * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
603 * have a native font hinter.
605 * - Otherwise, auto-hint for LIGHT hinting mode.
607 * - Exception: The font is `tricky' and requires the native hinter to
612 !( load_flags
& FT_LOAD_NO_HINTING
) &&
613 !( load_flags
& FT_LOAD_NO_AUTOHINT
) &&
614 FT_DRIVER_IS_SCALABLE( driver
) &&
615 FT_DRIVER_USES_OUTLINES( driver
) &&
616 !FT_IS_TRICKY( face
) &&
617 ( ( face
->internal
->transform_matrix
.yx
== 0 &&
618 face
->internal
->transform_matrix
.xx
!= 0 ) ||
619 ( face
->internal
->transform_matrix
.xx
== 0 &&
620 face
->internal
->transform_matrix
.yx
!= 0 ) ) )
622 if ( ( load_flags
& FT_LOAD_FORCE_AUTOHINT
) ||
623 !FT_DRIVER_HAS_HINTER( driver
) )
627 FT_Render_Mode mode
= FT_LOAD_TARGET_MODE( load_flags
);
630 if ( mode
== FT_RENDER_MODE_LIGHT
||
631 face
->internal
->ignore_unpatented_hinter
)
638 FT_AutoHinter_Service hinting
;
641 /* try to load embedded bitmaps first if available */
643 /* XXX: This is really a temporary hack that should disappear */
644 /* promptly with FreeType 2.1! */
646 if ( FT_HAS_FIXED_SIZES( face
) &&
647 ( load_flags
& FT_LOAD_NO_BITMAP
) == 0 )
649 error
= driver
->clazz
->load_glyph( slot
, face
->size
,
651 load_flags
| FT_LOAD_SBITS_ONLY
);
653 if ( !error
&& slot
->format
== FT_GLYPH_FORMAT_BITMAP
)
658 FT_Face_Internal internal
= face
->internal
;
659 FT_Int transform_flags
= internal
->transform_flags
;
662 /* since the auto-hinter calls FT_Load_Glyph by itself, */
663 /* make sure that glyphs aren't transformed */
664 internal
->transform_flags
= 0;
666 /* load auto-hinted outline */
667 hinting
= (FT_AutoHinter_Service
)hinter
->clazz
->module_interface
;
669 error
= hinting
->load_glyph( (FT_AutoHinter
)hinter
,
671 glyph_index
, load_flags
);
673 internal
->transform_flags
= transform_flags
;
678 error
= driver
->clazz
->load_glyph( slot
,
685 if ( slot
->format
== FT_GLYPH_FORMAT_OUTLINE
)
687 /* check that the loaded outline is correct */
688 error
= FT_Outline_Check( &slot
->outline
);
692 #ifdef GRID_FIT_METRICS
693 if ( !( load_flags
& FT_LOAD_NO_HINTING
) )
694 ft_glyphslot_grid_fit_metrics( slot
,
695 FT_BOOL( load_flags
& FT_LOAD_VERTICAL_LAYOUT
) );
701 /* compute the advance */
702 if ( load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
705 slot
->advance
.y
= slot
->metrics
.vertAdvance
;
709 slot
->advance
.x
= slot
->metrics
.horiAdvance
;
713 /* compute the linear advance in 16.16 pixels */
714 if ( ( load_flags
& FT_LOAD_LINEAR_DESIGN
) == 0 &&
715 ( FT_IS_SCALABLE( face
) ) )
717 FT_Size_Metrics
* metrics
= &face
->size
->metrics
;
721 slot
->linearHoriAdvance
= FT_MulDiv( slot
->linearHoriAdvance
,
722 metrics
->x_scale
, 64 );
724 slot
->linearVertAdvance
= FT_MulDiv( slot
->linearVertAdvance
,
725 metrics
->y_scale
, 64 );
728 if ( ( load_flags
& FT_LOAD_IGNORE_TRANSFORM
) == 0 )
730 FT_Face_Internal internal
= face
->internal
;
733 /* now, transform the glyph image if needed */
734 if ( internal
->transform_flags
)
737 FT_Renderer renderer
= ft_lookup_glyph_renderer( slot
);
741 error
= renderer
->clazz
->transform_glyph(
743 &internal
->transform_matrix
,
744 &internal
->transform_delta
);
745 else if ( slot
->format
== FT_GLYPH_FORMAT_OUTLINE
)
747 /* apply `standard' transformation if no renderer is available */
748 if ( &internal
->transform_matrix
)
749 FT_Outline_Transform( &slot
->outline
,
750 &internal
->transform_matrix
);
752 if ( &internal
->transform_delta
)
753 FT_Outline_Translate( &slot
->outline
,
754 internal
->transform_delta
.x
,
755 internal
->transform_delta
.y
);
758 /* transform advance */
759 FT_Vector_Transform( &slot
->advance
, &internal
->transform_matrix
);
763 FT_TRACE5(( " x advance: %d\n" , slot
->advance
.x
));
764 FT_TRACE5(( " y advance: %d\n" , slot
->advance
.y
));
766 FT_TRACE5(( " linear x advance: %d\n" , slot
->linearHoriAdvance
));
767 FT_TRACE5(( " linear y advance: %d\n" , slot
->linearVertAdvance
));
769 /* do we need to render the image now? */
771 slot
->format
!= FT_GLYPH_FORMAT_BITMAP
&&
772 slot
->format
!= FT_GLYPH_FORMAT_COMPOSITE
&&
773 load_flags
& FT_LOAD_RENDER
)
775 FT_Render_Mode mode
= FT_LOAD_TARGET_MODE( load_flags
);
778 if ( mode
== FT_RENDER_MODE_NORMAL
&&
779 (load_flags
& FT_LOAD_MONOCHROME
) )
780 mode
= FT_RENDER_MODE_MONO
;
782 error
= FT_Render_Glyph( slot
, mode
);
790 /* documentation is in freetype.h */
792 FT_EXPORT_DEF( FT_Error
)
793 FT_Load_Char( FT_Face face
,
795 FT_Int32 load_flags
)
801 return FT_Err_Invalid_Face_Handle
;
803 glyph_index
= (FT_UInt
)char_code
;
805 glyph_index
= FT_Get_Char_Index( face
, char_code
);
807 return FT_Load_Glyph( face
, glyph_index
, load_flags
);
811 /* destructor for sizes list */
813 destroy_size( FT_Memory memory
,
817 /* finalize client-specific data */
818 if ( size
->generic
.finalizer
)
819 size
->generic
.finalizer( size
);
821 /* finalize format-specific stuff */
822 if ( driver
->clazz
->done_size
)
823 driver
->clazz
->done_size( size
);
825 FT_FREE( size
->internal
);
831 ft_cmap_done_internal( FT_CMap cmap
);
835 destroy_charmaps( FT_Face face
,
844 for ( n
= 0; n
< face
->num_charmaps
; n
++ )
846 FT_CMap cmap
= FT_CMAP( face
->charmaps
[n
] );
849 ft_cmap_done_internal( cmap
);
851 face
->charmaps
[n
] = NULL
;
854 FT_FREE( face
->charmaps
);
855 face
->num_charmaps
= 0;
859 /* destructor for faces list */
861 destroy_face( FT_Memory memory
,
865 FT_Driver_Class clazz
= driver
->clazz
;
868 /* discard auto-hinting data */
869 if ( face
->autohint
.finalizer
)
870 face
->autohint
.finalizer( face
->autohint
.data
);
872 /* Discard glyph slots for this face. */
873 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
874 while ( face
->glyph
)
875 FT_Done_GlyphSlot( face
->glyph
);
877 /* discard all sizes for this face */
878 FT_List_Finalize( &face
->sizes_list
,
879 (FT_List_Destructor
)destroy_size
,
884 /* now discard client data */
885 if ( face
->generic
.finalizer
)
886 face
->generic
.finalizer( face
);
888 /* discard charmaps */
889 destroy_charmaps( face
, memory
);
891 /* finalize format-specific stuff */
892 if ( clazz
->done_face
)
893 clazz
->done_face( face
);
895 /* close the stream for this face if needed */
898 ( face
->face_flags
& FT_FACE_FLAG_EXTERNAL_STREAM
) != 0 );
903 if ( face
->internal
)
905 FT_FREE( face
->internal
);
912 Destroy_Driver( FT_Driver driver
)
914 FT_List_Finalize( &driver
->faces_list
,
915 (FT_List_Destructor
)destroy_face
,
919 /* check whether we need to drop the driver's glyph loader */
920 if ( FT_DRIVER_USES_OUTLINES( driver
) )
921 FT_GlyphLoader_Done( driver
->glyph_loader
);
925 /*************************************************************************/
928 /* find_unicode_charmap */
931 /* This function finds a Unicode charmap, if there is one. */
932 /* And if there is more than one, it tries to favour the more */
933 /* extensive one, i.e., one that supports UCS-4 against those which */
934 /* are limited to the BMP (said UCS-2 encoding.) */
936 /* This function is called from open_face() (just below), and also */
937 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
940 find_unicode_charmap( FT_Face face
)
946 /* caller should have already checked that `face' is valid */
949 first
= face
->charmaps
;
952 return FT_Err_Invalid_CharMap_Handle
;
955 * The original TrueType specification(s) only specified charmap
956 * formats that are capable of mapping 8 or 16 bit character codes to
959 * However, recent updates to the Apple and OpenType specifications
960 * introduced new formats that are capable of mapping 32-bit character
961 * codes as well. And these are already used on some fonts, mainly to
962 * map non-BMP Asian ideographs as defined in Unicode.
964 * For compatibility purposes, these fonts generally come with
965 * *several* Unicode charmaps:
967 * - One of them in the "old" 16-bit format, that cannot access
968 * all glyphs in the font.
970 * - Another one in the "new" 32-bit format, that can access all
973 * This function has been written to always favor a 32-bit charmap
974 * when found. Otherwise, a 16-bit one is returned when found.
977 /* Since the `interesting' table, with IDs (3,10), is normally the */
978 /* last one, we loop backwards. This loses with type1 fonts with */
979 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
980 /* chars (.01% ?), and this is the same about 99.99% of the time! */
982 cur
= first
+ face
->num_charmaps
; /* points after the last one */
984 for ( ; --cur
>= first
; )
986 if ( cur
[0]->encoding
== FT_ENCODING_UNICODE
)
988 /* XXX If some new encodings to represent UCS-4 are added, */
989 /* they should be added here. */
990 if ( ( cur
[0]->platform_id
== TT_PLATFORM_MICROSOFT
&&
991 cur
[0]->encoding_id
== TT_MS_ID_UCS_4
) ||
992 ( cur
[0]->platform_id
== TT_PLATFORM_APPLE_UNICODE
&&
993 cur
[0]->encoding_id
== TT_APPLE_ID_UNICODE_32
) )
995 face
->charmap
= cur
[0];
1001 /* We do not have any UCS-4 charmap. */
1002 /* Do the loop again and search for UCS-2 charmaps. */
1003 cur
= first
+ face
->num_charmaps
;
1005 for ( ; --cur
>= first
; )
1007 if ( cur
[0]->encoding
== FT_ENCODING_UNICODE
)
1009 face
->charmap
= cur
[0];
1014 return FT_Err_Invalid_CharMap_Handle
;
1018 /*************************************************************************/
1021 /* find_variant_selector_charmap */
1024 /* This function finds the variant selector charmap, if there is one. */
1025 /* There can only be one (platform=0, specific=5, format=14). */
1028 find_variant_selector_charmap( FT_Face face
)
1035 /* caller should have already checked that `face' is valid */
1038 first
= face
->charmaps
;
1043 end
= first
+ face
->num_charmaps
; /* points after the last one */
1045 for ( cur
= first
; cur
< end
; ++cur
)
1047 if ( cur
[0]->platform_id
== TT_PLATFORM_APPLE_UNICODE
&&
1048 cur
[0]->encoding_id
== TT_APPLE_ID_VARIANT_SELECTOR
&&
1049 FT_Get_CMap_Format( cur
[0] ) == 14 )
1057 /*************************************************************************/
1063 /* This function does some work for FT_Open_Face(). */
1066 open_face( FT_Driver driver
,
1070 FT_Parameter
* params
,
1074 FT_Driver_Class clazz
;
1076 FT_Error error
, error2
;
1077 FT_Face_Internal internal
= NULL
;
1080 clazz
= driver
->clazz
;
1081 memory
= driver
->root
.memory
;
1083 /* allocate the face object and perform basic initialization */
1084 if ( FT_ALLOC( face
, clazz
->face_object_size
) )
1087 if ( FT_NEW( internal
) )
1090 face
->internal
= internal
;
1092 face
->driver
= driver
;
1093 face
->memory
= memory
;
1094 face
->stream
= stream
;
1096 #ifdef FT_CONFIG_OPTION_INCREMENTAL
1101 face
->internal
->incremental_interface
= 0;
1102 for ( i
= 0; i
< num_params
&& !face
->internal
->incremental_interface
;
1104 if ( params
[i
].tag
== FT_PARAM_TAG_INCREMENTAL
)
1105 face
->internal
->incremental_interface
=
1106 (FT_Incremental_Interface
)params
[i
].data
;
1110 if ( clazz
->init_face
)
1111 error
= clazz
->init_face( stream
,
1119 /* select Unicode charmap by default */
1120 error2
= find_unicode_charmap( face
);
1122 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
1125 /* no error should happen, but we want to play safe */
1126 if ( error2
&& error2
!= FT_Err_Invalid_CharMap_Handle
)
1137 destroy_charmaps( face
, memory
);
1138 if ( clazz
->done_face
)
1139 clazz
->done_face( face
);
1140 FT_FREE( internal
);
1149 /* there's a Mac-specific extended implementation of FT_New_Face() */
1150 /* in src/base/ftmac.c */
1152 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
1154 /* documentation is in freetype.h */
1156 FT_EXPORT_DEF( FT_Error
)
1157 FT_New_Face( FT_Library library
,
1158 const char* pathname
,
1165 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1167 return FT_Err_Invalid_Argument
;
1169 args
.flags
= FT_OPEN_PATHNAME
;
1170 args
.pathname
= (char*)pathname
;
1173 return FT_Open_Face( library
, &args
, face_index
, aface
);
1176 #endif /* defined( FT_MACINTOSH ) && !defined( DARWIN_NO_CARBON ) */
1179 /* documentation is in freetype.h */
1181 FT_EXPORT_DEF( FT_Error
)
1182 FT_New_Memory_Face( FT_Library library
,
1183 const FT_Byte
* file_base
,
1191 /* test for valid `library' and `face' delayed to FT_Open_Face() */
1193 return FT_Err_Invalid_Argument
;
1195 args
.flags
= FT_OPEN_MEMORY
;
1196 args
.memory_base
= file_base
;
1197 args
.memory_size
= file_size
;
1200 return FT_Open_Face( library
, &args
, face_index
, aface
);
1204 #ifdef FT_CONFIG_OPTION_MAC_FONTS
1206 /* The behavior here is very similar to that in base/ftmac.c, but it */
1207 /* is designed to work on non-mac systems, so no mac specific calls. */
1209 /* We look at the file and determine if it is a mac dfont file or a mac */
1210 /* resource file, or a macbinary file containing a mac resource file. */
1212 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1213 /* the point, especially since there may be multiple `FOND' resources. */
1214 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1215 /* they occur in the file. */
1217 /* Note that multiple `POST' resources do not mean multiple postscript */
1218 /* fonts; they all get jammed together to make what is essentially a */
1221 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1223 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1226 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1227 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1228 /* going to try to save the kerning info. After all that lives in the */
1229 /* `FOND' which isn't in the file containing the `POST' resources so */
1230 /* we don't really have access to it. */
1233 /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
1234 /* It frees the memory it uses. */
1237 memory_stream_close( FT_Stream stream
)
1239 FT_Memory memory
= stream
->memory
;
1242 FT_FREE( stream
->base
);
1250 /* Create a new memory stream from a buffer and a size. */
1253 new_memory_stream( FT_Library library
,
1256 FT_Stream_CloseFunc close
,
1257 FT_Stream
*astream
)
1265 return FT_Err_Invalid_Library_Handle
;
1268 return FT_Err_Invalid_Argument
;
1271 memory
= library
->memory
;
1272 if ( FT_NEW( stream
) )
1275 FT_Stream_OpenMemory( stream
, base
, size
);
1277 stream
->close
= close
;
1286 /* Create a new FT_Face given a buffer and a driver name. */
1288 FT_LOCAL_DEF( FT_Error
)
1289 open_face_from_buffer( FT_Library library
,
1293 const char* driver_name
,
1298 FT_Stream stream
= NULL
;
1299 FT_Memory memory
= library
->memory
;
1302 error
= new_memory_stream( library
,
1305 memory_stream_close
,
1313 args
.flags
= FT_OPEN_STREAM
;
1314 args
.stream
= stream
;
1317 args
.flags
= args
.flags
| FT_OPEN_DRIVER
;
1318 args
.driver
= FT_Get_Module( library
, driver_name
);
1322 /* At this point, face_index has served its purpose; */
1323 /* whoever calls this function has already used it to */
1324 /* locate the correct font data. We should not propagate */
1325 /* this index to FT_Open_Face() (unless it is negative). */
1327 if ( face_index
> 0 )
1331 error
= FT_Open_Face( library
, &args
, face_index
, aface
);
1333 if ( error
== FT_Err_Ok
)
1334 (*aface
)->face_flags
&= ~FT_FACE_FLAG_EXTERNAL_STREAM
;
1337 FT_Stream_Free( stream
, 0 );
1340 FT_Stream_Close( stream
);
1349 /* Look up `TYP1' or `CID ' table from sfnt table directory. */
1350 /* `offset' and `length' must exclude the binary header in tables. */
1352 /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
1353 /* format too. Here, since we can't expect that the TrueType font */
1354 /* driver is loaded unconditially, we must parse the font by */
1355 /* ourselves. We are only interested in the name of the table and */
1359 ft_lookup_PS_in_sfnt_stream( FT_Stream stream
,
1363 FT_Bool
* is_sfnt_cid
)
1366 FT_UShort numTables
;
1367 FT_Long pstable_index
;
1374 *is_sfnt_cid
= FALSE
;
1376 /* TODO: support for sfnt-wrapped PS/CID in TTC format */
1378 /* version check for 'typ1' (should be ignored?) */
1379 if ( FT_READ_ULONG( tag
) )
1381 if ( tag
!= TTAG_typ1
)
1382 return FT_Err_Unknown_File_Format
;
1384 if ( FT_READ_USHORT( numTables
) )
1386 if ( FT_STREAM_SKIP( 2 * 3 ) ) /* skip binary search header */
1390 *is_sfnt_cid
= FALSE
;
1392 for ( i
= 0; i
< numTables
; i
++ )
1394 if ( FT_READ_ULONG( tag
) || FT_STREAM_SKIP( 4 ) ||
1395 FT_READ_ULONG( *offset
) || FT_READ_ULONG( *length
) )
1398 if ( tag
== TTAG_CID
)
1403 *is_sfnt_cid
= TRUE
;
1404 if ( face_index
< 0 )
1407 else if ( tag
== TTAG_TYP1
)
1412 *is_sfnt_cid
= FALSE
;
1413 if ( face_index
< 0 )
1416 if ( face_index
>= 0 && pstable_index
== face_index
)
1419 return FT_Err_Table_Missing
;
1423 FT_LOCAL_DEF( FT_Error
)
1424 open_face_PS_from_sfnt_stream( FT_Library library
,
1428 FT_Parameter
*params
,
1432 FT_Memory memory
= library
->memory
;
1433 FT_ULong offset
, length
;
1435 FT_Bool is_sfnt_cid
;
1438 FT_UNUSED( num_params
);
1439 FT_UNUSED( params
);
1442 pos
= FT_Stream_Pos( stream
);
1444 error
= ft_lookup_PS_in_sfnt_stream( stream
,
1452 if ( FT_Stream_Seek( stream
, pos
+ offset
) )
1455 if ( FT_ALLOC( sfnt_ps
, (FT_Long
)length
) )
1458 error
= FT_Stream_Read( stream
, (FT_Byte
*)sfnt_ps
, length
);
1462 error
= open_face_from_buffer( library
,
1465 face_index
< 0 ? face_index
: 0,
1466 is_sfnt_cid
? "cid" : "type1",
1473 if ( error
== FT_Err_Unknown_File_Format
)
1475 error1
= FT_Stream_Seek( stream
, pos
);
1485 #if !defined( FT_MACINTOSH ) || defined( DARWIN_NO_CARBON )
1487 /* The resource header says we've got resource_cnt `POST' (type1) */
1488 /* resources in this file. They all need to be coalesced into */
1489 /* one lump which gets passed on to the type1 driver. */
1490 /* Here can be only one PostScript font in a file so face_index */
1491 /* must be 0 (or -1). */
1494 Mac_Read_POST_Resource( FT_Library library
,
1497 FT_Long resource_cnt
,
1501 FT_Error error
= FT_Err_Cannot_Open_Resource
;
1502 FT_Memory memory
= library
->memory
;
1506 FT_Long pfb_len
, pfb_pos
, pfb_lenpos
;
1510 if ( face_index
== -1 )
1512 if ( face_index
!= 0 )
1515 /* Find the length of all the POST resources, concatenated. Assume */
1516 /* worst case (each resource in its own section). */
1518 for ( i
= 0; i
< resource_cnt
; ++i
)
1520 error
= FT_Stream_Seek( stream
, offsets
[i
] );
1523 if ( FT_READ_LONG( temp
) )
1525 pfb_len
+= temp
+ 6;
1528 if ( FT_ALLOC( pfb_data
, (FT_Long
)pfb_len
+ 2 ) )
1532 pfb_data
[1] = 1; /* Ascii section */
1533 pfb_data
[2] = 0; /* 4-byte length, fill in later */
1542 for ( i
= 0; i
< resource_cnt
; ++i
)
1544 error
= FT_Stream_Seek( stream
, offsets
[i
] );
1547 if ( FT_READ_LONG( rlen
) )
1549 if ( FT_READ_USHORT( flags
) )
1551 rlen
-= 2; /* the flags are part of the resource */
1552 if ( ( flags
>> 8 ) == type
)
1556 pfb_data
[pfb_lenpos
] = (FT_Byte
)( len
);
1557 pfb_data
[pfb_lenpos
+ 1] = (FT_Byte
)( len
>> 8 );
1558 pfb_data
[pfb_lenpos
+ 2] = (FT_Byte
)( len
>> 16 );
1559 pfb_data
[pfb_lenpos
+ 3] = (FT_Byte
)( len
>> 24 );
1561 if ( ( flags
>> 8 ) == 5 ) /* End of font mark */
1564 pfb_data
[pfb_pos
++] = 0x80;
1569 pfb_data
[pfb_pos
++] = (FT_Byte
)type
;
1570 pfb_lenpos
= pfb_pos
;
1571 pfb_data
[pfb_pos
++] = 0; /* 4-byte length, fill in later */
1572 pfb_data
[pfb_pos
++] = 0;
1573 pfb_data
[pfb_pos
++] = 0;
1574 pfb_data
[pfb_pos
++] = 0;
1577 error
= FT_Stream_Read( stream
, (FT_Byte
*)pfb_data
+ pfb_pos
, rlen
);
1581 pfb_data
[pfb_pos
++] = 0x80;
1582 pfb_data
[pfb_pos
++] = 3;
1584 pfb_data
[pfb_lenpos
] = (FT_Byte
)( len
);
1585 pfb_data
[pfb_lenpos
+ 1] = (FT_Byte
)( len
>> 8 );
1586 pfb_data
[pfb_lenpos
+ 2] = (FT_Byte
)( len
>> 16 );
1587 pfb_data
[pfb_lenpos
+ 3] = (FT_Byte
)( len
>> 24 );
1589 return open_face_from_buffer( library
,
1597 FT_FREE( pfb_data
);
1604 /* The resource header says we've got resource_cnt `sfnt' */
1605 /* (TrueType/OpenType) resources in this file. Look through */
1606 /* them for the one indicated by face_index, load it into mem, */
1607 /* pass it on the the truetype driver and return it. */
1610 Mac_Read_sfnt_Resource( FT_Library library
,
1613 FT_Long resource_cnt
,
1617 FT_Memory memory
= library
->memory
;
1620 FT_Long flag_offset
;
1623 FT_Long face_index_in_resource
= 0;
1626 if ( face_index
== -1 )
1628 if ( face_index
>= resource_cnt
)
1629 return FT_Err_Cannot_Open_Resource
;
1631 flag_offset
= offsets
[face_index
];
1632 error
= FT_Stream_Seek( stream
, flag_offset
);
1636 if ( FT_READ_LONG( rlen
) )
1639 return FT_Err_Cannot_Open_Resource
;
1641 error
= open_face_PS_from_sfnt_stream( library
,
1649 /* rewind sfnt stream before open_face_PS_from_sfnt_stream() */
1650 if ( FT_Stream_Seek( stream
, flag_offset
+ 4 ) )
1653 if ( FT_ALLOC( sfnt_data
, (FT_Long
)rlen
) )
1655 error
= FT_Stream_Read( stream
, (FT_Byte
*)sfnt_data
, rlen
);
1659 is_cff
= rlen
> 4 && !ft_memcmp( sfnt_data
, "OTTO", 4 );
1660 error
= open_face_from_buffer( library
,
1663 face_index_in_resource
,
1664 is_cff
? "cff" : "truetype",
1672 /* Check for a valid resource fork header, or a valid dfont */
1673 /* header. In a resource fork the first 16 bytes are repeated */
1674 /* at the location specified by bytes 4-7. In a dfont bytes */
1675 /* 4-7 point to 16 bytes of zeroes instead. */
1678 IsMacResource( FT_Library library
,
1680 FT_Long resource_offset
,
1684 FT_Memory memory
= library
->memory
;
1686 FT_Long map_offset
, rdara_pos
;
1687 FT_Long
*data_offsets
;
1691 error
= FT_Raccess_Get_HeaderInfo( library
, stream
, resource_offset
,
1692 &map_offset
, &rdara_pos
);
1696 error
= FT_Raccess_Get_DataOffsets( library
, stream
,
1697 map_offset
, rdara_pos
,
1699 &data_offsets
, &count
);
1702 error
= Mac_Read_POST_Resource( library
, stream
, data_offsets
, count
,
1703 face_index
, aface
);
1704 FT_FREE( data_offsets
);
1705 /* POST exists in an LWFN providing a single face */
1707 (*aface
)->num_faces
= 1;
1711 error
= FT_Raccess_Get_DataOffsets( library
, stream
,
1712 map_offset
, rdara_pos
,
1714 &data_offsets
, &count
);
1717 FT_Long face_index_internal
= face_index
% count
;
1720 error
= Mac_Read_sfnt_Resource( library
, stream
, data_offsets
, count
,
1721 face_index_internal
, aface
);
1722 FT_FREE( data_offsets
);
1724 (*aface
)->num_faces
= count
;
1731 /* Check for a valid macbinary header, and if we find one */
1732 /* check that the (flattened) resource fork in it is valid. */
1735 IsMacBinary( FT_Library library
,
1740 unsigned char header
[128];
1742 FT_Long dlen
, offset
;
1745 if ( NULL
== stream
)
1746 return FT_Err_Invalid_Stream_Operation
;
1748 error
= FT_Stream_Seek( stream
, 0 );
1752 error
= FT_Stream_Read( stream
, (FT_Byte
*)header
, 128 );
1756 if ( header
[ 0] != 0 ||
1762 header
[2 + header
[1]] != 0 )
1763 return FT_Err_Unknown_File_Format
;
1765 dlen
= ( header
[0x53] << 24 ) |
1766 ( header
[0x54] << 16 ) |
1767 ( header
[0x55] << 8 ) |
1770 rlen
= ( header
[0x57] << 24 ) |
1771 ( header
[0x58] << 16 ) |
1772 ( header
[0x59] << 8 ) |
1775 offset
= 128 + ( ( dlen
+ 127 ) & ~127 );
1777 return IsMacResource( library
, stream
, offset
, face_index
, aface
);
1785 load_face_in_embedded_rfork( FT_Library library
,
1789 const FT_Open_Args
*args
)
1793 #define FT_COMPONENT trace_raccess
1795 FT_Memory memory
= library
->memory
;
1796 FT_Error error
= FT_Err_Unknown_File_Format
;
1799 char * file_names
[FT_RACCESS_N_RULES
];
1800 FT_Long offsets
[FT_RACCESS_N_RULES
];
1801 FT_Error errors
[FT_RACCESS_N_RULES
];
1804 FT_Stream stream2
= 0;
1807 FT_Raccess_Guess( library
, stream
,
1808 args
->pathname
, file_names
, offsets
, errors
);
1810 for ( i
= 0; i
< FT_RACCESS_N_RULES
; i
++ )
1814 FT_TRACE3(( "Error[%d] has occurred in rule %d\n", errors
[i
], i
));
1818 args2
.flags
= FT_OPEN_PATHNAME
;
1819 args2
.pathname
= file_names
[i
] ? file_names
[i
] : args
->pathname
;
1821 FT_TRACE3(( "Try rule %d: %s (offset=%d) ...",
1822 i
, args2
.pathname
, offsets
[i
] ));
1824 error
= FT_Stream_New( library
, &args2
, &stream2
);
1827 FT_TRACE3(( "failed\n" ));
1831 error
= IsMacResource( library
, stream2
, offsets
[i
],
1832 face_index
, aface
);
1833 FT_Stream_Free( stream2
, 0 );
1835 FT_TRACE3(( "%s\n", error
? "failed": "successful" ));
1841 for (i
= 0; i
< FT_RACCESS_N_RULES
; i
++)
1843 if ( file_names
[i
] )
1844 FT_FREE( file_names
[i
] );
1847 /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
1849 error
= FT_Err_Unknown_File_Format
;
1854 #define FT_COMPONENT trace_objs
1859 /* Check for some macintosh formats without Carbon framework. */
1860 /* Is this a macbinary file? If so look at the resource fork. */
1861 /* Is this a mac dfont file? */
1862 /* Is this an old style resource fork? (in data) */
1863 /* Else call load_face_in_embedded_rfork to try extra rules */
1864 /* (defined in `ftrfork.c'). */
1867 load_mac_face( FT_Library library
,
1871 const FT_Open_Args
*args
)
1877 error
= IsMacBinary( library
, stream
, face_index
, aface
);
1878 if ( FT_ERROR_BASE( error
) == FT_Err_Unknown_File_Format
)
1882 #define FT_COMPONENT trace_raccess
1884 FT_TRACE3(( "Try as dfont: %s ...", args
->pathname
));
1886 error
= IsMacResource( library
, stream
, 0, face_index
, aface
);
1888 FT_TRACE3(( "%s\n", error
? "failed" : "successful" ));
1891 #define FT_COMPONENT trace_objs
1895 if ( ( FT_ERROR_BASE( error
) == FT_Err_Unknown_File_Format
||
1896 FT_ERROR_BASE( error
) == FT_Err_Invalid_Stream_Operation
) &&
1897 ( args
->flags
& FT_OPEN_PATHNAME
) )
1898 error
= load_face_in_embedded_rfork( library
, stream
,
1899 face_index
, aface
, args
);
1904 #endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
1907 /* documentation is in freetype.h */
1909 FT_EXPORT_DEF( FT_Error
)
1910 FT_Open_Face( FT_Library library
,
1911 const FT_Open_Args
* args
,
1918 FT_Stream stream
= 0;
1920 FT_ListNode node
= 0;
1921 FT_Bool external_stream
;
1926 /* test for valid `library' delayed to */
1927 /* FT_Stream_New() */
1929 if ( ( !aface
&& face_index
>= 0 ) || !args
)
1930 return FT_Err_Invalid_Argument
;
1932 external_stream
= FT_BOOL( ( args
->flags
& FT_OPEN_STREAM
) &&
1935 /* create input stream */
1936 error
= FT_Stream_New( library
, args
, &stream
);
1940 memory
= library
->memory
;
1942 /* If the font driver is specified in the `args' structure, use */
1943 /* it. Otherwise, we scan the list of registered drivers. */
1944 if ( ( args
->flags
& FT_OPEN_DRIVER
) && args
->driver
)
1946 driver
= FT_DRIVER( args
->driver
);
1948 /* not all modules are drivers, so check... */
1949 if ( FT_MODULE_IS_DRIVER( driver
) )
1951 FT_Int num_params
= 0;
1952 FT_Parameter
* params
= 0;
1955 if ( args
->flags
& FT_OPEN_PARAMS
)
1957 num_params
= args
->num_params
;
1958 params
= args
->params
;
1961 error
= open_face( driver
, stream
, face_index
,
1962 num_params
, params
, &face
);
1967 error
= FT_Err_Invalid_Handle
;
1969 FT_Stream_Free( stream
, external_stream
);
1974 /* check each font driver for an appropriate format */
1975 cur
= library
->modules
;
1976 limit
= cur
+ library
->num_modules
;
1979 for ( ; cur
< limit
; cur
++ )
1981 /* not all modules are font drivers, so check... */
1982 if ( FT_MODULE_IS_DRIVER( cur
[0] ) )
1984 FT_Int num_params
= 0;
1985 FT_Parameter
* params
= 0;
1988 driver
= FT_DRIVER( cur
[0] );
1990 if ( args
->flags
& FT_OPEN_PARAMS
)
1992 num_params
= args
->num_params
;
1993 params
= args
->params
;
1996 error
= open_face( driver
, stream
, face_index
,
1997 num_params
, params
, &face
);
2001 #ifdef FT_CONFIG_OPTION_MAC_FONTS
2002 if ( ft_strcmp( cur
[0]->clazz
->module_name
, "truetype" ) == 0 &&
2003 FT_ERROR_BASE( error
) == FT_Err_Table_Missing
)
2005 /* TrueType but essential tables are missing */
2006 if ( FT_Stream_Seek( stream
, 0 ) )
2009 error
= open_face_PS_from_sfnt_stream( library
,
2017 FT_Stream_Free( stream
, external_stream
);
2023 if ( FT_ERROR_BASE( error
) != FT_Err_Unknown_File_Format
)
2029 /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
2030 /* it may be because we have an empty data fork, so we need to check */
2031 /* the resource fork. */
2032 if ( FT_ERROR_BASE( error
) != FT_Err_Cannot_Open_Stream
&&
2033 FT_ERROR_BASE( error
) != FT_Err_Unknown_File_Format
&&
2034 FT_ERROR_BASE( error
) != FT_Err_Invalid_Stream_Operation
)
2037 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
2038 error
= load_mac_face( library
, stream
, face_index
, aface
, args
);
2041 /* We don't want to go to Success here. We've already done that. */
2042 /* On the other hand, if we succeeded we still need to close this */
2043 /* stream (we opened a different stream which extracted the */
2044 /* interesting information out of this stream here. That stream */
2045 /* will still be open and the face will point to it). */
2046 FT_Stream_Free( stream
, external_stream
);
2050 if ( FT_ERROR_BASE( error
) != FT_Err_Unknown_File_Format
)
2052 #endif /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
2054 /* no driver is able to handle this format */
2055 error
= FT_Err_Unknown_File_Format
;
2058 FT_Stream_Free( stream
, external_stream
);
2063 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ));
2065 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
2066 if ( external_stream
)
2067 face
->face_flags
|= FT_FACE_FLAG_EXTERNAL_STREAM
;
2069 /* add the face object to its driver's list */
2070 if ( FT_NEW( node
) )
2074 /* don't assume driver is the same as face->driver, so use */
2075 /* face->driver instead. */
2076 FT_List_Add( &face
->driver
->faces_list
, node
);
2078 /* now allocate a glyph slot object for the face */
2079 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
2081 if ( face_index
>= 0 )
2083 error
= FT_New_GlyphSlot( face
, NULL
);
2087 /* finally, allocate a size object for the face */
2092 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
2094 error
= FT_New_Size( face
, &size
);
2104 if ( FT_IS_SCALABLE( face
) )
2106 if ( face
->height
< 0 )
2107 face
->height
= (FT_Short
)-face
->height
;
2109 if ( !FT_HAS_VERTICAL( face
) )
2110 face
->max_advance_height
= (FT_Short
)face
->height
;
2113 if ( FT_HAS_FIXED_SIZES( face
) )
2118 for ( i
= 0; i
< face
->num_fixed_sizes
; i
++ )
2120 FT_Bitmap_Size
* bsize
= face
->available_sizes
+ i
;
2123 if ( bsize
->height
< 0 )
2124 bsize
->height
= (FT_Short
)-bsize
->height
;
2125 if ( bsize
->x_ppem
< 0 )
2126 bsize
->x_ppem
= (FT_Short
)-bsize
->x_ppem
;
2127 if ( bsize
->y_ppem
< 0 )
2128 bsize
->y_ppem
= -bsize
->y_ppem
;
2132 /* initialize internal face data */
2134 FT_Face_Internal internal
= face
->internal
;
2137 internal
->transform_matrix
.xx
= 0x10000L
;
2138 internal
->transform_matrix
.xy
= 0;
2139 internal
->transform_matrix
.yx
= 0;
2140 internal
->transform_matrix
.yy
= 0x10000L
;
2142 internal
->transform_delta
.x
= 0;
2143 internal
->transform_delta
.y
= 0;
2149 FT_Done_Face( face
);
2154 FT_Done_Face( face
);
2157 FT_TRACE4(( "FT_Open_Face: Return %d\n", error
));
2163 /* documentation is in freetype.h */
2165 FT_EXPORT_DEF( FT_Error
)
2166 FT_Attach_File( FT_Face face
,
2167 const char* filepathname
)
2172 /* test for valid `face' delayed to FT_Attach_Stream() */
2174 if ( !filepathname
)
2175 return FT_Err_Invalid_Argument
;
2178 open
.flags
= FT_OPEN_PATHNAME
;
2179 open
.pathname
= (char*)filepathname
;
2181 return FT_Attach_Stream( face
, &open
);
2185 /* documentation is in freetype.h */
2187 FT_EXPORT_DEF( FT_Error
)
2188 FT_Attach_Stream( FT_Face face
,
2189 FT_Open_Args
* parameters
)
2195 FT_Driver_Class clazz
;
2198 /* test for valid `parameters' delayed to FT_Stream_New() */
2201 return FT_Err_Invalid_Face_Handle
;
2203 driver
= face
->driver
;
2205 return FT_Err_Invalid_Driver_Handle
;
2207 error
= FT_Stream_New( driver
->root
.library
, parameters
, &stream
);
2211 /* we implement FT_Attach_Stream in each driver through the */
2212 /* `attach_file' interface */
2214 error
= FT_Err_Unimplemented_Feature
;
2215 clazz
= driver
->clazz
;
2216 if ( clazz
->attach_file
)
2217 error
= clazz
->attach_file( face
, stream
);
2219 /* close the attached stream */
2220 FT_Stream_Free( stream
,
2221 (FT_Bool
)( parameters
->stream
&&
2222 ( parameters
->flags
& FT_OPEN_STREAM
) ) );
2229 /* documentation is in freetype.h */
2231 FT_EXPORT_DEF( FT_Error
)
2232 FT_Done_Face( FT_Face face
)
2240 error
= FT_Err_Invalid_Face_Handle
;
2241 if ( face
&& face
->driver
)
2243 driver
= face
->driver
;
2244 memory
= driver
->root
.memory
;
2246 /* find face in driver's list */
2247 node
= FT_List_Find( &driver
->faces_list
, face
);
2250 /* remove face object from the driver's list */
2251 FT_List_Remove( &driver
->faces_list
, node
);
2254 /* now destroy the object proper */
2255 destroy_face( memory
, face
, driver
);
2263 /* documentation is in ftobjs.h */
2265 FT_EXPORT_DEF( FT_Error
)
2266 FT_New_Size( FT_Face face
,
2272 FT_Driver_Class clazz
;
2275 FT_ListNode node
= 0;
2279 return FT_Err_Invalid_Face_Handle
;
2282 return FT_Err_Invalid_Size_Handle
;
2284 if ( !face
->driver
)
2285 return FT_Err_Invalid_Driver_Handle
;
2289 driver
= face
->driver
;
2290 clazz
= driver
->clazz
;
2291 memory
= face
->memory
;
2293 /* Allocate new size object and perform basic initialisation */
2294 if ( FT_ALLOC( size
, clazz
->size_object_size
) || FT_NEW( node
) )
2299 /* for now, do not use any internal fields in size objects */
2302 if ( clazz
->init_size
)
2303 error
= clazz
->init_size( size
);
2305 /* in case of success, add to the face's list */
2310 FT_List_Add( &face
->sizes_list
, node
);
2324 /* documentation is in ftobjs.h */
2326 FT_EXPORT_DEF( FT_Error
)
2327 FT_Done_Size( FT_Size size
)
2337 return FT_Err_Invalid_Size_Handle
;
2341 return FT_Err_Invalid_Face_Handle
;
2343 driver
= face
->driver
;
2345 return FT_Err_Invalid_Driver_Handle
;
2347 memory
= driver
->root
.memory
;
2350 node
= FT_List_Find( &face
->sizes_list
, size
);
2353 FT_List_Remove( &face
->sizes_list
, node
);
2356 if ( face
->size
== size
)
2359 if ( face
->sizes_list
.head
)
2360 face
->size
= (FT_Size
)(face
->sizes_list
.head
->data
);
2363 destroy_size( memory
, size
, driver
);
2366 error
= FT_Err_Invalid_Size_Handle
;
2372 /* documentation is in ftobjs.h */
2374 FT_BASE_DEF( FT_Error
)
2375 FT_Match_Size( FT_Face face
,
2376 FT_Size_Request req
,
2377 FT_Bool ignore_width
,
2378 FT_ULong
* size_index
)
2384 if ( !FT_HAS_FIXED_SIZES( face
) )
2385 return FT_Err_Invalid_Face_Handle
;
2387 /* FT_Bitmap_Size doesn't provide enough info... */
2388 if ( req
->type
!= FT_SIZE_REQUEST_TYPE_NOMINAL
)
2389 return FT_Err_Unimplemented_Feature
;
2391 w
= FT_REQUEST_WIDTH ( req
);
2392 h
= FT_REQUEST_HEIGHT( req
);
2394 if ( req
->width
&& !req
->height
)
2396 else if ( !req
->width
&& req
->height
)
2399 w
= FT_PIX_ROUND( w
);
2400 h
= FT_PIX_ROUND( h
);
2402 for ( i
= 0; i
< face
->num_fixed_sizes
; i
++ )
2404 FT_Bitmap_Size
* bsize
= face
->available_sizes
+ i
;
2407 if ( h
!= FT_PIX_ROUND( bsize
->y_ppem
) )
2410 if ( w
== FT_PIX_ROUND( bsize
->x_ppem
) || ignore_width
)
2413 *size_index
= (FT_ULong
)i
;
2419 return FT_Err_Invalid_Pixel_Size
;
2423 /* documentation is in ftobjs.h */
2426 ft_synthesize_vertical_metrics( FT_Glyph_Metrics
* metrics
,
2429 FT_Pos height
= metrics
->height
;
2432 /* compensate for glyph with bbox above/below the baseline */
2433 if ( metrics
->horiBearingY
< 0 )
2435 if ( height
< metrics
->horiBearingY
)
2436 height
= metrics
->horiBearingY
;
2438 else if ( metrics
->horiBearingY
> 0 )
2439 height
-= metrics
->horiBearingY
;
2441 /* the factor 1.2 is a heuristical value */
2443 advance
= height
* 12 / 10;
2445 metrics
->vertBearingX
= metrics
->horiBearingX
- metrics
->horiAdvance
/ 2;
2446 metrics
->vertBearingY
= ( advance
- height
) / 2;
2447 metrics
->vertAdvance
= advance
;
2452 ft_recompute_scaled_metrics( FT_Face face
,
2453 FT_Size_Metrics
* metrics
)
2455 /* Compute root ascender, descender, test height, and max_advance */
2457 #ifdef GRID_FIT_METRICS
2458 metrics
->ascender
= FT_PIX_CEIL( FT_MulFix( face
->ascender
,
2459 metrics
->y_scale
) );
2461 metrics
->descender
= FT_PIX_FLOOR( FT_MulFix( face
->descender
,
2462 metrics
->y_scale
) );
2464 metrics
->height
= FT_PIX_ROUND( FT_MulFix( face
->height
,
2465 metrics
->y_scale
) );
2467 metrics
->max_advance
= FT_PIX_ROUND( FT_MulFix( face
->max_advance_width
,
2468 metrics
->x_scale
) );
2469 #else /* !GRID_FIT_METRICS */
2470 metrics
->ascender
= FT_MulFix( face
->ascender
,
2473 metrics
->descender
= FT_MulFix( face
->descender
,
2476 metrics
->height
= FT_MulFix( face
->height
,
2479 metrics
->max_advance
= FT_MulFix( face
->max_advance_width
,
2481 #endif /* !GRID_FIT_METRICS */
2486 FT_Select_Metrics( FT_Face face
,
2487 FT_ULong strike_index
)
2489 FT_Size_Metrics
* metrics
;
2490 FT_Bitmap_Size
* bsize
;
2493 metrics
= &face
->size
->metrics
;
2494 bsize
= face
->available_sizes
+ strike_index
;
2496 metrics
->x_ppem
= (FT_UShort
)( ( bsize
->x_ppem
+ 32 ) >> 6 );
2497 metrics
->y_ppem
= (FT_UShort
)( ( bsize
->y_ppem
+ 32 ) >> 6 );
2499 if ( FT_IS_SCALABLE( face
) )
2501 metrics
->x_scale
= FT_DivFix( bsize
->x_ppem
,
2502 face
->units_per_EM
);
2503 metrics
->y_scale
= FT_DivFix( bsize
->y_ppem
,
2504 face
->units_per_EM
);
2506 ft_recompute_scaled_metrics( face
, metrics
);
2510 metrics
->x_scale
= 1L << 16;
2511 metrics
->y_scale
= 1L << 16;
2512 metrics
->ascender
= bsize
->y_ppem
;
2513 metrics
->descender
= 0;
2514 metrics
->height
= bsize
->height
<< 6;
2515 metrics
->max_advance
= bsize
->x_ppem
;
2521 FT_Request_Metrics( FT_Face face
,
2522 FT_Size_Request req
)
2524 FT_Size_Metrics
* metrics
;
2527 metrics
= &face
->size
->metrics
;
2529 if ( FT_IS_SCALABLE( face
) )
2531 FT_Long w
= 0, h
= 0, scaled_w
= 0, scaled_h
= 0;
2534 switch ( req
->type
)
2536 case FT_SIZE_REQUEST_TYPE_NOMINAL
:
2537 w
= h
= face
->units_per_EM
;
2540 case FT_SIZE_REQUEST_TYPE_REAL_DIM
:
2541 w
= h
= face
->ascender
- face
->descender
;
2544 case FT_SIZE_REQUEST_TYPE_BBOX
:
2545 w
= face
->bbox
.xMax
- face
->bbox
.xMin
;
2546 h
= face
->bbox
.yMax
- face
->bbox
.yMin
;
2549 case FT_SIZE_REQUEST_TYPE_CELL
:
2550 w
= face
->max_advance_width
;
2551 h
= face
->ascender
- face
->descender
;
2554 case FT_SIZE_REQUEST_TYPE_SCALES
:
2555 metrics
->x_scale
= (FT_Fixed
)req
->width
;
2556 metrics
->y_scale
= (FT_Fixed
)req
->height
;
2557 if ( !metrics
->x_scale
)
2558 metrics
->x_scale
= metrics
->y_scale
;
2559 else if ( !metrics
->y_scale
)
2560 metrics
->y_scale
= metrics
->x_scale
;
2561 goto Calculate_Ppem
;
2563 case FT_SIZE_REQUEST_TYPE_MAX
:
2567 /* to be on the safe side */
2574 scaled_w
= FT_REQUEST_WIDTH ( req
);
2575 scaled_h
= FT_REQUEST_HEIGHT( req
);
2577 /* determine scales */
2580 metrics
->x_scale
= FT_DivFix( scaled_w
, w
);
2584 metrics
->y_scale
= FT_DivFix( scaled_h
, h
);
2586 if ( req
->type
== FT_SIZE_REQUEST_TYPE_CELL
)
2588 if ( metrics
->y_scale
> metrics
->x_scale
)
2589 metrics
->y_scale
= metrics
->x_scale
;
2591 metrics
->x_scale
= metrics
->y_scale
;
2596 metrics
->y_scale
= metrics
->x_scale
;
2597 scaled_h
= FT_MulDiv( scaled_w
, h
, w
);
2602 metrics
->x_scale
= metrics
->y_scale
= FT_DivFix( scaled_h
, h
);
2603 scaled_w
= FT_MulDiv( scaled_h
, w
, h
);
2607 /* calculate the ppems */
2608 if ( req
->type
!= FT_SIZE_REQUEST_TYPE_NOMINAL
)
2610 scaled_w
= FT_MulFix( face
->units_per_EM
, metrics
->x_scale
);
2611 scaled_h
= FT_MulFix( face
->units_per_EM
, metrics
->y_scale
);
2614 metrics
->x_ppem
= (FT_UShort
)( ( scaled_w
+ 32 ) >> 6 );
2615 metrics
->y_ppem
= (FT_UShort
)( ( scaled_h
+ 32 ) >> 6 );
2617 ft_recompute_scaled_metrics( face
, metrics
);
2622 metrics
->x_scale
= 1L << 16;
2623 metrics
->y_scale
= 1L << 16;
2628 /* documentation is in freetype.h */
2630 FT_EXPORT_DEF( FT_Error
)
2631 FT_Select_Size( FT_Face face
,
2632 FT_Int strike_index
)
2634 FT_Driver_Class clazz
;
2637 if ( !face
|| !FT_HAS_FIXED_SIZES( face
) )
2638 return FT_Err_Invalid_Face_Handle
;
2640 if ( strike_index
< 0 || strike_index
>= face
->num_fixed_sizes
)
2641 return FT_Err_Invalid_Argument
;
2643 clazz
= face
->driver
->clazz
;
2645 if ( clazz
->select_size
)
2646 return clazz
->select_size( face
->size
, (FT_ULong
)strike_index
);
2648 FT_Select_Metrics( face
, (FT_ULong
)strike_index
);
2654 /* documentation is in freetype.h */
2656 FT_EXPORT_DEF( FT_Error
)
2657 FT_Request_Size( FT_Face face
,
2658 FT_Size_Request req
)
2660 FT_Driver_Class clazz
;
2661 FT_ULong strike_index
;
2665 return FT_Err_Invalid_Face_Handle
;
2667 if ( !req
|| req
->width
< 0 || req
->height
< 0 ||
2668 req
->type
>= FT_SIZE_REQUEST_TYPE_MAX
)
2669 return FT_Err_Invalid_Argument
;
2671 clazz
= face
->driver
->clazz
;
2673 if ( clazz
->request_size
)
2674 return clazz
->request_size( face
->size
, req
);
2677 * The reason that a driver doesn't have `request_size' defined is
2678 * either that the scaling here suffices or that the supported formats
2679 * are bitmap-only and size matching is not implemented.
2681 * In the latter case, a simple size matching is done.
2683 if ( !FT_IS_SCALABLE( face
) && FT_HAS_FIXED_SIZES( face
) )
2688 error
= FT_Match_Size( face
, req
, 0, &strike_index
);
2692 FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
2695 return FT_Select_Size( face
, (FT_Int
)strike_index
);
2698 FT_Request_Metrics( face
, req
);
2704 /* documentation is in freetype.h */
2706 FT_EXPORT_DEF( FT_Error
)
2707 FT_Set_Char_Size( FT_Face face
,
2708 FT_F26Dot6 char_width
,
2709 FT_F26Dot6 char_height
,
2710 FT_UInt horz_resolution
,
2711 FT_UInt vert_resolution
)
2713 FT_Size_RequestRec req
;
2717 char_width
= char_height
;
2718 else if ( !char_height
)
2719 char_height
= char_width
;
2721 if ( !horz_resolution
)
2722 horz_resolution
= vert_resolution
;
2723 else if ( !vert_resolution
)
2724 vert_resolution
= horz_resolution
;
2726 if ( char_width
< 1 * 64 )
2727 char_width
= 1 * 64;
2728 if ( char_height
< 1 * 64 )
2729 char_height
= 1 * 64;
2731 if ( !horz_resolution
)
2732 horz_resolution
= vert_resolution
= 72;
2734 req
.type
= FT_SIZE_REQUEST_TYPE_NOMINAL
;
2735 req
.width
= char_width
;
2736 req
.height
= char_height
;
2737 req
.horiResolution
= horz_resolution
;
2738 req
.vertResolution
= vert_resolution
;
2740 return FT_Request_Size( face
, &req
);
2744 /* documentation is in freetype.h */
2746 FT_EXPORT_DEF( FT_Error
)
2747 FT_Set_Pixel_Sizes( FT_Face face
,
2748 FT_UInt pixel_width
,
2749 FT_UInt pixel_height
)
2751 FT_Size_RequestRec req
;
2754 if ( pixel_width
== 0 )
2755 pixel_width
= pixel_height
;
2756 else if ( pixel_height
== 0 )
2757 pixel_height
= pixel_width
;
2759 if ( pixel_width
< 1 )
2761 if ( pixel_height
< 1 )
2764 /* use `>=' to avoid potential compiler warning on 16bit platforms */
2765 if ( pixel_width
>= 0xFFFFU
)
2766 pixel_width
= 0xFFFFU
;
2767 if ( pixel_height
>= 0xFFFFU
)
2768 pixel_height
= 0xFFFFU
;
2770 req
.type
= FT_SIZE_REQUEST_TYPE_NOMINAL
;
2771 req
.width
= pixel_width
<< 6;
2772 req
.height
= pixel_height
<< 6;
2773 req
.horiResolution
= 0;
2774 req
.vertResolution
= 0;
2776 return FT_Request_Size( face
, &req
);
2780 /* documentation is in freetype.h */
2782 FT_EXPORT_DEF( FT_Error
)
2783 FT_Get_Kerning( FT_Face face
,
2785 FT_UInt right_glyph
,
2787 FT_Vector
*akerning
)
2789 FT_Error error
= FT_Err_Ok
;
2794 return FT_Err_Invalid_Face_Handle
;
2797 return FT_Err_Invalid_Argument
;
2799 driver
= face
->driver
;
2804 if ( driver
->clazz
->get_kerning
)
2806 error
= driver
->clazz
->get_kerning( face
,
2812 if ( kern_mode
!= FT_KERNING_UNSCALED
)
2814 akerning
->x
= FT_MulFix( akerning
->x
, face
->size
->metrics
.x_scale
);
2815 akerning
->y
= FT_MulFix( akerning
->y
, face
->size
->metrics
.y_scale
);
2817 if ( kern_mode
!= FT_KERNING_UNFITTED
)
2819 /* we scale down kerning values for small ppem values */
2820 /* to avoid that rounding makes them too big. */
2821 /* `25' has been determined heuristically. */
2822 if ( face
->size
->metrics
.x_ppem
< 25 )
2823 akerning
->x
= FT_MulDiv( akerning
->x
,
2824 face
->size
->metrics
.x_ppem
, 25 );
2825 if ( face
->size
->metrics
.y_ppem
< 25 )
2826 akerning
->y
= FT_MulDiv( akerning
->y
,
2827 face
->size
->metrics
.y_ppem
, 25 );
2829 akerning
->x
= FT_PIX_ROUND( akerning
->x
);
2830 akerning
->y
= FT_PIX_ROUND( akerning
->y
);
2840 /* documentation is in freetype.h */
2842 FT_EXPORT_DEF( FT_Error
)
2843 FT_Get_Track_Kerning( FT_Face face
,
2844 FT_Fixed point_size
,
2846 FT_Fixed
* akerning
)
2848 FT_Service_Kerning service
;
2849 FT_Error error
= FT_Err_Ok
;
2853 return FT_Err_Invalid_Face_Handle
;
2856 return FT_Err_Invalid_Argument
;
2858 FT_FACE_FIND_SERVICE( face
, service
, KERNING
);
2860 return FT_Err_Unimplemented_Feature
;
2862 error
= service
->get_track( face
,
2871 /* documentation is in freetype.h */
2873 FT_EXPORT_DEF( FT_Error
)
2874 FT_Select_Charmap( FT_Face face
,
2875 FT_Encoding encoding
)
2882 return FT_Err_Invalid_Face_Handle
;
2884 if ( encoding
== FT_ENCODING_NONE
)
2885 return FT_Err_Invalid_Argument
;
2887 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2888 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2890 /* This is done by find_unicode_charmap() above, to share code. */
2891 if ( encoding
== FT_ENCODING_UNICODE
)
2892 return find_unicode_charmap( face
);
2894 cur
= face
->charmaps
;
2896 return FT_Err_Invalid_CharMap_Handle
;
2898 limit
= cur
+ face
->num_charmaps
;
2900 for ( ; cur
< limit
; cur
++ )
2902 if ( cur
[0]->encoding
== encoding
)
2904 face
->charmap
= cur
[0];
2909 return FT_Err_Invalid_Argument
;
2913 /* documentation is in freetype.h */
2915 FT_EXPORT_DEF( FT_Error
)
2916 FT_Set_Charmap( FT_Face face
,
2917 FT_CharMap charmap
)
2924 return FT_Err_Invalid_Face_Handle
;
2926 cur
= face
->charmaps
;
2928 return FT_Err_Invalid_CharMap_Handle
;
2929 if ( FT_Get_CMap_Format( charmap
) == 14 )
2930 return FT_Err_Invalid_Argument
;
2932 limit
= cur
+ face
->num_charmaps
;
2934 for ( ; cur
< limit
; cur
++ )
2936 if ( cur
[0] == charmap
)
2938 face
->charmap
= cur
[0];
2942 return FT_Err_Invalid_Argument
;
2946 /* documentation is in freetype.h */
2948 FT_EXPORT_DEF( FT_Int
)
2949 FT_Get_Charmap_Index( FT_CharMap charmap
)
2954 for ( i
= 0; i
< charmap
->face
->num_charmaps
; i
++ )
2955 if ( charmap
->face
->charmaps
[i
] == charmap
)
2958 FT_ASSERT( i
< charmap
->face
->num_charmaps
);
2965 ft_cmap_done_internal( FT_CMap cmap
)
2967 FT_CMap_Class clazz
= cmap
->clazz
;
2968 FT_Face face
= cmap
->charmap
.face
;
2969 FT_Memory memory
= FT_FACE_MEMORY(face
);
2973 clazz
->done( cmap
);
2980 FT_CMap_Done( FT_CMap cmap
)
2984 FT_Face face
= cmap
->charmap
.face
;
2985 FT_Memory memory
= FT_FACE_MEMORY( face
);
2990 for ( i
= 0; i
< face
->num_charmaps
; i
++ )
2992 if ( (FT_CMap
)face
->charmaps
[i
] == cmap
)
2994 FT_CharMap last_charmap
= face
->charmaps
[face
->num_charmaps
- 1];
2997 if ( FT_RENEW_ARRAY( face
->charmaps
,
2999 face
->num_charmaps
- 1 ) )
3002 /* remove it from our list of charmaps */
3003 for ( j
= i
+ 1; j
< face
->num_charmaps
; j
++ )
3005 if ( j
== face
->num_charmaps
- 1 )
3006 face
->charmaps
[j
- 1] = last_charmap
;
3008 face
->charmaps
[j
- 1] = face
->charmaps
[j
];
3011 face
->num_charmaps
--;
3013 if ( (FT_CMap
)face
->charmap
== cmap
)
3014 face
->charmap
= NULL
;
3016 ft_cmap_done_internal( cmap
);
3025 FT_BASE_DEF( FT_Error
)
3026 FT_CMap_New( FT_CMap_Class clazz
,
3027 FT_Pointer init_data
,
3031 FT_Error error
= FT_Err_Ok
;
3037 if ( clazz
== NULL
|| charmap
== NULL
|| charmap
->face
== NULL
)
3038 return FT_Err_Invalid_Argument
;
3040 face
= charmap
->face
;
3041 memory
= FT_FACE_MEMORY( face
);
3043 if ( !FT_ALLOC( cmap
, clazz
->size
) )
3045 cmap
->charmap
= *charmap
;
3046 cmap
->clazz
= clazz
;
3050 error
= clazz
->init( cmap
, init_data
);
3055 /* add it to our list of charmaps */
3056 if ( FT_RENEW_ARRAY( face
->charmaps
,
3058 face
->num_charmaps
+ 1 ) )
3061 face
->charmaps
[face
->num_charmaps
++] = (FT_CharMap
)cmap
;
3071 ft_cmap_done_internal( cmap
);
3077 /* documentation is in freetype.h */
3079 FT_EXPORT_DEF( FT_UInt
)
3080 FT_Get_Char_Index( FT_Face face
,
3086 if ( face
&& face
->charmap
)
3088 FT_CMap cmap
= FT_CMAP( face
->charmap
);
3091 if ( charcode
> 0xFFFFFFFFUL
)
3093 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3094 FT_TRACE1(( " 0x%x is truncated\n", charcode
));
3096 result
= cmap
->clazz
->char_index( cmap
, (FT_UInt32
)charcode
);
3102 /* documentation is in freetype.h */
3104 FT_EXPORT_DEF( FT_ULong
)
3105 FT_Get_First_Char( FT_Face face
,
3108 FT_ULong result
= 0;
3112 if ( face
&& face
->charmap
)
3114 gindex
= FT_Get_Char_Index( face
, 0 );
3116 result
= FT_Get_Next_Char( face
, 0, &gindex
);
3126 /* documentation is in freetype.h */
3128 FT_EXPORT_DEF( FT_ULong
)
3129 FT_Get_Next_Char( FT_Face face
,
3133 FT_ULong result
= 0;
3137 if ( face
&& face
->charmap
)
3139 FT_UInt32 code
= (FT_UInt32
)charcode
;
3140 FT_CMap cmap
= FT_CMAP( face
->charmap
);
3143 gindex
= cmap
->clazz
->char_next( cmap
, &code
);
3144 result
= ( gindex
== 0 ) ? 0 : code
;
3154 /* documentation is in freetype.h */
3156 FT_EXPORT_DEF( FT_UInt
)
3157 FT_Face_GetCharVariantIndex( FT_Face face
,
3159 FT_ULong variantSelector
)
3164 if ( face
&& face
->charmap
&&
3165 face
->charmap
->encoding
== FT_ENCODING_UNICODE
)
3167 FT_CharMap charmap
= find_variant_selector_charmap( face
);
3168 FT_CMap ucmap
= FT_CMAP( face
->charmap
);
3171 if ( charmap
!= NULL
)
3173 FT_CMap vcmap
= FT_CMAP( charmap
);
3176 if ( charcode
> 0xFFFFFFFFUL
)
3178 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3179 FT_TRACE1(( " 0x%x is truncated\n", charcode
));
3181 if ( variantSelector
> 0xFFFFFFFFUL
)
3183 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
3184 FT_TRACE1(( " 0x%x is truncated\n", variantSelector
));
3187 result
= vcmap
->clazz
->char_var_index( vcmap
, ucmap
,
3188 (FT_UInt32
)charcode
,
3189 (FT_UInt32
)variantSelector
);
3197 /* documentation is in freetype.h */
3199 FT_EXPORT_DEF( FT_Int
)
3200 FT_Face_GetCharVariantIsDefault( FT_Face face
,
3202 FT_ULong variantSelector
)
3209 FT_CharMap charmap
= find_variant_selector_charmap( face
);
3212 if ( charmap
!= NULL
)
3214 FT_CMap vcmap
= FT_CMAP( charmap
);
3217 if ( charcode
> 0xFFFFFFFFUL
)
3219 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3220 FT_TRACE1(( " 0x%x is truncated\n", charcode
));
3222 if ( variantSelector
> 0xFFFFFFFFUL
)
3224 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
3225 FT_TRACE1(( " 0x%x is truncated\n", variantSelector
));
3228 result
= vcmap
->clazz
->char_var_default( vcmap
,
3229 (FT_UInt32
)charcode
,
3230 (FT_UInt32
)variantSelector
);
3238 /* documentation is in freetype.h */
3240 FT_EXPORT_DEF( FT_UInt32
* )
3241 FT_Face_GetVariantSelectors( FT_Face face
)
3243 FT_UInt32
*result
= NULL
;
3248 FT_CharMap charmap
= find_variant_selector_charmap( face
);
3251 if ( charmap
!= NULL
)
3253 FT_CMap vcmap
= FT_CMAP( charmap
);
3254 FT_Memory memory
= FT_FACE_MEMORY( face
);
3257 result
= vcmap
->clazz
->variant_list( vcmap
, memory
);
3265 /* documentation is in freetype.h */
3267 FT_EXPORT_DEF( FT_UInt32
* )
3268 FT_Face_GetVariantsOfChar( FT_Face face
,
3271 FT_UInt32
*result
= NULL
;
3276 FT_CharMap charmap
= find_variant_selector_charmap( face
);
3279 if ( charmap
!= NULL
)
3281 FT_CMap vcmap
= FT_CMAP( charmap
);
3282 FT_Memory memory
= FT_FACE_MEMORY( face
);
3285 if ( charcode
> 0xFFFFFFFFUL
)
3287 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ));
3288 FT_TRACE1(( " 0x%x is truncated\n", charcode
));
3291 result
= vcmap
->clazz
->charvariant_list( vcmap
, memory
,
3292 (FT_UInt32
)charcode
);
3299 /* documentation is in freetype.h */
3301 FT_EXPORT_DEF( FT_UInt32
* )
3302 FT_Face_GetCharsOfVariant( FT_Face face
,
3303 FT_ULong variantSelector
)
3305 FT_UInt32
*result
= NULL
;
3310 FT_CharMap charmap
= find_variant_selector_charmap( face
);
3313 if ( charmap
!= NULL
)
3315 FT_CMap vcmap
= FT_CMAP( charmap
);
3316 FT_Memory memory
= FT_FACE_MEMORY( face
);
3319 if ( variantSelector
> 0xFFFFFFFFUL
)
3321 FT_TRACE1(( "FT_Get_Char_Index: too large variantSelector" ));
3322 FT_TRACE1(( " 0x%x is truncated\n", variantSelector
));
3325 result
= vcmap
->clazz
->variantchar_list( vcmap
, memory
,
3326 (FT_UInt32
)variantSelector
);
3334 /* documentation is in freetype.h */
3336 FT_EXPORT_DEF( FT_UInt
)
3337 FT_Get_Name_Index( FT_Face face
,
3338 FT_String
* glyph_name
)
3343 if ( face
&& FT_HAS_GLYPH_NAMES( face
) )
3345 FT_Service_GlyphDict service
;
3348 FT_FACE_LOOKUP_SERVICE( face
,
3352 if ( service
&& service
->name_index
)
3353 result
= service
->name_index( face
, glyph_name
);
3360 /* documentation is in freetype.h */
3362 FT_EXPORT_DEF( FT_Error
)
3363 FT_Get_Glyph_Name( FT_Face face
,
3364 FT_UInt glyph_index
,
3366 FT_UInt buffer_max
)
3368 FT_Error error
= FT_Err_Invalid_Argument
;
3371 /* clean up buffer */
3372 if ( buffer
&& buffer_max
> 0 )
3373 ((FT_Byte
*)buffer
)[0] = 0;
3376 (FT_Long
)glyph_index
<= face
->num_glyphs
&&
3377 FT_HAS_GLYPH_NAMES( face
) )
3379 FT_Service_GlyphDict service
;
3382 FT_FACE_LOOKUP_SERVICE( face
,
3386 if ( service
&& service
->get_name
)
3387 error
= service
->get_name( face
, glyph_index
, buffer
, buffer_max
);
3394 /* documentation is in freetype.h */
3396 FT_EXPORT_DEF( const char* )
3397 FT_Get_Postscript_Name( FT_Face face
)
3399 const char* result
= NULL
;
3407 FT_Service_PsFontName service
;
3410 FT_FACE_LOOKUP_SERVICE( face
,
3412 POSTSCRIPT_FONT_NAME
);
3414 if ( service
&& service
->get_ps_font_name
)
3415 result
= service
->get_ps_font_name( face
);
3423 /* documentation is in tttables.h */
3425 FT_EXPORT_DEF( void* )
3426 FT_Get_Sfnt_Table( FT_Face face
,
3430 FT_Service_SFNT_Table service
;
3433 if ( face
&& FT_IS_SFNT( face
) )
3435 FT_FACE_FIND_SERVICE( face
, service
, SFNT_TABLE
);
3436 if ( service
!= NULL
)
3437 table
= service
->get_table( face
, tag
);
3444 /* documentation is in tttables.h */
3446 FT_EXPORT_DEF( FT_Error
)
3447 FT_Load_Sfnt_Table( FT_Face face
,
3453 FT_Service_SFNT_Table service
;
3456 if ( !face
|| !FT_IS_SFNT( face
) )
3457 return FT_Err_Invalid_Face_Handle
;
3459 FT_FACE_FIND_SERVICE( face
, service
, SFNT_TABLE
);
3460 if ( service
== NULL
)
3461 return FT_Err_Unimplemented_Feature
;
3463 return service
->load_table( face
, tag
, offset
, buffer
, length
);
3467 /* documentation is in tttables.h */
3469 FT_EXPORT_DEF( FT_Error
)
3470 FT_Sfnt_Table_Info( FT_Face face
,
3471 FT_UInt table_index
,
3475 FT_Service_SFNT_Table service
;
3479 if ( !face
|| !FT_IS_SFNT( face
) )
3480 return FT_Err_Invalid_Face_Handle
;
3482 FT_FACE_FIND_SERVICE( face
, service
, SFNT_TABLE
);
3483 if ( service
== NULL
)
3484 return FT_Err_Unimplemented_Feature
;
3486 return service
->table_info( face
, table_index
, tag
, &offset
, length
);
3490 /* documentation is in tttables.h */
3492 FT_EXPORT_DEF( FT_ULong
)
3493 FT_Get_CMap_Language_ID( FT_CharMap charmap
)
3495 FT_Service_TTCMaps service
;
3497 TT_CMapInfo cmap_info
;
3500 if ( !charmap
|| !charmap
->face
)
3503 face
= charmap
->face
;
3504 FT_FACE_FIND_SERVICE( face
, service
, TT_CMAP
);
3505 if ( service
== NULL
)
3507 if ( service
->get_cmap_info( charmap
, &cmap_info
))
3510 return cmap_info
.language
;
3514 /* documentation is in tttables.h */
3516 FT_EXPORT_DEF( FT_Long
)
3517 FT_Get_CMap_Format( FT_CharMap charmap
)
3519 FT_Service_TTCMaps service
;
3521 TT_CMapInfo cmap_info
;
3524 if ( !charmap
|| !charmap
->face
)
3527 face
= charmap
->face
;
3528 FT_FACE_FIND_SERVICE( face
, service
, TT_CMAP
);
3529 if ( service
== NULL
)
3531 if ( service
->get_cmap_info( charmap
, &cmap_info
))
3534 return cmap_info
.format
;
3538 /* documentation is in ftsizes.h */
3540 FT_EXPORT_DEF( FT_Error
)
3541 FT_Activate_Size( FT_Size size
)
3547 return FT_Err_Invalid_Argument
;
3550 if ( face
== NULL
|| face
->driver
== NULL
)
3551 return FT_Err_Invalid_Argument
;
3553 /* we don't need anything more complex than that; all size objects */
3554 /* are already listed by the face */
3561 /*************************************************************************/
3562 /*************************************************************************/
3563 /*************************************************************************/
3566 /**** R E N D E R E R S ****/
3569 /*************************************************************************/
3570 /*************************************************************************/
3571 /*************************************************************************/
3573 /* lookup a renderer by glyph format in the library's list */
3574 FT_BASE_DEF( FT_Renderer
)
3575 FT_Lookup_Renderer( FT_Library library
,
3576 FT_Glyph_Format format
,
3580 FT_Renderer result
= 0;
3586 cur
= library
->renderers
.head
;
3591 cur
= (*node
)->next
;
3597 FT_Renderer renderer
= FT_RENDERER( cur
->data
);
3600 if ( renderer
->glyph_format
== format
)
3617 ft_lookup_glyph_renderer( FT_GlyphSlot slot
)
3619 FT_Face face
= slot
->face
;
3620 FT_Library library
= FT_FACE_LIBRARY( face
);
3621 FT_Renderer result
= library
->cur_renderer
;
3624 if ( !result
|| result
->glyph_format
!= slot
->format
)
3625 result
= FT_Lookup_Renderer( library
, slot
->format
, 0 );
3632 ft_set_current_renderer( FT_Library library
)
3634 FT_Renderer renderer
;
3637 renderer
= FT_Lookup_Renderer( library
, FT_GLYPH_FORMAT_OUTLINE
, 0 );
3638 library
->cur_renderer
= renderer
;
3643 ft_add_renderer( FT_Module module
)
3645 FT_Library library
= module
->library
;
3646 FT_Memory memory
= library
->memory
;
3651 if ( FT_NEW( node
) )
3655 FT_Renderer render
= FT_RENDERER( module
);
3656 FT_Renderer_Class
* clazz
= (FT_Renderer_Class
*)module
->clazz
;
3659 render
->clazz
= clazz
;
3660 render
->glyph_format
= clazz
->glyph_format
;
3662 /* allocate raster object if needed */
3663 if ( clazz
->glyph_format
== FT_GLYPH_FORMAT_OUTLINE
&&
3664 clazz
->raster_class
->raster_new
)
3666 error
= clazz
->raster_class
->raster_new( memory
, &render
->raster
);
3670 render
->raster_render
= clazz
->raster_class
->raster_render
;
3671 render
->render
= clazz
->render_glyph
;
3675 node
->data
= module
;
3676 FT_List_Add( &library
->renderers
, node
);
3678 ft_set_current_renderer( library
);
3691 ft_remove_renderer( FT_Module module
)
3693 FT_Library library
= module
->library
;
3694 FT_Memory memory
= library
->memory
;
3698 node
= FT_List_Find( &library
->renderers
, module
);
3701 FT_Renderer render
= FT_RENDERER( module
);
3704 /* release raster object, if any */
3705 if ( render
->raster
)
3706 render
->clazz
->raster_class
->raster_done( render
->raster
);
3708 /* remove from list */
3709 FT_List_Remove( &library
->renderers
, node
);
3712 ft_set_current_renderer( library
);
3717 /* documentation is in ftrender.h */
3719 FT_EXPORT_DEF( FT_Renderer
)
3720 FT_Get_Renderer( FT_Library library
,
3721 FT_Glyph_Format format
)
3723 /* test for valid `library' delayed to FT_Lookup_Renderer() */
3725 return FT_Lookup_Renderer( library
, format
, 0 );
3729 /* documentation is in ftrender.h */
3731 FT_EXPORT_DEF( FT_Error
)
3732 FT_Set_Renderer( FT_Library library
,
3733 FT_Renderer renderer
,
3735 FT_Parameter
* parameters
)
3738 FT_Error error
= FT_Err_Ok
;
3742 return FT_Err_Invalid_Library_Handle
;
3745 return FT_Err_Invalid_Argument
;
3747 node
= FT_List_Find( &library
->renderers
, renderer
);
3750 error
= FT_Err_Invalid_Argument
;
3754 FT_List_Up( &library
->renderers
, node
);
3756 if ( renderer
->glyph_format
== FT_GLYPH_FORMAT_OUTLINE
)
3757 library
->cur_renderer
= renderer
;
3759 if ( num_params
> 0 )
3761 FT_Renderer_SetModeFunc set_mode
= renderer
->clazz
->set_mode
;
3764 for ( ; num_params
> 0; num_params
-- )
3766 error
= set_mode( renderer
, parameters
->tag
, parameters
->data
);
3777 FT_BASE_DEF( FT_Error
)
3778 FT_Render_Glyph_Internal( FT_Library library
,
3780 FT_Render_Mode render_mode
)
3782 FT_Error error
= FT_Err_Ok
;
3783 FT_Renderer renderer
;
3786 /* if it is already a bitmap, no need to do anything */
3787 switch ( slot
->format
)
3789 case FT_GLYPH_FORMAT_BITMAP
: /* already a bitmap, don't do anything */
3794 FT_ListNode node
= 0;
3798 /* small shortcut for the very common case */
3799 if ( slot
->format
== FT_GLYPH_FORMAT_OUTLINE
)
3801 renderer
= library
->cur_renderer
;
3802 node
= library
->renderers
.head
;
3805 renderer
= FT_Lookup_Renderer( library
, slot
->format
, &node
);
3807 error
= FT_Err_Unimplemented_Feature
;
3810 error
= renderer
->render( renderer
, slot
, render_mode
, NULL
);
3812 FT_ERROR_BASE( error
) != FT_Err_Cannot_Render_Glyph
)
3815 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
3816 /* is unsupported by the current renderer for this glyph image */
3819 /* now, look for another renderer that supports the same */
3821 renderer
= FT_Lookup_Renderer( library
, slot
->format
, &node
);
3825 /* if we changed the current renderer for the glyph image format */
3826 /* we need to select it as the next current one */
3827 if ( !error
&& update
&& renderer
)
3828 FT_Set_Renderer( library
, renderer
, 0, 0 );
3836 /* documentation is in freetype.h */
3838 FT_EXPORT_DEF( FT_Error
)
3839 FT_Render_Glyph( FT_GlyphSlot slot
,
3840 FT_Render_Mode render_mode
)
3846 return FT_Err_Invalid_Argument
;
3848 library
= FT_FACE_LIBRARY( slot
->face
);
3850 return FT_Render_Glyph_Internal( library
, slot
, render_mode
);
3854 /*************************************************************************/
3855 /*************************************************************************/
3856 /*************************************************************************/
3859 /**** M O D U L E S ****/
3862 /*************************************************************************/
3863 /*************************************************************************/
3864 /*************************************************************************/
3867 /*************************************************************************/
3870 /* Destroy_Module */
3873 /* Destroys a given module object. For drivers, this also destroys */
3874 /* all child faces. */
3877 /* module :: A handle to the target driver object. */
3880 /* The driver _must_ be LOCKED! */
3883 Destroy_Module( FT_Module module
)
3885 FT_Memory memory
= module
->memory
;
3886 FT_Module_Class
* clazz
= module
->clazz
;
3887 FT_Library library
= module
->library
;
3890 /* finalize client-data - before anything else */
3891 if ( module
->generic
.finalizer
)
3892 module
->generic
.finalizer( module
);
3894 if ( library
&& library
->auto_hinter
== module
)
3895 library
->auto_hinter
= 0;
3897 /* if the module is a renderer */
3898 if ( FT_MODULE_IS_RENDERER( module
) )
3899 ft_remove_renderer( module
);
3901 /* if the module is a font driver, add some steps */
3902 if ( FT_MODULE_IS_DRIVER( module
) )
3903 Destroy_Driver( FT_DRIVER( module
) );
3905 /* finalize the module object */
3906 if ( clazz
->module_done
)
3907 clazz
->module_done( module
);
3914 /* documentation is in ftmodapi.h */
3916 FT_EXPORT_DEF( FT_Error
)
3917 FT_Add_Module( FT_Library library
,
3918 const FT_Module_Class
* clazz
)
3926 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
3930 return FT_Err_Invalid_Library_Handle
;
3933 return FT_Err_Invalid_Argument
;
3935 /* check freetype version */
3936 if ( clazz
->module_requires
> FREETYPE_VER_FIXED
)
3937 return FT_Err_Invalid_Version
;
3939 /* look for a module with the same name in the library's table */
3940 for ( nn
= 0; nn
< library
->num_modules
; nn
++ )
3942 module
= library
->modules
[nn
];
3943 if ( ft_strcmp( module
->clazz
->module_name
, clazz
->module_name
) == 0 )
3945 /* this installed module has the same name, compare their versions */
3946 if ( clazz
->module_version
<= module
->clazz
->module_version
)
3947 return FT_Err_Lower_Module_Version
;
3949 /* remove the module from our list, then exit the loop to replace */
3950 /* it by our new version.. */
3951 FT_Remove_Module( library
, module
);
3956 memory
= library
->memory
;
3959 if ( library
->num_modules
>= FT_MAX_MODULES
)
3961 error
= FT_Err_Too_Many_Drivers
;
3965 /* allocate module object */
3966 if ( FT_ALLOC( module
, clazz
->module_size
) )
3969 /* base initialization */
3970 module
->library
= library
;
3971 module
->memory
= memory
;
3972 module
->clazz
= (FT_Module_Class
*)clazz
;
3974 /* check whether the module is a renderer - this must be performed */
3975 /* before the normal module initialization */
3976 if ( FT_MODULE_IS_RENDERER( module
) )
3978 /* add to the renderers list */
3979 error
= ft_add_renderer( module
);
3984 /* is the module a auto-hinter? */
3985 if ( FT_MODULE_IS_HINTER( module
) )
3986 library
->auto_hinter
= module
;
3988 /* if the module is a font driver */
3989 if ( FT_MODULE_IS_DRIVER( module
) )
3991 /* allocate glyph loader if needed */
3992 FT_Driver driver
= FT_DRIVER( module
);
3995 driver
->clazz
= (FT_Driver_Class
)module
->clazz
;
3996 if ( FT_DRIVER_USES_OUTLINES( driver
) )
3998 error
= FT_GlyphLoader_New( memory
, &driver
->glyph_loader
);
4004 if ( clazz
->module_init
)
4006 error
= clazz
->module_init( module
);
4011 /* add module to the library's table */
4012 library
->modules
[library
->num_modules
++] = module
;
4018 if ( FT_MODULE_IS_DRIVER( module
) )
4020 FT_Driver driver
= FT_DRIVER( module
);
4023 if ( FT_DRIVER_USES_OUTLINES( driver
) )
4024 FT_GlyphLoader_Done( driver
->glyph_loader
);
4027 if ( FT_MODULE_IS_RENDERER( module
) )
4029 FT_Renderer renderer
= FT_RENDERER( module
);
4032 if ( renderer
->raster
)
4033 renderer
->clazz
->raster_class
->raster_done( renderer
->raster
);
4041 /* documentation is in ftmodapi.h */
4043 FT_EXPORT_DEF( FT_Module
)
4044 FT_Get_Module( FT_Library library
,
4045 const char* module_name
)
4047 FT_Module result
= 0;
4052 if ( !library
|| !module_name
)
4055 cur
= library
->modules
;
4056 limit
= cur
+ library
->num_modules
;
4058 for ( ; cur
< limit
; cur
++ )
4059 if ( ft_strcmp( cur
[0]->clazz
->module_name
, module_name
) == 0 )
4069 /* documentation is in ftobjs.h */
4071 FT_BASE_DEF( const void* )
4072 FT_Get_Module_Interface( FT_Library library
,
4073 const char* mod_name
)
4078 /* test for valid `library' delayed to FT_Get_Module() */
4080 module
= FT_Get_Module( library
, mod_name
);
4082 return module
? module
->clazz
->module_interface
: 0;
4086 FT_BASE_DEF( FT_Pointer
)
4087 ft_module_get_service( FT_Module module
,
4088 const char* service_id
)
4090 FT_Pointer result
= NULL
;
4094 FT_ASSERT( module
->clazz
&& module
->clazz
->get_interface
);
4096 /* first, look for the service in the module
4098 if ( module
->clazz
->get_interface
)
4099 result
= module
->clazz
->get_interface( module
, service_id
);
4101 if ( result
== NULL
)
4103 /* we didn't find it, look in all other modules then
4105 FT_Library library
= module
->library
;
4106 FT_Module
* cur
= library
->modules
;
4107 FT_Module
* limit
= cur
+ library
->num_modules
;
4109 for ( ; cur
< limit
; cur
++ )
4111 if ( cur
[0] != module
)
4113 FT_ASSERT( cur
[0]->clazz
);
4115 if ( cur
[0]->clazz
->get_interface
)
4117 result
= cur
[0]->clazz
->get_interface( cur
[0], service_id
);
4118 if ( result
!= NULL
)
4130 /* documentation is in ftmodapi.h */
4132 FT_EXPORT_DEF( FT_Error
)
4133 FT_Remove_Module( FT_Library library
,
4136 /* try to find the module from the table, then remove it from there */
4139 return FT_Err_Invalid_Library_Handle
;
4143 FT_Module
* cur
= library
->modules
;
4144 FT_Module
* limit
= cur
+ library
->num_modules
;
4147 for ( ; cur
< limit
; cur
++ )
4149 if ( cur
[0] == module
)
4151 /* remove it from the table */
4152 library
->num_modules
--;
4154 while ( cur
< limit
)
4161 /* destroy the module */
4162 Destroy_Module( module
);
4168 return FT_Err_Invalid_Driver_Handle
;
4172 /*************************************************************************/
4173 /*************************************************************************/
4174 /*************************************************************************/
4177 /**** L I B R A R Y ****/
4180 /*************************************************************************/
4181 /*************************************************************************/
4182 /*************************************************************************/
4185 /* documentation is in ftmodapi.h */
4187 FT_EXPORT_DEF( FT_Error
)
4188 FT_New_Library( FT_Memory memory
,
4189 FT_Library
*alibrary
)
4191 FT_Library library
= 0;
4196 return FT_Err_Invalid_Argument
;
4198 #ifdef FT_DEBUG_LEVEL_ERROR
4199 /* init debugging support */
4203 /* first of all, allocate the library object */
4204 if ( FT_NEW( library
) )
4207 library
->memory
= memory
;
4209 #ifdef FT_CONFIG_OPTION_PIC
4210 /* initialize position independent code containers */
4211 error
= ft_pic_container_init( library
);
4216 /* allocate the render pool */
4217 library
->raster_pool_size
= FT_RENDER_POOL_SIZE
;
4218 #if FT_RENDER_POOL_SIZE > 0
4219 if ( FT_ALLOC( library
->raster_pool
, FT_RENDER_POOL_SIZE
) )
4223 library
->version_major
= FREETYPE_MAJOR
;
4224 library
->version_minor
= FREETYPE_MINOR
;
4225 library
->version_patch
= FREETYPE_PATCH
;
4228 *alibrary
= library
;
4233 #ifdef FT_CONFIG_OPTION_PIC
4234 ft_pic_container_destroy( library
);
4241 /* documentation is in freetype.h */
4243 FT_EXPORT_DEF( void )
4244 FT_Library_Version( FT_Library library
,
4256 major
= library
->version_major
;
4257 minor
= library
->version_minor
;
4258 patch
= library
->version_patch
;
4272 /* documentation is in ftmodapi.h */
4274 FT_EXPORT_DEF( FT_Error
)
4275 FT_Done_Library( FT_Library library
)
4281 return FT_Err_Invalid_Library_Handle
;
4283 memory
= library
->memory
;
4285 /* Discard client-data */
4286 if ( library
->generic
.finalizer
)
4287 library
->generic
.finalizer( library
);
4289 /* Close all faces in the library. If we don't do
4290 * this, we can have some subtle memory leaks.
4293 * - the cff font driver uses the pshinter module in cff_size_done
4294 * - if the pshinter module is destroyed before the cff font driver,
4295 * opened FT_Face objects managed by the driver are not properly
4296 * destroyed, resulting in a memory leak
4302 for ( n
= 0; n
< library
->num_modules
; n
++ )
4304 FT_Module module
= library
->modules
[n
];
4308 if ( ( module
->clazz
->module_flags
& FT_MODULE_FONT_DRIVER
) == 0 )
4311 faces
= &FT_DRIVER(module
)->faces_list
;
4312 while ( faces
->head
)
4314 FT_Done_Face( FT_FACE( faces
->head
->data
) );
4316 FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ));
4321 /* Close all other modules in the library */
4323 /* XXX Modules are removed in the reversed order so that */
4324 /* type42 module is removed before truetype module. This */
4325 /* avoids double free in some occasions. It is a hack. */
4326 while ( library
->num_modules
> 0 )
4327 FT_Remove_Module( library
,
4328 library
->modules
[library
->num_modules
- 1] );
4334 for ( n
= 0; n
< library
->num_modules
; n
++ )
4336 FT_Module module
= library
->modules
[n
];
4341 Destroy_Module( module
);
4342 library
->modules
[n
] = 0;
4348 /* Destroy raster objects */
4349 FT_FREE( library
->raster_pool
);
4350 library
->raster_pool_size
= 0;
4352 #ifdef FT_CONFIG_OPTION_PIC
4353 /* Destroy pic container contents */
4354 ft_pic_container_destroy( library
);
4362 /* documentation is in ftmodapi.h */
4364 FT_EXPORT_DEF( void )
4365 FT_Set_Debug_Hook( FT_Library library
,
4367 FT_DebugHook_Func debug_hook
)
4369 if ( library
&& debug_hook
&&
4371 ( sizeof ( library
->debug_hooks
) / sizeof ( void* ) ) )
4372 library
->debug_hooks
[hook_index
] = debug_hook
;
4376 /* documentation is in ftmodapi.h */
4378 FT_EXPORT_DEF( FT_TrueTypeEngineType
)
4379 FT_Get_TrueType_Engine_Type( FT_Library library
)
4381 FT_TrueTypeEngineType result
= FT_TRUETYPE_ENGINE_TYPE_NONE
;
4386 FT_Module module
= FT_Get_Module( library
, "truetype" );
4391 FT_Service_TrueTypeEngine service
;
4394 service
= (FT_Service_TrueTypeEngine
)
4395 ft_module_get_service( module
,
4396 FT_SERVICE_ID_TRUETYPE_ENGINE
);
4398 result
= service
->engine_type
;
4406 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
4408 FT_BASE_DEF( FT_Error
)
4409 ft_stub_set_char_sizes( FT_Size size
,
4415 FT_Size_RequestRec req
;
4416 FT_Driver driver
= size
->face
->driver
;
4419 if ( driver
->clazz
->request_size
)
4421 req
.type
= FT_SIZE_REQUEST_TYPE_NOMINAL
;
4423 req
.height
= height
;
4425 if ( horz_res
== 0 )
4426 horz_res
= vert_res
;
4428 if ( vert_res
== 0 )
4429 vert_res
= horz_res
;
4431 if ( horz_res
== 0 )
4432 horz_res
= vert_res
= 72;
4434 req
.horiResolution
= horz_res
;
4435 req
.vertResolution
= vert_res
;
4437 return driver
->clazz
->request_size( size
, &req
);
4444 FT_BASE_DEF( FT_Error
)
4445 ft_stub_set_pixel_sizes( FT_Size size
,
4449 FT_Size_RequestRec req
;
4450 FT_Driver driver
= size
->face
->driver
;
4453 if ( driver
->clazz
->request_size
)
4455 req
.type
= FT_SIZE_REQUEST_TYPE_NOMINAL
;
4456 req
.width
= width
<< 6;
4457 req
.height
= height
<< 6;
4458 req
.horiResolution
= 0;
4459 req
.vertResolution
= 0;
4461 return driver
->clazz
->request_size( size
, &req
);
4467 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
4470 FT_EXPORT_DEF( FT_Error
)
4471 FT_Get_SubGlyph_Info( FT_GlyphSlot glyph
,
4477 FT_Matrix
*p_transform
)
4479 FT_Error error
= FT_Err_Invalid_Argument
;
4482 if ( glyph
!= NULL
&&
4483 glyph
->format
== FT_GLYPH_FORMAT_COMPOSITE
&&
4484 sub_index
< glyph
->num_subglyphs
)
4486 FT_SubGlyph subg
= glyph
->subglyphs
+ sub_index
;
4489 *p_index
= subg
->index
;
4490 *p_flags
= subg
->flags
;
4491 *p_arg1
= subg
->arg1
;
4492 *p_arg2
= subg
->arg2
;
4493 *p_transform
= subg
->transform
;