1 /***************************************************************************/
2 /* */
3 /* ftobjs.c */
4 /* */
5 /* The FreeType private base classes (body). */
6 /* */
7 /* Copyright 1996-2001 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
19 #include <ft2build.h>
20 #include FT_LIST_H
21 #include FT_INTERNAL_OBJECTS_H
22 #include FT_INTERNAL_DEBUG_H
23 #include FT_INTERNAL_STREAM_H
24 #include FT_TRUETYPE_TABLES_H
26 #include <string.h> /* for strcmp() */
29 /*************************************************************************/
30 /*************************************************************************/
31 /*************************************************************************/
32 /**** ****/
33 /**** ****/
34 /**** M E M O R Y ****/
35 /**** ****/
36 /**** ****/
37 /*************************************************************************/
38 /*************************************************************************/
39 /*************************************************************************/
41 /*************************************************************************/
42 /* */
43 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
44 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
45 /* messages during execution. */
46 /* */
47 #undef FT_COMPONENT
48 #define FT_COMPONENT trace_memory
51 /* documentation is in ftmemory.h */
53 FT_BASE_DEF( FT_Error )
54 FT_Alloc( FT_Memory memory,
55 FT_Long size,
56 void* *P )
57 {
58 FT_Assert( P != 0 );
60 if ( size > 0 )
61 {
62 *P = memory->alloc( memory, size );
63 if ( !*P )
64 {
65 FT_ERROR(( "FT_Alloc:" ));
66 FT_ERROR(( " Out of memory? (%ld requested)\n",
67 size ));
69 return FT_Err_Out_Of_Memory;
70 }
71 MEM_Set( *P, 0, size );
72 }
73 else
74 *P = NULL;
76 FT_TRACE7(( "FT_Alloc:" ));
77 FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
78 size, *P, P ));
80 return FT_Err_Ok;
81 }
84 /* documentation is in ftmemory.h */
86 FT_BASE_DEF( FT_Error )
87 FT_Realloc( FT_Memory memory,
88 FT_Long current,
89 FT_Long size,
90 void** P )
91 {
92 void* Q;
95 FT_Assert( P != 0 );
97 /* if the original pointer is NULL, call FT_Alloc() */
98 if ( !*P )
99 return FT_Alloc( memory, size, P );
101 /* if the new block if zero-sized, clear the current one */
102 if ( size <= 0 )
103 {
104 FT_Free( memory, P );
105 return FT_Err_Ok;
106 }
108 Q = memory->realloc( memory, current, size, *P );
109 if ( !Q )
110 goto Fail;
112 *P = Q;
113 return FT_Err_Ok;
115 Fail:
116 FT_ERROR(( "FT_Realloc:" ));
117 FT_ERROR(( " Failed (current %ld, requested %ld)\n",
118 current, size ));
119 return FT_Err_Out_Of_Memory;
120 }
123 /* documentation is in ftmemory.h */
125 FT_BASE_DEF( void )
126 FT_Free( FT_Memory memory,
127 void** P )
128 {
129 FT_TRACE7(( "FT_Free:" ));
130 FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
131 P, P ? *P : (void*)0 ));
133 if ( P && *P )
134 {
135 memory->free( memory, *P );
136 *P = 0;
137 }
138 }
141 /*************************************************************************/
142 /*************************************************************************/
143 /*************************************************************************/
144 /**** ****/
145 /**** ****/
146 /**** S T R E A M ****/
147 /**** ****/
148 /**** ****/
149 /*************************************************************************/
150 /*************************************************************************/
151 /*************************************************************************/
154 /*************************************************************************/
155 /* */
156 /* <Function> */
157 /* ft_new_input_stream */
158 /* */
159 /* <Description> */
160 /* Creates a new input stream object from an FT_Open_Args structure. */
161 /* */
162 /* <Note> */
163 /* The function expects a valid `astream' parameter. */
164 /* */
165 static FT_Error
166 ft_new_input_stream( FT_Library library,
167 FT_Open_Args* args,
168 FT_Stream* astream )
169 {
170 FT_Error error;
171 FT_Memory memory;
172 FT_Stream stream;
175 if ( !library )
176 return FT_Err_Invalid_Library_Handle;
178 if ( !args )
179 return FT_Err_Invalid_Argument;
181 *astream = 0;
182 memory = library->memory;
183 if ( ALLOC( stream, sizeof ( *stream ) ) )
184 goto Exit;
186 stream->memory = memory;
188 /* now, look at the stream flags */
189 if ( args->flags & ft_open_memory )
190 {
191 error = 0;
192 FT_New_Memory_Stream( library,
193 (FT_Byte*)args->memory_base,
194 args->memory_size,
195 stream );
196 }
197 else if ( args->flags & ft_open_pathname )
198 {
199 error = FT_New_Stream( args->pathname, stream );
200 stream->pathname.pointer = args->pathname;
201 }
202 else if ( ( args->flags & ft_open_stream ) && args->stream )
203 {
204 /* in this case, we do not need to allocate a new stream object */
205 /* since the caller is responsible for closing it himself */
206 FREE( stream );
207 stream = args->stream;
208 }
209 else
210 error = FT_Err_Invalid_Argument;
212 if ( error )
213 FREE( stream );
215 *astream = stream;
217 Exit:
218 return error;
219 }
222 /* documentation is in ftobjs.h */
224 FT_EXPORT_DEF( void )
225 FT_Done_Stream( FT_Stream stream )
226 {
227 if ( stream && stream->close )
228 {
229 stream->close( stream );
230 stream->close = 0;
231 }
232 }
235 static void
236 ft_done_stream( FT_Stream* astream,
237 FT_Int external )
238 {
239 FT_Stream stream = *astream;
242 if ( stream->close )
243 stream->close( stream );
245 if ( !external )
246 {
247 FT_Memory memory = stream->memory;
250 FREE( stream );
251 }
252 *astream = 0;
253 }
256 #undef FT_COMPONENT
257 #define FT_COMPONENT trace_objs
260 /*************************************************************************/
261 /*************************************************************************/
262 /*************************************************************************/
263 /**** ****/
264 /**** ****/
265 /**** G L Y P H L O A D E R ****/
266 /**** ****/
267 /**** ****/
268 /*************************************************************************/
269 /*************************************************************************/
270 /*************************************************************************/
273 /*************************************************************************/
274 /* */
275 /* The glyph loader is a simple object which is used to load a set of */
276 /* glyphs easily. It is critical for the correct loading of composites. */
277 /* */
278 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
279 /* */
280 /* loader.base Is really the bottom of the stack. It describes a */
281 /* single glyph image made of the juxtaposition of */
282 /* several glyphs (those `in the stack'). */
283 /* */
284 /* loader.current Describes the top of the stack, on which a new */
285 /* glyph can be loaded. */
286 /* */
287 /* Rewind Clears the stack. */
288 /* Prepare Set up `loader.current' for addition of a new glyph */
289 /* image. */
290 /* Add Add the `current' glyph image to the `base' one, */
291 /* and prepare for another one. */
292 /* */
293 /* The glyph loader is now a base object. Each driver used to */
294 /* re-implement it in one way or the other, which wasted code and */
295 /* energy. */
296 /* */
297 /*************************************************************************/
300 /* create a new glyph loader */
301 FT_BASE_DEF( FT_Error )
302 FT_GlyphLoader_New( FT_Memory memory,
303 FT_GlyphLoader* *aloader )
304 {
305 FT_GlyphLoader* loader;
306 FT_Error error;
309 if ( !ALLOC( loader, sizeof ( *loader ) ) )
310 {
311 loader->memory = memory;
312 *aloader = loader;
313 }
314 return error;
315 }
318 /* rewind the glyph loader - reset counters to 0 */
319 FT_BASE_DEF( void )
320 FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
321 {
322 FT_GlyphLoad* base = &loader->base;
323 FT_GlyphLoad* current = &loader->current;
326 base->outline.n_points = 0;
327 base->outline.n_contours = 0;
328 base->num_subglyphs = 0;
330 *current = *base;
331 }
334 /* reset the glyph loader, frees all allocated tables */
335 /* and starts from zero */
336 FT_BASE_DEF( void )
337 FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
338 {
339 FT_Memory memory = loader->memory;
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 );
353 }
356 /* delete a glyph loader */
357 FT_BASE_DEF( void )
358 FT_GlyphLoader_Done( FT_GlyphLoader* loader )
359 {
360 if ( loader )
361 {
362 FT_Memory memory = loader->memory;
365 FT_GlyphLoader_Reset( loader );
366 FREE( loader );
367 }
368 }
371 /* re-adjust the `current' outline fields */
372 static void
373 FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
374 {
375 FT_Outline* base = &loader->base.outline;
376 FT_Outline* current = &loader->current.outline;
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;
387 }
390 FT_BASE_DEF( FT_Error )
391 FT_GlyphLoader_Create_Extra( FT_GlyphLoader* loader )
392 {
393 FT_Error error;
394 FT_Memory memory = loader->memory;
397 if ( !ALLOC_ARRAY( loader->base.extra_points,
398 loader->max_points, FT_Vector ) )
399 {
400 loader->use_extra = 1;
401 FT_GlyphLoader_Adjust_Points( loader );
402 }
403 return error;
404 }
407 /* re-adjust the `current' subglyphs field */
408 static void
409 FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
410 {
411 FT_GlyphLoad* base = &loader->base;
412 FT_GlyphLoad* current = &loader->current;
415 current->subglyphs = base->subglyphs + base->num_subglyphs;
416 }
419 /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
420 /* function reallocates its outline tables if necessary. Note that it */
421 /* DOESN'T change the number of points within the loader! */
422 /* */
423 FT_BASE_DEF( FT_Error )
424 FT_GlyphLoader_Check_Points( FT_GlyphLoader* loader,
425 FT_UInt n_points,
426 FT_UInt n_contours )
427 {
428 FT_Memory memory = loader->memory;
429 FT_Error error = FT_Err_Ok;
430 FT_Outline* base = &loader->base.outline;
431 FT_Outline* current = &loader->current.outline;
432 FT_Bool adjust = 1;
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 )
442 {
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 ) )
447 goto Exit;
449 if ( loader->use_extra &&
450 REALLOC_ARRAY( loader->base.extra_points, old_max,
451 new_max, FT_Vector ) )
452 goto Exit;
454 adjust = 1;
455 loader->max_points = new_max;
456 }
458 /* check contours */
459 old_max = loader->max_contours;
460 new_max = base->n_contours + current->n_contours +
461 n_contours;
462 if ( new_max > old_max )
463 {
464 new_max = ( new_max + 3 ) & -4;
465 if ( REALLOC_ARRAY( base->contours, old_max, new_max, FT_Short ) )
466 goto Exit;
468 adjust = 1;
469 loader->max_contours = new_max;
470 }
472 if ( adjust )
473 FT_GlyphLoader_Adjust_Points( loader );
475 Exit:
476 return error;
477 }
480 /* Ensure that we can add `n_subglyphs' to our glyph. this function */
481 /* reallocates its subglyphs table if necessary. Note that it DOES */
482 /* NOT change the number of subglyphs within the loader! */
483 /* */
484 FT_BASE_DEF( FT_Error )
485 FT_GlyphLoader_Check_Subglyphs( FT_GlyphLoader* loader,
486 FT_UInt n_subs )
487 {
488 FT_Memory memory = loader->memory;
489 FT_Error error = FT_Err_Ok;
490 FT_UInt new_max, old_max;
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 )
499 {
500 new_max = ( new_max + 1 ) & -2;
501 if ( REALLOC_ARRAY( base->subglyphs, old_max, new_max, FT_SubGlyph ) )
502 goto Exit;
504 loader->max_subglyphs = new_max;
506 FT_GlyphLoader_Adjust_Subglyphs( loader );
507 }
509 Exit:
510 return error;
511 }
514 /* prepare loader for the addition of a new glyph on top of the base one */
515 FT_BASE_DEF( void )
516 FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
517 {
518 FT_GlyphLoad* current = &loader->current;
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 );
527 }
530 /* add current glyph to the base image - and prepare for another */
531 FT_BASE_DEF( void )
532 FT_GlyphLoader_Add( FT_GlyphLoader* loader )
533 {
534 FT_GlyphLoad* base = &loader->base;
535 FT_GlyphLoad* current = &loader->current;
537 FT_UInt n_curr_contours = current->outline.n_contours;
538 FT_UInt n_base_points = base->outline.n_points;
539 FT_UInt n;
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 );
556 }
559 FT_BASE_DEF( FT_Error )
560 FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
561 FT_GlyphLoader* source )
562 {
563 FT_Error error;
564 FT_UInt num_points = source->base.outline.n_points;
565 FT_UInt num_contours = source->base.outline.n_contours;
568 error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
569 if ( !error )
570 {
571 FT_Outline* out = &target->base.outline;
572 FT_Outline* in = &source->base.outline;
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 );
591 }
593 return error;
594 }
597 /*************************************************************************/
598 /*************************************************************************/
599 /*************************************************************************/
600 /**** ****/
601 /**** ****/
602 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
603 /**** ****/
604 /**** ****/
605 /*************************************************************************/
606 /*************************************************************************/
607 /*************************************************************************/
610 static FT_Error
611 ft_glyphslot_init( FT_GlyphSlot slot )
612 {
613 FT_Driver driver = slot->face->driver;
614 FT_Driver_Class* clazz = driver->clazz;
615 FT_Memory memory = driver->root.memory;
616 FT_Error error = FT_Err_Ok;
617 FT_Slot_Internal internal;
620 slot->library = driver->root.library;
622 if ( ALLOC( internal, sizeof ( *internal ) ) )
623 goto Exit;
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 );
633 Exit:
634 return error;
635 }
638 static void
639 ft_glyphslot_clear( FT_GlyphSlot slot )
640 {
641 /* free bitmap if needed */
642 if ( slot->flags & ft_glyph_own_bitmap )
643 {
644 FT_Memory memory = FT_FACE_MEMORY( slot->face );
647 FREE( slot->bitmap.buffer );
648 slot->flags &= ~ft_glyph_own_bitmap;
649 }
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;
659 slot->subglyphs = 0;
660 slot->control_data = 0;
661 slot->control_len = 0;
662 slot->other = 0;
663 slot->format = ft_glyph_format_none;
665 slot->linearHoriAdvance = 0;
666 slot->linearVertAdvance = 0;
667 }
670 static void
671 ft_glyphslot_done( FT_GlyphSlot slot )
672 {
673 FT_Driver driver = slot->face->driver;
674 FT_Driver_Class* clazz = driver->clazz;
675 FT_Memory memory = driver->root.memory;
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 ) )
687 {
688 FT_GlyphLoader_Done( slot->internal->loader );
689 slot->internal->loader = 0;
690 }
692 FREE( slot->internal );
693 }
696 /* documentation is in ftobjs.h */
698 FT_BASE_DEF( FT_Error )
699 FT_New_GlyphSlot( FT_Face face,
700 FT_GlyphSlot *aslot )
701 {
702 FT_Error error;
703 FT_Driver driver;
704 FT_Driver_Class* clazz;
705 FT_Memory memory;
706 FT_GlyphSlot slot;
709 if ( !face || !aslot || !face->driver )
710 return FT_Err_Invalid_Argument;
712 *aslot = 0;
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 ) )
720 {
721 slot->face = face;
723 error = ft_glyphslot_init( slot );
724 if ( error )
725 {
726 ft_glyphslot_done( slot );
727 FREE( slot );
728 goto Exit;
729 }
731 *aslot = slot;
732 }
734 Exit:
735 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
736 return error;
737 }
740 /* documentation is in ftobjs.h */
742 FT_BASE_DEF( void )
743 FT_Done_GlyphSlot( FT_GlyphSlot slot )
744 {
745 if ( slot )
746 {
747 FT_Driver driver = slot->face->driver;
748 FT_Memory memory = driver->root.memory;
749 FT_GlyphSlot* parent;
750 FT_GlyphSlot cur;
753 /* Remove slot from its parent face's list */
754 parent = &slot->face->glyph;
755 cur = *parent;
757 while ( cur )
758 {
759 if ( cur == slot )
760 {
761 *parent = cur->next;
762 ft_glyphslot_done( slot );
763 FREE( slot );
764 break;
765 }
766 cur = cur->next;
767 }
768 }
769 }
772 /* documentation is in freetype.h */
774 FT_EXPORT_DEF( void )
775 FT_Set_Transform( FT_Face face,
776 FT_Matrix* matrix,
777 FT_Vector* delta )
778 {
779 FT_Face_Internal internal;
782 if ( !face )
783 return;
785 internal = face->internal;
787 internal->transform_flags = 0;
789 if ( !matrix )
790 {
791 internal->transform_matrix.xx = 0x10000L;
792 internal->transform_matrix.xy = 0;
793 internal->transform_matrix.yx = 0;
794 internal->transform_matrix.yy = 0x10000L;
795 matrix = &internal->transform_matrix;
796 }
797 else
798 internal->transform_matrix = *matrix;
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;
806 if ( !delta )
807 {
808 internal->transform_delta.x = 0;
809 internal->transform_delta.y = 0;
810 delta = &internal->transform_delta;
811 }
812 else
813 internal->transform_delta = *delta;
815 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
816 if ( delta->x | delta->y )
817 internal->transform_flags |= 2;
818 }
821 static FT_Renderer
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,
829 FT_UInt glyph_index,
830 FT_Int load_flags )
831 {
832 FT_Error error;
833 FT_Driver driver;
834 FT_GlyphSlot slot;
835 FT_Library library;
836 FT_Bool autohint;
837 FT_Module hinter;
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;
846 slot = face->glyph;
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 )
853 {
854 /* disable scaling, hinting, and transformation */
855 load_flags |= FT_LOAD_NO_SCALE |
856 FT_LOAD_NO_HINTING |
857 FT_LOAD_IGNORE_TRANSFORM;
859 /* disable bitmap rendering */
860 load_flags &= ~FT_LOAD_RENDER;
861 }
863 /* do we need to load the glyph through the auto-hinter? */
864 library = driver->root.library;
865 hinter = library->auto_hinter;
866 autohint =
867 FT_BOOL( hinter &&
868 !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) &&
869 FT_DRIVER_IS_SCALABLE( driver ) &&
870 FT_DRIVER_USES_OUTLINES( driver ) );
871 if ( autohint )
872 {
873 if ( FT_DRIVER_HAS_HINTER( driver ) &&
874 !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
875 autohint = 0;
876 }
878 if ( autohint )
879 {
880 FT_AutoHinter_Interface* hinting;
883 hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
885 error = hinting->load_glyph( (FT_AutoHinter)hinter,
886 slot, face->size,
887 glyph_index, load_flags );
888 }
889 else
890 error = driver->clazz->load_glyph( slot,
891 face->size,
892 glyph_index,
893 load_flags );
894 if ( error )
895 goto Exit;
897 /* compute the advance */
898 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
899 {
900 slot->advance.x = 0;
901 slot->advance.y = slot->metrics.vertAdvance;
902 }
903 else
904 {
905 slot->advance.x = slot->metrics.horiAdvance;
906 slot->advance.y = 0;
907 }
909 /* compute the linear advance in 16.16 pixels */
910 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN ) == 0 )
911 {
912 FT_UInt EM = face->units_per_EM;
913 FT_Size_Metrics* metrics = &face->size->metrics;
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 );
920 }
922 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM ) == 0 )
923 {
924 FT_Face_Internal internal = face->internal;
927 /* now, transform the glyph image if needed */
928 if ( internal->transform_flags )
929 {
930 /* get renderer */
931 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
934 if ( renderer )
935 error = renderer->clazz->transform_glyph(
936 renderer, slot,
937 &internal->transform_matrix,
938 &internal->transform_delta );
939 /* transform advance */
940 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
941 }
942 }
944 /* do we need to render the image now? */
945 if ( !error &&
946 slot->format != ft_glyph_format_bitmap &&
947 slot->format != ft_glyph_format_composite &&
948 load_flags & FT_LOAD_RENDER )
949 {
950 error = FT_Render_Glyph( slot,
951 ( load_flags & FT_LOAD_MONOCHROME )
952 ? ft_render_mode_mono
953 : ft_render_mode_normal );
954 }
956 Exit:
957 return error;
958 }
961 /* documentation is in freetype.h */
963 FT_EXPORT_DEF( FT_Error )
964 FT_Load_Char( FT_Face face,
965 FT_ULong char_code,
966 FT_Int load_flags )
967 {
968 FT_UInt glyph_index;
971 if ( !face )
972 return FT_Err_Invalid_Face_Handle;
974 glyph_index = (FT_UInt)char_code;
975 if ( face->charmap )
976 glyph_index = FT_Get_Char_Index( face, char_code );
978 return FT_Load_Glyph( face, glyph_index, load_flags );
979 }
982 /* destructor for sizes list */
983 static void
984 destroy_size( FT_Memory memory,
985 FT_Size size,
986 FT_Driver driver )
987 {
988 /* finalize client-specific data */
989 if ( size->generic.finalizer )
990 size->generic.finalizer( size );
992 /* finalize format-specific stuff */
993 if ( driver->clazz->done_size )
994 driver->clazz->done_size( size );
996 FREE( size->internal );
997 FREE( size );
998 }
1001 /* destructor for faces list */
1002 static void
1003 destroy_face( FT_Memory memory,
1004 FT_Face face,
1005 FT_Driver driver )
1006 {
1007 FT_Driver_Class* clazz = driver->clazz;
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,
1022 memory,
1023 driver );
1024 face->size = 0;
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 */
1035 ft_done_stream(
1036 &face->stream,
1037 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 );
1039 /* get rid of it */
1040 if ( face->internal )
1041 {
1042 FREE( face->internal->postscript_name );
1043 FREE( face->internal );
1044 }
1045 FREE( face );
1046 }
1049 static void
1050 Destroy_Driver( FT_Driver driver )
1051 {
1052 FT_List_Finalize( &driver->faces_list,
1053 (FT_List_Destructor)destroy_face,
1054 driver->root.memory,
1055 driver );
1057 /* check whether we need to drop the driver's glyph loader */
1058 if ( FT_DRIVER_USES_OUTLINES( driver ) )
1059 FT_GlyphLoader_Done( driver->glyph_loader );
1060 }
1063 /*************************************************************************/
1064 /* */
1065 /* <Function> */
1066 /* open_face */
1067 /* */
1068 /* <Description> */
1069 /* This function does some work for FT_Open_Face(). */
1070 /* */
1071 static FT_Error
1072 open_face( FT_Driver driver,
1073 FT_Stream stream,
1074 FT_Long face_index,
1075 FT_Int num_params,
1076 FT_Parameter* params,
1077 FT_Face* aface )
1078 {
1079 FT_Memory memory;
1080 FT_Driver_Class* clazz;
1081 FT_Face face = 0;
1082 FT_Error error;
1083 FT_Face_Internal internal;
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 ) )
1091 goto Fail;
1093 if ( ALLOC( internal, sizeof ( *internal ) ) )
1094 goto Fail;
1096 face->internal = internal;
1098 face->driver = driver;
1099 face->memory = memory;
1100 face->stream = stream;
1102 error = clazz->init_face( stream,
1103 face,
1104 face_index,
1105 num_params,
1106 params );
1107 if ( error )
1108 goto Fail;
1110 *aface = face;
1112 Fail:
1113 if ( error )
1114 {
1115 clazz->done_face( face );
1116 FREE( face->internal );
1117 FREE( face );
1118 *aface = 0;
1119 }
1121 return error;
1122 }
1125 /* there's a Mac-specific extended implementation of FT_New_Face() */
1126 /* in src/mac/ftmac.c */
1128 #ifndef macintosh
1130 /* documentation is in freetype.h */
1132 FT_EXPORT_DEF( FT_Error )
1133 FT_New_Face( FT_Library library,
1134 const char* pathname,
1135 FT_Long face_index,
1136 FT_Face *aface )
1137 {
1138 FT_Open_Args args;
1141 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1142 if ( !pathname )
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 );
1149 }
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,
1159 FT_Long file_size,
1160 FT_Long face_index,
1161 FT_Face *aface )
1162 {
1163 FT_Open_Args args;
1166 /* test for valid `library' and `face' delayed to FT_Open_Face() */
1167 if ( !file_base )
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 );
1175 }
1178 /* documentation is in freetype.h */
1180 FT_EXPORT_DEF( FT_Error )
1181 FT_Open_Face( FT_Library library,
1182 FT_Open_Args* args,
1183 FT_Long face_index,
1184 FT_Face *aface )
1185 {
1186 FT_Error error;
1187 FT_Driver driver;
1188 FT_Memory memory;
1189 FT_Stream stream;
1190 FT_Face face = 0;
1191 FT_ListNode node = 0;
1192 FT_Bool external_stream;
1195 /* test for valid `library' delayed to */
1196 /* ft_new_input_stream() */
1198 if ( !aface || !args )
1199 return FT_Err_Invalid_Argument;
1201 *aface = 0;
1203 external_stream = FT_BOOL( ( args->flags & ft_open_stream ) &&
1204 args->stream );
1206 /* create input stream */
1207 error = ft_new_input_stream( library, args, &stream );
1208 if ( error )
1209 goto Exit;
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 )
1216 {
1217 driver = FT_DRIVER( args->driver );
1219 /* not all modules are drivers, so check... */
1220 if ( FT_MODULE_IS_DRIVER( driver ) )
1221 {
1222 FT_Int num_params = 0;
1223 FT_Parameter* params = 0;
1226 if ( args->flags & ft_open_params )
1227 {
1228 num_params = args->num_params;
1229 params = args->params;
1230 }
1232 error = open_face( driver, stream, face_index,
1233 num_params, params, &face );
1234 if ( !error )
1235 goto Success;
1236 }
1237 else
1238 error = FT_Err_Invalid_Handle;
1240 ft_done_stream( &stream, external_stream );
1241 goto Fail;
1242 }
1243 else
1244 {
1245 /* check each font driver for an appropriate format */
1246 FT_Module* cur = library->modules;
1247 FT_Module* limit = cur + library->num_modules;
1250 for ( ; cur < limit; cur++ )
1251 {
1252 /* not all modules are font drivers, so check... */
1253 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
1254 {
1255 FT_Int num_params = 0;
1256 FT_Parameter* params = 0;
1259 driver = FT_DRIVER( cur[0] );
1261 if ( args->flags & ft_open_params )
1262 {
1263 num_params = args->num_params;
1264 params = args->params;
1265 }
1267 error = open_face( driver, stream, face_index,
1268 num_params, params, &face );
1269 if ( !error )
1270 goto Success;
1272 if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
1273 goto Fail2;
1274 }
1275 }
1277 /* no driver is able to handle this format */
1278 error = FT_Err_Unknown_File_Format;
1280 Fail2:
1281 ft_done_stream( &stream, external_stream );
1282 goto Fail;
1283 }
1285 Success:
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 ) ) )
1294 goto Fail;
1296 node->data = face;
1297 /* don't assume driver is the same as face->driver, so use */
1298 /* face->driver instead. */
1299 FT_List_Add( &face->driver->faces_list, node );
1301 /* now allocate a glyph slot object for the face */
1302 {
1303 FT_GlyphSlot slot;
1306 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
1308 error = FT_New_GlyphSlot( face, &slot );
1309 if ( error )
1310 goto Fail;
1312 face->glyph = slot;
1313 }
1315 /* finally, allocate a size object for the face */
1316 {
1317 FT_Size size;
1320 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1322 error = FT_New_Size( face, &size );
1323 if ( error )
1324 goto Fail;
1326 face->size = size;
1327 }
1329 /* initialize internal face data */
1330 {
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;
1341 }
1343 *aface = face;
1344 goto Exit;
1346 Fail:
1347 FT_Done_Face( face );
1349 Exit:
1350 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
1352 return error;
1353 }
1356 /* documentation is in freetype.h */
1358 FT_EXPORT_DEF( FT_Error )
1359 FT_Attach_File( FT_Face face,
1360 const char* filepathname )
1361 {
1362 FT_Open_Args open;
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 );
1374 }
1377 /* documentation is in freetype.h */
1379 FT_EXPORT_DEF( FT_Error )
1380 FT_Attach_Stream( FT_Face face,
1381 FT_Open_Args* parameters )
1382 {
1383 FT_Stream stream;
1384 FT_Error error;
1385 FT_Driver driver;
1387 FT_Driver_Class* clazz;
1390 /* test for valid `parameters' delayed to ft_new_input_stream() */
1392 if ( !face )
1393 return FT_Err_Invalid_Face_Handle;
1395 driver = face->driver;
1396 if ( !driver )
1397 return FT_Err_Invalid_Driver_Handle;
1399 error = ft_new_input_stream( driver->root.library, parameters, &stream );
1400 if ( error )
1401 goto Exit;
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 ) ) );
1416 Exit:
1417 return error;
1418 }
1421 /* documentation is in freetype.h */
1423 FT_EXPORT_DEF( FT_Error )
1424 FT_Done_Face( FT_Face face )
1425 {
1426 FT_Error error;
1427 FT_Driver driver;
1428 FT_Memory memory;
1429 FT_ListNode node;
1432 error = FT_Err_Invalid_Face_Handle;
1433 if ( face && face->driver )
1434 {
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 );
1440 if ( node )
1441 {
1442 /* remove face object from the driver's list */
1443 FT_List_Remove( &driver->faces_list, node );
1444 FREE( node );
1446 /* now destroy the object proper */
1447 destroy_face( memory, face, driver );
1448 error = FT_Err_Ok;
1449 }
1450 }
1451 return error;
1452 }
1455 /* documentation is in ftobjs.h */
1457 FT_EXPORT_DEF( FT_Error )
1458 FT_New_Size( FT_Face face,
1459 FT_Size *asize )
1460 {
1461 FT_Error error;
1462 FT_Memory memory;
1463 FT_Driver driver;
1464 FT_Driver_Class* clazz;
1466 FT_Size size = 0;
1467 FT_ListNode node = 0;
1470 if ( !face )
1471 return FT_Err_Invalid_Face_Handle;
1473 if ( !asize )
1474 return FT_Err_Invalid_Size_Handle;
1476 if ( !face->driver )
1477 return FT_Err_Invalid_Driver_Handle;
1479 *asize = 0;
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 ) ) )
1488 goto Exit;
1490 size->face = face;
1492 /* for now, do not use any internal fields in size objects */
1493 size->internal = 0;
1495 if ( clazz->init_size )
1496 error = clazz->init_size( size );
1498 /* in case of success, add to the face's list */
1499 if ( !error )
1500 {
1501 *asize = size;
1502 node->data = size;
1503 FT_List_Add( &face->sizes_list, node );
1504 }
1506 Exit:
1507 if ( error )
1508 {
1509 FREE( node );
1510 FREE( size );
1511 }
1513 return error;
1514 }
1517 /* documentation is in ftobjs.h */
1519 FT_EXPORT_DEF( FT_Error )
1520 FT_Done_Size( FT_Size size )
1521 {
1522 FT_Error error;
1523 FT_Driver driver;
1524 FT_Memory memory;
1525 FT_Face face;
1526 FT_ListNode node;
1529 if ( !size )
1530 return FT_Err_Invalid_Size_Handle;
1532 face = size->face;
1533 if ( !face )
1534 return FT_Err_Invalid_Face_Handle;
1536 driver = face->driver;
1537 if ( !driver )
1538 return FT_Err_Invalid_Driver_Handle;
1540 memory = driver->root.memory;
1542 error = FT_Err_Ok;
1543 node = FT_List_Find( &face->sizes_list, size );
1544 if ( node )
1545 {
1546 FT_List_Remove( &face->sizes_list, node );
1547 FREE( node );
1549 if ( face->size == size )
1550 {
1551 face->size = 0;
1552 if ( face->sizes_list.head )
1553 face->size = (FT_Size)(face->sizes_list.head->data);
1554 }
1556 destroy_size( memory, size, driver );
1557 }
1558 else
1559 error = FT_Err_Invalid_Size_Handle;
1561 return error;
1562 }
1565 static void
1566 ft_recompute_scaled_metrics( FT_Face face,
1567 FT_Size_Metrics* metrics )
1568 {
1569 /* Compute root ascender, descender, test height, and max_advance */
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;
1582 }
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 )
1593 {
1594 FT_Error error = FT_Err_Ok;
1595 FT_Driver driver;
1596 FT_Driver_Class* clazz;
1597 FT_Size_Metrics* metrics;
1598 FT_Long dim_x, dim_y;
1601 if ( !face || !face->size || !face->driver )
1602 return FT_Err_Invalid_Face_Handle;
1604 driver = face->driver;
1605 metrics = &face->size->metrics;
1607 if ( !char_width )
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 )
1639 {
1640 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1641 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
1643 ft_recompute_scaled_metrics( face, metrics );
1644 }
1646 if ( clazz->set_char_sizes )
1647 error = clazz->set_char_sizes( face->size,
1648 char_width,
1649 char_height,
1650 horz_resolution,
1651 vert_resolution );
1652 return error;
1653 }
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 )
1662 {
1663 FT_Error error = FT_Err_Ok;
1664 FT_Driver driver;
1665 FT_Driver_Class* clazz;
1666 FT_Size_Metrics* metrics = &face->size->metrics;
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 )
1683 pixel_width = 1;
1684 if ( pixel_height < 1 )
1685 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 )
1691 {
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 );
1699 }
1701 if ( clazz->set_pixel_sizes )
1702 error = clazz->set_pixel_sizes( face->size,
1703 pixel_width,
1704 pixel_height );
1705 return error;
1706 }
1709 /* documentation is in freetype.h */
1711 FT_EXPORT_DEF( FT_Error )
1712 FT_Get_Kerning( FT_Face face,
1713 FT_UInt left_glyph,
1714 FT_UInt right_glyph,
1715 FT_UInt kern_mode,
1716 FT_Vector *akerning )
1717 {
1718 FT_Error error = FT_Err_Ok;
1719 FT_Driver driver;
1722 if ( !face )
1723 return FT_Err_Invalid_Face_Handle;
1725 if ( !akerning )
1726 return FT_Err_Invalid_Argument;
1728 driver = face->driver;
1730 akerning->x = 0;
1731 akerning->y = 0;
1733 if ( driver->clazz->get_kerning )
1734 {
1735 error = driver->clazz->get_kerning( face,
1736 left_glyph,
1737 right_glyph,
1738 akerning );
1739 if ( !error )
1740 {
1741 if ( kern_mode != ft_kerning_unscaled )
1742 {
1743 akerning->x = FT_MulFix( akerning->x, face->size->metrics.x_scale );
1744 akerning->y = FT_MulFix( akerning->y, face->size->metrics.y_scale );
1746 if ( kern_mode != ft_kerning_unfitted )
1747 {
1748 akerning->x = ( akerning->x + 32 ) & -64;
1749 akerning->y = ( akerning->y + 32 ) & -64;
1750 }
1751 }
1752 }
1753 }
1755 return error;
1756 }
1759 /* documentation is in freetype.h */
1761 FT_EXPORT_DEF( FT_Error )
1762 FT_Select_Charmap( FT_Face face,
1763 FT_Encoding encoding )
1764 {
1765 FT_CharMap* cur;
1766 FT_CharMap* limit;
1769 if ( !face )
1770 return FT_Err_Invalid_Face_Handle;
1772 cur = face->charmaps;
1773 if ( !cur )
1774 return FT_Err_Invalid_CharMap_Handle;
1776 limit = cur + face->num_charmaps;
1778 for ( ; cur < limit; cur++ )
1779 {
1780 if ( cur[0]->encoding == encoding )
1781 {
1782 face->charmap = cur[0];
1783 return 0;
1784 }
1785 }
1787 return FT_Err_Invalid_Argument;
1788 }
1791 /* documentation is in freetype.h */
1793 FT_EXPORT_DEF( FT_Error )
1794 FT_Set_Charmap( FT_Face face,
1795 FT_CharMap charmap )
1796 {
1797 FT_CharMap* cur;
1798 FT_CharMap* limit;
1801 if ( !face )
1802 return FT_Err_Invalid_Face_Handle;
1804 cur = face->charmaps;
1805 if ( !cur )
1806 return FT_Err_Invalid_CharMap_Handle;
1808 limit = cur + face->num_charmaps;
1810 for ( ; cur < limit; cur++ )
1811 {
1812 if ( cur[0] == charmap )
1813 {
1814 face->charmap = cur[0];
1815 return 0;
1816 }
1817 }
1818 return FT_Err_Invalid_Argument;
1819 }
1822 /* documentation is in freetype.h */
1824 FT_EXPORT_DEF( FT_UInt )
1825 FT_Get_Char_Index( FT_Face face,
1826 FT_ULong charcode )
1827 {
1828 FT_UInt result;
1829 FT_Driver driver;
1832 result = 0;
1833 if ( face && face->charmap )
1834 {
1835 driver = face->driver;
1836 result = driver->clazz->get_char_index( face->charmap, charcode );
1837 }
1838 return result;
1839 }
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 )
1847 {
1848 FT_UInt result = 0;
1851 if ( face && FT_HAS_GLYPH_NAMES( face ) )
1852 {
1853 /* now, lookup for glyph name */
1854 FT_Driver driver = face->driver;
1855 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1858 if ( clazz->get_interface )
1859 {
1860 FT_Name_Index_Requester requester;
1863 requester = (FT_Name_Index_Requester)clazz->get_interface(
1864 FT_MODULE( driver ), "name_index" );
1865 if ( requester )
1866 result = requester( face, glyph_name );
1867 }
1868 }
1870 return result;
1871 }
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,
1878 FT_Pointer buffer,
1879 FT_UInt buffer_max )
1880 {
1881 FT_Error error = FT_Err_Invalid_Argument;
1884 /* clean up buffer */
1885 if ( buffer && buffer_max > 0 )
1886 ((FT_Byte*)buffer)[0] = 0;
1888 if ( face &&
1889 glyph_index < (FT_UInt)face->num_glyphs &&
1890 FT_HAS_GLYPH_NAMES( face ) )
1891 {
1892 /* now, lookup for glyph name */
1893 FT_Driver driver = face->driver;
1894 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1897 if ( clazz->get_interface )
1898 {
1899 FT_Glyph_Name_Requester requester;
1902 requester = (FT_Glyph_Name_Requester)clazz->get_interface(
1903 FT_MODULE( driver ), "glyph_name" );
1904 if ( requester )
1905 error = requester( face, glyph_index, buffer, buffer_max );
1906 }
1907 }
1909 return error;
1910 }
1913 /* documentation is in freetype.h */
1915 FT_EXPORT_DEF( const char* )
1916 FT_Get_Postscript_Name( FT_Face face )
1917 {
1918 const char* result = NULL;
1920 if ( !face )
1921 goto Exit;
1923 result = face->internal->postscript_name;
1924 if ( !result )
1925 {
1926 /* now, lookup for glyph name */
1927 FT_Driver driver = face->driver;
1928 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
1930 if ( clazz->get_interface )
1931 {
1932 FT_PSName_Requester requester;
1934 requester = (FT_PSName_Requester)clazz->get_interface(
1935 FT_MODULE( driver ), "postscript_name" );
1936 if ( requester )
1937 result = requester( face );
1938 }
1939 }
1940 Exit:
1941 return result;
1942 }
1945 /* documentation is in tttables.h */
1947 FT_EXPORT_DEF( void* )
1948 FT_Get_Sfnt_Table( FT_Face face,
1949 FT_Sfnt_Tag tag )
1950 {
1951 void* table = 0;
1952 FT_Get_Sfnt_Table_Func func;
1953 FT_Driver driver;
1956 if ( !face || !FT_IS_SFNT( face ) )
1957 goto Exit;
1959 driver = face->driver;
1960 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
1961 FT_MODULE( driver ), "get_sfnt" );
1962 if ( func )
1963 table = func( face, tag );
1965 Exit:
1966 return table;
1967 }
1970 FT_EXPORT_DEF( FT_Error )
1971 FT_Activate_Size( FT_Size size )
1972 {
1973 FT_Face face;
1976 if ( size == NULL )
1977 return FT_Err_Bad_Argument;
1979 face = size->face;
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 */
1985 face->size = size;
1987 return FT_Err_Ok;
1988 }
1991 /*************************************************************************/
1992 /*************************************************************************/
1993 /*************************************************************************/
1994 /**** ****/
1995 /**** ****/
1996 /**** R E N D E R E R S ****/
1997 /**** ****/
1998 /**** ****/
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,
2007 FT_ListNode* node )
2008 {
2009 FT_ListNode cur;
2010 FT_Renderer result = 0;
2013 if ( !library )
2014 goto Exit;
2016 cur = library->renderers.head;
2018 if ( node )
2019 {
2020 if ( *node )
2021 cur = (*node)->next;
2022 *node = 0;
2023 }
2025 while ( cur )
2026 {
2027 FT_Renderer renderer = FT_RENDERER( cur->data );
2030 if ( renderer->glyph_format == format )
2031 {
2032 if ( node )
2033 *node = cur;
2035 result = renderer;
2036 break;
2037 }
2038 cur = cur->next;
2039 }
2041 Exit:
2042 return result;
2043 }
2046 static FT_Renderer
2047 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
2048 {
2049 FT_Face face = slot->face;
2050 FT_Library library = FT_FACE_LIBRARY( face );
2051 FT_Renderer result = library->cur_renderer;
2054 if ( !result || result->glyph_format != slot->format )
2055 result = FT_Lookup_Renderer( library, slot->format, 0 );
2057 return result;
2058 }
2061 static void
2062 ft_set_current_renderer( FT_Library library )
2063 {
2064 FT_Renderer renderer;
2067 renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
2068 library->cur_renderer = renderer;
2069 }
2072 static FT_Error
2073 ft_add_renderer( FT_Module module )
2074 {
2075 FT_Library library = module->library;
2076 FT_Memory memory = library->memory;
2077 FT_Error error;
2078 FT_ListNode node;
2081 if ( ALLOC( node, sizeof ( *node ) ) )
2082 goto Exit;
2084 {
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 )
2095 {
2096 error = clazz->raster_class->raster_new( memory, &render->raster );
2097 if ( error )
2098 goto Fail;
2100 render->raster_render = clazz->raster_class->raster_render;
2101 render->render = clazz->render_glyph;
2102 }
2104 /* add to list */
2105 node->data = module;
2106 FT_List_Add( &library->renderers, node );
2108 ft_set_current_renderer( library );
2109 }
2111 Fail:
2112 if ( error )
2113 FREE( node );
2115 Exit:
2116 return error;
2117 }
2120 static void
2121 ft_remove_renderer( FT_Module module )
2122 {
2123 FT_Library library = module->library;
2124 FT_Memory memory = library->memory;
2125 FT_ListNode node;
2128 node = FT_List_Find( &library->renderers, module );
2129 if ( node )
2130 {
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 );
2140 FREE( node );
2142 ft_set_current_renderer( library );
2143 }
2144 }
2147 /* documentation is in ftrender.h */
2149 FT_EXPORT_DEF( FT_Renderer )
2150 FT_Get_Renderer( FT_Library library,
2151 FT_Glyph_Format format )
2152 {
2153 /* test for valid `library' delayed to FT_Lookup_Renderer() */
2155 return FT_Lookup_Renderer( library, format, 0 );
2156 }
2159 /* documentation is in ftrender.h */
2161 FT_EXPORT_DEF( FT_Error )
2162 FT_Set_Renderer( FT_Library library,
2163 FT_Renderer renderer,
2164 FT_UInt num_params,
2165 FT_Parameter* parameters )
2166 {
2167 FT_ListNode node;
2168 FT_Error error = FT_Err_Ok;
2171 if ( !library )
2172 return FT_Err_Invalid_Library_Handle;
2174 if ( !renderer )
2175 return FT_Err_Invalid_Argument;
2177 node = FT_List_Find( &library->renderers, renderer );
2178 if ( !node )
2179 {
2180 error = FT_Err_Invalid_Argument;
2181 goto Exit;
2182 }
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 )
2190 {
2191 FTRenderer_setMode set_mode = renderer->clazz->set_mode;
2194 for ( ; num_params > 0; num_params-- )
2195 {
2196 error = set_mode( renderer, parameters->tag, parameters->data );
2197 if ( error )
2198 break;
2199 }
2200 }
2202 Exit:
2203 return error;
2204 }
2207 FT_EXPORT_DEF( FT_Error )
2208 FT_Render_Glyph_Internal( FT_Library library,
2209 FT_GlyphSlot slot,
2210 FT_UInt render_mode )
2211 {
2212 FT_Error error = FT_Err_Ok;
2213 FT_Renderer renderer;
2216 /* if it is already a bitmap, no need to do anything */
2217 switch ( slot->format )
2218 {
2219 case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
2220 break;
2222 default:
2223 {
2224 FT_ListNode node = 0;
2225 FT_Bool update = 0;
2228 /* small shortcut for the very common case */
2229 if ( slot->format == ft_glyph_format_outline )
2230 {
2231 renderer = library->cur_renderer;
2232 node = library->renderers.head;
2233 }
2234 else
2235 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2237 error = FT_Err_Unimplemented_Feature;
2238 while ( renderer )
2239 {
2240 error = renderer->render( renderer, slot, render_mode, 0 );
2241 if ( !error ||
2242 FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
2243 break;
2245 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
2246 /* is unsupported by the current renderer for this glyph image */
2247 /* format. */
2249 /* now, look for another renderer that supports the same */
2250 /* format. */
2251 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2252 update = 1;
2253 }
2255 /* if we changed the current renderer for the glyph image format */
2256 /* we need to select it as the next current one */
2257 if ( !error && update && renderer )
2258 FT_Set_Renderer( library, renderer, 0, 0 );
2259 }
2260 }
2262 return error;
2263 }
2266 /* documentation is in freetype.h */
2268 FT_EXPORT_DEF( FT_Error )
2269 FT_Render_Glyph( FT_GlyphSlot slot,
2270 FT_UInt render_mode )
2271 {
2272 FT_Library library;
2275 if ( !slot )
2276 return FT_Err_Invalid_Argument;
2278 library = FT_FACE_LIBRARY( slot->face );
2280 return FT_Render_Glyph_Internal( library, slot, render_mode );
2281 }
2284 /*************************************************************************/
2285 /*************************************************************************/
2286 /*************************************************************************/
2287 /**** ****/
2288 /**** ****/
2289 /**** M O D U L E S ****/
2290 /**** ****/
2291 /**** ****/
2292 /*************************************************************************/
2293 /*************************************************************************/
2294 /*************************************************************************/
2297 /*************************************************************************/
2298 /* */
2299 /* <Function> */
2300 /* Destroy_Module */
2301 /* */
2302 /* <Description> */
2303 /* Destroys a given module object. For drivers, this also destroys */
2304 /* all child faces. */
2305 /* */
2306 /* <InOut> */
2307 /* module :: A handle to the target driver object. */
2308 /* */
2309 /* <Note> */
2310 /* The driver _must_ be LOCKED! */
2311 /* */
2312 static void
2313 Destroy_Module( FT_Module module )
2314 {
2315 FT_Memory memory = module->memory;
2316 FT_Module_Class* clazz = module->clazz;
2317 FT_Library library = module->library;
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 );
2339 /* discard it */
2340 FREE( module );
2341 }
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 )
2349 {
2350 FT_Error error;
2351 FT_Memory memory;
2352 FT_Module module;
2353 FT_UInt nn;
2356 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
2357 FREETYPE_MINOR )
2359 if ( !library )
2360 return FT_Err_Invalid_Library_Handle;
2362 if ( !clazz )
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++ )
2371 {
2372 module = library->modules[nn];
2373 if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
2374 {
2375 /* this installed module has the same name, compare their versions */
2376 if ( clazz->module_version <= module->clazz->module_version )
2377 return FT_Err_Lower_Module_Version;
2379 /* remove the module from our list, then exit the loop to replace */
2380 /* it by our new version.. */
2381 FT_Remove_Module( library, module );
2382 break;
2383 }
2384 }
2386 memory = library->memory;
2387 error = FT_Err_Ok;
2389 if ( library->num_modules >= FT_MAX_MODULES )
2390 {
2391 error = FT_Err_Too_Many_Drivers;
2392 goto Exit;
2393 }
2395 /* allocate module object */
2396 if ( ALLOC( module,clazz->module_size ) )
2397 goto Exit;
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 ) )
2407 {
2408 /* add to the renderers list */
2409 error = ft_add_renderer( module );
2410 if ( error )
2411 goto Fail;
2412 }
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 ) )
2420 {
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 ) )
2427 {
2428 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
2429 if ( error )
2430 goto Fail;
2431 }
2432 }
2434 if ( clazz->module_init )
2435 {
2436 error = clazz->module_init( module );
2437 if ( error )
2438 goto Fail;
2439 }
2441 /* add module to the library's table */
2442 library->modules[library->num_modules++] = module;
2444 Exit:
2445 return error;
2447 Fail:
2448 if ( FT_MODULE_IS_DRIVER( module ) )
2449 {
2450 FT_Driver driver = FT_DRIVER( module );
2453 if ( FT_DRIVER_USES_OUTLINES( driver ) )
2454 FT_GlyphLoader_Done( driver->glyph_loader );
2455 }
2457 if ( FT_MODULE_IS_RENDERER( module ) )
2458 {
2459 FT_Renderer renderer = FT_RENDERER( module );
2462 if ( renderer->raster )
2463 renderer->clazz->raster_class->raster_done( renderer->raster );
2464 }
2466 FREE( module );
2467 goto Exit;
2468 }
2471 /* documentation is in ftmodule.h */
2473 FT_EXPORT_DEF( FT_Module )
2474 FT_Get_Module( FT_Library library,
2475 const char* module_name )
2476 {
2477 FT_Module result = 0;
2478 FT_Module* cur;
2479 FT_Module* limit;
2482 if ( !library || !module_name )
2483 return result;
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 )
2490 {
2491 result = cur[0];
2492 break;
2493 }
2495 return result;
2496 }
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 )
2504 {
2505 FT_Module module;
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;
2513 }
2516 /* documentation is in ftmodule.h */
2518 FT_EXPORT_DEF( FT_Error )
2519 FT_Remove_Module( FT_Library library,
2520 FT_Module module )
2521 {
2522 /* try to find the module from the table, then remove it from there */
2524 if ( !library )
2525 return FT_Err_Invalid_Library_Handle;
2527 if ( module )
2528 {
2529 FT_Module* cur = library->modules;
2530 FT_Module* limit = cur + library->num_modules;
2533 for ( ; cur < limit; cur++ )
2534 {
2535 if ( cur[0] == module )
2536 {
2537 /* remove it from the table */
2538 library->num_modules--;
2539 limit--;
2540 while ( cur < limit )
2541 {
2542 cur[0] = cur[1];
2543 cur++;
2544 }
2545 limit[0] = 0;
2547 /* destroy the module */
2548 Destroy_Module( module );
2550 return FT_Err_Ok;
2551 }
2552 }
2553 }
2554 return FT_Err_Invalid_Driver_Handle;
2555 }
2558 /*************************************************************************/
2559 /*************************************************************************/
2560 /*************************************************************************/
2561 /**** ****/
2562 /**** ****/
2563 /**** L I B R A R Y ****/
2564 /**** ****/
2565 /**** ****/
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 )
2576 {
2577 FT_Library library = 0;
2578 FT_Error error;
2581 if ( !memory )
2582 return FT_Err_Invalid_Argument;
2584 /* first of all, allocate the library object */
2585 if ( ALLOC( library, sizeof ( *library ) ) )
2586 return error;
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 ) )
2593 goto Fail;
2595 /* That's ok now */
2596 *alibrary = library;
2598 return FT_Err_Ok;
2600 Fail:
2601 FREE( library );
2602 return error;
2603 }
2606 /* documentation is in ftmodule.h */
2608 FT_EXPORT_DEF( FT_Error )
2609 FT_Done_Library( FT_Library library )
2610 {
2611 FT_Memory memory;
2612 FT_UInt n;
2615 if ( !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++ )
2626 {
2627 FT_Module module = library->modules[n];
2630 if ( module )
2631 {
2632 Destroy_Module( module );
2633 library->modules[n] = 0;
2634 }
2635 }
2637 /* Destroy raster objects */
2638 FREE( library->raster_pool );
2639 library->raster_pool_size = 0;
2641 FREE( library );
2642 return FT_Err_Ok;
2643 }
2646 /* documentation is in ftmodule.h */
2648 FT_EXPORT_DEF( void )
2649 FT_Set_Debug_Hook( FT_Library library,
2650 FT_UInt hook_index,
2651 FT_DebugHook_Func debug_hook )
2652 {
2653 if ( library && debug_hook &&
2654 hook_index <
2655 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
2656 library->debug_hooks[hook_index] = debug_hook;
2657 }
2660 /* END */