]> git.saurik.com Git - wxWidgets.git/blob - src/freetype/base/ftobjs.c
added missing return on error
[wxWidgets.git] / src / freetype / base / ftobjs.c
1 /***************************************************************************/
2 /* */
3 /* ftobjs.c */
4 /* */
5 /* The FreeType private base classes (body). */
6 /* */
7 /* Copyright 1996-2000 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
17
18
19 #include <freetype/internal/ftobjs.h>
20 #include <freetype/internal/ftlist.h>
21 #include <freetype/internal/ftdebug.h>
22 #include <freetype/internal/ftstream.h>
23
24 #include <freetype/tttables.h>
25
26 #include <string.h> /* for strcmp() */
27
28
29 /*************************************************************************/
30 /*************************************************************************/
31 /*************************************************************************/
32 /**** ****/
33 /**** ****/
34 /**** M E M O R Y ****/
35 /**** ****/
36 /**** ****/
37 /*************************************************************************/
38 /*************************************************************************/
39 /*************************************************************************/
40
41 /*************************************************************************/
42 /* */
43 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
44 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
45 /* messages during execution. */
46 /* */
47 #undef FT_COMPONENT
48 #define FT_COMPONENT trace_memory
49
50
51 /*************************************************************************/
52 /* */
53 /* <Function> */
54 /* FT_Alloc */
55 /* */
56 /* <Description> */
57 /* Allocates a new block of memory. The returned area is always */
58 /* zero-filled; this is a strong convention in many FreeType parts. */
59 /* */
60 /* <Input> */
61 /* memory :: A handle to a given `memory object' which handles */
62 /* allocation. */
63 /* */
64 /* size :: The size in bytes of the block to allocate. */
65 /* */
66 /* <Output> */
67 /* P :: A pointer to the fresh new block. It should be set to */
68 /* NULL if `size' is 0, or in case of error. */
69 /* */
70 /* <Return> */
71 /* FreeType error code. 0 means success. */
72 /* */
73 BASE_FUNC( FT_Error ) FT_Alloc( FT_Memory memory,
74 FT_Long size,
75 void** P )
76 {
77 FT_Assert( P != 0 );
78
79 if ( size > 0 )
80 {
81 *P = memory->alloc( memory, size );
82 if ( !*P )
83 {
84 FT_ERROR(( "FT_Alloc:" ));
85 FT_ERROR(( " Out of memory? (%ld requested)\n",
86 size ));
87
88 return FT_Err_Out_Of_Memory;
89 }
90 MEM_Set( *P, 0, size );
91 }
92 else
93 *P = NULL;
94
95 FT_TRACE7(( "FT_Alloc:" ));
96 FT_TRACE7(( " size = %ld, block = 0x%08p, ref = 0x%08p\n",
97 size, *P, P ));
98
99 return FT_Err_Ok;
100 }
101
102
103 /*************************************************************************/
104 /* */
105 /* <Function> */
106 /* FT_Realloc */
107 /* */
108 /* <Description> */
109 /* Reallocates a block of memory pointed to by `*P' to `Size' bytes */
110 /* from the heap, possibly changing `*P'. */
111 /* */
112 /* <Input> */
113 /* memory :: A handle to a given `memory object' which handles */
114 /* reallocation. */
115 /* */
116 /* current :: The current block size in bytes. */
117 /* */
118 /* size :: The new block size in bytes. */
119 /* */
120 /* <InOut> */
121 /* P :: A pointer to the fresh new block. It should be set to */
122 /* NULL if `size' is 0, or in case of error. */
123 /* */
124 /* <Return> */
125 /* FreeType error code. 0 means success. */
126 /* */
127 /* <Note> */
128 /* All callers of FT_Realloc() _must_ provide the current block size */
129 /* as well as the new one. */
130 /* */
131 BASE_FUNC( FT_Error ) FT_Realloc( FT_Memory memory,
132 FT_Long current,
133 FT_Long size,
134 void** P )
135 {
136 void* Q;
137
138
139 FT_Assert( P != 0 );
140
141 /* if the original pointer is NULL, call FT_Alloc() */
142 if ( !*P )
143 return FT_Alloc( memory, size, P );
144
145 /* if the new block if zero-sized, clear the current one */
146 if ( size <= 0 )
147 {
148 FT_Free( memory, P );
149 return FT_Err_Ok;
150 }
151
152 Q = memory->realloc( memory, current, size, *P );
153 if ( !Q )
154 goto Fail;
155
156 *P = Q;
157 return FT_Err_Ok;
158
159 Fail:
160 FT_ERROR(( "FT_Realloc:" ));
161 FT_ERROR(( " Failed (current %ld, requested %ld)\n",
162 current, size ));
163 return FT_Err_Out_Of_Memory;
164 }
165
166
167 /*************************************************************************/
168 /* */
169 /* <Function> */
170 /* FT_Free */
171 /* */
172 /* <Description> */
173 /* Releases a given block of memory allocated through FT_Alloc(). */
174 /* */
175 /* <Input> */
176 /* memory :: A handle to a given `memory object' which handles */
177 /* memory deallocation */
178 /* */
179 /* P :: This is the _address_ of a _pointer_ which points to the */
180 /* allocated block. It is always set to NULL on exit. */
181 /* */
182 /* <Return> */
183 /* FreeType error code. 0 means success. */
184 /* */
185 /* <Note> */
186 /* If P or *P are NULL, this function should return successfully. */
187 /* This is a strong convention within all of FreeType and its */
188 /* drivers. */
189 /* */
190 BASE_FUNC( void ) FT_Free( FT_Memory memory,
191 void** P )
192 {
193 FT_TRACE7(( "FT_Free:" ));
194 FT_TRACE7(( " Freeing block 0x%08p, ref 0x%08p\n",
195 P, P ? *P : (void*)0 ));
196
197 if ( P && *P )
198 {
199 memory->free( memory, *P );
200 *P = 0;
201 }
202 }
203
204
205 /*************************************************************************/
206 /*************************************************************************/
207 /*************************************************************************/
208 /**** ****/
209 /**** ****/
210 /**** S T R E A M ****/
211 /**** ****/
212 /**** ****/
213 /*************************************************************************/
214 /*************************************************************************/
215 /*************************************************************************/
216
217
218 /*************************************************************************/
219 /* */
220 /* <Function> */
221 /* ft_new_input_stream */
222 /* */
223 /* <Description> */
224 /* Creates a new input stream object from an FT_Open_Args structure. */
225 /* */
226 /* <Note> */
227 /* The function expects a valid `astream' parameter. */
228 /* */
229 static
230 FT_Error ft_new_input_stream( FT_Library library,
231 FT_Open_Args* args,
232 FT_Stream* astream )
233 {
234 FT_Error error;
235 FT_Memory memory;
236 FT_Stream stream;
237
238
239 if ( !library )
240 return FT_Err_Invalid_Library_Handle;
241
242 if ( !args )
243 return FT_Err_Invalid_Argument;
244
245 *astream = 0;
246 memory = library->memory;
247 if ( ALLOC( stream, sizeof ( *stream ) ) )
248 goto Exit;
249
250 stream->memory = memory;
251
252 /* now, look at the stream flags */
253 if ( args->flags & ft_open_memory )
254 {
255 error = 0;
256 FT_New_Memory_Stream( library,
257 args->memory_base,
258 args->memory_size,
259 stream );
260 }
261 else if ( args->flags & ft_open_pathname )
262 {
263 error = FT_New_Stream( args->pathname, stream );
264 stream->pathname.pointer = args->pathname;
265 }
266 else if ( args->flags & ft_open_stream && args->stream )
267 {
268 *stream = *(args->stream);
269 stream->memory = memory;
270 }
271 else
272 error = FT_Err_Invalid_Argument;
273
274 if ( error )
275 FREE( stream );
276
277 *astream = stream;
278
279 Exit:
280 return error;
281 }
282
283
284 /*************************************************************************/
285 /* */
286 /* <Function> */
287 /* FT_Done_Stream */
288 /* */
289 /* <Description> */
290 /* Closes and destroys a stream object. */
291 /* */
292 /* <Input> */
293 /* stream :: The stream to be closed and destroyed. */
294 /* */
295 FT_EXPORT_FUNC( void ) FT_Done_Stream( FT_Stream stream )
296 {
297 if ( stream && stream->close )
298 stream->close( stream );
299 }
300
301
302 static
303 void ft_done_stream( FT_Stream* astream )
304 {
305 FT_Stream stream = *astream;
306 FT_Memory memory = stream->memory;
307
308
309 if ( stream->close )
310 stream->close( stream );
311
312 FREE( stream );
313 *astream = 0;
314 }
315
316
317 #undef FT_COMPONENT
318 #define FT_COMPONENT trace_objs
319
320
321 /*************************************************************************/
322 /*************************************************************************/
323 /*************************************************************************/
324 /**** ****/
325 /**** ****/
326 /**** G L Y P H L O A D E R ****/
327 /**** ****/
328 /**** ****/
329 /*************************************************************************/
330 /*************************************************************************/
331 /*************************************************************************/
332
333
334 /*************************************************************************/
335 /* */
336 /* The glyph loader is a simple object which is used to load a set of */
337 /* glyphs easily. It is critical for the correct loading of composites. */
338 /* */
339 /* Ideally, one can see it as a stack of abstract `glyph' objects. */
340 /* */
341 /* loader.base Is really the bottom of the stack. It describes a */
342 /* single glyph image made of the juxtaposition of */
343 /* several glyphs (those `in the stack'). */
344 /* */
345 /* loader.current Describes the top of the stack, on which a new */
346 /* glyph can be loaded. */
347 /* */
348 /* Rewind Clears the stack. */
349 /* Prepare Set up `loader.current' for addition of a new glyph */
350 /* image. */
351 /* Add Add the `current' glyph image to the `base' one, */
352 /* and prepare for another one. */
353 /* */
354 /* The glyph loader is now a base object. Each driver used to */
355 /* re-implement it in one way or the other, which wasted code and */
356 /* energy. */
357 /* */
358 /*************************************************************************/
359
360
361 /* create a new glyph loader */
362 BASE_FUNC( FT_Error ) FT_GlyphLoader_New( FT_Memory memory,
363 FT_GlyphLoader** aloader )
364 {
365 FT_GlyphLoader* loader;
366 FT_Error error;
367
368
369 if ( !ALLOC( loader, sizeof ( *loader ) ) )
370 {
371 loader->memory = memory;
372 *aloader = loader;
373 }
374 return error;
375 }
376
377
378 /* rewind the glyph loader - reset counters to 0 */
379 BASE_FUNC( void ) FT_GlyphLoader_Rewind( FT_GlyphLoader* loader )
380 {
381 FT_GlyphLoad* base = &loader->base;
382 FT_GlyphLoad* current = &loader->current;
383
384
385 base->outline.n_points = 0;
386 base->outline.n_contours = 0;
387 base->num_subglyphs = 0;
388
389 *current = *base;
390 }
391
392
393 /* reset the glyph loader, frees all allocated tables */
394 /* and starts from zero */
395 BASE_FUNC( void ) FT_GlyphLoader_Reset( FT_GlyphLoader* loader )
396 {
397 FT_Memory memory = loader->memory;
398
399
400 FREE( loader->base.outline.points );
401 FREE( loader->base.outline.tags );
402 FREE( loader->base.outline.contours );
403 FREE( loader->base.extra_points );
404 FREE( loader->base.subglyphs );
405
406 loader->max_points = 0;
407 loader->max_contours = 0;
408 loader->max_subglyphs = 0;
409
410 FT_GlyphLoader_Rewind( loader );
411 }
412
413
414 /* delete a glyph loader */
415 BASE_FUNC( void ) FT_GlyphLoader_Done( FT_GlyphLoader* loader )
416 {
417 if ( loader )
418 {
419 FT_Memory memory = loader->memory;
420
421
422 FT_GlyphLoader_Reset( loader );
423 FREE( loader );
424 }
425 }
426
427
428 /* re-adjust the `current' outline fields */
429 static
430 void FT_GlyphLoader_Adjust_Points( FT_GlyphLoader* loader )
431 {
432 FT_Outline* base = &loader->base.outline;
433 FT_Outline* current = &loader->current.outline;
434
435
436 current->points = base->points + base->n_points;
437 current->tags = base->tags + base->n_points;
438 current->contours = base->contours + base->n_contours;
439
440 /* handle extra points table - if any */
441 if ( loader->use_extra )
442 loader->current.extra_points =
443 loader->base.extra_points + base->n_points;
444 }
445
446
447 BASE_FUNC( FT_Error ) FT_GlyphLoader_Create_Extra(
448 FT_GlyphLoader* loader )
449 {
450 FT_Error error;
451 FT_Memory memory = loader->memory;
452
453
454 if ( !ALLOC_ARRAY( loader->base.extra_points,
455 loader->max_points, FT_Vector ) )
456 {
457 loader->use_extra = 1;
458 FT_GlyphLoader_Adjust_Points( loader );
459 }
460 return error;
461 }
462
463
464 /* re-adjust the `current' subglyphs field */
465 static
466 void FT_GlyphLoader_Adjust_Subglyphs( FT_GlyphLoader* loader )
467 {
468 FT_GlyphLoad* base = &loader->base;
469 FT_GlyphLoad* current = &loader->current;
470
471
472 current->subglyphs = base->subglyphs + base->num_subglyphs;
473 }
474
475
476 /* Ensure that we can add `n_points' and `n_contours' to our glyph. this */
477 /* function reallocates its outline tables if necessary. Note that it */
478 /* DOESN'T change the number of points within the loader! */
479 /* */
480 BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Points(
481 FT_GlyphLoader* loader,
482 FT_UInt n_points,
483 FT_UInt n_contours )
484 {
485 FT_Memory memory = loader->memory;
486 FT_Error error = FT_Err_Ok;
487 FT_Outline* base = &loader->base.outline;
488 FT_Outline* current = &loader->current.outline;
489 FT_Bool adjust = 1;
490
491 FT_UInt new_max;
492
493
494 /* check points & tags */
495 new_max = base->n_points + current->n_points + n_points;
496 if ( new_max > loader->max_points )
497 {
498 new_max = ( new_max + 7 ) & -8;
499 if ( REALLOC_ARRAY( base->points, base->n_points,
500 new_max, FT_Vector ) ||
501 REALLOC_ARRAY( base->tags, base->n_points,
502 new_max, FT_Byte ) )
503 goto Exit;
504
505 if ( loader->use_extra &&
506 REALLOC_ARRAY( loader->base.extra_points, base->n_points,
507 new_max, FT_Vector ) )
508 goto Exit;
509
510 adjust = 1;
511 loader->max_points = new_max;
512 }
513
514 /* check contours */
515 new_max = base->n_contours + current->n_contours +
516 n_contours;
517 if ( new_max > loader->max_contours )
518 {
519 new_max = ( new_max + 3 ) & -4;
520 if ( REALLOC_ARRAY( base->contours, base->n_contours,
521 new_max, FT_Short ) )
522 goto Exit;
523
524 adjust = 1;
525 loader->max_contours = new_max;
526 }
527
528 if ( adjust )
529 FT_GlyphLoader_Adjust_Points( loader );
530
531 Exit:
532 return error;
533 }
534
535
536 /* Ensure that we can add `n_subglyphs' to our glyph. this function */
537 /* reallocates its subglyphs table if necessary. Note that it DOES */
538 /* NOT change the number of subglyphs within the loader! */
539 /* */
540 BASE_FUNC( FT_Error ) FT_GlyphLoader_Check_Subglyphs(
541 FT_GlyphLoader* loader,
542 FT_UInt n_subs )
543 {
544 FT_Memory memory = loader->memory;
545 FT_Error error = FT_Err_Ok;
546 FT_UInt new_max;
547
548 FT_GlyphLoad* base = &loader->base;
549 FT_GlyphLoad* current = &loader->current;
550
551
552 new_max = base->num_subglyphs + current->num_subglyphs + n_subs;
553 if ( new_max > loader->max_subglyphs )
554 {
555 new_max = ( new_max + 1 ) & -2;
556 if ( REALLOC_ARRAY( base->subglyphs, base->num_subglyphs,
557 new_max, FT_SubGlyph ) )
558 goto Exit;
559
560 loader->max_subglyphs = new_max;
561
562 FT_GlyphLoader_Adjust_Subglyphs( loader );
563 }
564
565 Exit:
566 return error;
567 }
568
569
570 /* prepare loader for the addition of a new glyph on top of the base one */
571 BASE_FUNC( void ) FT_GlyphLoader_Prepare( FT_GlyphLoader* loader )
572 {
573 FT_GlyphLoad* current = &loader->current;
574
575
576 current->outline.n_points = 0;
577 current->outline.n_contours = 0;
578 current->num_subglyphs = 0;
579
580 FT_GlyphLoader_Adjust_Points ( loader );
581 FT_GlyphLoader_Adjust_Subglyphs( loader );
582 }
583
584
585 /* add current glyph to the base image - and prepare for another */
586 BASE_FUNC( void ) FT_GlyphLoader_Add( FT_GlyphLoader* loader )
587 {
588 FT_GlyphLoad* base = &loader->base;
589 FT_GlyphLoad* current = &loader->current;
590
591 FT_UInt n_curr_contours = current->outline.n_contours;
592 FT_UInt n_base_points = base->outline.n_points;
593 FT_UInt n;
594
595
596 base->outline.n_points += current->outline.n_points;
597 base->outline.n_contours += current->outline.n_contours;
598 base->num_subglyphs += current->num_subglyphs;
599
600 /* adjust contours count in newest outline */
601 for ( n = 0; n < n_curr_contours; n++ )
602 current->outline.contours[n] += n_base_points;
603
604 /* prepare for another new glyph image */
605 FT_GlyphLoader_Prepare( loader );
606 }
607
608
609 BASE_FUNC( FT_Error ) FT_GlyphLoader_Copy_Points( FT_GlyphLoader* target,
610 FT_GlyphLoader* source )
611 {
612 FT_Error error;
613 FT_UInt num_points = source->base.outline.n_points;
614 FT_UInt num_contours = source->base.outline.n_contours;
615
616
617 error = FT_GlyphLoader_Check_Points( target, num_points, num_contours );
618 if ( !error )
619 {
620 FT_Outline* out = &target->base.outline;
621 FT_Outline* in = &source->base.outline;
622
623
624 MEM_Copy( out->points, in->points,
625 num_points * sizeof ( FT_Vector ) );
626 MEM_Copy( out->tags, in->tags,
627 num_points * sizeof ( char ) );
628 MEM_Copy( out->contours, in->contours,
629 num_contours * sizeof ( short ) );
630
631 /* do we need to copy the extra points? */
632 if ( target->use_extra && source->use_extra )
633 MEM_Copy( target->base.extra_points, source->base.extra_points,
634 num_points * sizeof ( FT_Vector ) );
635
636 out->n_points = num_points;
637 out->n_contours = num_contours;
638
639 FT_GlyphLoader_Adjust_Points( target );
640 }
641
642 return error;
643 }
644
645
646 /*************************************************************************/
647 /*************************************************************************/
648 /*************************************************************************/
649 /**** ****/
650 /**** ****/
651 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
652 /**** ****/
653 /**** ****/
654 /*************************************************************************/
655 /*************************************************************************/
656 /*************************************************************************/
657
658
659 static
660 FT_Error ft_glyphslot_init( FT_GlyphSlot slot )
661 {
662 FT_Driver driver = slot->face->driver;
663 FT_Driver_Class* clazz = driver->clazz;
664 FT_Memory memory = driver->root.memory;
665 FT_Error error = FT_Err_Ok;
666
667
668 slot->library = driver->root.library;
669
670 if ( FT_DRIVER_USES_OUTLINES( driver ) )
671 error = FT_GlyphLoader_New( memory, &slot->loader );
672
673 if ( !error && clazz->init_slot )
674 error = clazz->init_slot( slot );
675
676 return error;
677 }
678
679
680 static
681 void ft_glyphslot_clear( FT_GlyphSlot slot )
682 {
683 /* free bitmap if needed */
684 if ( slot->flags & ft_glyph_own_bitmap )
685 {
686 FT_Memory memory = FT_FACE_MEMORY( slot->face );
687
688
689 FREE( slot->bitmap.buffer );
690 slot->flags &= ~ft_glyph_own_bitmap;
691 }
692
693 /* clear all public fields in the glyph slot */
694 MEM_Set( &slot->metrics, 0, sizeof ( slot->metrics ) );
695 MEM_Set( &slot->outline, 0, sizeof ( slot->outline ) );
696 MEM_Set( &slot->bitmap, 0, sizeof ( slot->bitmap ) );
697
698 slot->bitmap_left = 0;
699 slot->bitmap_top = 0;
700 slot->num_subglyphs = 0;
701 slot->subglyphs = 0;
702 slot->control_data = 0;
703 slot->control_len = 0;
704 slot->other = 0;
705 slot->format = ft_glyph_format_none;
706
707 slot->linearHoriAdvance = 0;
708 slot->linearVertAdvance = 0;
709 }
710
711
712 static
713 void ft_glyphslot_done( FT_GlyphSlot slot )
714 {
715 FT_Driver driver = slot->face->driver;
716 FT_Driver_Class* clazz = driver->clazz;
717 FT_Memory memory = driver->root.memory;
718
719
720 /* free bitmap buffer if needed */
721 if ( slot->flags & ft_glyph_own_bitmap )
722 FREE( slot->bitmap.buffer );
723
724 /* free glyph loader */
725 if ( FT_DRIVER_USES_OUTLINES( driver ) )
726 {
727 FT_GlyphLoader_Done( slot->loader );
728 slot->loader = 0;
729 }
730
731 if ( clazz->done_slot )
732 clazz->done_slot( slot );
733 }
734
735
736 /*************************************************************************/
737 /* */
738 /* <Function> */
739 /* FT_New_GlyphSlot */
740 /* */
741 /* <Description> */
742 /* It is sometimes useful to have more than one glyph slot for a */
743 /* given face object. This function is used to create additional */
744 /* slots. All of them are automatically discarded when the face is */
745 /* destroyed. */
746 /* */
747 /* <Input> */
748 /* face :: A handle to a parent face object. */
749 /* */
750 /* <Output> */
751 /* aslot :: A handle to a new glyph slot object. */
752 /* */
753 /* <Return> */
754 /* FreeType error code. 0 means success. */
755 /* */
756 FT_EXPORT_FUNC( FT_Error ) FT_New_GlyphSlot( FT_Face face,
757 FT_GlyphSlot* aslot )
758 {
759 FT_Error error;
760 FT_Driver driver;
761 FT_Driver_Class* clazz;
762 FT_Memory memory;
763 FT_GlyphSlot slot;
764
765
766 if ( !face || !aslot || !face->driver )
767 return FT_Err_Invalid_Argument;
768
769 *aslot = 0;
770
771 driver = face->driver;
772 clazz = driver->clazz;
773 memory = driver->root.memory;
774
775 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ));
776 if ( !ALLOC( slot, clazz->slot_object_size ) )
777 {
778 slot->face = face;
779
780 error = ft_glyphslot_init( slot );
781 if ( error )
782 {
783 ft_glyphslot_done( slot );
784 FREE( slot );
785 goto Exit;
786 }
787
788 *aslot = slot;
789 }
790
791 Exit:
792 FT_TRACE4(( "FT_New_GlyphSlot: Return %d\n", error ));
793 return error;
794 }
795
796
797 /*************************************************************************/
798 /* */
799 /* <Function> */
800 /* FT_Done_GlyphSlot */
801 /* */
802 /* <Description> */
803 /* Destroys a given glyph slot. Remember however that all slots are */
804 /* automatically destroyed with its parent. Using this function is */
805 /* not always mandatory. */
806 /* */
807 /* <Input> */
808 /* slot :: A handle to a target glyph slot. */
809 /* */
810 FT_EXPORT_FUNC( void ) FT_Done_GlyphSlot( FT_GlyphSlot slot )
811 {
812 if ( slot )
813 {
814 FT_Driver driver = slot->face->driver;
815 FT_Memory memory = driver->root.memory;
816 FT_GlyphSlot* parent;
817 FT_GlyphSlot cur;
818
819
820 /* Remove slot from its parent face's list */
821 parent = &slot->face->glyph;
822 cur = *parent;
823
824 while ( cur )
825 {
826 if ( cur == slot )
827 {
828 *parent = cur->next;
829 ft_glyphslot_done( slot );
830 FREE( slot );
831 break;
832 }
833 cur = cur->next;
834 }
835 }
836 }
837
838
839 /*************************************************************************/
840 /* */
841 /* <Function> */
842 /* FT_Set_Transform */
843 /* */
844 /* <Description> */
845 /* A function used to set the transformation that is applied to glyph */
846 /* images just before they are converted to bitmaps in a glyph slot */
847 /* when FT_Render_Glyph() is called. */
848 /* */
849 /* <InOut> */
850 /* face :: A handle to the source face object. */
851 /* */
852 /* <Input> */
853 /* matrix :: A pointer to the transformation's 2x2 matrix. Use 0 for */
854 /* the identity matrix. */
855 /* delta :: A pointer to the translation vector. Use 0 for the null */
856 /* vector. */
857 /* */
858 /* <Note> */
859 /* The transformation is only applied to scalable image formats after */
860 /* the glyph has been loaded. It means that hinting is unaltered by */
861 /* the transformation and is performed on the character size given in */
862 /* the last call to FT_Set_Char_Sizes() or FT_Set_Pixel_Sizes(). */
863 /* */
864 FT_EXPORT_FUNC( void ) FT_Set_Transform( FT_Face face,
865 FT_Matrix* matrix,
866 FT_Vector* delta )
867 {
868 if ( !face )
869 return;
870
871 face->transform_flags = 0;
872
873 if ( !matrix )
874 {
875 face->transform_matrix.xx = 0x10000L;
876 face->transform_matrix.xy = 0;
877 face->transform_matrix.yx = 0;
878 face->transform_matrix.yy = 0x10000L;
879 matrix = &face->transform_matrix;
880 }
881 else
882 face->transform_matrix = *matrix;
883
884 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
885 if ( ( matrix->xy | matrix->yx ) ||
886 matrix->xx != 0x10000L ||
887 matrix->yy != 0x10000L )
888 face->transform_flags |= 1;
889
890 if ( !delta )
891 {
892 face->transform_delta.x = 0;
893 face->transform_delta.y = 0;
894 delta = &face->transform_delta;
895 }
896 else
897 face->transform_delta = *delta;
898
899 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
900 if ( delta->x | delta->y )
901 face->transform_flags |= 2;
902 }
903
904
905 static FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot );
906
907
908 /*************************************************************************/
909 /* */
910 /* <Function> */
911 /* FT_Load_Glyph */
912 /* */
913 /* <Description> */
914 /* A function used to load a single glyph within a given glyph slot, */
915 /* for a given size. */
916 /* */
917 /* <Input> */
918 /* face :: A handle to the target face object where the glyph */
919 /* will be loaded. */
920 /* */
921 /* glyph_index :: The index of the glyph in the font file. */
922 /* */
923 /* load_flags :: A flag indicating what to load for this glyph. The */
924 /* FT_LOAD_XXX constants can be used to control the */
925 /* glyph loading process (e.g., whether the outline */
926 /* should be scaled, whether to load bitmaps or not, */
927 /* whether to hint the outline, etc). */
928 /* */
929 /* <Return> */
930 /* FreeType error code. 0 means success. */
931 /* */
932 /* <Note> */
933 /* If the glyph image is not a bitmap, and if the bit flag */
934 /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
935 /* transformed with the information passed to a previous call to */
936 /* FT_Set_Transform. */
937 /* */
938 /* Note that this also transforms the `face.glyph.advance' field, but */
939 /* *not* the values in `face.glyph.metrics'. */
940 /* */
941 FT_EXPORT_FUNC( FT_Error ) FT_Load_Glyph( FT_Face face,
942 FT_UInt glyph_index,
943 FT_Int load_flags )
944 {
945 FT_Error error;
946 FT_Driver driver;
947 FT_GlyphSlot slot;
948 FT_Library library;
949 FT_Bool autohint;
950 FT_Module hinter;
951
952
953 if ( !face || !face->size || !face->glyph )
954 return FT_Err_Invalid_Face_Handle;
955
956 if ( glyph_index >= (FT_UInt)face->num_glyphs )
957 return FT_Err_Invalid_Argument;
958
959 slot = face->glyph;
960 ft_glyphslot_clear( slot );
961
962 driver = face->driver;
963
964 /* when the flag NO_RECURSE is set, we disable hinting and scaling */
965 if ( load_flags & FT_LOAD_NO_RECURSE )
966 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
967
968 /* do we need to load the glyph through the auto-hinter? */
969 library = driver->root.library;
970 hinter = library->auto_hinter;
971 autohint = hinter &&
972 !( load_flags & ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) );
973 if ( autohint )
974 {
975 if ( FT_DRIVER_HAS_HINTER( driver ) &&
976 !( load_flags & FT_LOAD_FORCE_AUTOHINT ) )
977 autohint = 0;
978 }
979
980 if ( autohint )
981 {
982 FT_AutoHinter_Interface* hinting;
983
984
985 hinting = (FT_AutoHinter_Interface*)hinter->clazz->module_interface;
986 error = hinting->load_glyph( (FT_AutoHinter)hinter, slot, face->size,
987 glyph_index, load_flags );
988 }
989 else
990 error = driver->clazz->load_glyph( slot,
991 face->size,
992 glyph_index,
993 load_flags );
994 if ( error )
995 goto Exit;
996
997 /* compute the advance */
998 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT )
999 {
1000 slot->advance.x = 0;
1001 slot->advance.y = slot->metrics.vertAdvance;
1002 }
1003 else
1004 {
1005 slot->advance.x = slot->metrics.horiAdvance;
1006 slot->advance.y = 0;
1007 }
1008
1009 /* now, transform the glyph image when needed */
1010 if ( face->transform_flags )
1011 {
1012 /* get renderer */
1013 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
1014
1015
1016 if ( renderer )
1017 error = renderer->clazz->transform_glyph( renderer, slot,
1018 &face->transform_matrix,
1019 &face->transform_delta );
1020 /* transform advance */
1021 FT_Vector_Transform( &slot->advance, &face->transform_matrix );
1022 }
1023
1024 /* do we need to render the image now? */
1025 if ( !error &&
1026 slot->format != ft_glyph_format_bitmap &&
1027 slot->format != ft_glyph_format_composite &&
1028 load_flags & FT_LOAD_RENDER )
1029 {
1030 error = FT_Render_Glyph( slot,
1031 ( load_flags & FT_LOAD_MONOCHROME )
1032 ? ft_render_mode_mono
1033 : ft_render_mode_normal );
1034 }
1035
1036 Exit:
1037 return error;
1038 }
1039
1040
1041 /*************************************************************************/
1042 /* */
1043 /* <Function> */
1044 /* FT_Load_Char */
1045 /* */
1046 /* <Description> */
1047 /* A function used to load a single glyph within a given glyph slot, */
1048 /* for a given size, according to its character code. */
1049 /* */
1050 /* <Input> */
1051 /* face :: A handle to a target face object where the glyph */
1052 /* will be loaded. */
1053 /* */
1054 /* char_code :: The glyph's character code, according to the */
1055 /* current charmap used in the face. */
1056 /* */
1057 /* load_flags :: A flag indicating what to load for this glyph. The */
1058 /* FT_LOAD_XXX constants can be used to control the */
1059 /* glyph loading process (e.g., whether the outline */
1060 /* should be scaled, whether to load bitmaps or not, */
1061 /* whether to hint the outline, etc). */
1062 /* */
1063 /* <Return> */
1064 /* FreeType error code. 0 means success. */
1065 /* */
1066 /* <Note> */
1067 /* If the face has no current charmap, or if the character code */
1068 /* is not defined in the charmap, this function will return an */
1069 /* error. */
1070 /* */
1071 /* If the glyph image is not a bitmap, and if the bit flag */
1072 /* FT_LOAD_IGNORE_TRANSFORM is unset, the glyph image will be */
1073 /* transformed with the information passed to a previous call to */
1074 /* FT_Set_Transform(). */
1075 /* */
1076 /* Note that this also transforms the `face.glyph.advance' field, but */
1077 /* *not* the values in `face.glyph.metrics'. */
1078 /* */
1079 FT_EXPORT_FUNC( FT_Error ) FT_Load_Char( FT_Face face,
1080 FT_ULong char_code,
1081 FT_Int load_flags )
1082 {
1083 FT_UInt glyph_index;
1084
1085
1086 if ( !face )
1087 return FT_Err_Invalid_Face_Handle;
1088
1089 glyph_index = (FT_UInt)char_code;
1090 if ( face->charmap )
1091 glyph_index = FT_Get_Char_Index( face, char_code );
1092
1093 return FT_Load_Glyph( face, glyph_index, load_flags );
1094 }
1095
1096
1097 /* destructor for sizes list */
1098 static
1099 void destroy_size( FT_Memory memory,
1100 FT_Size size,
1101 FT_Driver driver )
1102 {
1103 /* finalize client-specific data */
1104 if ( size->generic.finalizer )
1105 size->generic.finalizer( size );
1106
1107 /* finalize format-specific stuff */
1108 if ( driver->clazz->done_size )
1109 driver->clazz->done_size( size );
1110
1111 FREE( size );
1112 }
1113
1114
1115 /* destructor for faces list */
1116 static
1117 void destroy_face( FT_Memory memory,
1118 FT_Face face,
1119 FT_Driver driver )
1120 {
1121 FT_Driver_Class* clazz = driver->clazz;
1122
1123
1124 /* discard auto-hinting data */
1125 if ( face->autohint.finalizer )
1126 face->autohint.finalizer( face->autohint.data );
1127
1128 /* Discard glyph slots for this face */
1129 /* Beware! FT_Done_GlyphSlot() changes the field `face->slot' */
1130 while ( face->glyph )
1131 FT_Done_GlyphSlot( face->glyph );
1132
1133 /* Discard all sizes for this face */
1134 FT_List_Finalize( &face->sizes_list,
1135 (FT_List_Destructor)destroy_size,
1136 memory,
1137 driver );
1138 face->size = 0;
1139
1140 /* Now discard client data */
1141 if ( face->generic.finalizer )
1142 face->generic.finalizer( face );
1143
1144 /* finalize format-specific stuff */
1145 if ( clazz->done_face )
1146 clazz->done_face( face );
1147
1148 /* close the stream for this face if needed */
1149 if ( ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) == 0 )
1150 ft_done_stream( &face->stream );
1151
1152 /* get rid of it */
1153 FREE( face );
1154 }
1155
1156
1157 static
1158 void Destroy_Driver( FT_Driver driver )
1159 {
1160 FT_List_Finalize( &driver->faces_list,
1161 (FT_List_Destructor)destroy_face,
1162 driver->root.memory,
1163 driver );
1164
1165 /* check whether we need to drop the driver's glyph loader */
1166 if ( FT_DRIVER_USES_OUTLINES( driver ) )
1167 FT_GlyphLoader_Done( driver->glyph_loader );
1168 }
1169
1170
1171 /*************************************************************************/
1172 /* */
1173 /* <Function> */
1174 /* open_face */
1175 /* */
1176 /* <Description> */
1177 /* This function does some work for FT_Open_Face(). */
1178 /* */
1179 static
1180 FT_Error open_face( FT_Driver driver,
1181 FT_Stream stream,
1182 FT_Long face_index,
1183 FT_Int num_params,
1184 FT_Parameter* params,
1185 FT_Face* aface )
1186 {
1187 FT_Memory memory;
1188 FT_Driver_Class* clazz;
1189 FT_Face face = 0;
1190 FT_Error error;
1191
1192
1193 clazz = driver->clazz;
1194 memory = driver->root.memory;
1195
1196 /* allocate the face object and perform basic initialization */
1197 if ( ALLOC( face, clazz->face_object_size ) )
1198 goto Fail;
1199
1200 face->driver = driver;
1201 face->memory = memory;
1202 face->stream = stream;
1203
1204 error = clazz->init_face( stream,
1205 face,
1206 face_index,
1207 num_params,
1208 params );
1209 if ( error )
1210 goto Fail;
1211
1212 *aface = face;
1213
1214 Fail:
1215 if ( error )
1216 {
1217 clazz->done_face( face );
1218 FREE( face );
1219 *aface = 0;
1220 }
1221
1222 return error;
1223 }
1224
1225
1226 /*************************************************************************/
1227 /* */
1228 /* <Function> */
1229 /* FT_New_Face */
1230 /* */
1231 /* <Description> */
1232 /* Creates a new face object from a given resource and typeface index */
1233 /* using a pathname to the font file. */
1234 /* */
1235 /* <InOut> */
1236 /* library :: A handle to the library resource. */
1237 /* */
1238 /* <Input> */
1239 /* pathname :: A path to the font file. */
1240 /* */
1241 /* face_index :: The index of the face within the resource. The */
1242 /* first face has index 0. */
1243 /* <Output> */
1244 /* aface :: A handle to a new face object. */
1245 /* */
1246 /* <Return> */
1247 /* FreeType error code. 0 means success. */
1248 /* */
1249 /* <Note> */
1250 /* Unlike FreeType 1.x, this function automatically creates a glyph */
1251 /* slot for the face object which can be accessed directly through */
1252 /* `face->glyph'. */
1253 /* */
1254 /* Note that additional slots can be added to each face with the */
1255 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1256 /* list through their `next' field. */
1257 /* */
1258 /* FT_New_Face() can be used to determine and/or check the font */
1259 /* format of a given font resource. If the `face_index' field is */
1260 /* negative, the function will _not_ return any face handle in */
1261 /* `*face'. Its return value should be 0 if the resource is */
1262 /* recognized, or non-zero if not. */
1263 /* */
1264 FT_EXPORT_FUNC( FT_Error ) FT_New_Face( FT_Library library,
1265 const char* pathname,
1266 FT_Long face_index,
1267 FT_Face* aface )
1268 {
1269 FT_Open_Args args;
1270
1271
1272 /* test for valid `library' and `aface' delayed to FT_Open_Face() */
1273 if ( !pathname )
1274 return FT_Err_Invalid_Argument;
1275
1276 args.flags = ft_open_pathname;
1277 args.pathname = (char*)pathname;
1278
1279 return FT_Open_Face( library, &args, face_index, aface );
1280 }
1281
1282
1283 /*************************************************************************/
1284 /* */
1285 /* <Function> */
1286 /* FT_New_Memory_Face */
1287 /* */
1288 /* <Description> */
1289 /* Creates a new face object from a given resource and typeface index */
1290 /* using a font file already loaded into memory. */
1291 /* */
1292 /* <InOut> */
1293 /* library :: A handle to the library resource. */
1294 /* */
1295 /* <Input> */
1296 /* file_base :: A pointer to the beginning of the font data. */
1297 /* */
1298 /* file_size :: The size of the memory chunk used by the font data. */
1299 /* */
1300 /* face_index :: The index of the face within the resource. The */
1301 /* first face has index 0. */
1302 /* <Output> */
1303 /* face :: A handle to a new face object. */
1304 /* */
1305 /* <Return> */
1306 /* FreeType error code. 0 means success. */
1307 /* */
1308 /* <Note> */
1309 /* Unlike FreeType 1.x, this function automatically creates a glyph */
1310 /* slot for the face object which can be accessed directly through */
1311 /* `face->glyph'. */
1312 /* */
1313 /* Note that additional slots can be added to each face with the */
1314 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1315 /* list through their `next' field. */
1316 /* */
1317 /* FT_New_Memory_Face() can be used to determine and/or check the */
1318 /* font format of a given font resource. If the `face_index' field */
1319 /* is negative, the function will _not_ return any face handle in */
1320 /* `*face'. Its return value should be 0 if the resource is */
1321 /* recognized, or non-zero if not. */
1322 /* */
1323 FT_EXPORT_FUNC( FT_Error ) FT_New_Memory_Face( FT_Library library,
1324 FT_Byte* file_base,
1325 FT_Long file_size,
1326 FT_Long face_index,
1327 FT_Face* face )
1328 {
1329 FT_Open_Args args;
1330
1331
1332 /* test for valid `library' and `face' delayed to FT_Open_Face() */
1333 if ( !file_base )
1334 return FT_Err_Invalid_Argument;
1335
1336 args.flags = ft_open_memory;
1337 args.memory_base = file_base;
1338 args.memory_size = file_size;
1339
1340 return FT_Open_Face( library, &args, face_index, face );
1341 }
1342
1343
1344 /*************************************************************************/
1345 /* */
1346 /* <Function> */
1347 /* FT_Open_Face */
1348 /* */
1349 /* <Description> */
1350 /* Opens a face object from a given resource and typeface index using */
1351 /* an `FT_Open_Args' structure. If the face object doesn't exist, it */
1352 /* will be created. */
1353 /* */
1354 /* <InOut> */
1355 /* library :: A handle to the library resource. */
1356 /* */
1357 /* <Input> */
1358 /* args :: A pointer to an `FT_Open_Args' structure which must */
1359 /* be filled by the caller. */
1360 /* */
1361 /* face_index :: The index of the face within the resource. The */
1362 /* first face has index 0. */
1363 /* <Output> */
1364 /* aface :: A handle to a new face object. */
1365 /* */
1366 /* <Return> */
1367 /* FreeType error code. 0 means success. */
1368 /* */
1369 /* <Note> */
1370 /* Unlike FreeType 1.x, this function automatically creates a glyph */
1371 /* slot for the face object which can be accessed directly through */
1372 /* `face->glyph'. */
1373 /* */
1374 /* Note that additional slots can be added to each face with the */
1375 /* FT_New_GlyphSlot() API function. Slots are linked in a single */
1376 /* list through their `next' field. */
1377 /* */
1378 /* FT_Open_Face() can be used to determine and/or check the font */
1379 /* format of a given font resource. If the `face_index' field is */
1380 /* negative, the function will _not_ return any face handle in */
1381 /* `*face'. Its return value should be 0 if the resource is */
1382 /* recognized, or non-zero if not. */
1383 /* */
1384 FT_EXPORT_FUNC( FT_Error ) FT_Open_Face( FT_Library library,
1385 FT_Open_Args* args,
1386 FT_Long face_index,
1387 FT_Face* aface )
1388 {
1389 FT_Error error;
1390 FT_Driver driver;
1391 FT_Memory memory;
1392 FT_Stream stream;
1393 FT_Face face = 0;
1394 FT_ListNode node = 0;
1395
1396
1397 /* test for valid `library' and `args' delayed to */
1398 /* ft_new_input_stream() */
1399
1400 if ( !aface )
1401 return FT_Err_Invalid_Argument;
1402
1403 *aface = 0;
1404
1405 /* create input stream */
1406 error = ft_new_input_stream( library, args, &stream );
1407 if ( error )
1408 goto Exit;
1409
1410 memory = library->memory;
1411
1412 /* If the font driver is specified in the `args' structure, use */
1413 /* it. Otherwise, we scan the list of registered drivers. */
1414 if ( args->flags & ft_open_driver && args->driver )
1415 {
1416 driver = FT_DRIVER( args->driver );
1417
1418 /* not all modules are drivers, so check... */
1419 if ( FT_MODULE_IS_DRIVER( driver ) )
1420 {
1421 FT_Int num_params = 0;
1422 FT_Parameter* params = 0;
1423
1424
1425 if ( args->flags & ft_open_params )
1426 {
1427 num_params = args->num_params;
1428 params = args->params;
1429 }
1430
1431 error = open_face( driver, stream, face_index,
1432 num_params, params, &face );
1433 if ( !error )
1434 goto Success;
1435 }
1436 else
1437 error = FT_Err_Invalid_Handle;
1438
1439 ft_done_stream( &stream );
1440 goto Fail;
1441 }
1442 else
1443 {
1444 /* check each font driver for an appropriate format */
1445 FT_Module* cur = library->modules;
1446 FT_Module* limit = cur + library->num_modules;
1447
1448
1449 for ( ; cur < limit; cur++ )
1450 {
1451 /* not all modules are font drivers, so check... */
1452 if ( FT_MODULE_IS_DRIVER( cur[0] ) )
1453 {
1454 FT_Int num_params = 0;
1455 FT_Parameter* params = 0;
1456
1457
1458 driver = FT_DRIVER( cur[0] );
1459
1460 if ( args->flags & ft_open_params )
1461 {
1462 num_params = args->num_params;
1463 params = args->params;
1464 }
1465
1466 error = open_face( driver, stream, face_index,
1467 num_params, params, &face );
1468 if ( !error )
1469 goto Success;
1470
1471 if ( error != FT_Err_Unknown_File_Format )
1472 goto Fail;
1473 }
1474 }
1475
1476 ft_done_stream( &stream );
1477
1478 /* no driver is able to handle this format */
1479 error = FT_Err_Unknown_File_Format;
1480 goto Fail;
1481 }
1482
1483 Success:
1484 FT_TRACE4(( "FT_New_Face: New face object, adding to list\n" ));
1485
1486 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
1487 if ( args->flags & ft_open_stream && args->stream )
1488 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM;
1489
1490 /* add the face object to its driver's list */
1491 if ( ALLOC( node, sizeof ( *node ) ) )
1492 goto Fail;
1493
1494 node->data = face;
1495 /* don't assume driver is the same as face->driver, so use */
1496 /* face->driver instead. */
1497 FT_List_Add( &face->driver->faces_list, node );
1498
1499 /* now allocate a glyph slot object for the face */
1500 {
1501 FT_GlyphSlot slot;
1502
1503
1504 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ));
1505
1506 error = FT_New_GlyphSlot( face, &slot );
1507 if ( error )
1508 goto Fail;
1509
1510 face->glyph = slot;
1511 }
1512
1513 /* finally, allocate a size object for the face */
1514 {
1515 FT_Size size;
1516
1517
1518 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ));
1519
1520 error = FT_New_Size( face, &size );
1521 if ( error )
1522 goto Fail;
1523
1524 face->size = size;
1525 }
1526
1527 /* initialize transformation for convenience functions */
1528 face->transform_matrix.xx = 0x10000L;
1529 face->transform_matrix.xy = 0;
1530 face->transform_matrix.yx = 0;
1531 face->transform_matrix.yy = 0x10000L;
1532
1533 face->transform_delta.x = 0;
1534 face->transform_delta.y = 0;
1535
1536 *aface = face;
1537 goto Exit;
1538
1539 Fail:
1540 FT_Done_Face( face );
1541
1542 Exit:
1543 FT_TRACE4(( "FT_Open_Face: Return %d\n", error ));
1544
1545 return error;
1546 }
1547
1548
1549 /*************************************************************************/
1550 /* */
1551 /* <Function> */
1552 /* FT_Attach_File */
1553 /* */
1554 /* <Description> */
1555 /* `Attaches' a given font file to an existing face. This is usually */
1556 /* to read additional information for a single face object. For */
1557 /* example, it is used to read the AFM files that come with Type 1 */
1558 /* fonts in order to add kerning data and other metrics. */
1559 /* */
1560 /* <InOut> */
1561 /* face :: The target face object. */
1562 /* */
1563 /* <Input> */
1564 /* filepathname :: An 8-bit pathname naming the `metrics' file. */
1565 /* */
1566 /* <Return> */
1567 /* FreeType error code. 0 means success. */
1568 /* */
1569 /* <Note> */
1570 /* If your font file is in memory, or if you want to provide your */
1571 /* own input stream object, use FT_Attach_Stream(). */
1572 /* */
1573 /* The meaning of the `attach' action (i.e., what really happens when */
1574 /* the new file is read) is not fixed by FreeType itself. It really */
1575 /* depends on the font format (and thus the font driver). */
1576 /* */
1577 /* Client applications are expected to know what they are doing */
1578 /* when invoking this function. Most drivers simply do not implement */
1579 /* file attachments. */
1580 /* */
1581 FT_EXPORT_FUNC( FT_Error ) FT_Attach_File( FT_Face face,
1582 const char* filepathname )
1583 {
1584 FT_Open_Args open;
1585
1586
1587 /* test for valid `face' delayed to FT_Attach_Stream() */
1588
1589 if ( !filepathname )
1590 return FT_Err_Invalid_Argument;
1591
1592 open.flags = ft_open_pathname;
1593 open.pathname = (char*)filepathname;
1594
1595 return FT_Attach_Stream( face, &open );
1596 }
1597
1598
1599 /*************************************************************************/
1600 /* */
1601 /* <Function> */
1602 /* FT_Attach_Stream */
1603 /* */
1604 /* <Description> */
1605 /* This function is similar to FT_Attach_File() with the exception */
1606 /* that it reads the attachment from an arbitrary stream. */
1607 /* */
1608 /* <Input> */
1609 /* face :: The target face object. */
1610 /* */
1611 /* parameters :: A pointer to an FT_Open_Args structure used to */
1612 /* describe the input stream to FreeType. */
1613 /* <Return> */
1614 /* FreeType error code. 0 means success. */
1615 /* */
1616 /* <Note> */
1617 /* The meaning of the `attach' (i.e. what really happens when the */
1618 /* new file is read) is not fixed by FreeType itself. It really */
1619 /* depends on the font format (and thus the font driver). */
1620 /* */
1621 /* Client applications are expected to know what they are doing */
1622 /* when invoking this function. Most drivers simply do not implement */
1623 /* file attachments. */
1624 /* */
1625 FT_EXPORT_FUNC( FT_Error ) FT_Attach_Stream( FT_Face face,
1626 FT_Open_Args* parameters )
1627 {
1628 FT_Stream stream;
1629 FT_Error error;
1630 FT_Driver driver;
1631
1632 FT_Driver_Class* clazz;
1633
1634
1635 /* test for valid `parameters' delayed to ft_new_input_stream() */
1636
1637 if ( !face )
1638 return FT_Err_Invalid_Face_Handle;
1639
1640 driver = face->driver;
1641 if ( !driver )
1642 return FT_Err_Invalid_Driver_Handle;
1643
1644 error = ft_new_input_stream( driver->root.library, parameters, &stream );
1645 if ( error )
1646 goto Exit;
1647
1648 /* we implement FT_Attach_Stream in each driver through the */
1649 /* `attach_file' interface */
1650
1651 error = FT_Err_Unimplemented_Feature;
1652 clazz = driver->clazz;
1653 if ( clazz->attach_file )
1654 error = clazz->attach_file( face, stream );
1655
1656 /* close the attached stream */
1657 if ( !parameters->stream || ( parameters->flags & ft_open_stream ) )
1658 ft_done_stream( &stream );
1659
1660 Exit:
1661 return error;
1662 }
1663
1664
1665 /*************************************************************************/
1666 /* */
1667 /* <Function> */
1668 /* FT_Done_Face */
1669 /* */
1670 /* <Description> */
1671 /* Discards a given face object, as well as all of its child slots */
1672 /* and sizes. */
1673 /* */
1674 /* <Input> */
1675 /* face :: A handle to a target face object. */
1676 /* */
1677 /* <Return> */
1678 /* FreeType error code. 0 means success. */
1679 /* */
1680 FT_EXPORT_FUNC( FT_Error ) FT_Done_Face( FT_Face face )
1681 {
1682 FT_Error error;
1683 FT_Driver driver;
1684 FT_Memory memory;
1685 FT_ListNode node;
1686
1687
1688 error = FT_Err_Invalid_Face_Handle;
1689 if ( face && face->driver )
1690 {
1691 driver = face->driver;
1692 memory = driver->root.memory;
1693
1694 /* find face in driver's list */
1695 node = FT_List_Find( &driver->faces_list, face );
1696 if ( node )
1697 {
1698 /* remove face object from the driver's list */
1699 FT_List_Remove( &driver->faces_list, node );
1700 FREE( node );
1701
1702 /* now destroy the object proper */
1703 destroy_face( memory, face, driver );
1704 error = FT_Err_Ok;
1705 }
1706 }
1707 return error;
1708 }
1709
1710
1711 /*************************************************************************/
1712 /* */
1713 /* <Function> */
1714 /* FT_New_Size */
1715 /* */
1716 /* <Description> */
1717 /* Creates a new size object from a given face object. */
1718 /* */
1719 /* <Input> */
1720 /* face :: A handle to a parent face object. */
1721 /* */
1722 /* <Output> */
1723 /* asize :: A handle to a new size object. */
1724 /* */
1725 /* <Return> */
1726 /* FreeType error code. 0 means success. */
1727 /* */
1728 FT_EXPORT_FUNC( FT_Error ) FT_New_Size( FT_Face face,
1729 FT_Size* asize )
1730 {
1731 FT_Error error;
1732 FT_Memory memory;
1733 FT_Driver driver;
1734 FT_Driver_Class* clazz;
1735
1736 FT_Size size = 0;
1737 FT_ListNode node = 0;
1738
1739
1740 if ( !face )
1741 return FT_Err_Invalid_Face_Handle;
1742
1743 if ( !asize )
1744 return FT_Err_Invalid_Size_Handle;
1745
1746 if ( !face->driver )
1747 return FT_Err_Invalid_Driver_Handle;
1748
1749 *asize = 0;
1750
1751 driver = face->driver;
1752 clazz = driver->clazz;
1753 memory = face->memory;
1754
1755 /* Allocate new size object and perform basic initialisation */
1756 if ( ALLOC( size, clazz->size_object_size ) ||
1757 ALLOC( node, sizeof ( FT_ListNodeRec ) ) )
1758 goto Exit;
1759
1760 size->face = face;
1761
1762 if ( clazz->init_size )
1763 error = clazz->init_size( size );
1764
1765 /* in case of success, add to the face's list */
1766 if ( !error )
1767 {
1768 *asize = size;
1769 node->data = size;
1770 FT_List_Add( &face->sizes_list, node );
1771 }
1772
1773 Exit:
1774 if ( error )
1775 {
1776 FREE( node );
1777 FREE( size );
1778 }
1779
1780 return error;
1781 }
1782
1783
1784 /*************************************************************************/
1785 /* */
1786 /* <Function> */
1787 /* FT_Done_Size */
1788 /* */
1789 /* <Description> */
1790 /* Discards a given size object. */
1791 /* */
1792 /* <Input> */
1793 /* size :: A handle to a target size object. */
1794 /* */
1795 /* <Return> */
1796 /* FreeType error code. 0 means success. */
1797 /* */
1798 FT_EXPORT_FUNC( FT_Error ) FT_Done_Size( FT_Size size )
1799 {
1800 FT_Error error;
1801 FT_Driver driver;
1802 FT_Memory memory;
1803 FT_Face face;
1804 FT_ListNode node;
1805
1806
1807 if ( !size )
1808 return FT_Err_Invalid_Size_Handle;
1809
1810 face = size->face;
1811 if ( !face )
1812 return FT_Err_Invalid_Face_Handle;
1813
1814 driver = face->driver;
1815 if ( !driver )
1816 return FT_Err_Invalid_Driver_Handle;
1817
1818 memory = driver->root.memory;
1819
1820 error = FT_Err_Ok;
1821 node = FT_List_Find( &face->sizes_list, size );
1822 if ( node )
1823 {
1824 FT_List_Remove( &face->sizes_list, node );
1825 FREE( node );
1826
1827 if ( face->size == size )
1828 {
1829 face->size = 0;
1830 if ( face->sizes_list.head )
1831 face->size = (FT_Size)(face->sizes_list.head->data);
1832 }
1833
1834 destroy_size( memory, size, driver );
1835 }
1836 else
1837 error = FT_Err_Invalid_Size_Handle;
1838
1839 return FT_Err_Ok;
1840 }
1841
1842
1843 static
1844 void ft_recompute_scaled_metrics( FT_Face face,
1845 FT_Size_Metrics* metrics )
1846 {
1847 /* Compute root ascender, descender, test height, and max_advance */
1848
1849 metrics->ascender = ( FT_MulFix( face->ascender,
1850 metrics->y_scale ) + 32 ) & -64;
1851
1852 metrics->descender = ( FT_MulFix( face->descender,
1853 metrics->y_scale ) + 32 ) & -64;
1854
1855 metrics->height = ( FT_MulFix( face->height,
1856 metrics->y_scale ) + 32 ) & -64;
1857
1858 metrics->max_advance = ( FT_MulFix( face->max_advance_width,
1859 metrics->x_scale ) + 32 ) & -64;
1860 }
1861
1862
1863 /*************************************************************************/
1864 /* */
1865 /* <Function> */
1866 /* FT_Set_Char_Size */
1867 /* */
1868 /* <Description> */
1869 /* Sets the character dimensions of a given face object. The */
1870 /* `char_width' and `char_height' values are used for the width and */
1871 /* height, respectively, expressed in 26.6 fractional points. */
1872 /* */
1873 /* If the horizontal or vertical resolution values are zero, a */
1874 /* default value of 72dpi is used. Similarly, if one of the */
1875 /* character dimensions is zero, its value is set equal to the other. */
1876 /* */
1877 /* <InOut> */
1878 /* size :: A handle to a target size object. */
1879 /* */
1880 /* <Input> */
1881 /* char_width :: The character width, in 26.6 fractional points. */
1882 /* */
1883 /* char_height :: The character height, in 26.6 fractional */
1884 /* points. */
1885 /* */
1886 /* horz_resolution :: The horizontal resolution. */
1887 /* */
1888 /* vert_resolution :: The vertical resolution. */
1889 /* */
1890 /* <Return> */
1891 /* FreeType error code. 0 means success. */
1892 /* */
1893 /* <Note> */
1894 /* When dealing with fixed-size faces (i.e., non-scalable formats), */
1895 /* use the function FT_Set_Pixel_Sizes(). */
1896 /* */
1897 FT_EXPORT_FUNC( FT_Error ) FT_Set_Char_Size( FT_Face face,
1898 FT_F26Dot6 char_width,
1899 FT_F26Dot6 char_height,
1900 FT_UInt horz_resolution,
1901 FT_UInt vert_resolution )
1902 {
1903 FT_Error error = FT_Err_Ok;
1904 FT_Driver driver;
1905 FT_Memory memory;
1906 FT_Driver_Class* clazz;
1907 FT_Size_Metrics* metrics;
1908 FT_Long dim_x, dim_y;
1909
1910
1911 if ( !face || !face->size || !face->driver )
1912 return FT_Err_Invalid_Face_Handle;
1913
1914 driver = face->driver;
1915 metrics = &face->size->metrics;
1916
1917 if ( !char_width )
1918 char_width = char_height;
1919
1920 else if ( !char_height )
1921 char_height = char_width;
1922
1923 if ( !horz_resolution )
1924 horz_resolution = 72;
1925
1926 if ( !vert_resolution )
1927 vert_resolution = 72;
1928
1929 driver = face->driver;
1930 clazz = driver->clazz;
1931 memory = driver->root.memory;
1932
1933 /* default processing -- this can be overridden by the driver */
1934 if ( char_width < 1 * 64 )
1935 char_width = 1 * 64;
1936 if ( char_height < 1 * 64 )
1937 char_height = 1 * 64;
1938
1939 /* Compute pixel sizes in 26.6 units */
1940 dim_x = ( ( ( char_width * horz_resolution ) / 72 ) + 32 ) & -64;
1941 dim_y = ( ( ( char_height * vert_resolution ) / 72 ) + 32 ) & -64;
1942
1943 metrics->x_ppem = (FT_UShort)( dim_x >> 6 );
1944 metrics->y_ppem = (FT_UShort)( dim_y >> 6 );
1945
1946 metrics->x_scale = 0x10000L;
1947 metrics->y_scale = 0x10000L;
1948
1949 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
1950 {
1951 metrics->x_scale = FT_DivFix( dim_x, face->units_per_EM );
1952 metrics->y_scale = FT_DivFix( dim_y, face->units_per_EM );
1953
1954 ft_recompute_scaled_metrics( face, metrics );
1955 }
1956
1957 if ( clazz->set_char_sizes )
1958 error = clazz->set_char_sizes( face->size,
1959 char_width,
1960 char_height,
1961 horz_resolution,
1962 vert_resolution );
1963 return error;
1964 }
1965
1966
1967 /*************************************************************************/
1968 /* */
1969 /* <Function> */
1970 /* FT_Set_Pixel_Sizes */
1971 /* */
1972 /* <Description> */
1973 /* Sets the character dimensions of a given face object. The width */
1974 /* and height are expressed in integer pixels. */
1975 /* */
1976 /* If one of the character dimensions is zero, its value is set equal */
1977 /* to the other. */
1978 /* */
1979 /* <InOut> */
1980 /* face :: A handle to the target face object. */
1981 /* */
1982 /* <Input> */
1983 /* pixel_width :: The character width, in integer pixels. */
1984 /* */
1985 /* pixel_height :: The character height, in integer pixels. */
1986 /* */
1987 /* <Return> */
1988 /* FreeType error code. 0 means success. */
1989 /* */
1990 FT_EXPORT_FUNC( FT_Error ) FT_Set_Pixel_Sizes( FT_Face face,
1991 FT_UInt pixel_width,
1992 FT_UInt pixel_height )
1993 {
1994 FT_Error error = FT_Err_Ok;
1995 FT_Driver driver;
1996 FT_Memory memory;
1997 FT_Driver_Class* clazz;
1998 FT_Size_Metrics* metrics = &face->size->metrics;
1999
2000
2001 if ( !face || !face->size || !face->driver )
2002 return FT_Err_Invalid_Face_Handle;
2003
2004 driver = face->driver;
2005 clazz = driver->clazz;
2006 memory = driver->root.memory;
2007
2008 /* default processing -- this can be overridden by the driver */
2009 if ( pixel_width == 0 )
2010 pixel_width = pixel_height;
2011
2012 else if ( pixel_height == 0 )
2013 pixel_height = pixel_width;
2014
2015 if ( pixel_width < 1 )
2016 pixel_width = 1;
2017 if ( pixel_height < 1 )
2018 pixel_height = 1;
2019
2020 metrics->x_ppem = pixel_width;
2021 metrics->y_ppem = pixel_height;
2022
2023 if ( face->face_flags & FT_FACE_FLAG_SCALABLE )
2024 {
2025 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6,
2026 face->units_per_EM );
2027
2028 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6,
2029 face->units_per_EM );
2030
2031 ft_recompute_scaled_metrics( face, metrics );
2032 }
2033
2034 if ( clazz->set_pixel_sizes )
2035 error = clazz->set_pixel_sizes( face->size,
2036 pixel_width,
2037 pixel_height );
2038 return error;
2039 }
2040
2041
2042 /*************************************************************************/
2043 /* */
2044 /* <Function> */
2045 /* FT_Get_Kerning */
2046 /* */
2047 /* <Description> */
2048 /* Returns the kerning vector between two glyphs of a same face. */
2049 /* */
2050 /* <Input> */
2051 /* face :: A handle to a source face object. */
2052 /* */
2053 /* left_glyph :: The index of the left glyph in the kern pair. */
2054 /* */
2055 /* right_glyph :: The index of the right glyph in the kern pair. */
2056 /* */
2057 /* kern_mode :: See FT_Kerning_Mode() for more information. */
2058 /* Determines the scale/dimension of the returned */
2059 /* kerning vector. */
2060 /* */
2061 /* <Output> */
2062 /* kerning :: The kerning vector. This is in font units for */
2063 /* scalable formats, and in pixels for fixed-sizes */
2064 /* formats. */
2065 /* */
2066 /* <Return> */
2067 /* FreeType error code. 0 means success. */
2068 /* */
2069 /* <Note> */
2070 /* Only horizontal layouts (left-to-right & right-to-left) are */
2071 /* supported by this method. Other layouts, or more sophisticated */
2072 /* kernings, are out of the scope of this API function -- they can be */
2073 /* implemented through format-specific interfaces. */
2074 /* */
2075 FT_EXPORT_FUNC( FT_Error ) FT_Get_Kerning( FT_Face face,
2076 FT_UInt left_glyph,
2077 FT_UInt right_glyph,
2078 FT_UInt kern_mode,
2079 FT_Vector* kerning )
2080 {
2081 FT_Error error = FT_Err_Ok;
2082 FT_Driver driver;
2083 FT_Memory memory;
2084
2085
2086 if ( !face )
2087 return FT_Err_Invalid_Face_Handle;
2088
2089 if ( !kerning )
2090 return FT_Err_Invalid_Argument;
2091
2092 driver = face->driver;
2093 memory = driver->root.memory;
2094
2095 kerning->x = 0;
2096 kerning->y = 0;
2097
2098 if ( driver->clazz->get_kerning )
2099 {
2100 error = driver->clazz->get_kerning( face,
2101 left_glyph,
2102 right_glyph,
2103 kerning );
2104 if ( !error )
2105 {
2106 if ( kern_mode != ft_kerning_unscaled )
2107 {
2108 kerning->x = FT_MulFix( kerning->x, face->size->metrics.x_scale );
2109 kerning->y = FT_MulFix( kerning->y, face->size->metrics.y_scale );
2110
2111 if ( kern_mode != ft_kerning_unfitted )
2112 {
2113 kerning->x = ( kerning->x + 32 ) & -64;
2114 kerning->y = ( kerning->y + 32 ) & -64;
2115 }
2116 }
2117 }
2118 }
2119
2120 return error;
2121 }
2122
2123
2124 /*************************************************************************/
2125 /* */
2126 /* <Function> */
2127 /* FT_Select_Charmap */
2128 /* */
2129 /* <Description> */
2130 /* Selects a given charmap by its encoding tag (as listed in */
2131 /* `freetype.h'). */
2132 /* */
2133 /* <Input> */
2134 /* face :: A handle to the source face object. */
2135 /* */
2136 /* encoding :: A handle to the selected charmap. */
2137 /* */
2138 /* <Return> */
2139 /* FreeType error code. 0 means success. */
2140 /* */
2141 /* <Note> */
2142 /* This function will return an error if no charmap in the face */
2143 /* corresponds to the encoding queried here. */
2144 /* */
2145 FT_EXPORT_FUNC( FT_Error ) FT_Select_Charmap( FT_Face face,
2146 FT_Encoding encoding )
2147 {
2148 FT_CharMap* cur;
2149 FT_CharMap* limit;
2150
2151
2152 if ( !face )
2153 return FT_Err_Invalid_Face_Handle;
2154
2155 cur = face->charmaps;
2156 if ( !cur )
2157 return FT_Err_Invalid_CharMap_Handle;
2158
2159 limit = cur + face->num_charmaps;
2160
2161 for ( ; cur < limit; cur++ )
2162 {
2163 if ( cur[0]->encoding == encoding )
2164 {
2165 face->charmap = cur[0];
2166 return 0;
2167 }
2168 }
2169
2170 return FT_Err_Invalid_Argument;
2171 }
2172
2173
2174 /*************************************************************************/
2175 /* */
2176 /* <Function> */
2177 /* FT_Set_Charmap */
2178 /* */
2179 /* <Description> */
2180 /* Selects a given charmap for character code to glyph index */
2181 /* decoding. */
2182 /* */
2183 /* <Input> */
2184 /* face :: A handle to the source face object. */
2185 /* charmap :: A handle to the selected charmap. */
2186 /* */
2187 /* <Return> */
2188 /* FreeType error code. 0 means success. */
2189 /* */
2190 /* <Note> */
2191 /* This function will return an error if the charmap is not part of */
2192 /* the face (i.e., if it is not listed in the face->charmaps[] */
2193 /* table). */
2194 /* */
2195 FT_EXPORT_FUNC( FT_Error ) FT_Set_Charmap( FT_Face face,
2196 FT_CharMap charmap )
2197 {
2198 FT_CharMap* cur;
2199 FT_CharMap* limit;
2200
2201
2202 if ( !face )
2203 return FT_Err_Invalid_Face_Handle;
2204
2205 cur = face->charmaps;
2206 if ( !cur )
2207 return FT_Err_Invalid_CharMap_Handle;
2208
2209 limit = cur + face->num_charmaps;
2210
2211 for ( ; cur < limit; cur++ )
2212 {
2213 if ( cur[0] == charmap )
2214 {
2215 face->charmap = cur[0];
2216 return 0;
2217 }
2218 }
2219 return FT_Err_Invalid_Argument;
2220 }
2221
2222
2223 /*************************************************************************/
2224 /* */
2225 /* <Function> */
2226 /* FT_Get_Char_Index */
2227 /* */
2228 /* <Description> */
2229 /* Returns the glyph index of a given character code. This function */
2230 /* uses a charmap object to do the translation. */
2231 /* */
2232 /* <Input> */
2233 /* face :: A handle to the source face object. */
2234 /* */
2235 /* charcode :: The character code. */
2236 /* */
2237 /* <Return> */
2238 /* The glyph index. 0 means `undefined character code'. */
2239 /* */
2240 FT_EXPORT_FUNC( FT_UInt ) FT_Get_Char_Index( FT_Face face,
2241 FT_ULong charcode )
2242 {
2243 FT_UInt result;
2244 FT_Driver driver;
2245
2246
2247 result = 0;
2248 if ( face && face->charmap )
2249 {
2250 driver = face->driver;
2251 result = driver->clazz->get_char_index( face->charmap, charcode );
2252 }
2253 return result;
2254 }
2255
2256
2257 /*************************************************************************/
2258 /* */
2259 /* <Function> */
2260 /* FT_Get_Glyph_Name */
2261 /* */
2262 /* <Description> */
2263 /* Retrieves the ASCII name of a given glyph in a face. This only */
2264 /* works for those faces where FT_HAS_GLYPH_NAME(face) returns true. */
2265 /* */
2266 /* <Input> */
2267 /* face :: A handle to a source face object. */
2268 /* */
2269 /* glyph_index :: The glyph index. */
2270 /* */
2271 /* buffer :: A pointer to a target buffer where the name will be */
2272 /* copied to. */
2273 /* */
2274 /* buffer_max :: The maximal number of bytes available in the */
2275 /* buffer. */
2276 /* */
2277 /* <Return> */
2278 /* FreeType error code. 0 means success. */
2279 /* */
2280 /* <Note> */
2281 /* An error is returned if the face doesn't provide glyph names or if */
2282 /* the glyph index is invalid. In all cases of failure, the first */
2283 /* byte of `buffer' will be set to 0 to indicate an empty name. */
2284 /* */
2285 /* The glyph name is truncated to fit within the buffer if it is too */
2286 /* long. The returned string is always zero-terminated. */
2287 /* */
2288 /* This function is not compiled within the library if the config */
2289 /* macro FT_CONFIG_OPTION_NO_GLYPH_NAMES is defined in */
2290 /* `include/freetype/config/ftoptions.h' */
2291 /* */
2292 FT_EXPORT_FUNC( FT_Error ) FT_Get_Glyph_Name( FT_Face face,
2293 FT_UInt glyph_index,
2294 FT_Pointer buffer,
2295 FT_UInt buffer_max )
2296 {
2297 FT_Error error = FT_Err_Invalid_Argument;
2298
2299
2300 /* clean up buffer */
2301 if ( buffer && buffer_max > 0 )
2302 ((FT_Byte*)buffer)[0] = 0;
2303
2304 if ( face &&
2305 glyph_index < (FT_UInt)face->num_glyphs &&
2306 FT_HAS_GLYPH_NAMES( face ) )
2307 {
2308 /* now, lookup for glyph name */
2309 FT_Driver driver = face->driver;
2310 FT_Module_Class* clazz = FT_MODULE_CLASS( driver );
2311
2312
2313 if ( clazz->get_interface )
2314 {
2315 FT_Glyph_Name_Requester requester;
2316
2317
2318 requester = (FT_Glyph_Name_Requester)clazz->get_interface(
2319 FT_MODULE( driver ), "glyph_name" );
2320 if ( requester )
2321 error = requester( face, glyph_index, buffer, buffer_max );
2322 }
2323 }
2324
2325 return error;
2326 }
2327
2328
2329 /*************************************************************************/
2330 /* */
2331 /* <Function> */
2332 /* FT_Get_Sfnt_Table */
2333 /* */
2334 /* <Description> */
2335 /* Returns a pointer to a given SFNT table within a face. */
2336 /* */
2337 /* <Input> */
2338 /* face :: A handle to the source face object. */
2339 /* tag :: An index of an SFNT table. */
2340 /* */
2341 /* <Return> */
2342 /* A type-less pointer to the table. This will be 0 in case of */
2343 /* error, or if the corresponding table was not found *OR* loaded */
2344 /* from the file. */
2345 /* */
2346 /* <Note> */
2347 /* The table is owned by the face object, and disappears with it. */
2348 /* */
2349 /* This function is only useful to access SFNT tables that are loaded */
2350 /* by the sfnt/truetype/opentype drivers. See the FT_Sfnt_Tag */
2351 /* enumeration in `tttables.h' for a list. */
2352 /* */
2353 /* You can load any table with a different function.. XXX */
2354 /* */
2355 FT_EXPORT_FUNC( void* ) FT_Get_Sfnt_Table( FT_Face face,
2356 FT_Sfnt_Tag tag )
2357 {
2358 void* table = 0;
2359 FT_Get_Sfnt_Table_Func func;
2360 FT_Driver driver;
2361
2362
2363 if ( !face || !FT_IS_SFNT( face ) )
2364 goto Exit;
2365
2366 driver = face->driver;
2367 func = (FT_Get_Sfnt_Table_Func)driver->root.clazz->get_interface(
2368 FT_MODULE( driver ), "get_sfnt" );
2369 if ( func )
2370 table = func( face, tag );
2371
2372 Exit:
2373 return table;
2374 }
2375
2376
2377 /*************************************************************************/
2378 /*************************************************************************/
2379 /*************************************************************************/
2380 /**** ****/
2381 /**** ****/
2382 /**** R E N D E R E R S ****/
2383 /**** ****/
2384 /**** ****/
2385 /*************************************************************************/
2386 /*************************************************************************/
2387 /*************************************************************************/
2388
2389 /* lookup a renderer by glyph format in the library's list */
2390 BASE_FUNC( FT_Renderer ) FT_Lookup_Renderer( FT_Library library,
2391 FT_Glyph_Format format,
2392 FT_ListNode* node )
2393 {
2394 FT_ListNode cur;
2395 FT_Renderer result = 0;
2396
2397
2398 if ( !library )
2399 goto Exit;
2400
2401 cur = library->renderers.head;
2402
2403 if ( node )
2404 {
2405 if ( *node )
2406 cur = (*node)->next;
2407 *node = 0;
2408 }
2409
2410 while ( cur )
2411 {
2412 FT_Renderer renderer = FT_RENDERER( cur->data );
2413
2414
2415 if ( renderer->glyph_format == format )
2416 {
2417 if ( node )
2418 *node = cur;
2419
2420 result = renderer;
2421 break;
2422 }
2423 cur = cur->next;
2424 }
2425
2426 Exit:
2427 return result;
2428 }
2429
2430
2431 static
2432 FT_Renderer ft_lookup_glyph_renderer( FT_GlyphSlot slot )
2433 {
2434 FT_Face face = slot->face;
2435 FT_Library library = FT_FACE_LIBRARY( face );
2436 FT_Renderer result = library->cur_renderer;
2437
2438
2439 if ( !result || result->glyph_format != slot->format )
2440 result = FT_Lookup_Renderer( library, slot->format, 0 );
2441
2442 return result;
2443 }
2444
2445
2446 static
2447 void ft_set_current_renderer( FT_Library library )
2448 {
2449 FT_Renderer renderer;
2450
2451
2452 renderer = FT_Lookup_Renderer( library, ft_glyph_format_outline, 0 );
2453 library->cur_renderer = renderer;
2454 }
2455
2456
2457 static
2458 FT_Error ft_add_renderer( FT_Module module )
2459 {
2460 FT_Library library = module->library;
2461 FT_Memory memory = library->memory;
2462 FT_Error error;
2463 FT_ListNode node;
2464
2465
2466 if ( ALLOC( node, sizeof ( *node ) ) )
2467 goto Exit;
2468
2469 {
2470 FT_Renderer render = FT_RENDERER( module );
2471 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2472
2473
2474 render->clazz = clazz;
2475 render->glyph_format = clazz->glyph_format;
2476
2477 /* allocate raster object if needed */
2478 if ( clazz->glyph_format == ft_glyph_format_outline &&
2479 clazz->raster_class->raster_new )
2480 {
2481 error = clazz->raster_class->raster_new( memory, &render->raster );
2482 if ( error )
2483 goto Fail;
2484
2485 render->raster_render = clazz->raster_class->raster_render;
2486 render->render = clazz->render_glyph;
2487 }
2488
2489 /* add to list */
2490 node->data = module;
2491 FT_List_Add( &library->renderers, node );
2492
2493 ft_set_current_renderer( library );
2494 }
2495
2496 Fail:
2497 if ( error )
2498 FREE( node );
2499
2500 Exit:
2501 return error;
2502 }
2503
2504
2505 static
2506 void ft_remove_renderer( FT_Module module )
2507 {
2508 FT_Library library = module->library;
2509 FT_Memory memory = library->memory;
2510 FT_ListNode node;
2511
2512
2513 node = FT_List_Find( &library->renderers, module );
2514 if ( node )
2515 {
2516 FT_Renderer render = FT_RENDERER( module );
2517
2518
2519 /* release raster object, if any */
2520 if ( render->raster )
2521 render->clazz->raster_class->raster_done( render->raster );
2522
2523 /* remove from list */
2524 FT_List_Remove( &library->renderers, node );
2525 FREE( node );
2526
2527 ft_set_current_renderer( library );
2528 }
2529 }
2530
2531
2532 /*************************************************************************/
2533 /* */
2534 /* <Function> */
2535 /* FT_Get_Renderer */
2536 /* */
2537 /* <Description> */
2538 /* Retrieves the current renderer for a given glyph format. */
2539 /* */
2540 /* <Input> */
2541 /* library :: A handle to the library object. */
2542 /* */
2543 /* format :: The glyph format. */
2544 /* */
2545 /* <Return> */
2546 /* A renderer handle. 0 if none found. */
2547 /* */
2548 /* <Note> */
2549 /* An error will be returned if a module already exists by that name, */
2550 /* or if the module requires a version of FreeType that is too great. */
2551 /* */
2552 /* To add a new renderer, simply use FT_Add_Module(). To retrieve a */
2553 /* renderer by its name, use FT_Get_Module(). */
2554 /* */
2555 FT_EXPORT_FUNC( FT_Renderer ) FT_Get_Renderer( FT_Library library,
2556 FT_Glyph_Format format )
2557 {
2558 /* test for valid `library' delayed to FT_Lookup_Renderer() */
2559
2560 return FT_Lookup_Renderer( library, format, 0 );
2561 }
2562
2563
2564 /*************************************************************************/
2565 /* */
2566 /* <Function> */
2567 /* FT_Set_Renderer */
2568 /* */
2569 /* <Description> */
2570 /* Sets the current renderer to use, and set additional mode. */
2571 /* */
2572 /* <Input> */
2573 /* library :: A handle to the library object. */
2574 /* */
2575 /* renderer :: A handle to the renderer object. */
2576 /* */
2577 /* num_params :: The number of additional parameters. */
2578 /* */
2579 /* parameters :: Additional parameters. */
2580 /* */
2581 /* <Return> */
2582 /* FreeType error code. 0 means success. */
2583 /* */
2584 /* <Note> */
2585 /* In case of success, the renderer will be used to convert glyph */
2586 /* images in the renderer's known format into bitmaps. */
2587 /* */
2588 /* This doesn't change the current renderer for other formats. */
2589 /* */
2590 FT_EXPORT_DEF( FT_Error ) FT_Set_Renderer( FT_Library library,
2591 FT_Renderer renderer,
2592 FT_UInt num_params,
2593 FT_Parameter* parameters )
2594 {
2595 FT_ListNode node;
2596 FT_Error error = FT_Err_Ok;
2597
2598
2599 if ( !library )
2600 return FT_Err_Invalid_Library_Handle;
2601
2602 if ( !renderer )
2603 return FT_Err_Invalid_Argument;
2604
2605 node = FT_List_Find( &library->renderers, renderer );
2606 if ( !node )
2607 {
2608 error = FT_Err_Invalid_Argument;
2609 goto Exit;
2610 }
2611
2612 FT_List_Up( &library->renderers, node );
2613
2614 if ( renderer->glyph_format == ft_glyph_format_outline )
2615 library->cur_renderer = renderer;
2616
2617 if ( num_params > 0 )
2618 {
2619 FTRenderer_setMode set_mode = renderer->clazz->set_mode;
2620
2621
2622 for ( ; num_params > 0; num_params-- )
2623 {
2624 error = set_mode( renderer, parameters->tag, parameters->data );
2625 if ( error )
2626 break;
2627 }
2628 }
2629
2630 Exit:
2631 return error;
2632 }
2633
2634
2635 LOCAL_FUNC
2636 FT_Error FT_Render_Glyph_Internal( FT_Library library,
2637 FT_GlyphSlot slot,
2638 FT_UInt render_mode )
2639 {
2640 FT_Error error = FT_Err_Ok;
2641 FT_Renderer renderer;
2642
2643
2644 /* if it is already a bitmap, no need to do anything */
2645 switch ( slot->format )
2646 {
2647 case ft_glyph_format_bitmap: /* already a bitmap, don't do anything */
2648 break;
2649
2650 default:
2651 {
2652 FT_ListNode node = 0;
2653 FT_Bool update = 0;
2654
2655
2656 /* small shortcut for the very common case */
2657 if ( slot->format == ft_glyph_format_outline )
2658 {
2659 renderer = library->cur_renderer;
2660 node = library->renderers.head;
2661 }
2662 else
2663 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2664
2665 error = FT_Err_Unimplemented_Feature;
2666 while ( renderer )
2667 {
2668 error = renderer->render( renderer, slot, render_mode, 0 );
2669 if ( !error || error != FT_Err_Cannot_Render_Glyph )
2670 break;
2671
2672 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
2673 /* is unsupported by the current renderer for this glyph image */
2674 /* format. */
2675
2676 /* now, look for another renderer that supports the same */
2677 /* format. */
2678 renderer = FT_Lookup_Renderer( library, slot->format, &node );
2679 update = 1;
2680 }
2681
2682 /* if we changed the current renderer for the glyph image format */
2683 /* we need to select it as the next current one */
2684 if ( !error && update && renderer )
2685 FT_Set_Renderer( library, renderer, 0, 0 );
2686 }
2687 }
2688
2689 return error;
2690 }
2691
2692
2693 /*************************************************************************/
2694 /* */
2695 /* <Function> */
2696 /* FT_Render_Glyph */
2697 /* */
2698 /* <Description> */
2699 /* Converts a given glyph image to a bitmap. It does so by */
2700 /* inspecting the glyph image format, find the relevant renderer, and */
2701 /* invoke it. */
2702 /* */
2703 /* <Input> */
2704 /* slot :: A handle to the glyph slot containing the image to */
2705 /* convert. */
2706 /* */
2707 /* render_mode :: This is the render mode used to render the glyph */
2708 /* image into a bitmap. See FT_Render_Mode for a list */
2709 /* of possible values. */
2710 /* */
2711 /* <Return> */
2712 /* FreeType error code. 0 means success. */
2713 /* */
2714 FT_EXPORT_FUNC( FT_Error ) FT_Render_Glyph( FT_GlyphSlot slot,
2715 FT_UInt render_mode )
2716 {
2717 FT_Library library;
2718
2719
2720 if ( !slot )
2721 return FT_Err_Invalid_Argument;
2722
2723 library = FT_FACE_LIBRARY( slot->face );
2724
2725 return FT_Render_Glyph_Internal( library, slot, render_mode );
2726 }
2727
2728
2729 /*************************************************************************/
2730 /*************************************************************************/
2731 /*************************************************************************/
2732 /**** ****/
2733 /**** ****/
2734 /**** M O D U L E S ****/
2735 /**** ****/
2736 /**** ****/
2737 /*************************************************************************/
2738 /*************************************************************************/
2739 /*************************************************************************/
2740
2741
2742 /*************************************************************************/
2743 /* */
2744 /* <Function> */
2745 /* Destroy_Module */
2746 /* */
2747 /* <Description> */
2748 /* Destroys a given module object. For drivers, this also destroys */
2749 /* all child faces. */
2750 /* */
2751 /* <InOut> */
2752 /* module :: A handle to the target driver object. */
2753 /* */
2754 /* <Note> */
2755 /* The driver _must_ be LOCKED! */
2756 /* */
2757 static
2758 void Destroy_Module( FT_Module module )
2759 {
2760 FT_Memory memory = module->memory;
2761 FT_Module_Class* clazz = module->clazz;
2762 FT_Library library = module->library;
2763
2764
2765 /* finalize client-data - before anything else */
2766 if ( module->generic.finalizer )
2767 module->generic.finalizer( module );
2768
2769 if ( library && library->auto_hinter == module )
2770 library->auto_hinter = 0;
2771
2772 /* if the module is a renderer */
2773 if ( FT_MODULE_IS_RENDERER( module ) )
2774 ft_remove_renderer( module );
2775
2776 /* if the module is a font driver, add some steps */
2777 if ( FT_MODULE_IS_DRIVER( module ) )
2778 Destroy_Driver( FT_DRIVER( module ) );
2779
2780 /* finalize the module object */
2781 if ( clazz->module_done )
2782 clazz->module_done( module );
2783
2784 /* discard it */
2785 FREE( module );
2786 }
2787
2788
2789 /*************************************************************************/
2790 /* */
2791 /* <Function> */
2792 /* FT_Add_Module */
2793 /* */
2794 /* <Description> */
2795 /* Adds a new module to a given library instance. */
2796 /* */
2797 /* <Input> */
2798 /* library :: A handle to the library object. */
2799 /* */
2800 /* clazz :: A pointer to class descriptor for the module. */
2801 /* */
2802 /* <Return> */
2803 /* FreeType error code. 0 means success. */
2804 /* */
2805 /* <Note> */
2806 /* An error will be returned if a module already exists by that name, */
2807 /* or if the module requires a version of FreeType that is too great. */
2808 /* */
2809 FT_EXPORT_FUNC( FT_Error ) FT_Add_Module( FT_Library library,
2810 const FT_Module_Class* clazz )
2811 {
2812 FT_Error error;
2813 FT_Memory memory;
2814 FT_Module module;
2815 FT_UInt nn;
2816
2817
2818 #define FREETYPE_VER_FIXED ( ( (FT_Long)FREETYPE_MAJOR << 16 ) | \
2819 FREETYPE_MINOR )
2820
2821 if ( !library )
2822 return FT_Err_Invalid_Library_Handle;
2823
2824 if ( !clazz )
2825 return FT_Err_Invalid_Argument;
2826
2827 /* check freetype version */
2828 if ( clazz->module_requires > FREETYPE_VER_FIXED )
2829 return FT_Err_Invalid_Version;
2830
2831 /* look for a module with the same name in the library's table */
2832 for ( nn = 0; nn < library->num_modules; nn++ )
2833 {
2834 module = library->modules[nn];
2835 if ( strcmp( module->clazz->module_name, clazz->module_name ) == 0 )
2836 {
2837 /* this installed module has the same name, compare their versions */
2838 if ( clazz->module_version <= module->clazz->module_version )
2839 return FT_Err_Lower_Module_Version;
2840
2841 /* remove the module from our list, then exit the loop to replace */
2842 /* it by our new version.. */
2843 FT_Remove_Module( library, module );
2844 break;
2845 }
2846 }
2847
2848 memory = library->memory;
2849 error = FT_Err_Ok;
2850
2851 if ( library->num_modules >= FT_MAX_MODULES )
2852 {
2853 error = FT_Err_Too_Many_Drivers;
2854 goto Exit;
2855 }
2856
2857 /* allocate module object */
2858 if ( ALLOC( module,clazz->module_size ) )
2859 goto Exit;
2860
2861 /* base initialization */
2862 module->library = library;
2863 module->memory = memory;
2864 module->clazz = (FT_Module_Class*)clazz;
2865
2866 /* check whether the module is a renderer - this must be performed */
2867 /* before the normal module initialization */
2868 if ( FT_MODULE_IS_RENDERER( module ) )
2869 {
2870 /* add to the renderers list */
2871 error = ft_add_renderer( module );
2872 if ( error )
2873 goto Fail;
2874 }
2875
2876 /* is the module a auto-hinter? */
2877 if ( FT_MODULE_IS_HINTER( module ) )
2878 library->auto_hinter = module;
2879
2880 /* if the module is a font driver */
2881 if ( FT_MODULE_IS_DRIVER( module ) )
2882 {
2883 /* allocate glyph loader if needed */
2884 FT_Driver driver = FT_DRIVER( module );
2885
2886
2887 driver->clazz = (FT_Driver_Class*)module->clazz;
2888 if ( FT_DRIVER_USES_OUTLINES( driver ) )
2889 {
2890 error = FT_GlyphLoader_New( memory, &driver->glyph_loader );
2891 if ( error )
2892 goto Fail;
2893 }
2894 }
2895
2896 if ( clazz->module_init )
2897 {
2898 error = clazz->module_init( module );
2899 if ( error )
2900 goto Fail;
2901 }
2902
2903 /* add module to the library's table */
2904 library->modules[library->num_modules++] = module;
2905
2906 Exit:
2907 return error;
2908
2909 Fail:
2910 if ( FT_MODULE_IS_DRIVER( module ) )
2911 {
2912 FT_Driver driver = FT_DRIVER( module );
2913
2914
2915 if ( FT_DRIVER_USES_OUTLINES( driver ) )
2916 FT_GlyphLoader_Done( driver->glyph_loader );
2917 }
2918
2919 if ( FT_MODULE_IS_RENDERER( module ) )
2920 {
2921 FT_Renderer renderer = FT_RENDERER( module );
2922
2923
2924 if ( renderer->raster )
2925 renderer->clazz->raster_class->raster_done( renderer->raster );
2926 }
2927
2928 FREE( module );
2929 goto Exit;
2930 }
2931
2932
2933 /*************************************************************************/
2934 /* */
2935 /* <Function> */
2936 /* FT_Get_Module */
2937 /* */
2938 /* <Description> */
2939 /* Finds a module by its name. */
2940 /* */
2941 /* <Input> */
2942 /* library :: A handle to the library object. */
2943 /* */
2944 /* module_name :: The module's name (as an ASCII string). */
2945 /* */
2946 /* <Return> */
2947 /* A module handle. 0 if none was found. */
2948 /* */
2949 /* <Note> */
2950 /* You should better be familiar with FreeType internals to know */
2951 /* which module to look for :-) */
2952 /* */
2953 FT_EXPORT_FUNC( FT_Module ) FT_Get_Module( FT_Library library,
2954 const char* module_name )
2955 {
2956 FT_Module result = 0;
2957 FT_Module* cur;
2958 FT_Module* limit;
2959
2960
2961 if ( !library || !module_name )
2962 return result;
2963
2964 cur = library->modules;
2965 limit = cur + library->num_modules;
2966
2967 for ( ; cur < limit; cur++ )
2968 if ( strcmp( cur[0]->clazz->module_name, module_name ) == 0 )
2969 {
2970 result = cur[0];
2971 break;
2972 }
2973
2974 return result;
2975 }
2976
2977
2978 /*************************************************************************/
2979 /* */
2980 /* <Function> */
2981 /* FT_Get_Module_Interface */
2982 /* */
2983 /* <Description> */
2984 /* Finds a module and returns its specific interface as a typeless */
2985 /* pointer. */
2986 /* */
2987 /* <Input> */
2988 /* library :: A handle to the library object. */
2989 /* */
2990 /* module_name :: The module's name (as an ASCII string). */
2991 /* */
2992 /* <Return> */
2993 /* A module-specific interface if available, 0 otherwise. */
2994 /* */
2995 /* <Note> */
2996 /* You should better be familiar with FreeType internals to know */
2997 /* which module to look for, and what its interface is :-) */
2998 /* */
2999 BASE_FUNC( const void* ) FT_Get_Module_Interface( FT_Library library,
3000 const char* mod_name )
3001 {
3002 FT_Module module;
3003
3004
3005 /* test for valid `library' delayed to FT_Get_Module() */
3006
3007 module = FT_Get_Module( library, mod_name );
3008
3009 return module ? module->clazz->module_interface : 0;
3010 }
3011
3012
3013 /*************************************************************************/
3014 /* */
3015 /* <Function> */
3016 /* FT_Remove_Module */
3017 /* */
3018 /* <Description> */
3019 /* Removes a given module from a library instance. */
3020 /* */
3021 /* <Input> */
3022 /* library :: A handle to a library object. */
3023 /* */
3024 /* module :: A handle to a module object. */
3025 /* */
3026 /* <Return> */
3027 /* FreeType error code. 0 means success. */
3028 /* */
3029 /* <Note> */
3030 /* The module object is destroyed by the function in case of success. */
3031 /* */
3032 FT_EXPORT_FUNC( FT_Error ) FT_Remove_Module( FT_Library library,
3033 FT_Module module )
3034 {
3035 /* try to find the module from the table, then remove it from there */
3036
3037 if ( !library )
3038 return FT_Err_Invalid_Library_Handle;
3039
3040 if ( module )
3041 {
3042 FT_Module* cur = library->modules;
3043 FT_Module* limit = cur + library->num_modules;
3044
3045
3046 for ( ; cur < limit; cur++ )
3047 {
3048 if ( cur[0] == module )
3049 {
3050 /* remove it from the table */
3051 library->num_modules--;
3052 limit--;
3053 while ( cur < limit )
3054 {
3055 cur[0] = cur[1];
3056 cur++;
3057 }
3058 limit[0] = 0;
3059
3060 /* destroy the module */
3061 Destroy_Module( module );
3062
3063 return FT_Err_Ok;
3064 }
3065 }
3066 }
3067 return FT_Err_Invalid_Driver_Handle;
3068 }
3069
3070
3071 /*************************************************************************/
3072 /*************************************************************************/
3073 /*************************************************************************/
3074 /**** ****/
3075 /**** ****/
3076 /**** L I B R A R Y ****/
3077 /**** ****/
3078 /**** ****/
3079 /*************************************************************************/
3080 /*************************************************************************/
3081 /*************************************************************************/
3082
3083
3084 /*************************************************************************/
3085 /* */
3086 /* <Function> */
3087 /* FT_New_Library */
3088 /* */
3089 /* <Description> */
3090 /* This function is used to create a new FreeType library instance */
3091 /* from a given memory object. It is thus possible to use libraries */
3092 /* with distinct memory allocators within the same program. */
3093 /* */
3094 /* <Input> */
3095 /* memory :: A handle to the original memory object. */
3096 /* */
3097 /* <Output> */
3098 /* alibrary :: A pointer to handle of a new library object. */
3099 /* */
3100 /* <Return> */
3101 /* FreeType error code. 0 means success. */
3102 /* */
3103 FT_EXPORT_FUNC( FT_Error ) FT_New_Library( FT_Memory memory,
3104 FT_Library* alibrary )
3105 {
3106 FT_Library library = 0;
3107 FT_Error error;
3108
3109
3110 if ( !memory )
3111 return FT_Err_Invalid_Argument;
3112
3113 /* first of all, allocate the library object */
3114 if ( ALLOC( library, sizeof ( *library ) ) )
3115 return error;
3116
3117 library->memory = memory;
3118
3119 /* allocate the render pool */
3120 library->raster_pool_size = FT_RENDER_POOL_SIZE;
3121 if ( ALLOC( library->raster_pool, FT_RENDER_POOL_SIZE ) )
3122 goto Fail;
3123
3124 /* That's ok now */
3125 *alibrary = library;
3126
3127 return FT_Err_Ok;
3128
3129 Fail:
3130 FREE( library );
3131 return error;
3132 }
3133
3134
3135 /*************************************************************************/
3136 /* */
3137 /* <Function> */
3138 /* FT_Done_Library */
3139 /* */
3140 /* <Description> */
3141 /* Discards a given library object. This closes all drivers and */
3142 /* discards all resource objects. */
3143 /* */
3144 /* <Input> */
3145 /* library :: A handle to the target library. */
3146 /* */
3147 /* <Return> */
3148 /* FreeType error code. 0 means success. */
3149 /* */
3150 FT_EXPORT_FUNC( FT_Error ) FT_Done_Library( FT_Library library )
3151 {
3152 FT_Memory memory;
3153 FT_UInt n;
3154
3155
3156 if ( !library )
3157 return FT_Err_Invalid_Library_Handle;
3158
3159 memory = library->memory;
3160
3161 /* Discard client-data */
3162 if ( library->generic.finalizer )
3163 library->generic.finalizer( library );
3164
3165 /* Close all modules in the library */
3166 for ( n = 0; n < library->num_modules; n++ )
3167 {
3168 FT_Module module = library->modules[n];
3169
3170
3171 if ( module )
3172 {
3173 Destroy_Module( module );
3174 library->modules[n] = 0;
3175 }
3176 }
3177
3178 /* Destroy raster objects */
3179 FREE( library->raster_pool );
3180 library->raster_pool_size = 0;
3181
3182 FREE( library );
3183 return FT_Err_Ok;
3184 }
3185
3186
3187 /*************************************************************************/
3188 /* */
3189 /* <Function> */
3190 /* FT_Set_Debug_Hook */
3191 /* */
3192 /* <Description> */
3193 /* Sets a debug hook function for debugging the interpreter of a font */
3194 /* format. */
3195 /* */
3196 /* <Input> */
3197 /* library :: A handle to the library object. */
3198 /* */
3199 /* hook_index :: The index of the debug hook. You should use the */
3200 /* values defined in ftobjs.h, e.g. */
3201 /* FT_DEBUG_HOOK_TRUETYPE */
3202 /* */
3203 /* debug_hook :: The function used to debug the interpreter. */
3204 /* */
3205 /* <Note> */
3206 /* Currently, four debug hook slots are available, but only two (for */
3207 /* the TrueType and the Type 1 interpreter) are defined. */
3208 /* */
3209 FT_EXPORT_FUNC( void ) FT_Set_Debug_Hook( FT_Library library,
3210 FT_UInt hook_index,
3211 FT_DebugHook_Func debug_hook )
3212 {
3213 if ( library && debug_hook &&
3214 hook_index <
3215 ( sizeof ( library->debug_hooks ) / sizeof ( void* ) ) )
3216 library->debug_hooks[hook_index] = debug_hook;
3217 }
3218
3219
3220 /*************************************************************************/
3221 /* */
3222 /* <Function> */
3223 /* FT_Done_FreeType */
3224 /* */
3225 /* <Description> */
3226 /* Destroys a given FreeType library object and all of its childs, */
3227 /* including resources, drivers, faces, sizes, etc. */
3228 /* */
3229 /* <Input> */
3230 /* library :: A handle to the target library object. */
3231 /* */
3232 /* <Return> */
3233 /* FreeType error code. 0 means success. */
3234 /* */
3235 FT_EXPORT_FUNC( FT_Error ) FT_Done_FreeType( FT_Library library )
3236 {
3237 /* test for valid `library' delayed to FT_Done_Library() */
3238
3239 /* Discard the library object */
3240 FT_Done_Library( library );
3241
3242 return FT_Err_Ok;
3243 }
3244
3245
3246 /* END */