Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3918 | Serge | 1 | /***************************************************************************/ |
2 | /* */ |
||
3 | /* ftglyph.c */ |
||
4 | /* */ |
||
5 | /* FreeType convenience functions to handle glyphs (body). */ |
||
6 | /* */ |
||
7 | /* Copyright 1996-2005, 2007, 2008, 2010, 2012, 2013 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 | /* */ |
||
20 | /* This file contains the definition of several convenience functions */ |
||
21 | /* that can be used by client applications to easily retrieve glyph */ |
||
22 | /* bitmaps and outlines from a given face. */ |
||
23 | /* */ |
||
24 | /* These functions should be optional if you are writing a font server */ |
||
25 | /* or text layout engine on top of FreeType. However, they are pretty */ |
||
26 | /* handy for many other simple uses of the library. */ |
||
27 | /* */ |
||
28 | /*************************************************************************/ |
||
29 | |||
30 | |||
31 | #include |
||
32 | #include FT_INTERNAL_DEBUG_H |
||
33 | |||
34 | #include FT_GLYPH_H |
||
35 | #include FT_OUTLINE_H |
||
36 | #include FT_BITMAP_H |
||
37 | #include FT_INTERNAL_OBJECTS_H |
||
38 | |||
39 | #include "basepic.h" |
||
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_glyph |
||
49 | |||
50 | |||
51 | /*************************************************************************/ |
||
52 | /*************************************************************************/ |
||
53 | /**** ****/ |
||
54 | /**** FT_BitmapGlyph support ****/ |
||
55 | /**** ****/ |
||
56 | /*************************************************************************/ |
||
57 | /*************************************************************************/ |
||
58 | |||
59 | FT_CALLBACK_DEF( FT_Error ) |
||
60 | ft_bitmap_glyph_init( FT_Glyph bitmap_glyph, |
||
61 | FT_GlyphSlot slot ) |
||
62 | { |
||
63 | FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; |
||
64 | FT_Error error = FT_Err_Ok; |
||
65 | FT_Library library = FT_GLYPH( glyph )->library; |
||
66 | |||
67 | |||
68 | if ( slot->format != FT_GLYPH_FORMAT_BITMAP ) |
||
69 | { |
||
70 | error = FT_THROW( Invalid_Glyph_Format ); |
||
71 | goto Exit; |
||
72 | } |
||
73 | |||
74 | glyph->left = slot->bitmap_left; |
||
75 | glyph->top = slot->bitmap_top; |
||
76 | |||
77 | /* do lazy copying whenever possible */ |
||
78 | if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) |
||
79 | { |
||
80 | glyph->bitmap = slot->bitmap; |
||
81 | slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP; |
||
82 | } |
||
83 | else |
||
84 | { |
||
85 | FT_Bitmap_New( &glyph->bitmap ); |
||
86 | error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap ); |
||
87 | } |
||
88 | |||
89 | Exit: |
||
90 | return error; |
||
91 | } |
||
92 | |||
93 | |||
94 | FT_CALLBACK_DEF( FT_Error ) |
||
95 | ft_bitmap_glyph_copy( FT_Glyph bitmap_source, |
||
96 | FT_Glyph bitmap_target ) |
||
97 | { |
||
98 | FT_Library library = bitmap_source->library; |
||
99 | FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source; |
||
100 | FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target; |
||
101 | |||
102 | |||
103 | target->left = source->left; |
||
104 | target->top = source->top; |
||
105 | |||
106 | return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap ); |
||
107 | } |
||
108 | |||
109 | |||
110 | FT_CALLBACK_DEF( void ) |
||
111 | ft_bitmap_glyph_done( FT_Glyph bitmap_glyph ) |
||
112 | { |
||
113 | FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; |
||
114 | FT_Library library = FT_GLYPH( glyph )->library; |
||
115 | |||
116 | |||
117 | FT_Bitmap_Done( library, &glyph->bitmap ); |
||
118 | } |
||
119 | |||
120 | |||
121 | FT_CALLBACK_DEF( void ) |
||
122 | ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph, |
||
123 | FT_BBox* cbox ) |
||
124 | { |
||
125 | FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph; |
||
126 | |||
127 | |||
128 | cbox->xMin = glyph->left << 6; |
||
129 | cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 ); |
||
130 | cbox->yMax = glyph->top << 6; |
||
131 | cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 ); |
||
132 | } |
||
133 | |||
134 | |||
135 | FT_DEFINE_GLYPH(ft_bitmap_glyph_class, |
||
136 | sizeof ( FT_BitmapGlyphRec ), |
||
137 | FT_GLYPH_FORMAT_BITMAP, |
||
138 | |||
139 | ft_bitmap_glyph_init, |
||
140 | ft_bitmap_glyph_done, |
||
141 | ft_bitmap_glyph_copy, |
||
142 | 0, /* FT_Glyph_TransformFunc */ |
||
143 | ft_bitmap_glyph_bbox, |
||
144 | |||
145 | ) |
||
146 | |||
147 | |||
148 | /*************************************************************************/ |
||
149 | /*************************************************************************/ |
||
150 | /**** ****/ |
||
151 | /**** FT_OutlineGlyph support ****/ |
||
152 | /**** ****/ |
||
153 | /*************************************************************************/ |
||
154 | /*************************************************************************/ |
||
155 | |||
156 | |||
157 | FT_CALLBACK_DEF( FT_Error ) |
||
158 | ft_outline_glyph_init( FT_Glyph outline_glyph, |
||
159 | FT_GlyphSlot slot ) |
||
160 | { |
||
161 | FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; |
||
162 | FT_Error error = FT_Err_Ok; |
||
163 | FT_Library library = FT_GLYPH( glyph )->library; |
||
164 | FT_Outline* source = &slot->outline; |
||
165 | FT_Outline* target = &glyph->outline; |
||
166 | |||
167 | |||
168 | /* check format in glyph slot */ |
||
169 | if ( slot->format != FT_GLYPH_FORMAT_OUTLINE ) |
||
170 | { |
||
171 | error = FT_THROW( Invalid_Glyph_Format ); |
||
172 | goto Exit; |
||
173 | } |
||
174 | |||
175 | /* allocate new outline */ |
||
176 | error = FT_Outline_New( library, source->n_points, source->n_contours, |
||
177 | &glyph->outline ); |
||
178 | if ( error ) |
||
179 | goto Exit; |
||
180 | |||
181 | FT_Outline_Copy( source, target ); |
||
182 | |||
183 | Exit: |
||
184 | return error; |
||
185 | } |
||
186 | |||
187 | |||
188 | FT_CALLBACK_DEF( void ) |
||
189 | ft_outline_glyph_done( FT_Glyph outline_glyph ) |
||
190 | { |
||
191 | FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; |
||
192 | |||
193 | |||
194 | FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline ); |
||
195 | } |
||
196 | |||
197 | |||
198 | FT_CALLBACK_DEF( FT_Error ) |
||
199 | ft_outline_glyph_copy( FT_Glyph outline_source, |
||
200 | FT_Glyph outline_target ) |
||
201 | { |
||
202 | FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source; |
||
203 | FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target; |
||
204 | FT_Error error; |
||
205 | FT_Library library = FT_GLYPH( source )->library; |
||
206 | |||
207 | |||
208 | error = FT_Outline_New( library, source->outline.n_points, |
||
209 | source->outline.n_contours, &target->outline ); |
||
210 | if ( !error ) |
||
211 | FT_Outline_Copy( &source->outline, &target->outline ); |
||
212 | |||
213 | return error; |
||
214 | } |
||
215 | |||
216 | |||
217 | FT_CALLBACK_DEF( void ) |
||
218 | ft_outline_glyph_transform( FT_Glyph outline_glyph, |
||
219 | const FT_Matrix* matrix, |
||
220 | const FT_Vector* delta ) |
||
221 | { |
||
222 | FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; |
||
223 | |||
224 | |||
225 | if ( matrix ) |
||
226 | FT_Outline_Transform( &glyph->outline, matrix ); |
||
227 | |||
228 | if ( delta ) |
||
229 | FT_Outline_Translate( &glyph->outline, delta->x, delta->y ); |
||
230 | } |
||
231 | |||
232 | |||
233 | FT_CALLBACK_DEF( void ) |
||
234 | ft_outline_glyph_bbox( FT_Glyph outline_glyph, |
||
235 | FT_BBox* bbox ) |
||
236 | { |
||
237 | FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; |
||
238 | |||
239 | |||
240 | FT_Outline_Get_CBox( &glyph->outline, bbox ); |
||
241 | } |
||
242 | |||
243 | |||
244 | FT_CALLBACK_DEF( FT_Error ) |
||
245 | ft_outline_glyph_prepare( FT_Glyph outline_glyph, |
||
246 | FT_GlyphSlot slot ) |
||
247 | { |
||
248 | FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph; |
||
249 | |||
250 | |||
251 | slot->format = FT_GLYPH_FORMAT_OUTLINE; |
||
252 | slot->outline = glyph->outline; |
||
253 | slot->outline.flags &= ~FT_OUTLINE_OWNER; |
||
254 | |||
255 | return FT_Err_Ok; |
||
256 | } |
||
257 | |||
258 | |||
259 | FT_DEFINE_GLYPH( ft_outline_glyph_class, |
||
260 | sizeof ( FT_OutlineGlyphRec ), |
||
261 | FT_GLYPH_FORMAT_OUTLINE, |
||
262 | |||
263 | ft_outline_glyph_init, |
||
264 | ft_outline_glyph_done, |
||
265 | ft_outline_glyph_copy, |
||
266 | ft_outline_glyph_transform, |
||
267 | ft_outline_glyph_bbox, |
||
268 | ft_outline_glyph_prepare |
||
269 | ) |
||
270 | |||
271 | |||
272 | /*************************************************************************/ |
||
273 | /*************************************************************************/ |
||
274 | /**** ****/ |
||
275 | /**** FT_Glyph class and API ****/ |
||
276 | /**** ****/ |
||
277 | /*************************************************************************/ |
||
278 | /*************************************************************************/ |
||
279 | |||
280 | static FT_Error |
||
281 | ft_new_glyph( FT_Library library, |
||
282 | const FT_Glyph_Class* clazz, |
||
283 | FT_Glyph* aglyph ) |
||
284 | { |
||
285 | FT_Memory memory = library->memory; |
||
286 | FT_Error error; |
||
287 | FT_Glyph glyph = NULL; |
||
288 | |||
289 | |||
290 | *aglyph = 0; |
||
291 | |||
292 | if ( !FT_ALLOC( glyph, clazz->glyph_size ) ) |
||
293 | { |
||
294 | glyph->library = library; |
||
295 | glyph->clazz = clazz; |
||
296 | glyph->format = clazz->glyph_format; |
||
297 | |||
298 | *aglyph = glyph; |
||
299 | } |
||
300 | |||
301 | return error; |
||
302 | } |
||
303 | |||
304 | |||
305 | /* documentation is in ftglyph.h */ |
||
306 | |||
307 | FT_EXPORT_DEF( FT_Error ) |
||
308 | FT_Glyph_Copy( FT_Glyph source, |
||
309 | FT_Glyph *target ) |
||
310 | { |
||
311 | FT_Glyph copy; |
||
312 | FT_Error error; |
||
313 | const FT_Glyph_Class* clazz; |
||
314 | |||
315 | |||
316 | /* check arguments */ |
||
317 | if ( !target ) |
||
318 | { |
||
319 | error = FT_THROW( Invalid_Argument ); |
||
320 | goto Exit; |
||
321 | } |
||
322 | |||
323 | *target = 0; |
||
324 | |||
325 | if ( !source || !source->clazz ) |
||
326 | { |
||
327 | error = FT_THROW( Invalid_Argument ); |
||
328 | goto Exit; |
||
329 | } |
||
330 | |||
331 | clazz = source->clazz; |
||
332 | error = ft_new_glyph( source->library, clazz, © ); |
||
333 | if ( error ) |
||
334 | goto Exit; |
||
335 | |||
336 | copy->advance = source->advance; |
||
337 | copy->format = source->format; |
||
338 | |||
339 | if ( clazz->glyph_copy ) |
||
340 | error = clazz->glyph_copy( source, copy ); |
||
341 | |||
342 | if ( error ) |
||
343 | FT_Done_Glyph( copy ); |
||
344 | else |
||
345 | *target = copy; |
||
346 | |||
347 | Exit: |
||
348 | return error; |
||
349 | } |
||
350 | |||
351 | |||
352 | /* documentation is in ftglyph.h */ |
||
353 | |||
354 | FT_EXPORT_DEF( FT_Error ) |
||
355 | FT_Get_Glyph( FT_GlyphSlot slot, |
||
356 | FT_Glyph *aglyph ) |
||
357 | { |
||
358 | FT_Library library; |
||
359 | FT_Error error; |
||
360 | FT_Glyph glyph; |
||
361 | |||
362 | const FT_Glyph_Class* clazz = 0; |
||
363 | |||
364 | |||
365 | if ( !slot ) |
||
366 | return FT_THROW( Invalid_Slot_Handle ); |
||
367 | |||
368 | library = slot->library; |
||
369 | |||
370 | if ( !aglyph ) |
||
371 | return FT_THROW( Invalid_Argument ); |
||
372 | |||
373 | /* if it is a bitmap, that's easy :-) */ |
||
374 | if ( slot->format == FT_GLYPH_FORMAT_BITMAP ) |
||
375 | clazz = FT_BITMAP_GLYPH_CLASS_GET; |
||
376 | |||
377 | /* if it is an outline */ |
||
378 | else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE ) |
||
379 | clazz = FT_OUTLINE_GLYPH_CLASS_GET; |
||
380 | |||
381 | else |
||
382 | { |
||
383 | /* try to find a renderer that supports the glyph image format */ |
||
384 | FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 ); |
||
385 | |||
386 | |||
387 | if ( render ) |
||
388 | clazz = &render->glyph_class; |
||
389 | } |
||
390 | |||
391 | if ( !clazz ) |
||
392 | { |
||
393 | error = FT_THROW( Invalid_Glyph_Format ); |
||
394 | goto Exit; |
||
395 | } |
||
396 | |||
397 | /* create FT_Glyph object */ |
||
398 | error = ft_new_glyph( library, clazz, &glyph ); |
||
399 | if ( error ) |
||
400 | goto Exit; |
||
401 | |||
402 | /* copy advance while converting it to 16.16 format */ |
||
403 | glyph->advance.x = slot->advance.x << 10; |
||
404 | glyph->advance.y = slot->advance.y << 10; |
||
405 | |||
406 | /* now import the image from the glyph slot */ |
||
407 | error = clazz->glyph_init( glyph, slot ); |
||
408 | |||
409 | /* if an error occurred, destroy the glyph */ |
||
410 | if ( error ) |
||
411 | FT_Done_Glyph( glyph ); |
||
412 | else |
||
413 | *aglyph = glyph; |
||
414 | |||
415 | Exit: |
||
416 | return error; |
||
417 | } |
||
418 | |||
419 | |||
420 | /* documentation is in ftglyph.h */ |
||
421 | |||
422 | FT_EXPORT_DEF( FT_Error ) |
||
423 | FT_Glyph_Transform( FT_Glyph glyph, |
||
424 | FT_Matrix* matrix, |
||
425 | FT_Vector* delta ) |
||
426 | { |
||
427 | const FT_Glyph_Class* clazz; |
||
428 | FT_Error error = FT_Err_Ok; |
||
429 | |||
430 | |||
431 | if ( !glyph || !glyph->clazz ) |
||
432 | error = FT_THROW( Invalid_Argument ); |
||
433 | else |
||
434 | { |
||
435 | clazz = glyph->clazz; |
||
436 | if ( clazz->glyph_transform ) |
||
437 | { |
||
438 | /* transform glyph image */ |
||
439 | clazz->glyph_transform( glyph, matrix, delta ); |
||
440 | |||
441 | /* transform advance vector */ |
||
442 | if ( matrix ) |
||
443 | FT_Vector_Transform( &glyph->advance, matrix ); |
||
444 | } |
||
445 | else |
||
446 | error = FT_THROW( Invalid_Glyph_Format ); |
||
447 | } |
||
448 | return error; |
||
449 | } |
||
450 | |||
451 | |||
452 | /* documentation is in ftglyph.h */ |
||
453 | |||
454 | FT_EXPORT_DEF( void ) |
||
455 | FT_Glyph_Get_CBox( FT_Glyph glyph, |
||
456 | FT_UInt bbox_mode, |
||
457 | FT_BBox *acbox ) |
||
458 | { |
||
459 | const FT_Glyph_Class* clazz; |
||
460 | |||
461 | |||
462 | if ( !acbox ) |
||
463 | return; |
||
464 | |||
465 | acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0; |
||
466 | |||
467 | if ( !glyph || !glyph->clazz ) |
||
468 | return; |
||
469 | else |
||
470 | { |
||
471 | clazz = glyph->clazz; |
||
472 | if ( !clazz->glyph_bbox ) |
||
473 | return; |
||
474 | else |
||
475 | { |
||
476 | /* retrieve bbox in 26.6 coordinates */ |
||
477 | clazz->glyph_bbox( glyph, acbox ); |
||
478 | |||
479 | /* perform grid fitting if needed */ |
||
480 | if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT || |
||
481 | bbox_mode == FT_GLYPH_BBOX_PIXELS ) |
||
482 | { |
||
483 | acbox->xMin = FT_PIX_FLOOR( acbox->xMin ); |
||
484 | acbox->yMin = FT_PIX_FLOOR( acbox->yMin ); |
||
485 | acbox->xMax = FT_PIX_CEIL( acbox->xMax ); |
||
486 | acbox->yMax = FT_PIX_CEIL( acbox->yMax ); |
||
487 | } |
||
488 | |||
489 | /* convert to integer pixels if needed */ |
||
490 | if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE || |
||
491 | bbox_mode == FT_GLYPH_BBOX_PIXELS ) |
||
492 | { |
||
493 | acbox->xMin >>= 6; |
||
494 | acbox->yMin >>= 6; |
||
495 | acbox->xMax >>= 6; |
||
496 | acbox->yMax >>= 6; |
||
497 | } |
||
498 | } |
||
499 | } |
||
500 | return; |
||
501 | } |
||
502 | |||
503 | |||
504 | /* documentation is in ftglyph.h */ |
||
505 | |||
506 | FT_EXPORT_DEF( FT_Error ) |
||
507 | FT_Glyph_To_Bitmap( FT_Glyph* the_glyph, |
||
508 | FT_Render_Mode render_mode, |
||
509 | FT_Vector* origin, |
||
510 | FT_Bool destroy ) |
||
511 | { |
||
512 | FT_GlyphSlotRec dummy; |
||
513 | FT_GlyphSlot_InternalRec dummy_internal; |
||
514 | FT_Error error = FT_Err_Ok; |
||
515 | FT_Glyph b, glyph; |
||
516 | FT_BitmapGlyph bitmap = NULL; |
||
517 | const FT_Glyph_Class* clazz; |
||
518 | |||
519 | /* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */ |
||
520 | FT_Library library; |
||
521 | |||
522 | |||
523 | /* check argument */ |
||
524 | if ( !the_glyph ) |
||
525 | goto Bad; |
||
526 | glyph = *the_glyph; |
||
527 | if ( !glyph ) |
||
528 | goto Bad; |
||
529 | |||
530 | clazz = glyph->clazz; |
||
531 | library = glyph->library; |
||
532 | if ( !library || !clazz ) |
||
533 | goto Bad; |
||
534 | |||
535 | /* when called with a bitmap glyph, do nothing and return successfully */ |
||
536 | if ( clazz == FT_BITMAP_GLYPH_CLASS_GET ) |
||
537 | goto Exit; |
||
538 | |||
539 | if ( !clazz->glyph_prepare ) |
||
540 | goto Bad; |
||
541 | |||
542 | /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */ |
||
543 | /* then calling FT_Render_Glyph_Internal() */ |
||
544 | |||
545 | FT_MEM_ZERO( &dummy, sizeof ( dummy ) ); |
||
546 | FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) ); |
||
547 | dummy.internal = &dummy_internal; |
||
548 | dummy.library = library; |
||
549 | dummy.format = clazz->glyph_format; |
||
550 | |||
551 | /* create result bitmap glyph */ |
||
552 | error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET, &b ); |
||
553 | if ( error ) |
||
554 | goto Exit; |
||
555 | bitmap = (FT_BitmapGlyph)b; |
||
556 | |||
557 | #if 1 |
||
558 | /* if `origin' is set, translate the glyph image */ |
||
559 | if ( origin ) |
||
560 | FT_Glyph_Transform( glyph, 0, origin ); |
||
561 | #else |
||
562 | FT_UNUSED( origin ); |
||
563 | #endif |
||
564 | |||
565 | /* prepare dummy slot for rendering */ |
||
566 | error = clazz->glyph_prepare( glyph, &dummy ); |
||
567 | if ( !error ) |
||
568 | error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode ); |
||
569 | |||
570 | #if 1 |
||
571 | if ( !destroy && origin ) |
||
572 | { |
||
573 | FT_Vector v; |
||
574 | |||
575 | |||
576 | v.x = -origin->x; |
||
577 | v.y = -origin->y; |
||
578 | FT_Glyph_Transform( glyph, 0, &v ); |
||
579 | } |
||
580 | #endif |
||
581 | |||
582 | if ( error ) |
||
583 | goto Exit; |
||
584 | |||
585 | /* in case of success, copy the bitmap to the glyph bitmap */ |
||
586 | error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy ); |
||
587 | if ( error ) |
||
588 | goto Exit; |
||
589 | |||
590 | /* copy advance */ |
||
591 | bitmap->root.advance = glyph->advance; |
||
592 | |||
593 | if ( destroy ) |
||
594 | FT_Done_Glyph( glyph ); |
||
595 | |||
596 | *the_glyph = FT_GLYPH( bitmap ); |
||
597 | |||
598 | Exit: |
||
599 | if ( error && bitmap ) |
||
600 | FT_Done_Glyph( FT_GLYPH( bitmap ) ); |
||
601 | |||
602 | return error; |
||
603 | |||
604 | Bad: |
||
605 | error = FT_THROW( Invalid_Argument ); |
||
606 | goto Exit; |
||
607 | } |
||
608 | |||
609 | |||
610 | /* documentation is in ftglyph.h */ |
||
611 | |||
612 | FT_EXPORT_DEF( void ) |
||
613 | FT_Done_Glyph( FT_Glyph glyph ) |
||
614 | { |
||
615 | if ( glyph ) |
||
616 | { |
||
617 | FT_Memory memory = glyph->library->memory; |
||
618 | const FT_Glyph_Class* clazz = glyph->clazz; |
||
619 | |||
620 | |||
621 | if ( clazz->glyph_done ) |
||
622 | clazz->glyph_done( glyph ); |
||
623 | |||
624 | FT_FREE( glyph ); |
||
625 | } |
||
626 | } |
||
627 | |||
628 | |||
629 | /* END */><>><>><>><>><>><> |