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