Bug Summary

File:./freetype/ftobjs.c
Warning:line 354, column 5
Value stored to 'y_shift' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple amd64-unknown-openbsd6.8 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name _ftbase.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mthread-model posix -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/local/lib/clang/10.0.1 -I /usr/X11R6/include -I /usr/local/include -fdebug-compilation-dir /home/ben/Projects/ClassiCube/src -ferror-limit 19 -fmessage-length 0 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -fobjc-runtime=gnustep -fdiagnostics-show-option -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/ClassiCube/src/scan/2020-12-10-180422-33404-1 -x c _ftbase.c
1/***************************************************************************/
2/* */
3/* ftobjs.c */
4/* */
5/* The FreeType private base classes (body). */
6/* */
7/* Copyright 1996-2018 by */
8/* David Turner, Robert Wilhelm, and Werner Lemberg. */
9/* */
10/* This file is part of the FreeType project, and may only be used, */
11/* modified, and distributed under the terms of the FreeType project */
12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13/* this file you indicate that you have read the license and */
14/* understand and accept it fully. */
15/* */
16/***************************************************************************/
17
18
19#include "ft2build.h"
20#include FT_LIST_H"ftlist.h"
21#include FT_OUTLINE_H"ftoutln.h"
22#include FT_FONT_FORMATS_H"ftfntfmt.h"
23
24#include FT_INTERNAL_VALIDATE_H"ftvalid.h"
25#include FT_INTERNAL_OBJECTS_H"ftobjs.h"
26#include FT_INTERNAL_DEBUG_H"ftdebug.h"
27#include FT_INTERNAL_STREAM_H"ftstream.h"
28#include FT_INTERNAL_SFNT_H"sfnt.h" /* for SFNT_Load_Table_Func */
29#include FT_INTERNAL_POSTSCRIPT_AUX_H"psaux.h" /* for PS_Driver */
30
31#include FT_TRUETYPE_TABLES_H"tttables.h"
32#include FT_TRUETYPE_TAGS_H"tttags.h"
33#include FT_TRUETYPE_IDS_H"ttnameid.h"
34
35#include FT_SERVICE_GLYPH_DICT_H"svgldict.h"
36#include FT_SERVICE_TT_CMAP_H"svttcmap.h"
37
38#include FT_DRIVER_H"ftdriver.h"
39
40
41#define GRID_FIT_METRICS
42
43
44 /* forward declaration */
45 static FT_Error
46 ft_open_face_internal( FT_Library library,
47 const FT_Open_Args* args,
48 FT_Long face_index,
49 FT_Face *aface,
50 FT_Bool test_mac_fonts );
51
52
53 FT_BASE_DEF( FT_Pointer )FT_Pointer
54 ft_service_list_lookup( FT_ServiceDesc service_descriptors,
55 const char* service_id )
56 {
57 FT_Pointer result = NULL((void*)0);
58 FT_ServiceDesc desc = service_descriptors;
59
60
61 if ( desc && service_id )
62 {
63 for ( ; desc->serv_id != NULL((void*)0); desc++ )
64 {
65 if ( ft_strcmpstrcmp( desc->serv_id, service_id ) == 0 )
66 {
67 result = (FT_Pointer)desc->serv_data;
68 break;
69 }
70 }
71 }
72
73 return result;
74 }
75
76
77 FT_BASE_DEF( void )void
78 ft_validator_init( FT_Validator valid,
79 const FT_Byte* base,
80 const FT_Byte* limit,
81 FT_ValidationLevel level )
82 {
83 valid->base = base;
84 valid->limit = limit;
85 valid->level = level;
86 valid->error = FT_Err_Ok;
87 }
88
89
90 FT_BASE_DEF( void )void
91 ft_validator_error( FT_Validator valid,
92 FT_Error error )
93 {
94 /* since the cast below also disables the compiler's */
95 /* type check, we introduce a dummy variable, which */
96 /* will be optimized away */
97 volatile ft_jmp_bufjmp_buf* jump_buffer = &valid->jump_buffer;
98
99
100 valid->error = error;
101
102 /* throw away volatileness; use `jump_buffer' or the */
103 /* compiler may warn about an unused local variable */
104 ft_longjmplongjmp( *(ft_jmp_bufjmp_buf*) jump_buffer, 1 );
105 }
106
107
108 /*************************************************************************/
109 /*************************************************************************/
110 /*************************************************************************/
111 /**** ****/
112 /**** ****/
113 /**** S T R E A M ****/
114 /**** ****/
115 /**** ****/
116 /*************************************************************************/
117 /*************************************************************************/
118 /*************************************************************************/
119
120
121 /* create a new input stream from an FT_Open_Args structure */
122 /* */
123 FT_BASE_DEF( FT_Error )FT_Error
124 FT_Stream_New( FT_Library library,
125 const FT_Open_Args* args,
126 FT_Stream *astream )
127 {
128 FT_Error error;
129 FT_Memory memory;
130 FT_Stream stream = NULL((void*)0);
131
132
133 *astream = NULL((void*)0);
134
135 if ( !library )
136 return FT_THROW( Invalid_Library_Handle )FT_Err_Invalid_Library_Handle;
137
138 if ( !args )
139 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
140
141 memory = library->memory;
142
143 if ( FT_NEW( stream )( ((stream) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(stream
) )), &error ))), error != 0 )
)
144 goto Exit;
145
146 stream->memory = memory;
147
148 if ( args->flags & FT_OPEN_MEMORY0x1 )
149 {
150 /* create a memory-based stream */
151 FT_Stream_OpenMemory( stream,
152 (const FT_Byte*)args->memory_base,
153 (FT_ULong)args->memory_size );
154 }
155
156#ifndef FT_CONFIG_OPTION_DISABLE_STREAM_SUPPORT
157 else if ( ( args->flags & FT_OPEN_STREAM0x2 ) && args->stream )
158 {
159 /* use an existing, user-provided stream */
160
161 /* in this case, we do not need to allocate a new stream object */
162 /* since the caller is responsible for closing it himself */
163 FT_FREE( stream )do { ft_mem_free( memory, (stream) ); (stream) = ((void*)0); }
while ( 0 )
;
164 stream = args->stream;
165 }
166
167#endif
168
169 else
170 error = FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
171
172 if ( error )
173 FT_FREE( stream )do { ft_mem_free( memory, (stream) ); (stream) = ((void*)0); }
while ( 0 )
;
174 else
175 stream->memory = memory; /* just to be certain */
176
177 *astream = stream;
178
179 Exit:
180 return error;
181 }
182
183
184 FT_BASE_DEF( void )void
185 FT_Stream_Free( FT_Stream stream,
186 FT_Int external )
187 {
188 if ( stream )
189 {
190 FT_Memory memory = stream->memory;
191
192
193 FT_Stream_Close( stream );
194
195 if ( !external )
196 FT_FREE( stream )do { ft_mem_free( memory, (stream) ); (stream) = ((void*)0); }
while ( 0 )
;
197 }
198 }
199
200
201 /*************************************************************************/
202 /* */
203 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
204 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
205 /* messages during execution. */
206 /* */
207#undef FT_COMPONENTtrace_list
208#define FT_COMPONENTtrace_list trace_objs
209
210
211 /*************************************************************************/
212 /*************************************************************************/
213 /*************************************************************************/
214 /**** ****/
215 /**** ****/
216 /**** FACE, SIZE & GLYPH SLOT OBJECTS ****/
217 /**** ****/
218 /**** ****/
219 /*************************************************************************/
220 /*************************************************************************/
221 /*************************************************************************/
222
223
224 static FT_Error
225 ft_glyphslot_init( FT_GlyphSlot slot )
226 {
227 FT_Driver driver = slot->face->driver;
228 FT_Driver_Class clazz = driver->clazz;
229 FT_Memory memory = driver->root.memory;
230 FT_Error error = FT_Err_Ok;
231 FT_Slot_Internal internal = NULL((void*)0);
232
233
234 slot->library = driver->root.library;
235
236 if ( FT_NEW( internal )( ((internal) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(internal
) )), &error ))), error != 0 )
)
237 goto Exit;
238
239 slot->internal = internal;
240
241 if ( FT_DRIVER_USES_OUTLINES( driver )!( ( (FT_Module)(driver) )->clazz->module_flags & 0x200
)
)
242 error = FT_GlyphLoader_New( memory, &internal->loader );
243
244 if ( !error && clazz->init_slot )
245 error = clazz->init_slot( slot );
246
247 Exit:
248 return error;
249 }
250
251
252 FT_BASE_DEF( void )void
253 ft_glyphslot_free_bitmap( FT_GlyphSlot slot )
254 {
255 if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP0x1U ) )
256 {
257 FT_Memory memory = FT_FACE_MEMORY( slot->face )( (FT_Face)(slot->face) )->memory;
258
259
260 FT_FREE( slot->bitmap.buffer )do { ft_mem_free( memory, (slot->bitmap.buffer) ); (slot->
bitmap.buffer) = ((void*)0); } while ( 0 )
;
261 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP0x1U;
262 }
263 else
264 {
265 /* assume that the bitmap buffer was stolen or not */
266 /* allocated from the heap */
267 slot->bitmap.buffer = NULL((void*)0);
268 }
269 }
270
271
272 FT_BASE_DEF( void )void
273 ft_glyphslot_preset_bitmap( FT_GlyphSlot slot,
274 FT_Render_Mode mode,
275 const FT_Vector* origin )
276 {
277 FT_Outline* outline = &slot->outline;
278 FT_Bitmap* bitmap = &slot->bitmap;
279
280 FT_Pixel_Mode pixel_mode;
281
282 FT_BBox cbox;
283 FT_Pos x_shift = 0;
284 FT_Pos y_shift = 0;
285 FT_Pos x_left, y_top;
286 FT_Pos width, height, pitch;
287
288
289 if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP0x1U ) )
290 return;
291
292 if ( origin )
293 {
294 x_shift = origin->x;
295 y_shift = origin->y;
296 }
297
298 /* compute the control box, and grid-fit it, */
299 /* taking into account the origin shift */
300 FT_Outline_Get_CBox( outline, &cbox );
301
302 cbox.xMin += x_shift;
303 cbox.yMin += y_shift;
304 cbox.xMax += x_shift;
305 cbox.yMax += y_shift;
306
307 switch ( mode )
308 {
309 case FT_RENDER_MODE_MONO:
310 pixel_mode = FT_PIXEL_MODE_MONO;
311#if 1
312 /* undocumented but confirmed: bbox values get rounded */
313 /* unless the rounded box can collapse for a narrow glyph */
314 if ( cbox.xMax - cbox.xMin < 64 )
315 {
316 cbox.xMin = FT_PIX_FLOOR( cbox.xMin )( (cbox.xMin) & ~( __typeof__ ( cbox.xMin ) )63 );
317 cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax )( ((FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong
)(63) ) ) )63 )
;
318 }
319 else
320 {
321 cbox.xMin = FT_PIX_ROUND_LONG( cbox.xMin )( ((FT_Long)( (FT_ULong)((cbox.xMin)) + (FT_ULong)(32) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.xMin)) + (FT_ULong
)(32) ) ) )63 )
;
322 cbox.xMax = FT_PIX_ROUND_LONG( cbox.xMax )( ((FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong)(32) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong
)(32) ) ) )63 )
;
323 }
324
325 if ( cbox.yMax - cbox.yMin < 64 )
326 {
327 cbox.yMin = FT_PIX_FLOOR( cbox.yMin )( (cbox.yMin) & ~( __typeof__ ( cbox.yMin ) )63 );
328 cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax )( ((FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong
)(63) ) ) )63 )
;
329 }
330 else
331 {
332 cbox.yMin = FT_PIX_ROUND_LONG( cbox.yMin )( ((FT_Long)( (FT_ULong)((cbox.yMin)) + (FT_ULong)(32) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.yMin)) + (FT_ULong
)(32) ) ) )63 )
;
333 cbox.yMax = FT_PIX_ROUND_LONG( cbox.yMax )( ((FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong)(32) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong
)(32) ) ) )63 )
;
334 }
335#else
336 cbox.xMin = FT_PIX_FLOOR( cbox.xMin )( (cbox.xMin) & ~( __typeof__ ( cbox.xMin ) )63 );
337 cbox.yMin = FT_PIX_FLOOR( cbox.yMin )( (cbox.yMin) & ~( __typeof__ ( cbox.yMin ) )63 );
338 cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax )( ((FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong
)(63) ) ) )63 )
;
339 cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax )( ((FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong
)(63) ) ) )63 )
;
340#endif
341 break;
342
343 case FT_RENDER_MODE_NORMAL:
344 case FT_RENDER_MODE_LIGHT:
345 default:
346 pixel_mode = FT_PIXEL_MODE_GRAY;
347 cbox.xMin = FT_PIX_FLOOR( cbox.xMin )( (cbox.xMin) & ~( __typeof__ ( cbox.xMin ) )63 );
348 cbox.yMin = FT_PIX_FLOOR( cbox.yMin )( (cbox.yMin) & ~( __typeof__ ( cbox.yMin ) )63 );
349 cbox.xMax = FT_PIX_CEIL_LONG( cbox.xMax )( ((FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.xMax)) + (FT_ULong
)(63) ) ) )63 )
;
350 cbox.yMax = FT_PIX_CEIL_LONG( cbox.yMax )( ((FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)((cbox.yMax)) + (FT_ULong
)(63) ) ) )63 )
;
351 }
352
353 x_shift = SUB_LONG( x_shift, cbox.xMin )(FT_Long)( (FT_ULong)(x_shift) - (FT_ULong)(cbox.xMin) );
354 y_shift = SUB_LONG( y_shift, cbox.yMin )(FT_Long)( (FT_ULong)(y_shift) - (FT_ULong)(cbox.yMin) );
Value stored to 'y_shift' is never read
355
356 x_left = cbox.xMin >> 6;
357 y_top = cbox.yMax >> 6;
358
359 width = ( (FT_ULong)cbox.xMax - (FT_ULong)cbox.xMin ) >> 6;
360 height = ( (FT_ULong)cbox.yMax - (FT_ULong)cbox.yMin ) >> 6;
361
362 switch ( pixel_mode )
363 {
364 case FT_PIXEL_MODE_MONO:
365 pitch = ( ( width + 15 ) >> 4 ) << 1;
366 break;
367
368 case FT_PIXEL_MODE_GRAY:
369 default:
370 pitch = width;
371 }
372
373 slot->bitmap_left = (FT_Int)x_left;
374 slot->bitmap_top = (FT_Int)y_top;
375
376 bitmap->pixel_mode = (unsigned char)pixel_mode;
377 bitmap->num_grays = 256;
378 bitmap->width = (unsigned int)width;
379 bitmap->rows = (unsigned int)height;
380 bitmap->pitch = pitch;
381 }
382
383
384 FT_BASE_DEF( void )void
385 ft_glyphslot_set_bitmap( FT_GlyphSlot slot,
386 FT_Byte* buffer )
387 {
388 ft_glyphslot_free_bitmap( slot );
389
390 slot->bitmap.buffer = buffer;
391
392 FT_ASSERT( (slot->internal->flags & FT_GLYPH_OWN_BITMAP) == 0 )do { } while ( 0 );
393 }
394
395
396 FT_BASE_DEF( FT_Error )FT_Error
397 ft_glyphslot_alloc_bitmap( FT_GlyphSlot slot,
398 FT_ULong size )
399 {
400 FT_Memory memory = FT_FACE_MEMORY( slot->face )( (FT_Face)(slot->face) )->memory;
401 FT_Error error;
402
403
404 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP0x1U )
405 FT_FREE( slot->bitmap.buffer )do { ft_mem_free( memory, (slot->bitmap.buffer) ); (slot->
bitmap.buffer) = ((void*)0); } while ( 0 )
;
406 else
407 slot->internal->flags |= FT_GLYPH_OWN_BITMAP0x1U;
408
409 (void)FT_ALLOC( slot->bitmap.buffer, size )( ((slot->bitmap.buffer) = (ft_mem_alloc( memory, (FT_Long
)(size), &error ))), error != 0 )
;
410 return error;
411 }
412
413
414 static void
415 ft_glyphslot_clear( FT_GlyphSlot slot )
416 {
417 /* free bitmap if needed */
418 ft_glyphslot_free_bitmap( slot );
419
420 /* clear all public fields in the glyph slot */
421 FT_ZERO( &slot->metrics )memset( &slot->metrics, 0, (FT_Offset)(sizeof ( *(&
slot->metrics) )) )
;
422 FT_ZERO( &slot->outline )memset( &slot->outline, 0, (FT_Offset)(sizeof ( *(&
slot->outline) )) )
;
423
424 slot->bitmap.width = 0;
425 slot->bitmap.rows = 0;
426 slot->bitmap.pitch = 0;
427 slot->bitmap.pixel_mode = 0;
428 /* `slot->bitmap.buffer' has been handled by ft_glyphslot_free_bitmap */
429
430 slot->bitmap_left = 0;
431 slot->bitmap_top = 0;
432 slot->num_subglyphs = 0;
433 slot->subglyphs = NULL((void*)0);
434 slot->control_data = NULL((void*)0);
435 slot->control_len = 0;
436 slot->other = NULL((void*)0);
437 slot->format = FT_GLYPH_FORMAT_NONE;
438
439 slot->linearHoriAdvance = 0;
440 slot->linearVertAdvance = 0;
441 slot->lsb_delta = 0;
442 slot->rsb_delta = 0;
443 }
444
445
446 static void
447 ft_glyphslot_done( FT_GlyphSlot slot )
448 {
449 FT_Driver driver = slot->face->driver;
450 FT_Driver_Class clazz = driver->clazz;
451 FT_Memory memory = driver->root.memory;
452
453
454 if ( clazz->done_slot )
455 clazz->done_slot( slot );
456
457 /* free bitmap buffer if needed */
458 ft_glyphslot_free_bitmap( slot );
459
460 /* slot->internal might be NULL in out-of-memory situations */
461 if ( slot->internal )
462 {
463 /* free glyph loader */
464 if ( FT_DRIVER_USES_OUTLINES( driver )!( ( (FT_Module)(driver) )->clazz->module_flags & 0x200
)
)
465 {
466 FT_GlyphLoader_Done( slot->internal->loader );
467 slot->internal->loader = NULL((void*)0);
468 }
469
470 FT_FREE( slot->internal )do { ft_mem_free( memory, (slot->internal) ); (slot->internal
) = ((void*)0); } while ( 0 )
;
471 }
472 }
473
474
475 /* documentation is in ftobjs.h */
476
477 FT_BASE_DEF( FT_Error )FT_Error
478 FT_New_GlyphSlot( FT_Face face,
479 FT_GlyphSlot *aslot )
480 {
481 FT_Error error;
482 FT_Driver driver;
483 FT_Driver_Class clazz;
484 FT_Memory memory;
485 FT_GlyphSlot slot = NULL((void*)0);
486
487
488 if ( !face )
489 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
490
491 if ( !face->driver )
492 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
493
494 driver = face->driver;
495 clazz = driver->clazz;
496 memory = driver->root.memory;
497
498 FT_TRACE4(( "FT_New_GlyphSlot: Creating new slot object\n" ))do { } while ( 0 );
499 if ( !FT_ALLOC( slot, clazz->slot_object_size )( ((slot) = (ft_mem_alloc( memory, (FT_Long)(clazz->slot_object_size
), &error ))), error != 0 )
)
500 {
501 slot->face = face;
502
503 error = ft_glyphslot_init( slot );
504 if ( error )
505 {
506 ft_glyphslot_done( slot );
507 FT_FREE( slot )do { ft_mem_free( memory, (slot) ); (slot) = ((void*)0); } while
( 0 )
;
508 goto Exit;
509 }
510
511 slot->next = face->glyph;
512 face->glyph = slot;
513
514 if ( aslot )
515 *aslot = slot;
516 }
517 else if ( aslot )
518 *aslot = NULL((void*)0);
519
520
521 Exit:
522 FT_TRACE4(( "FT_New_GlyphSlot: Return 0x%x\n", error ))do { } while ( 0 );
523
524 return error;
525 }
526
527
528 /* documentation is in ftobjs.h */
529
530 FT_BASE_DEF( void )void
531 FT_Done_GlyphSlot( FT_GlyphSlot slot )
532 {
533 if ( slot )
534 {
535 FT_Driver driver = slot->face->driver;
536 FT_Memory memory = driver->root.memory;
537 FT_GlyphSlot prev;
538 FT_GlyphSlot cur;
539
540
541 /* Remove slot from its parent face's list */
542 prev = NULL((void*)0);
543 cur = slot->face->glyph;
544
545 while ( cur )
546 {
547 if ( cur == slot )
548 {
549 if ( !prev )
550 slot->face->glyph = cur->next;
551 else
552 prev->next = cur->next;
553
554 /* finalize client-specific data */
555 if ( slot->generic.finalizer )
556 slot->generic.finalizer( slot );
557
558 ft_glyphslot_done( slot );
559 FT_FREE( slot )do { ft_mem_free( memory, (slot) ); (slot) = ((void*)0); } while
( 0 )
;
560 break;
561 }
562 prev = cur;
563 cur = cur->next;
564 }
565 }
566 }
567
568
569 /* documentation is in freetype.h */
570
571 FT_EXPORT_DEF( void )extern void
572 FT_Set_Transform( FT_Face face,
573 FT_Matrix* matrix,
574 FT_Vector* delta )
575 {
576 FT_Face_Internal internal;
577
578
579 if ( !face )
580 return;
581
582 internal = face->internal;
583
584 internal->transform_flags = 0;
585
586 if ( !matrix )
587 {
588 internal->transform_matrix.xx = 0x10000L;
589 internal->transform_matrix.xy = 0;
590 internal->transform_matrix.yx = 0;
591 internal->transform_matrix.yy = 0x10000L;
592
593 matrix = &internal->transform_matrix;
594 }
595 else
596 internal->transform_matrix = *matrix;
597
598 /* set transform_flags bit flag 0 if `matrix' isn't the identity */
599 if ( ( matrix->xy | matrix->yx ) ||
600 matrix->xx != 0x10000L ||
601 matrix->yy != 0x10000L )
602 internal->transform_flags |= 1;
603
604 if ( !delta )
605 {
606 internal->transform_delta.x = 0;
607 internal->transform_delta.y = 0;
608
609 delta = &internal->transform_delta;
610 }
611 else
612 internal->transform_delta = *delta;
613
614 /* set transform_flags bit flag 1 if `delta' isn't the null vector */
615 if ( delta->x | delta->y )
616 internal->transform_flags |= 2;
617 }
618
619
620 static FT_Renderer
621 ft_lookup_glyph_renderer( FT_GlyphSlot slot );
622
623
624#ifdef GRID_FIT_METRICS
625 static void
626 ft_glyphslot_grid_fit_metrics( FT_GlyphSlot slot,
627 FT_Bool vertical )
628 {
629 FT_Glyph_Metrics* metrics = &slot->metrics;
630 FT_Pos right, bottom;
631
632
633 if ( vertical )
634 {
635 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX )( (metrics->horiBearingX) & ~( __typeof__ ( metrics->
horiBearingX ) )63 )
;
636 metrics->horiBearingY = FT_PIX_CEIL_LONG( metrics->horiBearingY )( ((FT_Long)( (FT_ULong)((metrics->horiBearingY)) + (FT_ULong
)(63) )) & ~( __typeof__ ( (FT_Long)( (FT_ULong)((metrics
->horiBearingY)) + (FT_ULong)(63) ) ) )63 )
;
637
638 right = FT_PIX_CEIL_LONG( ADD_LONG( metrics->vertBearingX,( ((FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)(metrics->vertBearingX
) + (FT_ULong)(metrics->width) ))) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)
(metrics->vertBearingX) + (FT_ULong)(metrics->width) ))
) + (FT_ULong)(63) ) ) )63 )
639 metrics->width ) )( ((FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)(metrics->vertBearingX
) + (FT_ULong)(metrics->width) ))) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)
(metrics->vertBearingX) + (FT_ULong)(metrics->width) ))
) + (FT_ULong)(63) ) ) )63 )
;
640 bottom = FT_PIX_CEIL_LONG( ADD_LONG( metrics->vertBearingY,( ((FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)(metrics->vertBearingY
) + (FT_ULong)(metrics->height) ))) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)
(metrics->vertBearingY) + (FT_ULong)(metrics->height) )
)) + (FT_ULong)(63) ) ) )63 )
641 metrics->height ) )( ((FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)(metrics->vertBearingY
) + (FT_ULong)(metrics->height) ))) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)
(metrics->vertBearingY) + (FT_ULong)(metrics->height) )
)) + (FT_ULong)(63) ) ) )63 )
;
642
643 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX )( (metrics->vertBearingX) & ~( __typeof__ ( metrics->
vertBearingX ) )63 )
;
644 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY )( (metrics->vertBearingY) & ~( __typeof__ ( metrics->
vertBearingY ) )63 )
;
645
646 metrics->width = SUB_LONG( right,(FT_Long)( (FT_ULong)(right) - (FT_ULong)(metrics->vertBearingX
) )
647 metrics->vertBearingX )(FT_Long)( (FT_ULong)(right) - (FT_ULong)(metrics->vertBearingX
) )
;
648 metrics->height = SUB_LONG( bottom,(FT_Long)( (FT_ULong)(bottom) - (FT_ULong)(metrics->vertBearingY
) )
649 metrics->vertBearingY )(FT_Long)( (FT_ULong)(bottom) - (FT_ULong)(metrics->vertBearingY
) )
;
650 }
651 else
652 {
653 metrics->vertBearingX = FT_PIX_FLOOR( metrics->vertBearingX )( (metrics->vertBearingX) & ~( __typeof__ ( metrics->
vertBearingX ) )63 )
;
654 metrics->vertBearingY = FT_PIX_FLOOR( metrics->vertBearingY )( (metrics->vertBearingY) & ~( __typeof__ ( metrics->
vertBearingY ) )63 )
;
655
656 right = FT_PIX_CEIL_LONG( ADD_LONG( metrics->horiBearingX,( ((FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)(metrics->horiBearingX
) + (FT_ULong)(metrics->width) ))) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)
(metrics->horiBearingX) + (FT_ULong)(metrics->width) ))
) + (FT_ULong)(63) ) ) )63 )
657 metrics->width ) )( ((FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)(metrics->horiBearingX
) + (FT_ULong)(metrics->width) ))) + (FT_ULong)(63) )) &
~( __typeof__ ( (FT_Long)( (FT_ULong)(((FT_Long)( (FT_ULong)
(metrics->horiBearingX) + (FT_ULong)(metrics->width) ))
) + (FT_ULong)(63) ) ) )63 )
;
658 bottom = FT_PIX_FLOOR( SUB_LONG( metrics->horiBearingY,( ((FT_Long)( (FT_ULong)(metrics->horiBearingY) - (FT_ULong
)(metrics->height) )) & ~( __typeof__ ( (FT_Long)( (FT_ULong
)(metrics->horiBearingY) - (FT_ULong)(metrics->height) )
) )63 )
659 metrics->height ) )( ((FT_Long)( (FT_ULong)(metrics->horiBearingY) - (FT_ULong
)(metrics->height) )) & ~( __typeof__ ( (FT_Long)( (FT_ULong
)(metrics->horiBearingY) - (FT_ULong)(metrics->height) )
) )63 )
;
660
661 metrics->horiBearingX = FT_PIX_FLOOR( metrics->horiBearingX )( (metrics->horiBearingX) & ~( __typeof__ ( metrics->
horiBearingX ) )63 )
;
662 metrics->horiBearingY = FT_PIX_CEIL_LONG( metrics->horiBearingY )( ((FT_Long)( (FT_ULong)((metrics->horiBearingY)) + (FT_ULong
)(63) )) & ~( __typeof__ ( (FT_Long)( (FT_ULong)((metrics
->horiBearingY)) + (FT_ULong)(63) ) ) )63 )
;
663
664 metrics->width = SUB_LONG( right,(FT_Long)( (FT_ULong)(right) - (FT_ULong)(metrics->horiBearingX
) )
665 metrics->horiBearingX )(FT_Long)( (FT_ULong)(right) - (FT_ULong)(metrics->horiBearingX
) )
;
666 metrics->height = SUB_LONG( metrics->horiBearingY,(FT_Long)( (FT_ULong)(metrics->horiBearingY) - (FT_ULong)(
bottom) )
667 bottom )(FT_Long)( (FT_ULong)(metrics->horiBearingY) - (FT_ULong)(
bottom) )
;
668 }
669
670 metrics->horiAdvance = FT_PIX_ROUND_LONG( metrics->horiAdvance )( ((FT_Long)( (FT_ULong)((metrics->horiAdvance)) + (FT_ULong
)(32) )) & ~( __typeof__ ( (FT_Long)( (FT_ULong)((metrics
->horiAdvance)) + (FT_ULong)(32) ) ) )63 )
;
671 metrics->vertAdvance = FT_PIX_ROUND_LONG( metrics->vertAdvance )( ((FT_Long)( (FT_ULong)((metrics->vertAdvance)) + (FT_ULong
)(32) )) & ~( __typeof__ ( (FT_Long)( (FT_ULong)((metrics
->vertAdvance)) + (FT_ULong)(32) ) ) )63 )
;
672 }
673#endif /* GRID_FIT_METRICS */
674
675
676 /* documentation is in freetype.h */
677
678 FT_EXPORT_DEF( FT_Error )extern FT_Error
679 FT_Load_Glyph( FT_Face face,
680 FT_UInt glyph_index,
681 FT_Int32 load_flags )
682 {
683 FT_Error error;
684 FT_Driver driver;
685 FT_GlyphSlot slot;
686 FT_Library library;
687 FT_Bool autohint = FALSE0;
688 FT_Module hinter;
689 TT_Face ttface = (TT_Face)face;
690
691
692 if ( !face || !face->size || !face->glyph )
693 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
694
695 /* The validity test for `glyph_index' is performed by the */
696 /* font drivers. */
697
698 slot = face->glyph;
699 ft_glyphslot_clear( slot );
700
701 driver = face->driver;
702 library = driver->root.library;
703 hinter = library->auto_hinter;
704
705 /* resolve load flags dependencies */
706
707 if ( load_flags & FT_LOAD_NO_RECURSE( 1L << 10 ) )
708 load_flags |= FT_LOAD_NO_SCALE( 1L << 0 ) |
709 FT_LOAD_IGNORE_TRANSFORM( 1L << 11 );
710
711 if ( load_flags & FT_LOAD_NO_SCALE( 1L << 0 ) )
712 {
713 load_flags |= FT_LOAD_NO_HINTING( 1L << 1 ) |
714 FT_LOAD_NO_BITMAP( 1L << 3 );
715
716 load_flags &= ~FT_LOAD_RENDER( 1L << 2 );
717 }
718
719 if ( load_flags & FT_LOAD_BITMAP_METRICS_ONLY( 1L << 22 ) )
720 load_flags &= ~FT_LOAD_RENDER( 1L << 2 );
721
722 /*
723 * Determine whether we need to auto-hint or not.
724 * The general rules are:
725 *
726 * - Do only auto-hinting if we have
727 *
728 * - a hinter module,
729 * - a scalable font format dealing with outlines,
730 * - not a tricky font, and
731 * - no transforms except simple slants and/or rotations by
732 * integer multiples of 90 degrees.
733 *
734 * - Then, auto-hint if FT_LOAD_FORCE_AUTOHINT is set or if we don't
735 * have a native font hinter.
736 *
737 * - Otherwise, auto-hint for LIGHT hinting mode or if there isn't
738 * any hinting bytecode in the TrueType/OpenType font.
739 *
740 * - Exception: The font is `tricky' and requires the native hinter to
741 * load properly.
742 */
743
744 if ( hinter &&
745 !( load_flags & FT_LOAD_NO_HINTING( 1L << 1 ) ) &&
746 !( load_flags & FT_LOAD_NO_AUTOHINT( 1L << 15 ) ) &&
747 FT_DRIVER_IS_SCALABLE( driver )( ( (FT_Module)(driver) )->clazz->module_flags & 0x100
)
&&
748 FT_DRIVER_USES_OUTLINES( driver )!( ( (FT_Module)(driver) )->clazz->module_flags & 0x200
)
&&
749 !FT_IS_TRICKY( face )( (face)->face_flags & ( 1L << 13 ) ) &&
750 ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM( 1L << 11 ) ) ||
751 ( face->internal->transform_matrix.yx == 0 &&
752 face->internal->transform_matrix.xx != 0 ) ||
753 ( face->internal->transform_matrix.xx == 0 &&
754 face->internal->transform_matrix.yx != 0 ) ) )
755 {
756 if ( ( load_flags & FT_LOAD_FORCE_AUTOHINT( 1L << 5 ) ) ||
757 !FT_DRIVER_HAS_HINTER( driver )( ( (FT_Module)(driver) )->clazz->module_flags & 0x400
)
)
758 autohint = TRUE1;
759 else
760 {
761 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags )( (FT_Render_Mode)( ( (load_flags) >> 16 ) & 15 ) );
762 FT_Bool is_light_type1;
763
764
765 /* only the new Adobe engine (for both CFF and Type 1) is `light'; */
766 /* we use `strstr' to catch both `Type 1' and `CID Type 1' */
767 is_light_type1 =
768 ft_strstrstrstr( FT_Get_Font_Format( face ), "Type 1" ) != NULL((void*)0) &&
769 ((PS_Driver)driver)->hinting_engine == FT_HINTING_ADOBE1;
770
771 /* the check for `num_locations' assures that we actually */
772 /* test for instructions in a TTF and not in a CFF-based OTF */
773 /* */
774 /* since `maxSizeOfInstructions' might be unreliable, we */
775 /* check the size of the `fpgm' and `prep' tables, too -- */
776 /* the assumption is that there don't exist real TTFs where */
777 /* both `fpgm' and `prep' tables are missing */
778 if ( ( mode == FT_RENDER_MODE_LIGHT &&
779 ( !FT_DRIVER_HINTS_LIGHTLY( driver )( ( (FT_Module)(driver) )->clazz->module_flags & 0x800
)
&&
780 !is_light_type1 ) ) ||
781 ( FT_IS_SFNT( face )( (face)->face_flags & ( 1L << 3 ) ) &&
782 ttface->num_locations &&
783 ttface->max_profile.maxSizeOfInstructions == 0 &&
784 ttface->font_program_size == 0 &&
785 ttface->cvt_program_size == 0 ) )
786 autohint = TRUE1;
787 }
788 }
789
790 if ( autohint )
791 {
792 FT_AutoHinter_Interface hinting;
793
794
795 /* try to load embedded bitmaps first if available */
796 /* */
797 /* XXX: This is really a temporary hack that should disappear */
798 /* promptly with FreeType 2.1! */
799 /* */
800 if ( FT_HAS_FIXED_SIZES( face )( (face)->face_flags & ( 1L << 1 ) ) &&
801 ( load_flags & FT_LOAD_NO_BITMAP( 1L << 3 ) ) == 0 )
802 {
803 error = driver->clazz->load_glyph( slot, face->size,
804 glyph_index,
805 load_flags | FT_LOAD_SBITS_ONLY( 1L << 14 ) );
806
807 if ( !error && slot->format == FT_GLYPH_FORMAT_BITMAP )
808 goto Load_Ok;
809 }
810
811 {
812 FT_Face_Internal internal = face->internal;
813 FT_Int transform_flags = internal->transform_flags;
814
815
816 /* since the auto-hinter calls FT_Load_Glyph by itself, */
817 /* make sure that glyphs aren't transformed */
818 internal->transform_flags = 0;
819
820 /* load auto-hinted outline */
821 hinting = (FT_AutoHinter_Interface)hinter->clazz->module_interface;
822
823 error = hinting->load_glyph( (FT_AutoHinter)hinter,
824 slot, face->size,
825 glyph_index, load_flags );
826
827 internal->transform_flags = transform_flags;
828 }
829 }
830 else
831 {
832 error = driver->clazz->load_glyph( slot,
833 face->size,
834 glyph_index,
835 load_flags );
836 if ( error )
837 goto Exit;
838
839 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
840 {
841 /* check that the loaded outline is correct */
842 error = FT_Outline_Check( &slot->outline );
843 if ( error )
844 goto Exit;
845
846#ifdef GRID_FIT_METRICS
847 if ( !( load_flags & FT_LOAD_NO_HINTING( 1L << 1 ) ) )
848 ft_glyphslot_grid_fit_metrics( slot,
849 FT_BOOL( load_flags & FT_LOAD_VERTICAL_LAYOUT )( (FT_Bool)( load_flags & ( 1L << 4 ) ) ) );
850#endif
851 }
852 }
853
854 Load_Ok:
855 /* compute the advance */
856 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT( 1L << 4 ) )
857 {
858 slot->advance.x = 0;
859 slot->advance.y = slot->metrics.vertAdvance;
860 }
861 else
862 {
863 slot->advance.x = slot->metrics.horiAdvance;
864 slot->advance.y = 0;
865 }
866
867 /* compute the linear advance in 16.16 pixels */
868 if ( ( load_flags & FT_LOAD_LINEAR_DESIGN( 1L << 13 ) ) == 0 &&
869 FT_IS_SCALABLE( face )( (face)->face_flags & ( 1L << 0 ) ) )
870 {
871 FT_Size_Metrics* metrics = &face->size->metrics;
872
873
874 /* it's tricky! */
875 slot->linearHoriAdvance = FT_MulDiv( slot->linearHoriAdvance,
876 metrics->x_scale, 64 );
877
878 slot->linearVertAdvance = FT_MulDiv( slot->linearVertAdvance,
879 metrics->y_scale, 64 );
880 }
881
882 if ( ( load_flags & FT_LOAD_IGNORE_TRANSFORM( 1L << 11 ) ) == 0 )
883 {
884 FT_Face_Internal internal = face->internal;
885
886
887 /* now, transform the glyph image if needed */
888 if ( internal->transform_flags )
889 {
890 /* get renderer */
891 FT_Renderer renderer = ft_lookup_glyph_renderer( slot );
892
893
894 if ( renderer )
895 error = renderer->clazz->transform_glyph(
896 renderer, slot,
897 &internal->transform_matrix,
898 &internal->transform_delta );
899 else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
900 {
901 /* apply `standard' transformation if no renderer is available */
902 if ( internal->transform_flags & 1 )
903 FT_Outline_Transform( &slot->outline,
904 &internal->transform_matrix );
905
906 if ( internal->transform_flags & 2 )
907 FT_Outline_Translate( &slot->outline,
908 internal->transform_delta.x,
909 internal->transform_delta.y );
910 }
911
912 /* transform advance */
913 FT_Vector_Transform( &slot->advance, &internal->transform_matrix );
914 }
915 }
916
917 /* do we need to render the image or preset the bitmap now? */
918 if ( !error &&
919 ( load_flags & FT_LOAD_NO_SCALE( 1L << 0 ) ) == 0 &&
920 slot->format != FT_GLYPH_FORMAT_BITMAP &&
921 slot->format != FT_GLYPH_FORMAT_COMPOSITE )
922 {
923 FT_Render_Mode mode = FT_LOAD_TARGET_MODE( load_flags )( (FT_Render_Mode)( ( (load_flags) >> 16 ) & 15 ) );
924
925
926 if ( mode == FT_RENDER_MODE_NORMAL &&
927 load_flags & FT_LOAD_MONOCHROME( 1L << 12 ) )
928 mode = FT_RENDER_MODE_MONO;
929
930 if ( load_flags & FT_LOAD_RENDER( 1L << 2 ) )
931 error = FT_Render_Glyph( slot, mode );
932 else
933 ft_glyphslot_preset_bitmap( slot, mode, NULL((void*)0) );
934 }
935
936 FT_TRACE5(( "FT_Load_Glyph: index %d, flags %x\n",do { } while ( 0 )
937 glyph_index, load_flags ))do { } while ( 0 );
938 FT_TRACE5(( " x advance: %f\n", slot->advance.x / 64.0 ))do { } while ( 0 );
939 FT_TRACE5(( " y advance: %f\n", slot->advance.y / 64.0 ))do { } while ( 0 );
940 FT_TRACE5(( " linear x advance: %f\n",do { } while ( 0 )
941 slot->linearHoriAdvance / 65536.0 ))do { } while ( 0 );
942 FT_TRACE5(( " linear y advance: %f\n",do { } while ( 0 )
943 slot->linearVertAdvance / 65536.0 ))do { } while ( 0 );
944 FT_TRACE5(( " bitmap %dx%d, mode %d\n",do { } while ( 0 )
945 slot->bitmap.width, slot->bitmap.rows,do { } while ( 0 )
946 slot->bitmap.pixel_mode ))do { } while ( 0 );
947
948 Exit:
949 return error;
950 }
951
952
953 /* documentation is in freetype.h */
954
955 FT_EXPORT_DEF( FT_Error )extern FT_Error
956 FT_Load_Char( FT_Face face,
957 FT_ULong char_code,
958 FT_Int32 load_flags )
959 {
960 FT_UInt glyph_index;
961
962
963 if ( !face )
964 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
965
966 glyph_index = (FT_UInt)char_code;
967 if ( face->charmap )
968 glyph_index = FT_Get_Char_Index( face, char_code );
969
970 return FT_Load_Glyph( face, glyph_index, load_flags );
971 }
972
973
974 /* destructor for sizes list */
975 static void
976 destroy_size( FT_Memory memory,
977 FT_Size size,
978 FT_Driver driver )
979 {
980 /* finalize client-specific data */
981 if ( size->generic.finalizer )
982 size->generic.finalizer( size );
983
984 /* finalize format-specific stuff */
985 if ( driver->clazz->done_size )
986 driver->clazz->done_size( size );
987
988 FT_FREE( size->internal )do { ft_mem_free( memory, (size->internal) ); (size->internal
) = ((void*)0); } while ( 0 )
;
989 FT_FREE( size )do { ft_mem_free( memory, (size) ); (size) = ((void*)0); } while
( 0 )
;
990 }
991
992
993 static void
994 ft_cmap_done_internal( FT_CMap cmap );
995
996
997 static void
998 destroy_charmaps( FT_Face face,
999 FT_Memory memory )
1000 {
1001 FT_Int n;
1002
1003
1004 if ( !face )
1005 return;
1006
1007 for ( n = 0; n < face->num_charmaps; n++ )
1008 {
1009 FT_CMap cmap = FT_CMAP( face->charmaps[n] )( (FT_CMap)( face->charmaps[n] ) );
1010
1011
1012 ft_cmap_done_internal( cmap );
1013
1014 face->charmaps[n] = NULL((void*)0);
1015 }
1016
1017 FT_FREE( face->charmaps )do { ft_mem_free( memory, (face->charmaps) ); (face->charmaps
) = ((void*)0); } while ( 0 )
;
1018 face->num_charmaps = 0;
1019 }
1020
1021
1022 /* destructor for faces list */
1023 static void
1024 destroy_face( FT_Memory memory,
1025 FT_Face face,
1026 FT_Driver driver )
1027 {
1028 FT_Driver_Class clazz = driver->clazz;
1029
1030
1031 /* discard auto-hinting data */
1032 if ( face->autohint.finalizer )
1033 face->autohint.finalizer( face->autohint.data );
1034
1035 /* Discard glyph slots for this face. */
1036 /* Beware! FT_Done_GlyphSlot() changes the field `face->glyph' */
1037 while ( face->glyph )
1038 FT_Done_GlyphSlot( face->glyph );
1039
1040 /* discard all sizes for this face */
1041 FT_List_Finalize( &face->sizes_list,
1042 (FT_List_Destructor)destroy_size,
1043 memory,
1044 driver );
1045 face->size = NULL((void*)0);
1046
1047 /* now discard client data */
1048 if ( face->generic.finalizer )
1049 face->generic.finalizer( face );
1050
1051 /* discard charmaps */
1052 destroy_charmaps( face, memory );
1053
1054 /* finalize format-specific stuff */
1055 if ( clazz->done_face )
1056 clazz->done_face( face );
1057
1058 /* close the stream for this face if needed */
1059 FT_Stream_Free(
1060 face->stream,
1061 ( face->face_flags & FT_FACE_FLAG_EXTERNAL_STREAM( 1L << 10 ) ) != 0 );
1062
1063 face->stream = NULL((void*)0);
1064
1065 /* get rid of it */
1066 if ( face->internal )
1067 {
1068 FT_FREE( face->internal )do { ft_mem_free( memory, (face->internal) ); (face->internal
) = ((void*)0); } while ( 0 )
;
1069 }
1070 FT_FREE( face )do { ft_mem_free( memory, (face) ); (face) = ((void*)0); } while
( 0 )
;
1071 }
1072
1073
1074 static void
1075 Destroy_Driver( FT_Driver driver )
1076 {
1077 FT_List_Finalize( &driver->faces_list,
1078 (FT_List_Destructor)destroy_face,
1079 driver->root.memory,
1080 driver );
1081 }
1082
1083
1084 /*************************************************************************/
1085 /* */
1086 /* <Function> */
1087 /* find_unicode_charmap */
1088 /* */
1089 /* <Description> */
1090 /* This function finds a Unicode charmap, if there is one. */
1091 /* And if there is more than one, it tries to favour the more */
1092 /* extensive one, i.e., one that supports UCS-4 against those which */
1093 /* are limited to the BMP (said UCS-2 encoding.) */
1094 /* */
1095 /* This function is called from open_face() (just below), and also */
1096 /* from FT_Select_Charmap( ..., FT_ENCODING_UNICODE ). */
1097 /* */
1098 static FT_Error
1099 find_unicode_charmap( FT_Face face )
1100 {
1101 FT_CharMap* first;
1102 FT_CharMap* cur;
1103
1104
1105 /* caller should have already checked that `face' is valid */
1106 FT_ASSERT( face )do { } while ( 0 );
1107
1108 first = face->charmaps;
1109
1110 if ( !first )
1111 return FT_THROW( Invalid_CharMap_Handle )FT_Err_Invalid_CharMap_Handle;
1112
1113 /*
1114 * The original TrueType specification(s) only specified charmap
1115 * formats that are capable of mapping 8 or 16 bit character codes to
1116 * glyph indices.
1117 *
1118 * However, recent updates to the Apple and OpenType specifications
1119 * introduced new formats that are capable of mapping 32-bit character
1120 * codes as well. And these are already used on some fonts, mainly to
1121 * map non-BMP Asian ideographs as defined in Unicode.
1122 *
1123 * For compatibility purposes, these fonts generally come with
1124 * *several* Unicode charmaps:
1125 *
1126 * - One of them in the "old" 16-bit format, that cannot access
1127 * all glyphs in the font.
1128 *
1129 * - Another one in the "new" 32-bit format, that can access all
1130 * the glyphs.
1131 *
1132 * This function has been written to always favor a 32-bit charmap
1133 * when found. Otherwise, a 16-bit one is returned when found.
1134 */
1135
1136 /* Since the `interesting' table, with IDs (3,10), is normally the */
1137 /* last one, we loop backwards. This loses with type1 fonts with */
1138 /* non-BMP characters (<.0001%), this wins with .ttf with non-BMP */
1139 /* chars (.01% ?), and this is the same about 99.99% of the time! */
1140
1141 cur = first + face->num_charmaps; /* points after the last one */
1142
1143 for ( ; --cur >= first; )
1144 {
1145 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
1146 {
1147 /* XXX If some new encodings to represent UCS-4 are added, */
1148 /* they should be added here. */
1149 if ( ( cur[0]->platform_id == TT_PLATFORM_MICROSOFT3 &&
1150 cur[0]->encoding_id == TT_MS_ID_UCS_410 ) ||
1151 ( cur[0]->platform_id == TT_PLATFORM_APPLE_UNICODE0 &&
1152 cur[0]->encoding_id == TT_APPLE_ID_UNICODE_324 ) )
1153 {
1154 face->charmap = cur[0];
1155 return FT_Err_Ok;
1156 }
1157 }
1158 }
1159
1160 /* We do not have any UCS-4 charmap. */
1161 /* Do the loop again and search for UCS-2 charmaps. */
1162 cur = first + face->num_charmaps;
1163
1164 for ( ; --cur >= first; )
1165 {
1166 if ( cur[0]->encoding == FT_ENCODING_UNICODE )
1167 {
1168 face->charmap = cur[0];
1169 return FT_Err_Ok;
1170 }
1171 }
1172
1173 return FT_THROW( Invalid_CharMap_Handle )FT_Err_Invalid_CharMap_Handle;
1174 }
1175
1176
1177 /*************************************************************************/
1178 /* */
1179 /* <Function> */
1180 /* open_face */
1181 /* */
1182 /* <Description> */
1183 /* This function does some work for FT_Open_Face(). */
1184 /* */
1185 static FT_Error
1186 open_face( FT_Driver driver,
1187 FT_Stream *astream,
1188 FT_Bool external_stream,
1189 FT_Long face_index,
1190 FT_Int num_params,
1191 FT_Parameter* params,
1192 FT_Face *aface )
1193 {
1194 FT_Memory memory;
1195 FT_Driver_Class clazz;
1196 FT_Face face = NULL((void*)0);
1197 FT_Face_Internal internal = NULL((void*)0);
1198
1199 FT_Error error, error2;
1200
1201
1202 clazz = driver->clazz;
1203 memory = driver->root.memory;
1204
1205 /* allocate the face object and perform basic initialization */
1206 if ( FT_ALLOC( face, clazz->face_object_size )( ((face) = (ft_mem_alloc( memory, (FT_Long)(clazz->face_object_size
), &error ))), error != 0 )
)
1207 goto Fail;
1208
1209 face->driver = driver;
1210 face->memory = memory;
1211 face->stream = *astream;
1212
1213 /* set the FT_FACE_FLAG_EXTERNAL_STREAM bit for FT_Done_Face */
1214 if ( external_stream )
1215 face->face_flags |= FT_FACE_FLAG_EXTERNAL_STREAM( 1L << 10 );
1216
1217 if ( FT_NEW( internal )( ((internal) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(internal
) )), &error ))), error != 0 )
)
1218 goto Fail;
1219
1220 face->internal = internal;
1221
1222 face->internal->random_seed = -1;
1223
1224 if ( clazz->init_face )
1225 error = clazz->init_face( *astream,
1226 face,
1227 (FT_Int)face_index,
1228 num_params,
1229 params );
1230 *astream = face->stream; /* Stream may have been changed. */
1231 if ( error )
1232 goto Fail;
1233
1234 /* select Unicode charmap by default */
1235 error2 = find_unicode_charmap( face );
1236
1237 /* if no Unicode charmap can be found, FT_Err_Invalid_CharMap_Handle */
1238 /* is returned. */
1239
1240 /* no error should happen, but we want to play safe */
1241 if ( error2 && FT_ERR_NEQ( error2, Invalid_CharMap_Handle )( ( (error2) & 0xFF ) != ( (FT_Err_Invalid_CharMap_Handle
) & 0xFF ) )
)
1242 {
1243 error = error2;
1244 goto Fail;
1245 }
1246
1247 *aface = face;
1248
1249 Fail:
1250 if ( error )
1251 {
1252 destroy_charmaps( face, memory );
1253 if ( clazz->done_face )
1254 clazz->done_face( face );
1255 FT_FREE( internal )do { ft_mem_free( memory, (internal) ); (internal) = ((void*)
0); } while ( 0 )
;
1256 FT_FREE( face )do { ft_mem_free( memory, (face) ); (face) = ((void*)0); } while
( 0 )
;
1257 *aface = NULL((void*)0);
1258 }
1259
1260 return error;
1261 }
1262
1263
1264#ifdef FT_MACINTOSH
1265
1266 /* The behavior here is very similar to that in base/ftmac.c, but it */
1267 /* is designed to work on non-mac systems, so no mac specific calls. */
1268 /* */
1269 /* We look at the file and determine if it is a mac dfont file or a mac */
1270 /* resource file, or a macbinary file containing a mac resource file. */
1271 /* */
1272 /* Unlike ftmac I'm not going to look at a `FOND'. I don't really see */
1273 /* the point, especially since there may be multiple `FOND' resources. */
1274 /* Instead I'll just look for `sfnt' and `POST' resources, ordered as */
1275 /* they occur in the file. */
1276 /* */
1277 /* Note that multiple `POST' resources do not mean multiple postscript */
1278 /* fonts; they all get jammed together to make what is essentially a */
1279 /* pfb file. */
1280 /* */
1281 /* We aren't interested in `NFNT' or `FONT' bitmap resources. */
1282 /* */
1283 /* As soon as we get an `sfnt' load it into memory and pass it off to */
1284 /* FT_Open_Face. */
1285 /* */
1286 /* If we have a (set of) `POST' resources, massage them into a (memory) */
1287 /* pfb file and pass that to FT_Open_Face. (As with ftmac.c I'm not */
1288 /* going to try to save the kerning info. After all that lives in the */
1289 /* `FOND' which isn't in the file containing the `POST' resources so */
1290 /* we don't really have access to it. */
1291
1292
1293 /* Finalizer for a memory stream; gets called by FT_Done_Face(). */
1294 /* It frees the memory it uses. */
1295 /* From `ftmac.c'. */
1296 static void
1297 memory_stream_close( FT_Stream stream )
1298 {
1299 FT_Memory memory = stream->memory;
1300
1301
1302 FT_FREE( stream->base )do { ft_mem_free( memory, (stream->base) ); (stream->base
) = ((void*)0); } while ( 0 )
;
1303
1304 stream->size = 0;
1305 stream->base = NULL((void*)0);
1306 stream->close = NULL((void*)0);
1307 }
1308
1309
1310 /* Create a new memory stream from a buffer and a size. */
1311 /* From `ftmac.c'. */
1312 static FT_Error
1313 new_memory_stream( FT_Library library,
1314 FT_Byte* base,
1315 FT_ULong size,
1316 FT_Stream_CloseFunc close,
1317 FT_Stream *astream )
1318 {
1319 FT_Error error;
1320 FT_Memory memory;
1321 FT_Stream stream = NULL((void*)0);
1322
1323
1324 if ( !library )
1325 return FT_THROW( Invalid_Library_Handle )FT_Err_Invalid_Library_Handle;
1326
1327 if ( !base )
1328 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
1329
1330 *astream = NULL((void*)0);
1331 memory = library->memory;
1332 if ( FT_NEW( stream )( ((stream) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(stream
) )), &error ))), error != 0 )
)
1333 goto Exit;
1334
1335 FT_Stream_OpenMemory( stream, base, size );
1336
1337 stream->close = close;
1338
1339 *astream = stream;
1340
1341 Exit:
1342 return error;
1343 }
1344
1345
1346 /* Create a new FT_Face given a buffer and a driver name. */
1347 /* From `ftmac.c'. */
1348 FT_LOCAL_DEF( FT_Error )static FT_Error
1349 open_face_from_buffer( FT_Library library,
1350 FT_Byte* base,
1351 FT_ULong size,
1352 FT_Long face_index,
1353 const char* driver_name,
1354 FT_Face *aface )
1355 {
1356 FT_Open_Args args;
1357 FT_Error error;
1358 FT_Stream stream = NULL((void*)0);
1359 FT_Memory memory = library->memory;
1360
1361
1362 error = new_memory_stream( library,
1363 base,
1364 size,
1365 memory_stream_close,
1366 &stream );
1367 if ( error )
1368 {
1369 FT_FREE( base )do { ft_mem_free( memory, (base) ); (base) = ((void*)0); } while
( 0 )
;
1370 return error;
1371 }
1372
1373 args.flags = FT_OPEN_STREAM0x2;
1374 args.stream = stream;
1375 if ( driver_name )
1376 {
1377 args.flags = args.flags | FT_OPEN_DRIVER0x8;
1378 args.driver = FT_Get_Module( library, driver_name );
1379 }
1380
1381 /* At this point, the face index has served its purpose; */
1382 /* whoever calls this function has already used it to */
1383 /* locate the correct font data. We should not propagate */
1384 /* this index to FT_Open_Face() (unless it is negative). */
1385
1386 if ( face_index > 0 )
1387 face_index &= 0x7FFF0000L; /* retain GX data */
1388
1389 error = ft_open_face_internal( library, &args, face_index, aface, 0 );
1390
1391 if ( !error )
1392 (*aface)->face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM( 1L << 10 );
1393 else
1394 FT_Stream_Free( stream, 0 );
1395
1396 return error;
1397 }
1398
1399
1400 /* Look up `TYP1' or `CID ' table from sfnt table directory. */
1401 /* `offset' and `length' must exclude the binary header in tables. */
1402
1403 /* Type 1 and CID-keyed font drivers should recognize sfnt-wrapped */
1404 /* format too. Here, since we can't expect that the TrueType font */
1405 /* driver is loaded unconditionally, we must parse the font by */
1406 /* ourselves. We are only interested in the name of the table and */
1407 /* the offset. */
1408
1409 static FT_Error
1410 ft_lookup_PS_in_sfnt_stream( FT_Stream stream,
1411 FT_Long face_index,
1412 FT_ULong* offset,
1413 FT_ULong* length,
1414 FT_Bool* is_sfnt_cid )
1415 {
1416 FT_Error error;
1417 FT_UShort numTables;
1418 FT_Long pstable_index;
1419 FT_ULong tag;
1420 int i;
1421
1422
1423 *offset = 0;
1424 *length = 0;
1425 *is_sfnt_cid = FALSE0;
1426
1427 /* TODO: support for sfnt-wrapped PS/CID in TTC format */
1428
1429 /* version check for 'typ1' (should be ignored?) */
1430 if ( FT_READ_ULONG( tag )( tag = (FT_ULong)FT_Stream_ReadULong( stream, &error ), error
!= FT_Err_Ok )
)
1431 return error;
1432 if ( tag != TTAG_typ1(FT_Tag) ( ( (FT_ULong)'t' << 24 ) | ( (FT_ULong)'y' <<
16 ) | ( (FT_ULong)'p' << 8 ) | (FT_ULong)'1' )
)
1433 return FT_THROW( Unknown_File_Format )FT_Err_Unknown_File_Format;
1434
1435 if ( FT_READ_USHORT( numTables )( numTables = (FT_UShort)FT_Stream_ReadUShort( stream, &error
), error != FT_Err_Ok )
)
1436 return error;
1437 if ( FT_STREAM_SKIP( 2 * 3 )( ( error = (FT_Stream_Skip( stream, (FT_Long)(2 * 3) )) ) !=
0 )
) /* skip binary search header */
1438 return error;
1439
1440 pstable_index = -1;
1441 *is_sfnt_cid = FALSE0;
1442
1443 for ( i = 0; i < numTables; i++ )
1444 {
1445 if ( FT_READ_ULONG( tag )( tag = (FT_ULong)FT_Stream_ReadULong( stream, &error ), error
!= FT_Err_Ok )
|| FT_STREAM_SKIP( 4 )( ( error = (FT_Stream_Skip( stream, (FT_Long)(4) )) ) != 0 ) ||
1446 FT_READ_ULONG( *offset )( *offset = (FT_ULong)FT_Stream_ReadULong( stream, &error
), error != FT_Err_Ok )
|| FT_READ_ULONG( *length )( *length = (FT_ULong)FT_Stream_ReadULong( stream, &error
), error != FT_Err_Ok )
)
1447 return error;
1448
1449 if ( tag == TTAG_CID(FT_Tag) ( ( (FT_ULong)'C' << 24 ) | ( (FT_ULong)'I' <<
16 ) | ( (FT_ULong)'D' << 8 ) | (FT_ULong)' ' )
)
1450 {
1451 pstable_index++;
1452 *offset += 22;
1453 *length -= 22;
1454 *is_sfnt_cid = TRUE1;
1455 if ( face_index < 0 )
1456 return FT_Err_Ok;
1457 }
1458 else if ( tag == TTAG_TYP1(FT_Tag) ( ( (FT_ULong)'T' << 24 ) | ( (FT_ULong)'Y' <<
16 ) | ( (FT_ULong)'P' << 8 ) | (FT_ULong)'1' )
)
1459 {
1460 pstable_index++;
1461 *offset += 24;
1462 *length -= 24;
1463 *is_sfnt_cid = FALSE0;
1464 if ( face_index < 0 )
1465 return FT_Err_Ok;
1466 }
1467 if ( face_index >= 0 && pstable_index == face_index )
1468 return FT_Err_Ok;
1469 }
1470
1471 return FT_THROW( Table_Missing )FT_Err_Table_Missing;
1472 }
1473
1474
1475 FT_LOCAL_DEF( FT_Error )static FT_Error
1476 open_face_PS_from_sfnt_stream( FT_Library library,
1477 FT_Stream stream,
1478 FT_Long face_index,
1479 FT_Int num_params,
1480 FT_Parameter *params,
1481 FT_Face *aface )
1482 {
1483 FT_Error error;
1484 FT_Memory memory = library->memory;
1485 FT_ULong offset, length;
1486 FT_ULong pos;
1487 FT_Bool is_sfnt_cid;
1488 FT_Byte* sfnt_ps = NULL((void*)0);
1489
1490 FT_UNUSED( num_params )( (num_params) = (num_params) );
1491 FT_UNUSED( params )( (params) = (params) );
1492
1493
1494 /* ignore GX stuff */
1495 if ( face_index > 0 )
1496 face_index &= 0xFFFFL;
1497
1498 pos = FT_STREAM_POS()FT_Stream_Pos( stream );
1499
1500 error = ft_lookup_PS_in_sfnt_stream( stream,
1501 face_index,
1502 &offset,
1503 &length,
1504 &is_sfnt_cid );
1505 if ( error )
1506 goto Exit;
1507
1508 if ( offset > stream->size )
1509 {
1510 FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table offset\n" ))do { } while ( 0 );
1511 error = FT_THROW( Invalid_Table )FT_Err_Invalid_Table;
1512 goto Exit;
1513 }
1514 else if ( length > stream->size - offset )
1515 {
1516 FT_TRACE2(( "open_face_PS_from_sfnt_stream: invalid table length\n" ))do { } while ( 0 );
1517 error = FT_THROW( Invalid_Table )FT_Err_Invalid_Table;
1518 goto Exit;
1519 }
1520
1521 error = FT_Stream_Seek( stream, pos + offset );
1522 if ( error )
1523 goto Exit;
1524
1525 if ( FT_ALLOC( sfnt_ps, (FT_Long)length )( ((sfnt_ps) = (ft_mem_alloc( memory, (FT_Long)((FT_Long)length
), &error ))), error != 0 )
)
1526 goto Exit;
1527
1528 error = FT_Stream_Read( stream, (FT_Byte *)sfnt_ps, length );
1529 if ( error )
1530 {
1531 FT_FREE( sfnt_ps )do { ft_mem_free( memory, (sfnt_ps) ); (sfnt_ps) = ((void*)0)
; } while ( 0 )
;
1532 goto Exit;
1533 }
1534
1535 error = open_face_from_buffer( library,
1536 sfnt_ps,
1537 length,
1538 FT_MIN( face_index, 0 )( (face_index) < (0) ? (face_index) : (0) ),
1539 is_sfnt_cid ? "cid" : "type1",
1540 aface );
1541 Exit:
1542 {
1543 FT_Error error1;
1544
1545
1546 if ( FT_ERR_EQ( error, Unknown_File_Format )( ( (error) & 0xFF ) == ( (FT_Err_Unknown_File_Format) &
0xFF ) )
)
1547 {
1548 error1 = FT_Stream_Seek( stream, pos );
1549 if ( error1 )
1550 return error1;
1551 }
1552
1553 return error;
1554 }
1555 }
1556#endif /* FT_MACINTOSH */
1557
1558
1559 /* documentation is in freetype.h */
1560
1561#ifndef FT_MACINTOSH
1562 FT_EXPORT_DEF( FT_Error )extern FT_Error
1563 FT_New_Face( FT_Library library,
1564 const FT_Open_Args* args,
1565 FT_Long face_index,
1566 FT_Face *aface )
1567 {
1568 return FT_Open_Face( library, args, face_index, aface );
1569 }
1570#endif
1571
1572 FT_EXPORT_DEF( FT_Error )extern FT_Error
1573 FT_Open_Face( FT_Library library,
1574 const FT_Open_Args* args,
1575 FT_Long face_index,
1576 FT_Face *aface )
1577 {
1578 return ft_open_face_internal( library, args, face_index, aface, 1 );
1579 }
1580
1581
1582 static FT_Error
1583 ft_open_face_internal( FT_Library library,
1584 const FT_Open_Args* args,
1585 FT_Long face_index,
1586 FT_Face *aface,
1587 FT_Bool test_mac_fonts )
1588 {
1589 FT_Error error;
1590 FT_Driver driver = NULL((void*)0);
1591 FT_Memory memory = NULL((void*)0);
1592 FT_Stream stream = NULL((void*)0);
1593 FT_Face face = NULL((void*)0);
1594 FT_ListNode node = NULL((void*)0);
1595 FT_Bool external_stream;
1596 FT_Module* cur;
1597 FT_Module* limit;
1598
1599 FT_UNUSED( test_mac_fonts )( (test_mac_fonts) = (test_mac_fonts) );
1600
1601 /* test for valid `library' delayed to `FT_Stream_New' */
1602
1603 if ( ( !aface && face_index >= 0 ) || !args )
1604 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
1605
1606 external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&( (FT_Bool)( ( args->flags & 0x2 ) && args->
stream ) )
1607 args->stream )( (FT_Bool)( ( args->flags & 0x2 ) && args->
stream ) )
;
1608
1609 /* create input stream */
1610 error = FT_Stream_New( library, args, &stream );
1611 if ( error )
1612 goto Fail3;
1613
1614 memory = library->memory;
1615
1616 /* If the font driver is specified in the `args' structure, use */
1617 /* it. Otherwise, we scan the list of registered drivers. */
1618 if ( ( args->flags & FT_OPEN_DRIVER0x8 ) && args->driver )
1619 {
1620 driver = FT_DRIVER( args->driver )( (FT_Driver)(args->driver) );
1621
1622 /* not all modules are drivers, so check... */
1623 if ( FT_MODULE_IS_DRIVER( driver )( ( (FT_Module)(driver) )->clazz->module_flags & 1 ) )
1624 {
1625 FT_Int num_params = 0;
1626 FT_Parameter* params = NULL((void*)0);
1627
1628
1629 if ( args->flags & FT_OPEN_PARAMS0x10 )
1630 {
1631 num_params = args->num_params;
1632 params = args->params;
1633 }
1634
1635 error = open_face( driver, &stream, external_stream, face_index,
1636 num_params, params, &face );
1637 if ( !error )
1638 goto Success;
1639 }
1640 else
1641 error = FT_THROW( Invalid_Handle )FT_Err_Invalid_Handle;
1642
1643 FT_Stream_Free( stream, external_stream );
1644 goto Fail;
1645 }
1646 else
1647 {
1648 error = FT_ERR( Missing_Module )FT_Err_Missing_Module;
1649
1650 /* check each font driver for an appropriate format */
1651 cur = library->modules;
1652 limit = cur + library->num_modules;
1653
1654 for ( ; cur < limit; cur++ )
1655 {
1656 /* not all modules are font drivers, so check... */
1657 if ( FT_MODULE_IS_DRIVER( cur[0] )( ( (FT_Module)(cur[0]) )->clazz->module_flags & 1 ) )
1658 {
1659 FT_Int num_params = 0;
1660 FT_Parameter* params = NULL((void*)0);
1661
1662
1663 driver = FT_DRIVER( cur[0] )( (FT_Driver)(cur[0]) );
1664
1665 if ( args->flags & FT_OPEN_PARAMS0x10 )
1666 {
1667 num_params = args->num_params;
1668 params = args->params;
1669 }
1670
1671 error = open_face( driver, &stream, external_stream, face_index,
1672 num_params, params, &face );
1673 if ( !error )
1674 goto Success;
1675
1676 if ( FT_ERR_NEQ( error, Unknown_File_Format )( ( (error) & 0xFF ) != ( (FT_Err_Unknown_File_Format) &
0xFF ) )
)
1677 goto Fail3;
1678 }
1679 }
1680
1681 Fail3:
1682 /* If we are on the mac, and we get an */
1683 /* FT_Err_Invalid_Stream_Operation it may be because we have an */
1684 /* empty data fork, so we need to check the resource fork. */
1685 if ( FT_ERR_NEQ( error, Cannot_Open_Stream )( ( (error) & 0xFF ) != ( (FT_Err_Cannot_Open_Stream) &
0xFF ) )
&&
1686 FT_ERR_NEQ( error, Unknown_File_Format )( ( (error) & 0xFF ) != ( (FT_Err_Unknown_File_Format) &
0xFF ) )
&&
1687 FT_ERR_NEQ( error, Invalid_Stream_Operation )( ( (error) & 0xFF ) != ( (FT_Err_Invalid_Stream_Operation
) & 0xFF ) )
)
1688 goto Fail2;
1689
1690 /* no driver is able to handle this format */
1691 error = FT_THROW( Unknown_File_Format )FT_Err_Unknown_File_Format;
1692
1693 Fail2:
1694 FT_Stream_Free( stream, external_stream );
1695 goto Fail;
1696 }
1697
1698 Success:
1699 FT_TRACE4(( "FT_Open_Face: New face object, adding to list\n" ))do { } while ( 0 );
1700
1701 /* add the face object to its driver's list */
1702 if ( FT_NEW( node )( ((node) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(node)
)), &error ))), error != 0 )
)
1703 goto Fail;
1704
1705 node->data = face;
1706 /* don't assume driver is the same as face->driver, so use */
1707 /* face->driver instead. */
1708 FT_List_Add( &face->driver->faces_list, node );
1709
1710 /* now allocate a glyph slot object for the face */
1711 FT_TRACE4(( "FT_Open_Face: Creating glyph slot\n" ))do { } while ( 0 );
1712
1713 if ( face_index >= 0 )
1714 {
1715 error = FT_New_GlyphSlot( face, NULL((void*)0) );
1716 if ( error )
1717 goto Fail;
1718
1719 /* finally, allocate a size object for the face */
1720 {
1721 FT_Size size;
1722
1723
1724 FT_TRACE4(( "FT_Open_Face: Creating size object\n" ))do { } while ( 0 );
1725
1726 error = FT_New_Size( face, &size );
1727 if ( error )
1728 goto Fail;
1729
1730 face->size = size;
1731 }
1732 }
1733
1734 /* some checks */
1735
1736 if ( FT_IS_SCALABLE( face )( (face)->face_flags & ( 1L << 0 ) ) )
1737 {
1738 if ( face->height < 0 )
1739 face->height = (FT_Short)-face->height;
1740
1741 if ( !FT_HAS_VERTICAL( face )( (face)->face_flags & ( 1L << 5 ) ) )
1742 face->max_advance_height = (FT_Short)face->height;
1743 }
1744
1745 if ( FT_HAS_FIXED_SIZES( face )( (face)->face_flags & ( 1L << 1 ) ) )
1746 {
1747 FT_Int i;
1748
1749
1750 for ( i = 0; i < face->num_fixed_sizes; i++ )
1751 {
1752 FT_Bitmap_Size* bsize = face->available_sizes + i;
1753
1754
1755 if ( bsize->height < 0 )
1756 bsize->height = -bsize->height;
1757 if ( bsize->x_ppem < 0 )
1758 bsize->x_ppem = -bsize->x_ppem;
1759 if ( bsize->y_ppem < 0 )
1760 bsize->y_ppem = -bsize->y_ppem;
1761
1762 /* check whether negation actually has worked */
1763 if ( bsize->height < 0 || bsize->x_ppem < 0 || bsize->y_ppem < 0 )
1764 {
1765 FT_TRACE0(( "FT_Open_Face:"do { } while ( 0 )
1766 " Invalid bitmap dimensions for strike %d,"do { } while ( 0 )
1767 " now disabled\n", i ))do { } while ( 0 );
1768 bsize->width = 0;
1769 bsize->height = 0;
1770 bsize->size = 0;
1771 bsize->x_ppem = 0;
1772 bsize->y_ppem = 0;
1773 }
1774 }
1775 }
1776
1777 /* initialize internal face data */
1778 {
1779 FT_Face_Internal internal = face->internal;
1780
1781
1782 internal->transform_matrix.xx = 0x10000L;
1783 internal->transform_matrix.xy = 0;
1784 internal->transform_matrix.yx = 0;
1785 internal->transform_matrix.yy = 0x10000L;
1786
1787 internal->transform_delta.x = 0;
1788 internal->transform_delta.y = 0;
1789
1790 internal->refcount = 1;
1791
1792 internal->no_stem_darkening = -1;
1793 }
1794
1795 if ( aface )
1796 *aface = face;
1797 else
1798 FT_Done_Face( face );
1799
1800 goto Exit;
1801
1802 Fail:
1803 if ( node )
1804 FT_Done_Face( face ); /* face must be in the driver's list */
1805 else if ( face )
1806 destroy_face( memory, face, driver );
1807
1808 Exit:
1809#ifdef FT_DEBUG_LEVEL_TRACE
1810 if ( !error && face_index < 0 )
1811 {
1812 FT_TRACE3(( "FT_Open_Face: The font has %ld face%s\n"do { } while ( 0 )
1813 " and %ld named instance%s for face %ld\n",do { } while ( 0 )
1814 face->num_faces,do { } while ( 0 )
1815 face->num_faces == 1 ? "" : "s",do { } while ( 0 )
1816 face->style_flags >> 16,do { } while ( 0 )
1817 ( face->style_flags >> 16 ) == 1 ? "" : "s",do { } while ( 0 )
1818 -face_index - 1 ))do { } while ( 0 );
1819 }
1820#endif
1821
1822 FT_TRACE4(( "FT_Open_Face: Return 0x%x\n", error ))do { } while ( 0 );
1823
1824 return error;
1825 }
1826
1827
1828 /* documentation is in freetype.h */
1829
1830 FT_EXPORT_DEF( FT_Error )extern FT_Error
1831 FT_Done_Face( FT_Face face )
1832 {
1833 FT_Error error;
1834 FT_Driver driver;
1835 FT_Memory memory;
1836 FT_ListNode node;
1837
1838
1839 error = FT_ERR( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
1840 if ( face && face->driver )
1841 {
1842 face->internal->refcount--;
1843 if ( face->internal->refcount > 0 )
1844 error = FT_Err_Ok;
1845 else
1846 {
1847 driver = face->driver;
1848 memory = driver->root.memory;
1849
1850 /* find face in driver's list */
1851 node = FT_List_Find( &driver->faces_list, face );
1852 if ( node )
1853 {
1854 /* remove face object from the driver's list */
1855 FT_List_Remove( &driver->faces_list, node );
1856 FT_FREE( node )do { ft_mem_free( memory, (node) ); (node) = ((void*)0); } while
( 0 )
;
1857
1858 /* now destroy the object proper */
1859 destroy_face( memory, face, driver );
1860 error = FT_Err_Ok;
1861 }
1862 }
1863 }
1864
1865 return error;
1866 }
1867
1868
1869 /* documentation is in ftobjs.h */
1870
1871 FT_EXPORT_DEF( FT_Error )extern FT_Error
1872 FT_New_Size( FT_Face face,
1873 FT_Size *asize )
1874 {
1875 FT_Error error;
1876 FT_Memory memory;
1877 FT_Driver driver;
1878 FT_Driver_Class clazz;
1879
1880 FT_Size size = NULL((void*)0);
1881 FT_ListNode node = NULL((void*)0);
1882
1883 FT_Size_Internal internal = NULL((void*)0);
1884
1885
1886 if ( !face )
1887 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
1888
1889 if ( !asize )
1890 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
1891
1892 if ( !face->driver )
1893 return FT_THROW( Invalid_Driver_Handle )FT_Err_Invalid_Driver_Handle;
1894
1895 *asize = NULL((void*)0);
1896
1897 driver = face->driver;
1898 clazz = driver->clazz;
1899 memory = face->memory;
1900
1901 /* Allocate new size object and perform basic initialisation */
1902 if ( FT_ALLOC( size, clazz->size_object_size )( ((size) = (ft_mem_alloc( memory, (FT_Long)(clazz->size_object_size
), &error ))), error != 0 )
|| FT_NEW( node )( ((node) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(node)
)), &error ))), error != 0 )
)
1903 goto Exit;
1904
1905 size->face = face;
1906
1907 if ( FT_NEW( internal )( ((internal) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(internal
) )), &error ))), error != 0 )
)
1908 goto Exit;
1909
1910 size->internal = internal;
1911
1912 if ( clazz->init_size )
1913 error = clazz->init_size( size );
1914
1915 /* in case of success, add to the face's list */
1916 if ( !error )
1917 {
1918 *asize = size;
1919 node->data = size;
1920 FT_List_Add( &face->sizes_list, node );
1921 }
1922
1923 Exit:
1924 if ( error )
1925 {
1926 FT_FREE( node )do { ft_mem_free( memory, (node) ); (node) = ((void*)0); } while
( 0 )
;
1927 FT_FREE( size )do { ft_mem_free( memory, (size) ); (size) = ((void*)0); } while
( 0 )
;
1928 }
1929
1930 return error;
1931 }
1932
1933
1934 /* documentation is in ftobjs.h */
1935
1936 FT_EXPORT_DEF( FT_Error )extern FT_Error
1937 FT_Done_Size( FT_Size size )
1938 {
1939 FT_Error error;
1940 FT_Driver driver;
1941 FT_Memory memory;
1942 FT_Face face;
1943 FT_ListNode node;
1944
1945
1946 if ( !size )
1947 return FT_THROW( Invalid_Size_Handle )FT_Err_Invalid_Size_Handle;
1948
1949 face = size->face;
1950 if ( !face )
1951 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
1952
1953 driver = face->driver;
1954 if ( !driver )
1955 return FT_THROW( Invalid_Driver_Handle )FT_Err_Invalid_Driver_Handle;
1956
1957 memory = driver->root.memory;
1958
1959 error = FT_Err_Ok;
1960 node = FT_List_Find( &face->sizes_list, size );
1961 if ( node )
1962 {
1963 FT_List_Remove( &face->sizes_list, node );
1964 FT_FREE( node )do { ft_mem_free( memory, (node) ); (node) = ((void*)0); } while
( 0 )
;
1965
1966 if ( face->size == size )
1967 {
1968 face->size = NULL((void*)0);
1969 if ( face->sizes_list.head )
1970 face->size = (FT_Size)(face->sizes_list.head->data);
1971 }
1972
1973 destroy_size( memory, size, driver );
1974 }
1975 else
1976 error = FT_THROW( Invalid_Size_Handle )FT_Err_Invalid_Size_Handle;
1977
1978 return error;
1979 }
1980
1981
1982 /* documentation is in ftobjs.h */
1983
1984 FT_BASE_DEF( FT_Error )FT_Error
1985 FT_Match_Size( FT_Face face,
1986 FT_Size_Request req,
1987 FT_Bool ignore_width,
1988 FT_ULong* size_index )
1989 {
1990 FT_Int i;
1991 FT_Long w, h;
1992
1993
1994 if ( !FT_HAS_FIXED_SIZES( face )( (face)->face_flags & ( 1L << 1 ) ) )
1995 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
1996
1997 /* FT_Bitmap_Size doesn't provide enough info... */
1998 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
1999 return FT_THROW( Unimplemented_Feature )FT_Err_Unimplemented_Feature;
2000
2001 w = FT_REQUEST_WIDTH ( req )( (req)->horiResolution ? ( (req)->width * (FT_Pos)(req
)->horiResolution + 36 ) / 72 : (req)->width )
;
2002 h = FT_REQUEST_HEIGHT( req )( (req)->vertResolution ? ( (req)->height * (FT_Pos)(req
)->vertResolution + 36 ) / 72 : (req)->height )
;
2003
2004 if ( req->width && !req->height )
2005 h = w;
2006 else if ( !req->width && req->height )
2007 w = h;
2008
2009 w = FT_PIX_ROUND( w )( ((w) + 32) & ~( __typeof__ ( (w) + 32 ) )63 );
2010 h = FT_PIX_ROUND( h )( ((h) + 32) & ~( __typeof__ ( (h) + 32 ) )63 );
2011
2012 if ( !w || !h )
2013 return FT_THROW( Invalid_Pixel_Size )FT_Err_Invalid_Pixel_Size;
2014
2015 for ( i = 0; i < face->num_fixed_sizes; i++ )
2016 {
2017 FT_Bitmap_Size* bsize = face->available_sizes + i;
2018
2019
2020 if ( h != FT_PIX_ROUND( bsize->y_ppem )( ((bsize->y_ppem) + 32) & ~( __typeof__ ( (bsize->
y_ppem) + 32 ) )63 )
)
2021 continue;
2022
2023 if ( w == FT_PIX_ROUND( bsize->x_ppem )( ((bsize->x_ppem) + 32) & ~( __typeof__ ( (bsize->
x_ppem) + 32 ) )63 )
|| ignore_width )
2024 {
2025 FT_TRACE3(( "FT_Match_Size: bitmap strike %d matches\n", i ))do { } while ( 0 );
2026
2027 if ( size_index )
2028 *size_index = (FT_ULong)i;
2029
2030 return FT_Err_Ok;
2031 }
2032 }
2033
2034 FT_TRACE3(( "FT_Match_Size: no matching bitmap strike\n" ))do { } while ( 0 );
2035
2036 return FT_THROW( Invalid_Pixel_Size )FT_Err_Invalid_Pixel_Size;
2037 }
2038
2039
2040 /* documentation is in ftobjs.h */
2041
2042 FT_BASE_DEF( void )void
2043 ft_synthesize_vertical_metrics( FT_Glyph_Metrics* metrics,
2044 FT_Pos advance )
2045 {
2046 FT_Pos height = metrics->height;
2047
2048
2049 /* compensate for glyph with bbox above/below the baseline */
2050 if ( metrics->horiBearingY < 0 )
2051 {
2052 if ( height < metrics->horiBearingY )
2053 height = metrics->horiBearingY;
2054 }
2055 else if ( metrics->horiBearingY > 0 )
2056 height -= metrics->horiBearingY;
2057
2058 /* the factor 1.2 is a heuristical value */
2059 if ( !advance )
2060 advance = height * 12 / 10;
2061
2062 metrics->vertBearingX = metrics->horiBearingX - metrics->horiAdvance / 2;
2063 metrics->vertBearingY = ( advance - height ) / 2;
2064 metrics->vertAdvance = advance;
2065 }
2066
2067
2068 static void
2069 ft_recompute_scaled_metrics( FT_Face face,
2070 FT_Size_Metrics* metrics )
2071 {
2072 /* Compute root ascender, descender, test height, and max_advance */
2073
2074#ifdef GRID_FIT_METRICS
2075 metrics->ascender = FT_PIX_CEIL( FT_MulFix( face->ascender,( ((FT_MulFix( face->ascender, metrics->y_scale )) + 63
) & ~( __typeof__ ( (FT_MulFix( face->ascender, metrics
->y_scale )) + 63 ) )63 )
2076 metrics->y_scale ) )( ((FT_MulFix( face->ascender, metrics->y_scale )) + 63
) & ~( __typeof__ ( (FT_MulFix( face->ascender, metrics
->y_scale )) + 63 ) )63 )
;
2077
2078 metrics->descender = FT_PIX_FLOOR( FT_MulFix( face->descender,( (FT_MulFix( face->descender, metrics->y_scale )) &
~( __typeof__ ( FT_MulFix( face->descender, metrics->y_scale
) ) )63 )
2079 metrics->y_scale ) )( (FT_MulFix( face->descender, metrics->y_scale )) &
~( __typeof__ ( FT_MulFix( face->descender, metrics->y_scale
) ) )63 )
;
2080
2081 metrics->height = FT_PIX_ROUND( FT_MulFix( face->height,( ((FT_MulFix( face->height, metrics->y_scale )) + 32) &
~( __typeof__ ( (FT_MulFix( face->height, metrics->y_scale
)) + 32 ) )63 )
2082 metrics->y_scale ) )( ((FT_MulFix( face->height, metrics->y_scale )) + 32) &
~( __typeof__ ( (FT_MulFix( face->height, metrics->y_scale
)) + 32 ) )63 )
;
2083
2084 metrics->max_advance = FT_PIX_ROUND( FT_MulFix( face->max_advance_width,( ((FT_MulFix( face->max_advance_width, metrics->x_scale
)) + 32) & ~( __typeof__ ( (FT_MulFix( face->max_advance_width
, metrics->x_scale )) + 32 ) )63 )
2085 metrics->x_scale ) )( ((FT_MulFix( face->max_advance_width, metrics->x_scale
)) + 32) & ~( __typeof__ ( (FT_MulFix( face->max_advance_width
, metrics->x_scale )) + 32 ) )63 )
;
2086#else /* !GRID_FIT_METRICS */
2087 metrics->ascender = FT_MulFix( face->ascender,
2088 metrics->y_scale );
2089
2090 metrics->descender = FT_MulFix( face->descender,
2091 metrics->y_scale );
2092
2093 metrics->height = FT_MulFix( face->height,
2094 metrics->y_scale );
2095
2096 metrics->max_advance = FT_MulFix( face->max_advance_width,
2097 metrics->x_scale );
2098#endif /* !GRID_FIT_METRICS */
2099 }
2100
2101
2102 FT_BASE_DEF( void )void
2103 FT_Select_Metrics( FT_Face face,
2104 FT_ULong strike_index )
2105 {
2106 FT_Size_Metrics* metrics;
2107 FT_Bitmap_Size* bsize;
2108
2109
2110 metrics = &face->size->metrics;
2111 bsize = face->available_sizes + strike_index;
2112
2113 metrics->x_ppem = (FT_UShort)( ( bsize->x_ppem + 32 ) >> 6 );
2114 metrics->y_ppem = (FT_UShort)( ( bsize->y_ppem + 32 ) >> 6 );
2115
2116 if ( FT_IS_SCALABLE( face )( (face)->face_flags & ( 1L << 0 ) ) )
2117 {
2118 metrics->x_scale = FT_DivFix( bsize->x_ppem,
2119 face->units_per_EM );
2120 metrics->y_scale = FT_DivFix( bsize->y_ppem,
2121 face->units_per_EM );
2122
2123 ft_recompute_scaled_metrics( face, metrics );
2124 }
2125 else
2126 {
2127 metrics->x_scale = 1L << 16;
2128 metrics->y_scale = 1L << 16;
2129 metrics->ascender = bsize->y_ppem;
2130 metrics->descender = 0;
2131 metrics->height = bsize->height << 6;
2132 metrics->max_advance = bsize->x_ppem;
2133 }
2134 }
2135
2136
2137 FT_BASE_DEF( void )void
2138 FT_Request_Metrics( FT_Face face,
2139 FT_Size_Request req )
2140 {
2141 FT_Size_Metrics* metrics;
2142
2143
2144 metrics = &face->size->metrics;
2145
2146 if ( FT_IS_SCALABLE( face )( (face)->face_flags & ( 1L << 0 ) ) )
2147 {
2148 FT_Long w = 0, h = 0, scaled_w = 0, scaled_h = 0;
2149
2150
2151 switch ( req->type )
2152 {
2153 case FT_SIZE_REQUEST_TYPE_NOMINAL:
2154 w = h = face->units_per_EM;
2155 break;
2156
2157 case FT_SIZE_REQUEST_TYPE_REAL_DIM:
2158 w = h = face->ascender - face->descender;
2159 break;
2160
2161 case FT_SIZE_REQUEST_TYPE_BBOX:
2162 w = face->bbox.xMax - face->bbox.xMin;
2163 h = face->bbox.yMax - face->bbox.yMin;
2164 break;
2165
2166 case FT_SIZE_REQUEST_TYPE_CELL:
2167 w = face->max_advance_width;
2168 h = face->ascender - face->descender;
2169 break;
2170
2171 case FT_SIZE_REQUEST_TYPE_SCALES:
2172 metrics->x_scale = (FT_Fixed)req->width;
2173 metrics->y_scale = (FT_Fixed)req->height;
2174 if ( !metrics->x_scale )
2175 metrics->x_scale = metrics->y_scale;
2176 else if ( !metrics->y_scale )
2177 metrics->y_scale = metrics->x_scale;
2178 goto Calculate_Ppem;
2179
2180 case FT_SIZE_REQUEST_TYPE_MAX:
2181 break;
2182 }
2183
2184 /* to be on the safe side */
2185 if ( w < 0 )
2186 w = -w;
2187
2188 if ( h < 0 )
2189 h = -h;
2190
2191 scaled_w = FT_REQUEST_WIDTH ( req )( (req)->horiResolution ? ( (req)->width * (FT_Pos)(req
)->horiResolution + 36 ) / 72 : (req)->width )
;
2192 scaled_h = FT_REQUEST_HEIGHT( req )( (req)->vertResolution ? ( (req)->height * (FT_Pos)(req
)->vertResolution + 36 ) / 72 : (req)->height )
;
2193
2194 /* determine scales */
2195 if ( req->width )
2196 {
2197 metrics->x_scale = FT_DivFix( scaled_w, w );
2198
2199 if ( req->height )
2200 {
2201 metrics->y_scale = FT_DivFix( scaled_h, h );
2202
2203 if ( req->type == FT_SIZE_REQUEST_TYPE_CELL )
2204 {
2205 if ( metrics->y_scale > metrics->x_scale )
2206 metrics->y_scale = metrics->x_scale;
2207 else
2208 metrics->x_scale = metrics->y_scale;
2209 }
2210 }
2211 else
2212 {
2213 metrics->y_scale = metrics->x_scale;
2214 scaled_h = FT_MulDiv( scaled_w, h, w );
2215 }
2216 }
2217 else
2218 {
2219 metrics->x_scale = metrics->y_scale = FT_DivFix( scaled_h, h );
2220 scaled_w = FT_MulDiv( scaled_h, w, h );
2221 }
2222
2223 Calculate_Ppem:
2224 /* calculate the ppems */
2225 if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
2226 {
2227 scaled_w = FT_MulFix( face->units_per_EM, metrics->x_scale );
2228 scaled_h = FT_MulFix( face->units_per_EM, metrics->y_scale );
2229 }
2230
2231 metrics->x_ppem = (FT_UShort)( ( scaled_w + 32 ) >> 6 );
2232 metrics->y_ppem = (FT_UShort)( ( scaled_h + 32 ) >> 6 );
2233
2234 ft_recompute_scaled_metrics( face, metrics );
2235 }
2236 else
2237 {
2238 FT_ZERO( metrics )memset( metrics, 0, (FT_Offset)(sizeof ( *(metrics) )) );
2239 metrics->x_scale = 1L << 16;
2240 metrics->y_scale = 1L << 16;
2241 }
2242 }
2243
2244
2245 /* documentation is in freetype.h */
2246
2247 FT_EXPORT_DEF( FT_Error )extern FT_Error
2248 FT_Select_Size( FT_Face face,
2249 FT_Int strike_index )
2250 {
2251 FT_Error error = FT_Err_Ok;
2252 FT_Driver_Class clazz;
2253
2254
2255 if ( !face || !FT_HAS_FIXED_SIZES( face )( (face)->face_flags & ( 1L << 1 ) ) )
2256 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
2257
2258 if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
2259 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2260
2261 clazz = face->driver->clazz;
2262
2263 if ( clazz->select_size )
2264 {
2265 error = clazz->select_size( face->size, (FT_ULong)strike_index );
2266
2267 FT_TRACE5(( "FT_Select_Size (%s driver):\n",do { } while ( 0 )
2268 face->driver->root.clazz->module_name ))do { } while ( 0 );
2269 }
2270 else
2271 {
2272 FT_Select_Metrics( face, (FT_ULong)strike_index );
2273
2274 FT_TRACE5(( "FT_Select_Size:\n" ))do { } while ( 0 );
2275 }
2276
2277#ifdef FT_DEBUG_LEVEL_TRACE
2278 {
2279 FT_Size_Metrics* metrics = &face->size->metrics;
2280
2281
2282 FT_TRACE5(( " x scale: %d (%f)\n",do { } while ( 0 )
2283 metrics->x_scale, metrics->x_scale / 65536.0 ))do { } while ( 0 );
2284 FT_TRACE5(( " y scale: %d (%f)\n",do { } while ( 0 )
2285 metrics->y_scale, metrics->y_scale / 65536.0 ))do { } while ( 0 );
2286 FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ))do { } while ( 0 );
2287 FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ))do { } while ( 0 );
2288 FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ))do { } while ( 0 );
2289 FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ))do { } while ( 0 );
2290 FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ))do { } while ( 0 );
2291 FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ))do { } while ( 0 );
2292 }
2293#endif
2294
2295 return error;
2296 }
2297
2298
2299 /* documentation is in freetype.h */
2300
2301 FT_EXPORT_DEF( FT_Error )extern FT_Error
2302 FT_Request_Size( FT_Face face,
2303 FT_Size_Request req )
2304 {
2305 FT_Error error = FT_Err_Ok;
2306 FT_Driver_Class clazz;
2307 FT_ULong strike_index;
2308
2309
2310 if ( !face )
2311 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
2312
2313 if ( !req || req->width < 0 || req->height < 0 ||
2314 req->type >= FT_SIZE_REQUEST_TYPE_MAX )
2315 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2316
2317 /* signal the auto-hinter to recompute its size metrics */
2318 /* (if requested) */
2319 face->size->internal->autohint_metrics.x_scale = 0;
2320
2321 clazz = face->driver->clazz;
2322
2323 if ( clazz->request_size )
2324 {
2325 error = clazz->request_size( face->size, req );
2326
2327 FT_TRACE5(( "FT_Request_Size (%s driver):\n",do { } while ( 0 )
2328 face->driver->root.clazz->module_name ))do { } while ( 0 );
2329 }
2330 else if ( !FT_IS_SCALABLE( face )( (face)->face_flags & ( 1L << 0 ) ) && FT_HAS_FIXED_SIZES( face )( (face)->face_flags & ( 1L << 1 ) ) )
2331 {
2332 /*
2333 * The reason that a driver doesn't have `request_size' defined is
2334 * either that the scaling here suffices or that the supported formats
2335 * are bitmap-only and size matching is not implemented.
2336 *
2337 * In the latter case, a simple size matching is done.
2338 */
2339 error = FT_Match_Size( face, req, 0, &strike_index );
2340 if ( error )
2341 return error;
2342
2343 return FT_Select_Size( face, (FT_Int)strike_index );
2344 }
2345 else
2346 {
2347 FT_Request_Metrics( face, req );
2348
2349 FT_TRACE5(( "FT_Request_Size:\n" ))do { } while ( 0 );
2350 }
2351
2352#ifdef FT_DEBUG_LEVEL_TRACE
2353 {
2354 FT_Size_Metrics* metrics = &face->size->metrics;
2355
2356
2357 FT_TRACE5(( " x scale: %d (%f)\n",do { } while ( 0 )
2358 metrics->x_scale, metrics->x_scale / 65536.0 ))do { } while ( 0 );
2359 FT_TRACE5(( " y scale: %d (%f)\n",do { } while ( 0 )
2360 metrics->y_scale, metrics->y_scale / 65536.0 ))do { } while ( 0 );
2361 FT_TRACE5(( " ascender: %f\n", metrics->ascender / 64.0 ))do { } while ( 0 );
2362 FT_TRACE5(( " descender: %f\n", metrics->descender / 64.0 ))do { } while ( 0 );
2363 FT_TRACE5(( " height: %f\n", metrics->height / 64.0 ))do { } while ( 0 );
2364 FT_TRACE5(( " max advance: %f\n", metrics->max_advance / 64.0 ))do { } while ( 0 );
2365 FT_TRACE5(( " x ppem: %d\n", metrics->x_ppem ))do { } while ( 0 );
2366 FT_TRACE5(( " y ppem: %d\n", metrics->y_ppem ))do { } while ( 0 );
2367 }
2368#endif
2369
2370 return error;
2371 }
2372
2373
2374 /* documentation is in freetype.h */
2375
2376 FT_EXPORT_DEF( FT_Error )extern FT_Error
2377 FT_Set_Char_Size( FT_Face face,
2378 FT_F26Dot6 char_width,
2379 FT_F26Dot6 char_height,
2380 FT_UInt horz_resolution,
2381 FT_UInt vert_resolution )
2382 {
2383 FT_Size_RequestRec req;
2384
2385
2386 /* check of `face' delayed to `FT_Request_Size' */
2387
2388 if ( !char_width )
2389 char_width = char_height;
2390 else if ( !char_height )
2391 char_height = char_width;
2392
2393 if ( !horz_resolution )
2394 horz_resolution = vert_resolution;
2395 else if ( !vert_resolution )
2396 vert_resolution = horz_resolution;
2397
2398 if ( char_width < 1 * 64 )
2399 char_width = 1 * 64;
2400 if ( char_height < 1 * 64 )
2401 char_height = 1 * 64;
2402
2403 if ( !horz_resolution )
2404 horz_resolution = vert_resolution = 72;
2405
2406 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2407 req.width = char_width;
2408 req.height = char_height;
2409 req.horiResolution = horz_resolution;
2410 req.vertResolution = vert_resolution;
2411
2412 return FT_Request_Size( face, &req );
2413 }
2414
2415
2416 /* documentation is in freetype.h */
2417
2418 FT_EXPORT_DEF( FT_Error )extern FT_Error
2419 FT_Set_Pixel_Sizes( FT_Face face,
2420 FT_UInt pixel_width,
2421 FT_UInt pixel_height )
2422 {
2423 FT_Size_RequestRec req;
2424
2425
2426 /* check of `face' delayed to `FT_Request_Size' */
2427
2428 if ( pixel_width == 0 )
2429 pixel_width = pixel_height;
2430 else if ( pixel_height == 0 )
2431 pixel_height = pixel_width;
2432
2433 if ( pixel_width < 1 )
2434 pixel_width = 1;
2435 if ( pixel_height < 1 )
2436 pixel_height = 1;
2437
2438 /* use `>=' to avoid potential compiler warning on 16bit platforms */
2439 if ( pixel_width >= 0xFFFFU )
2440 pixel_width = 0xFFFFU;
2441 if ( pixel_height >= 0xFFFFU )
2442 pixel_height = 0xFFFFU;
2443
2444 req.type = FT_SIZE_REQUEST_TYPE_NOMINAL;
2445 req.width = (FT_Long)( pixel_width << 6 );
2446 req.height = (FT_Long)( pixel_height << 6 );
2447 req.horiResolution = 0;
2448 req.vertResolution = 0;
2449
2450 return FT_Request_Size( face, &req );
2451 }
2452
2453
2454 /* documentation is in freetype.h */
2455
2456 FT_EXPORT_DEF( FT_Error )extern FT_Error
2457 FT_Select_Charmap( FT_Face face,
2458 FT_Encoding encoding )
2459 {
2460 FT_CharMap* cur;
2461 FT_CharMap* limit;
2462
2463
2464 if ( !face )
2465 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
2466
2467 if ( encoding == FT_ENCODING_NONE )
2468 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2469
2470 /* FT_ENCODING_UNICODE is special. We try to find the `best' Unicode */
2471 /* charmap available, i.e., one with UCS-4 characters, if possible. */
2472 /* */
2473 /* This is done by find_unicode_charmap() above, to share code. */
2474 if ( encoding == FT_ENCODING_UNICODE )
2475 return find_unicode_charmap( face );
2476
2477 cur = face->charmaps;
2478 if ( !cur )
2479 return FT_THROW( Invalid_CharMap_Handle )FT_Err_Invalid_CharMap_Handle;
2480
2481 limit = cur + face->num_charmaps;
2482
2483 for ( ; cur < limit; cur++ )
2484 {
2485 if ( cur[0]->encoding == encoding )
2486 {
2487 face->charmap = cur[0];
2488 return 0;
2489 }
2490 }
2491
2492 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2493 }
2494
2495
2496 /* documentation is in freetype.h */
2497
2498 FT_EXPORT_DEF( FT_Error )extern FT_Error
2499 FT_Set_Charmap( FT_Face face,
2500 FT_CharMap charmap )
2501 {
2502 FT_CharMap* cur;
2503 FT_CharMap* limit;
2504
2505
2506 if ( !face )
2507 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
2508
2509 cur = face->charmaps;
2510 if ( !cur || !charmap )
2511 return FT_THROW( Invalid_CharMap_Handle )FT_Err_Invalid_CharMap_Handle;
2512
2513 if ( FT_Get_CMap_Format( charmap ) == 14 )
2514 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2515
2516 limit = cur + face->num_charmaps;
2517
2518 for ( ; cur < limit; cur++ )
2519 {
2520 if ( cur[0] == charmap )
2521 {
2522 face->charmap = cur[0];
2523 return FT_Err_Ok;
2524 }
2525 }
2526
2527 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2528 }
2529
2530
2531 static void
2532 ft_cmap_done_internal( FT_CMap cmap )
2533 {
2534 FT_CMap_Class clazz = cmap->clazz;
2535 FT_Face face = cmap->charmap.face;
2536 FT_Memory memory = FT_FACE_MEMORY( face )( (FT_Face)(face) )->memory;
2537
2538
2539 if ( clazz->done )
2540 clazz->done( cmap );
2541
2542 FT_FREE( cmap )do { ft_mem_free( memory, (cmap) ); (cmap) = ((void*)0); } while
( 0 )
;
2543 }
2544
2545
2546 FT_BASE_DEF( void )void
2547 FT_CMap_Done( FT_CMap cmap )
2548 {
2549 if ( cmap )
2550 {
2551 FT_Face face = cmap->charmap.face;
2552 FT_Memory memory = FT_FACE_MEMORY( face )( (FT_Face)(face) )->memory;
2553 FT_Error error;
2554 FT_Int i, j;
2555
2556
2557 for ( i = 0; i < face->num_charmaps; i++ )
2558 {
2559 if ( (FT_CMap)face->charmaps[i] == cmap )
2560 {
2561 FT_CharMap last_charmap = face->charmaps[face->num_charmaps - 1];
2562
2563
2564 if ( FT_RENEW_ARRAY( face->charmaps,( ((face->charmaps) = (ft_mem_realloc( memory, sizeof ( *(
face->charmaps) ), (FT_Long)(face->num_charmaps), (FT_Long
)(face->num_charmaps - 1), (face->charmaps), &error
))), error != 0 )
2565 face->num_charmaps,( ((face->charmaps) = (ft_mem_realloc( memory, sizeof ( *(
face->charmaps) ), (FT_Long)(face->num_charmaps), (FT_Long
)(face->num_charmaps - 1), (face->charmaps), &error
))), error != 0 )
2566 face->num_charmaps - 1 )( ((face->charmaps) = (ft_mem_realloc( memory, sizeof ( *(
face->charmaps) ), (FT_Long)(face->num_charmaps), (FT_Long
)(face->num_charmaps - 1), (face->charmaps), &error
))), error != 0 )
)
2567 return;
2568
2569 /* remove it from our list of charmaps */
2570 for ( j = i + 1; j < face->num_charmaps; j++ )
2571 {
2572 if ( j == face->num_charmaps - 1 )
2573 face->charmaps[j - 1] = last_charmap;
2574 else
2575 face->charmaps[j - 1] = face->charmaps[j];
2576 }
2577
2578 face->num_charmaps--;
2579
2580 if ( (FT_CMap)face->charmap == cmap )
2581 face->charmap = NULL((void*)0);
2582
2583 ft_cmap_done_internal( cmap );
2584
2585 break;
2586 }
2587 }
2588 }
2589 }
2590
2591
2592 FT_BASE_DEF( FT_Error )FT_Error
2593 FT_CMap_New( FT_CMap_Class clazz,
2594 FT_Pointer init_data,
2595 FT_CharMap charmap,
2596 FT_CMap *acmap )
2597 {
2598 FT_Error error = FT_Err_Ok;
2599 FT_Face face;
2600 FT_Memory memory;
2601 FT_CMap cmap = NULL((void*)0);
2602
2603
2604 if ( !clazz || !charmap || !charmap->face )
2605 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2606
2607 face = charmap->face;
2608 memory = FT_FACE_MEMORY( face )( (FT_Face)(face) )->memory;
2609
2610 if ( !FT_ALLOC( cmap, clazz->size )( ((cmap) = (ft_mem_alloc( memory, (FT_Long)(clazz->size),
&error ))), error != 0 )
)
2611 {
2612 cmap->charmap = *charmap;
2613 cmap->clazz = clazz;
2614
2615 if ( clazz->init )
2616 {
2617 error = clazz->init( cmap, init_data );
2618 if ( error )
2619 goto Fail;
2620 }
2621
2622 /* add it to our list of charmaps */
2623 if ( FT_RENEW_ARRAY( face->charmaps,( ((face->charmaps) = (ft_mem_realloc( memory, sizeof ( *(
face->charmaps) ), (FT_Long)(face->num_charmaps), (FT_Long
)(face->num_charmaps + 1), (face->charmaps), &error
))), error != 0 )
2624 face->num_charmaps,( ((face->charmaps) = (ft_mem_realloc( memory, sizeof ( *(
face->charmaps) ), (FT_Long)(face->num_charmaps), (FT_Long
)(face->num_charmaps + 1), (face->charmaps), &error
))), error != 0 )
2625 face->num_charmaps + 1 )( ((face->charmaps) = (ft_mem_realloc( memory, sizeof ( *(
face->charmaps) ), (FT_Long)(face->num_charmaps), (FT_Long
)(face->num_charmaps + 1), (face->charmaps), &error
))), error != 0 )
)
2626 goto Fail;
2627
2628 face->charmaps[face->num_charmaps++] = (FT_CharMap)cmap;
2629 }
2630
2631 Exit:
2632 if ( acmap )
2633 *acmap = cmap;
2634
2635 return error;
2636
2637 Fail:
2638 ft_cmap_done_internal( cmap );
2639 cmap = NULL((void*)0);
2640 goto Exit;
2641 }
2642
2643
2644 /* documentation is in freetype.h */
2645
2646 FT_EXPORT_DEF( FT_UInt )extern FT_UInt
2647 FT_Get_Char_Index( FT_Face face,
2648 FT_ULong charcode )
2649 {
2650 FT_UInt result = 0;
2651
2652
2653 if ( face && face->charmap )
2654 {
2655 FT_CMap cmap = FT_CMAP( face->charmap )( (FT_CMap)( face->charmap ) );
2656
2657
2658 if ( charcode > 0xFFFFFFFFUL )
2659 {
2660 FT_TRACE1(( "FT_Get_Char_Index: too large charcode" ))do { } while ( 0 );
2661 FT_TRACE1(( " 0x%x is truncated\n", charcode ))do { } while ( 0 );
2662 }
2663
2664 result = cmap->clazz->char_index( cmap, (FT_UInt32)charcode );
2665 if ( result >= (FT_UInt)face->num_glyphs )
2666 result = 0;
2667 }
2668
2669 return result;
2670 }
2671
2672
2673 /* documentation is in freetype.h */
2674
2675 FT_EXPORT_DEF( FT_ULong )extern FT_ULong
2676 FT_Get_Next_Char( FT_Face face,
2677 FT_ULong charcode,
2678 FT_UInt *agindex )
2679 {
2680 FT_ULong result = 0;
2681 FT_UInt gindex = 0;
2682
2683
2684 if ( face && face->charmap && face->num_glyphs )
2685 {
2686 FT_UInt32 code = (FT_UInt32)charcode;
2687 FT_CMap cmap = FT_CMAP( face->charmap )( (FT_CMap)( face->charmap ) );
2688
2689
2690 do
2691 {
2692 gindex = cmap->clazz->char_next( cmap, &code );
2693
2694 } while ( gindex >= (FT_UInt)face->num_glyphs );
2695
2696 result = ( gindex == 0 ) ? 0 : code;
2697 }
2698
2699 if ( agindex )
2700 *agindex = gindex;
2701
2702 return result;
2703 }
2704
2705
2706 /* documentation is in freetype.h */
2707
2708 FT_EXPORT_DEF( FT_Error )extern FT_Error
2709 FT_Face_Properties( FT_Face face,
2710 FT_UInt num_properties,
2711 FT_Parameter* properties )
2712 {
2713 FT_Error error = FT_Err_Ok;
2714
2715
2716 if ( num_properties > 0 && !properties )
2717 {
2718 error = FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2719 goto Exit;
2720 }
2721
2722 for ( ; num_properties > 0; num_properties-- )
2723 {
2724 if ( properties->tag == FT_PARAM_TAG_STEM_DARKENING(FT_Tag) ( ( (FT_ULong)'d' << 24 ) | ( (FT_ULong)'a' <<
16 ) | ( (FT_ULong)'r' << 8 ) | (FT_ULong)'k' )
)
2725 {
2726 if ( properties->data )
2727 {
2728 if ( *( (FT_Bool*)properties->data ) == TRUE1 )
2729 face->internal->no_stem_darkening = FALSE0;
2730 else
2731 face->internal->no_stem_darkening = TRUE1;
2732 }
2733 else
2734 {
2735 /* use module default */
2736 face->internal->no_stem_darkening = -1;
2737 }
2738 }
2739 else
2740 {
2741 error = FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2742 goto Exit;
2743 }
2744
2745 if ( error )
2746 break;
2747
2748 properties++;
2749 }
2750
2751 Exit:
2752 return error;
2753 }
2754
2755
2756 /* documentation is in freetype.h */
2757
2758 FT_EXPORT_DEF( FT_Error )extern FT_Error
2759 FT_Get_Glyph_Name( FT_Face face,
2760 FT_UInt glyph_index,
2761 FT_Pointer buffer,
2762 FT_UInt buffer_max )
2763 {
2764 FT_Error error;
2765 FT_Service_GlyphDict service;
2766
2767
2768 if ( !face )
2769 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
2770
2771 if ( !buffer || buffer_max == 0 )
2772 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2773
2774 /* clean up buffer */
2775 ((FT_Byte*)buffer)[0] = '\0';
2776
2777 if ( (FT_Long)glyph_index >= face->num_glyphs )
2778 return FT_THROW( Invalid_Glyph_Index )FT_Err_Invalid_Glyph_Index;
2779
2780 if ( !FT_HAS_GLYPH_NAMES( face )( (face)->face_flags & ( 1L << 9 ) ) )
2781 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2782
2783 FT_FACE_LOOKUP_SERVICE( face, service, GLYPH_DICT )do { FT_Pointer svc; svc = ( (FT_Face)(face) )->internal->
services. service_GLYPH_DICT; if ( svc == ((FT_Pointer)~(FT_PtrDist
)1) ) svc = ((void*)0); else if ( svc == ((void*)0) ) { do { FT_Module
module = ( (FT_Module)(( (FT_Face)(face) )->driver) ); FT_Pointer
_tmp_ = ((void*)0); if ( module->clazz->get_interface )
_tmp_ = module->clazz->get_interface( module, "glyph-dict"
); svc = _tmp_; } while ( 0 ); ( (FT_Face)(face) )->internal
->services. service_GLYPH_DICT = (FT_Pointer)( svc != ((void
*)0) ? svc : ((FT_Pointer)~(FT_PtrDist)1) ); } service = svc;
} while ( 0 )
;
2784 if ( service && service->get_name )
2785 error = service->get_name( face, glyph_index, buffer, buffer_max );
2786 else
2787 error = FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
2788
2789 return error;
2790 }
2791
2792
2793 /* documentation is in tttables.h */
2794
2795 FT_EXPORT_DEF( FT_Long )extern FT_Long
2796 FT_Get_CMap_Format( FT_CharMap charmap )
2797 {
2798 FT_Service_TTCMaps service;
2799 FT_Face face;
2800 TT_CMapInfo cmap_info;
2801
2802
2803 if ( !charmap || !charmap->face )
2804 return -1;
2805
2806 face = charmap->face;
2807 FT_FACE_FIND_SERVICE( face, service, TT_CMAP )do { FT_Module module = ( (FT_Module)(( (FT_Face)(face) )->
driver) ); FT_Pointer _tmp_ = ((void*)0); if ( module->clazz
->get_interface ) _tmp_ = module->clazz->get_interface
( module, "tt-cmaps" ); service = _tmp_; } while ( 0 )
;
2808 if ( !service )
2809 return -1;
2810 if ( service->get_cmap_info( charmap, &cmap_info ))
2811 return -1;
2812
2813 return cmap_info.format;
2814 }
2815
2816
2817 /* documentation is in ftsizes.h */
2818
2819 FT_EXPORT_DEF( FT_Error )extern FT_Error
2820 FT_Activate_Size( FT_Size size )
2821 {
2822 FT_Face face;
2823
2824
2825 if ( !size )
2826 return FT_THROW( Invalid_Size_Handle )FT_Err_Invalid_Size_Handle;
2827
2828 face = size->face;
2829 if ( !face || !face->driver )
2830 return FT_THROW( Invalid_Face_Handle )FT_Err_Invalid_Face_Handle;
2831
2832 /* we don't need anything more complex than that; all size objects */
2833 /* are already listed by the face */
2834 face->size = size;
2835
2836 return FT_Err_Ok;
2837 }
2838
2839
2840 /*************************************************************************/
2841 /*************************************************************************/
2842 /*************************************************************************/
2843 /**** ****/
2844 /**** ****/
2845 /**** R E N D E R E R S ****/
2846 /**** ****/
2847 /**** ****/
2848 /*************************************************************************/
2849 /*************************************************************************/
2850 /*************************************************************************/
2851
2852 /* lookup a renderer by glyph format in the library's list */
2853 FT_BASE_DEF( FT_Renderer )FT_Renderer
2854 FT_Lookup_Renderer( FT_Library library,
2855 FT_Glyph_Format format,
2856 FT_ListNode* node )
2857 {
2858 FT_ListNode cur;
2859 FT_Renderer result = NULL((void*)0);
2860
2861
2862 if ( !library )
2863 goto Exit;
2864
2865 cur = library->renderers.head;
2866
2867 if ( node )
2868 {
2869 if ( *node )
2870 cur = (*node)->next;
2871 *node = NULL((void*)0);
2872 }
2873
2874 while ( cur )
2875 {
2876 FT_Renderer renderer = FT_RENDERER( cur->data )( (FT_Renderer)(cur->data) );
2877
2878
2879 if ( renderer->glyph_format == format )
2880 {
2881 if ( node )
2882 *node = cur;
2883
2884 result = renderer;
2885 break;
2886 }
2887 cur = cur->next;
2888 }
2889
2890 Exit:
2891 return result;
2892 }
2893
2894
2895 static FT_Renderer
2896 ft_lookup_glyph_renderer( FT_GlyphSlot slot )
2897 {
2898 FT_Face face = slot->face;
2899 FT_Library library = FT_FACE_LIBRARY( face )( (FT_Face)(face) )->driver->root.library;
2900 FT_Renderer result = library->cur_renderer;
2901
2902
2903 if ( !result || result->glyph_format != slot->format )
2904 result = FT_Lookup_Renderer( library, slot->format, 0 );
2905
2906 return result;
2907 }
2908
2909
2910 static void
2911 ft_set_current_renderer( FT_Library library )
2912 {
2913 FT_Renderer renderer;
2914
2915
2916 renderer = FT_Lookup_Renderer( library, FT_GLYPH_FORMAT_OUTLINE, 0 );
2917 library->cur_renderer = renderer;
2918 }
2919
2920
2921 static FT_Error
2922 ft_add_renderer( FT_Module module )
2923 {
2924 FT_Library library = module->library;
2925 FT_Memory memory = library->memory;
2926 FT_Error error;
2927 FT_ListNode node = NULL((void*)0);
2928
2929
2930 if ( FT_NEW( node )( ((node) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(node)
)), &error ))), error != 0 )
)
2931 goto Exit;
2932
2933 {
2934 FT_Renderer render = FT_RENDERER( module )( (FT_Renderer)(module) );
2935 FT_Renderer_Class* clazz = (FT_Renderer_Class*)module->clazz;
2936
2937
2938 render->clazz = clazz;
2939 render->glyph_format = clazz->glyph_format;
2940
2941 /* allocate raster object if needed */
2942 if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
2943 clazz->raster_class->raster_new )
2944 {
2945 error = clazz->raster_class->raster_new( memory, &render->raster );
2946 if ( error )
2947 goto Fail;
2948
2949 render->raster_render = clazz->raster_class->raster_render;
2950 render->render = clazz->render_glyph;
2951 }
2952
2953 /* add to list */
2954 node->data = module;
2955 FT_List_Add( &library->renderers, node );
2956
2957 ft_set_current_renderer( library );
2958 }
2959
2960 Fail:
2961 if ( error )
2962 FT_FREE( node )do { ft_mem_free( memory, (node) ); (node) = ((void*)0); } while
( 0 )
;
2963
2964 Exit:
2965 return error;
2966 }
2967
2968
2969 static void
2970 ft_remove_renderer( FT_Module module )
2971 {
2972 FT_Library library;
2973 FT_Memory memory;
2974 FT_ListNode node;
2975
2976
2977 library = module->library;
2978 if ( !library )
2979 return;
2980
2981 memory = library->memory;
2982
2983 node = FT_List_Find( &library->renderers, module );
2984 if ( node )
2985 {
2986 FT_Renderer render = FT_RENDERER( module )( (FT_Renderer)(module) );
2987
2988
2989 /* release raster object, if any */
2990 if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
2991 render->raster )
2992 render->clazz->raster_class->raster_done( render->raster );
2993
2994 /* remove from list */
2995 FT_List_Remove( &library->renderers, node );
2996 FT_FREE( node )do { ft_mem_free( memory, (node) ); (node) = ((void*)0); } while
( 0 )
;
2997
2998 ft_set_current_renderer( library );
2999 }
3000 }
3001
3002
3003 FT_BASE_DEF( FT_Error )FT_Error
3004 FT_Render_Glyph_Internal( FT_Library library,
3005 FT_GlyphSlot slot,
3006 FT_Render_Mode render_mode )
3007 {
3008 FT_Error error = FT_Err_Ok;
3009 FT_Renderer renderer;
3010
3011
3012 /* if it is already a bitmap, no need to do anything */
3013 switch ( slot->format )
3014 {
3015 case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
3016 break;
3017
3018 default:
3019 {
3020 FT_ListNode node = NULL((void*)0);
3021
3022
3023 /* small shortcut for the very common case */
3024 if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
3025 {
3026 renderer = library->cur_renderer;
3027 node = library->renderers.head;
3028 }
3029 else
3030 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3031
3032 error = FT_ERR( Unimplemented_Feature )FT_Err_Unimplemented_Feature;
3033 while ( renderer )
3034 {
3035 error = renderer->render( renderer, slot, render_mode, NULL((void*)0) );
3036 if ( !error ||
3037 FT_ERR_NEQ( error, Cannot_Render_Glyph )( ( (error) & 0xFF ) != ( (FT_Err_Cannot_Render_Glyph) &
0xFF ) )
)
3038 break;
3039
3040 /* FT_Err_Cannot_Render_Glyph is returned if the render mode */
3041 /* is unsupported by the current renderer for this glyph image */
3042 /* format. */
3043
3044 /* now, look for another renderer that supports the same */
3045 /* format. */
3046 renderer = FT_Lookup_Renderer( library, slot->format, &node );
3047 }
3048 }
3049 }
3050
3051 return error;
3052 }
3053
3054
3055 /* documentation is in freetype.h */
3056
3057 FT_EXPORT_DEF( FT_Error )extern FT_Error
3058 FT_Render_Glyph( FT_GlyphSlot slot,
3059 FT_Render_Mode render_mode )
3060 {
3061 FT_Library library;
3062
3063
3064 if ( !slot || !slot->face )
3065 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
3066
3067 library = FT_FACE_LIBRARY( slot->face )( (FT_Face)(slot->face) )->driver->root.library;
3068
3069 return FT_Render_Glyph_Internal( library, slot, render_mode );
3070 }
3071
3072
3073 /*************************************************************************/
3074 /*************************************************************************/
3075 /*************************************************************************/
3076 /**** ****/
3077 /**** ****/
3078 /**** M O D U L E S ****/
3079 /**** ****/
3080 /**** ****/
3081 /*************************************************************************/
3082 /*************************************************************************/
3083 /*************************************************************************/
3084
3085
3086 /*************************************************************************/
3087 /* */
3088 /* <Function> */
3089 /* Destroy_Module */
3090 /* */
3091 /* <Description> */
3092 /* Destroys a given module object. For drivers, this also destroys */
3093 /* all child faces. */
3094 /* */
3095 /* <InOut> */
3096 /* module :: A handle to the target driver object. */
3097 /* */
3098 /* <Note> */
3099 /* The driver _must_ be LOCKED! */
3100 /* */
3101 static void
3102 Destroy_Module( FT_Module module )
3103 {
3104 FT_Memory memory = module->memory;
3105 FT_Module_Class* clazz = module->clazz;
3106 FT_Library library = module->library;
3107
3108
3109 if ( library && library->auto_hinter == module )
3110 library->auto_hinter = NULL((void*)0);
3111
3112 /* if the module is a renderer */
3113 if ( FT_MODULE_IS_RENDERER( module )( ( (FT_Module)(module) )->clazz->module_flags & 2 ) )
3114 ft_remove_renderer( module );
3115
3116 /* if the module is a font driver, add some steps */
3117 if ( FT_MODULE_IS_DRIVER( module )( ( (FT_Module)(module) )->clazz->module_flags & 1 ) )
3118 Destroy_Driver( FT_DRIVER( module )( (FT_Driver)(module) ) );
3119
3120 /* finalize the module object */
3121 if ( clazz->module_done )
3122 clazz->module_done( module );
3123
3124 /* discard it */
3125 FT_FREE( module )do { ft_mem_free( memory, (module) ); (module) = ((void*)0); }
while ( 0 )
;
3126 }
3127
3128
3129 /* documentation is in ftmodapi.h */
3130
3131 FT_EXPORT_DEF( FT_Error )extern FT_Error
3132 FT_Add_Module( FT_Library library,
3133 const FT_Module_Class* clazz )
3134 {
3135 FT_Error error;
3136 FT_Memory memory;
3137 FT_Module module = NULL((void*)0);
3138 FT_UInt nn;
3139
3140
3141#define FREETYPE_VER_FIXED( ( (FT_Long)2 << 16 ) | 9 ) ( ( (FT_Long)FREETYPE_MAJOR2 << 16 ) | \
3142 FREETYPE_MINOR9 )
3143
3144 if ( !library )
3145 return FT_THROW( Invalid_Library_Handle )FT_Err_Invalid_Library_Handle;
3146
3147 if ( !clazz )
3148 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
3149
3150 /* check FreeType version */
3151 if ( clazz->module_requires > FREETYPE_VER_FIXED( ( (FT_Long)2 << 16 ) | 9 ) )
3152 return FT_THROW( Invalid_Version )FT_Err_Invalid_Version;
3153
3154 /* look for a module with the same name in the library's table */
3155 for ( nn = 0; nn < library->num_modules; nn++ )
3156 {
3157 module = library->modules[nn];
3158 if ( ft_strcmpstrcmp( module->clazz->module_name, clazz->module_name ) == 0 )
3159 {
3160 /* this installed module has the same name, compare their versions */
3161 if ( clazz->module_version <= module->clazz->module_version )
3162 return FT_THROW( Lower_Module_Version )FT_Err_Lower_Module_Version;
3163
3164 /* remove the module from our list, then exit the loop to replace */
3165 /* it by our new version.. */
3166 FT_Remove_Module( library, module );
3167 break;
3168 }
3169 }
3170
3171 memory = library->memory;
3172 error = FT_Err_Ok;
3173
3174 if ( library->num_modules >= FT_MAX_MODULES32 )
3175 {
3176 error = FT_THROW( Too_Many_Drivers )FT_Err_Too_Many_Drivers;
3177 goto Exit;
3178 }
3179
3180 /* allocate module object */
3181 if ( FT_ALLOC( module, clazz->module_size )( ((module) = (ft_mem_alloc( memory, (FT_Long)(clazz->module_size
), &error ))), error != 0 )
)
3182 goto Exit;
3183
3184 /* base initialization */
3185 module->library = library;
3186 module->memory = memory;
3187 module->clazz = (FT_Module_Class*)clazz;
3188
3189 /* check whether the module is a renderer - this must be performed */
3190 /* before the normal module initialization */
3191 if ( FT_MODULE_IS_RENDERER( module )( ( (FT_Module)(module) )->clazz->module_flags & 2 ) )
3192 {
3193 /* add to the renderers list */
3194 error = ft_add_renderer( module );
3195 if ( error )
3196 goto Fail;
3197 }
3198
3199 /* is the module a auto-hinter? */
3200 if ( FT_MODULE_IS_HINTER( module )( ( (FT_Module)(module) )->clazz->module_flags & 4 ) )
3201 library->auto_hinter = module;
3202
3203 /* if the module is a font driver */
3204 if ( FT_MODULE_IS_DRIVER( module )( ( (FT_Module)(module) )->clazz->module_flags & 1 ) )
3205 {
3206 FT_Driver driver = FT_DRIVER( module )( (FT_Driver)(module) );
3207
3208
3209 driver->clazz = (FT_Driver_Class)module->clazz;
3210 }
3211
3212 if ( clazz->module_init )
3213 {
3214 error = clazz->module_init( module );
3215 if ( error )
3216 goto Fail;
3217 }
3218
3219 /* add module to the library's table */
3220 library->modules[library->num_modules++] = module;
3221
3222 Exit:
3223 return error;
3224
3225 Fail:
3226 if ( FT_MODULE_IS_RENDERER( module )( ( (FT_Module)(module) )->clazz->module_flags & 2 ) )
3227 {
3228 FT_Renderer renderer = FT_RENDERER( module )( (FT_Renderer)(module) );
3229
3230
3231 if ( renderer->clazz &&
3232 renderer->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
3233 renderer->raster )
3234 renderer->clazz->raster_class->raster_done( renderer->raster );
3235 }
3236
3237 FT_FREE( module )do { ft_mem_free( memory, (module) ); (module) = ((void*)0); }
while ( 0 )
;
3238 goto Exit;
3239 }
3240
3241
3242 /* documentation is in ftmodapi.h */
3243
3244 FT_EXPORT_DEF( FT_Module )extern FT_Module
3245 FT_Get_Module( FT_Library library,
3246 const char* module_name )
3247 {
3248 FT_Module result = NULL((void*)0);
3249 FT_Module* cur;
3250 FT_Module* limit;
3251
3252
3253 if ( !library || !module_name )
3254 return result;
3255
3256 cur = library->modules;
3257 limit = cur + library->num_modules;
3258
3259 for ( ; cur < limit; cur++ )
3260 if ( ft_strcmpstrcmp( cur[0]->clazz->module_name, module_name ) == 0 )
3261 {
3262 result = cur[0];
3263 break;
3264 }
3265
3266 return result;
3267 }
3268
3269
3270 /* documentation is in ftobjs.h */
3271
3272 FT_BASE_DEF( const void* )const void*
3273 FT_Get_Module_Interface( FT_Library library,
3274 const char* mod_name )
3275 {
3276 FT_Module module;
3277
3278
3279 /* test for valid `library' delayed to FT_Get_Module() */
3280
3281 module = FT_Get_Module( library, mod_name );
3282
3283 return module ? module->clazz->module_interface : 0;
3284 }
3285
3286
3287 FT_BASE_DEF( FT_Pointer )FT_Pointer
3288 ft_module_get_service( FT_Module module,
3289 const char* service_id,
3290 FT_Bool global )
3291 {
3292 FT_Pointer result = NULL((void*)0);
3293
3294
3295 if ( module )
3296 {
3297 FT_ASSERT( module->clazz && module->clazz->get_interface )do { } while ( 0 );
3298
3299 /* first, look for the service in the module */
3300 if ( module->clazz->get_interface )
3301 result = module->clazz->get_interface( module, service_id );
3302
3303 if ( global && !result )
3304 {
3305 /* we didn't find it, look in all other modules then */
3306 FT_Library library = module->library;
3307 FT_Module* cur = library->modules;
3308 FT_Module* limit = cur + library->num_modules;
3309
3310
3311 for ( ; cur < limit; cur++ )
3312 {
3313 if ( cur[0] != module )
3314 {
3315 FT_ASSERT( cur[0]->clazz )do { } while ( 0 );
3316
3317 if ( cur[0]->clazz->get_interface )
3318 {
3319 result = cur[0]->clazz->get_interface( cur[0], service_id );
3320 if ( result )
3321 break;
3322 }
3323 }
3324 }
3325 }
3326 }
3327
3328 return result;
3329 }
3330
3331
3332 /* documentation is in ftmodapi.h */
3333
3334 FT_EXPORT_DEF( FT_Error )extern FT_Error
3335 FT_Remove_Module( FT_Library library,
3336 FT_Module module )
3337 {
3338 /* try to find the module from the table, then remove it from there */
3339
3340 if ( !library )
3341 return FT_THROW( Invalid_Library_Handle )FT_Err_Invalid_Library_Handle;
3342
3343 if ( module )
3344 {
3345 FT_Module* cur = library->modules;
3346 FT_Module* limit = cur + library->num_modules;
3347
3348
3349 for ( ; cur < limit; cur++ )
3350 {
3351 if ( cur[0] == module )
3352 {
3353 /* remove it from the table */
3354 library->num_modules--;
3355 limit--;
3356 while ( cur < limit )
3357 {
3358 cur[0] = cur[1];
3359 cur++;
3360 }
3361 limit[0] = NULL((void*)0);
3362
3363 /* destroy the module */
3364 Destroy_Module( module );
3365
3366 return FT_Err_Ok;
3367 }
3368 }
3369 }
3370 return FT_THROW( Invalid_Driver_Handle )FT_Err_Invalid_Driver_Handle;
3371 }
3372
3373
3374 /*************************************************************************/
3375 /*************************************************************************/
3376 /*************************************************************************/
3377 /**** ****/
3378 /**** ****/
3379 /**** L I B R A R Y ****/
3380 /**** ****/
3381 /**** ****/
3382 /*************************************************************************/
3383 /*************************************************************************/
3384 /*************************************************************************/
3385
3386
3387 /* documentation is in ftmodapi.h */
3388
3389 FT_EXPORT_DEF( FT_Error )extern FT_Error
3390 FT_New_Library( FT_Memory memory,
3391 FT_Library *alibrary )
3392 {
3393 FT_Library library = NULL((void*)0);
3394 FT_Error error;
3395
3396
3397 if ( !memory || !alibrary )
3398 return FT_THROW( Invalid_Argument )FT_Err_Invalid_Argument;
3399
3400 /* first of all, allocate the library object */
3401 if ( FT_NEW( library )( ((library) = (ft_mem_alloc( memory, (FT_Long)(sizeof ( *(library
) )), &error ))), error != 0 )
)
3402 return error;
3403
3404 library->memory = memory;
3405 library->refcount = 1;
3406
3407 /* That's ok now */
3408 *alibrary = library;
3409
3410 return FT_Err_Ok;
3411 }
3412
3413
3414 /* documentation is in ftmodapi.h */
3415
3416 FT_EXPORT_DEF( FT_Error )extern FT_Error
3417 FT_Done_Library( FT_Library library )
3418 {
3419 FT_Memory memory;
3420
3421
3422 if ( !library )
3423 return FT_THROW( Invalid_Library_Handle )FT_Err_Invalid_Library_Handle;
3424
3425 library->refcount--;
3426 if ( library->refcount > 0 )
3427 goto Exit;
3428
3429 memory = library->memory;
3430
3431 /*
3432 * Close all faces in the library. If we don't do this, we can have
3433 * some subtle memory leaks.
3434 *
3435 * Example:
3436 *
3437 * - the cff font driver uses the pshinter module in cff_size_done
3438 * - if the pshinter module is destroyed before the cff font driver,
3439 * opened FT_Face objects managed by the driver are not properly
3440 * destroyed, resulting in a memory leak
3441 *
3442 * Some faces are dependent on other faces, like Type42 faces that
3443 * depend on TrueType faces synthesized internally.
3444 *
3445 * The order of drivers should be specified in driver_name[].
3446 */
3447 {
3448 FT_UInt m, n;
3449 const char* driver_name[] = { "type42", NULL((void*)0) };
3450
3451
3452 for ( m = 0;
3453 m < sizeof ( driver_name ) / sizeof ( driver_name[0] );
3454 m++ )
3455 {
3456 for ( n = 0; n < library->num_modules; n++ )
3457 {
3458 FT_Module module = library->modules[n];
3459 const char* module_name = module->clazz->module_name;
3460 FT_List faces;
3461
3462
3463 if ( driver_name[m] &&
3464 ft_strcmpstrcmp( module_name, driver_name[m] ) != 0 )
3465 continue;
3466
3467 if ( ( module->clazz->module_flags & FT_MODULE_FONT_DRIVER1 ) == 0 )
3468 continue;
3469
3470 FT_TRACE7(( "FT_Done_Library: close faces for %s\n", module_name ))do { } while ( 0 );
3471
3472 faces = &FT_DRIVER( module )( (FT_Driver)(module) )->faces_list;
3473 while ( faces->head )
3474 {
3475 FT_Done_Face( FT_FACE( faces->head->data )( (FT_Face)(faces->head->data) ) );
3476 if ( faces->head )
3477 FT_TRACE0(( "FT_Done_Library: failed to free some faces\n" ))do { } while ( 0 );
3478 }
3479 }
3480 }
3481 }
3482
3483 /* Close all other modules in the library */
3484#if 1
3485 /* XXX Modules are removed in the reversed order so that */
3486 /* type42 module is removed before truetype module. This */
3487 /* avoids double free in some occasions. It is a hack. */
3488 while ( library->num_modules > 0 )
3489 FT_Remove_Module( library,
3490 library->modules[library->num_modules - 1] );
3491#else
3492 {
3493 FT_UInt n;
3494
3495
3496 for ( n = 0; n < library->num_modules; n++ )
3497 {
3498 FT_Module module = library->modules[n];
3499
3500
3501 if ( module )
3502 {
3503 Destroy_Module( module );
3504 library->modules[n] = NULL((void*)0);
3505 }
3506 }
3507 }
3508#endif
3509
3510 FT_FREE( library )do { ft_mem_free( memory, (library) ); (library) = ((void*)0)
; } while ( 0 )
;
3511
3512 Exit:
3513 return FT_Err_Ok;
3514 }
3515
3516
3517/* END */