Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / modules / freetype2 / src / base / ftglyph.c
blob4130cb110284034b59a82dac6769e0dc2be706f5
1 /***************************************************************************/
2 /* */
3 /* ftglyph.c */
4 /* */
5 /* FreeType convenience functions to handle glyphs (body). */
6 /* */
7 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008 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 /***************************************************************************/
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 /*************************************************************************/
31 #include <ft2build.h>
32 #include FT_GLYPH_H
33 #include FT_OUTLINE_H
34 #include FT_BITMAP_H
35 #include FT_INTERNAL_OBJECTS_H
38 /*************************************************************************/
39 /* */
40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
41 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
42 /* messages during execution. */
43 /* */
44 #undef FT_COMPONENT
45 #define FT_COMPONENT trace_glyph
48 /*************************************************************************/
49 /*************************************************************************/
50 /**** ****/
51 /**** FT_BitmapGlyph support ****/
52 /**** ****/
53 /*************************************************************************/
54 /*************************************************************************/
56 FT_CALLBACK_DEF( FT_Error )
57 ft_bitmap_glyph_init( FT_Glyph bitmap_glyph,
58 FT_GlyphSlot slot )
60 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
61 FT_Error error = FT_Err_Ok;
62 FT_Library library = FT_GLYPH( glyph )->library;
65 if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
67 error = FT_Err_Invalid_Glyph_Format;
68 goto Exit;
71 glyph->left = slot->bitmap_left;
72 glyph->top = slot->bitmap_top;
74 /* do lazy copying whenever possible */
75 if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
77 glyph->bitmap = slot->bitmap;
78 slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
80 else
82 FT_Bitmap_New( &glyph->bitmap );
83 error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
86 Exit:
87 return error;
91 FT_CALLBACK_DEF( FT_Error )
92 ft_bitmap_glyph_copy( FT_Glyph bitmap_source,
93 FT_Glyph bitmap_target )
95 FT_Library library = bitmap_source->library;
96 FT_BitmapGlyph source = (FT_BitmapGlyph)bitmap_source;
97 FT_BitmapGlyph target = (FT_BitmapGlyph)bitmap_target;
100 target->left = source->left;
101 target->top = source->top;
103 return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
107 FT_CALLBACK_DEF( void )
108 ft_bitmap_glyph_done( FT_Glyph bitmap_glyph )
110 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
111 FT_Library library = FT_GLYPH( glyph )->library;
114 FT_Bitmap_Done( library, &glyph->bitmap );
118 FT_CALLBACK_DEF( void )
119 ft_bitmap_glyph_bbox( FT_Glyph bitmap_glyph,
120 FT_BBox* cbox )
122 FT_BitmapGlyph glyph = (FT_BitmapGlyph)bitmap_glyph;
125 cbox->xMin = glyph->left << 6;
126 cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
127 cbox->yMax = glyph->top << 6;
128 cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
132 FT_CALLBACK_TABLE_DEF
133 const FT_Glyph_Class ft_bitmap_glyph_class =
135 sizeof ( FT_BitmapGlyphRec ),
136 FT_GLYPH_FORMAT_BITMAP,
138 ft_bitmap_glyph_init,
139 ft_bitmap_glyph_done,
140 ft_bitmap_glyph_copy,
141 0, /* FT_Glyph_TransformFunc */
142 ft_bitmap_glyph_bbox,
143 0 /* FT_Glyph_PrepareFunc */
147 /*************************************************************************/
148 /*************************************************************************/
149 /**** ****/
150 /**** FT_OutlineGlyph support ****/
151 /**** ****/
152 /*************************************************************************/
153 /*************************************************************************/
156 FT_CALLBACK_DEF( FT_Error )
157 ft_outline_glyph_init( FT_Glyph outline_glyph,
158 FT_GlyphSlot slot )
160 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
161 FT_Error error = FT_Err_Ok;
162 FT_Library library = FT_GLYPH( glyph )->library;
163 FT_Outline* source = &slot->outline;
164 FT_Outline* target = &glyph->outline;
167 /* check format in glyph slot */
168 if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
170 error = FT_Err_Invalid_Glyph_Format;
171 goto Exit;
174 /* allocate new outline */
175 error = FT_Outline_New( library, source->n_points, source->n_contours,
176 &glyph->outline );
177 if ( error )
178 goto Exit;
180 FT_Outline_Copy( source, target );
182 Exit:
183 return error;
187 FT_CALLBACK_DEF( void )
188 ft_outline_glyph_done( FT_Glyph outline_glyph )
190 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
193 FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
197 FT_CALLBACK_DEF( FT_Error )
198 ft_outline_glyph_copy( FT_Glyph outline_source,
199 FT_Glyph outline_target )
201 FT_OutlineGlyph source = (FT_OutlineGlyph)outline_source;
202 FT_OutlineGlyph target = (FT_OutlineGlyph)outline_target;
203 FT_Error error;
204 FT_Library library = FT_GLYPH( source )->library;
207 error = FT_Outline_New( library, source->outline.n_points,
208 source->outline.n_contours, &target->outline );
209 if ( !error )
210 FT_Outline_Copy( &source->outline, &target->outline );
212 return error;
216 FT_CALLBACK_DEF( void )
217 ft_outline_glyph_transform( FT_Glyph outline_glyph,
218 const FT_Matrix* matrix,
219 const FT_Vector* delta )
221 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
224 if ( matrix )
225 FT_Outline_Transform( &glyph->outline, matrix );
227 if ( delta )
228 FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
232 FT_CALLBACK_DEF( void )
233 ft_outline_glyph_bbox( FT_Glyph outline_glyph,
234 FT_BBox* bbox )
236 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
239 FT_Outline_Get_CBox( &glyph->outline, bbox );
243 FT_CALLBACK_DEF( FT_Error )
244 ft_outline_glyph_prepare( FT_Glyph outline_glyph,
245 FT_GlyphSlot slot )
247 FT_OutlineGlyph glyph = (FT_OutlineGlyph)outline_glyph;
250 slot->format = FT_GLYPH_FORMAT_OUTLINE;
251 slot->outline = glyph->outline;
252 slot->outline.flags &= ~FT_OUTLINE_OWNER;
254 return FT_Err_Ok;
258 FT_CALLBACK_TABLE_DEF
259 const FT_Glyph_Class ft_outline_glyph_class =
261 sizeof ( FT_OutlineGlyphRec ),
262 FT_GLYPH_FORMAT_OUTLINE,
264 ft_outline_glyph_init,
265 ft_outline_glyph_done,
266 ft_outline_glyph_copy,
267 ft_outline_glyph_transform,
268 ft_outline_glyph_bbox,
269 ft_outline_glyph_prepare
273 /*************************************************************************/
274 /*************************************************************************/
275 /**** ****/
276 /**** FT_Glyph class and API ****/
277 /**** ****/
278 /*************************************************************************/
279 /*************************************************************************/
281 static FT_Error
282 ft_new_glyph( FT_Library library,
283 const FT_Glyph_Class* clazz,
284 FT_Glyph* aglyph )
286 FT_Memory memory = library->memory;
287 FT_Error error;
288 FT_Glyph glyph;
291 *aglyph = 0;
293 if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
295 glyph->library = library;
296 glyph->clazz = clazz;
297 glyph->format = clazz->glyph_format;
299 *aglyph = glyph;
302 return error;
306 /* documentation is in ftglyph.h */
308 FT_EXPORT_DEF( FT_Error )
309 FT_Glyph_Copy( FT_Glyph source,
310 FT_Glyph *target )
312 FT_Glyph copy;
313 FT_Error error;
314 const FT_Glyph_Class* clazz;
317 /* check arguments */
318 if ( !target )
320 error = FT_Err_Invalid_Argument;
321 goto Exit;
324 *target = 0;
326 if ( !source || !source->clazz )
328 error = FT_Err_Invalid_Argument;
329 goto Exit;
332 clazz = source->clazz;
333 error = ft_new_glyph( source->library, clazz, &copy );
334 if ( error )
335 goto Exit;
337 copy->advance = source->advance;
338 copy->format = source->format;
340 if ( clazz->glyph_copy )
341 error = clazz->glyph_copy( source, copy );
343 if ( error )
344 FT_Done_Glyph( copy );
345 else
346 *target = copy;
348 Exit:
349 return error;
353 /* documentation is in ftglyph.h */
355 FT_EXPORT_DEF( FT_Error )
356 FT_Get_Glyph( FT_GlyphSlot slot,
357 FT_Glyph *aglyph )
359 FT_Library library;
360 FT_Error error;
361 FT_Glyph glyph;
363 const FT_Glyph_Class* clazz = 0;
366 if ( !slot )
367 return FT_Err_Invalid_Slot_Handle;
369 library = slot->library;
371 if ( !aglyph )
372 return FT_Err_Invalid_Argument;
374 /* if it is a bitmap, that's easy :-) */
375 if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
376 clazz = &ft_bitmap_glyph_class;
378 /* it it is an outline too */
379 else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
380 clazz = &ft_outline_glyph_class;
382 else
384 /* try to find a renderer that supports the glyph image format */
385 FT_Renderer render = FT_Lookup_Renderer( library, slot->format, 0 );
388 if ( render )
389 clazz = &render->glyph_class;
392 if ( !clazz )
394 error = FT_Err_Invalid_Glyph_Format;
395 goto Exit;
398 /* create FT_Glyph object */
399 error = ft_new_glyph( library, clazz, &glyph );
400 if ( error )
401 goto Exit;
403 /* copy advance while converting it to 16.16 format */
404 glyph->advance.x = slot->advance.x << 10;
405 glyph->advance.y = slot->advance.y << 10;
407 /* now import the image from the glyph slot */
408 error = clazz->glyph_init( glyph, slot );
410 /* if an error occurred, destroy the glyph */
411 if ( error )
412 FT_Done_Glyph( glyph );
413 else
414 *aglyph = glyph;
416 Exit:
417 return error;
421 /* documentation is in ftglyph.h */
423 FT_EXPORT_DEF( FT_Error )
424 FT_Glyph_Transform( FT_Glyph glyph,
425 FT_Matrix* matrix,
426 FT_Vector* delta )
428 const FT_Glyph_Class* clazz;
429 FT_Error error = FT_Err_Ok;
432 if ( !glyph || !glyph->clazz )
433 error = FT_Err_Invalid_Argument;
434 else
436 clazz = glyph->clazz;
437 if ( clazz->glyph_transform )
439 /* transform glyph image */
440 clazz->glyph_transform( glyph, matrix, delta );
442 /* transform advance vector */
443 if ( matrix )
444 FT_Vector_Transform( &glyph->advance, matrix );
446 else
447 error = FT_Err_Invalid_Glyph_Format;
449 return error;
453 /* documentation is in ftglyph.h */
455 FT_EXPORT_DEF( void )
456 FT_Glyph_Get_CBox( FT_Glyph glyph,
457 FT_UInt bbox_mode,
458 FT_BBox *acbox )
460 const FT_Glyph_Class* clazz;
463 if ( !acbox )
464 return;
466 acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
468 if ( !glyph || !glyph->clazz )
469 return;
470 else
472 clazz = glyph->clazz;
473 if ( !clazz->glyph_bbox )
474 return;
475 else
477 /* retrieve bbox in 26.6 coordinates */
478 clazz->glyph_bbox( glyph, acbox );
480 /* perform grid fitting if needed */
481 if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
482 bbox_mode == FT_GLYPH_BBOX_PIXELS )
484 acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
485 acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
486 acbox->xMax = FT_PIX_CEIL( acbox->xMax );
487 acbox->yMax = FT_PIX_CEIL( acbox->yMax );
490 /* convert to integer pixels if needed */
491 if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
492 bbox_mode == FT_GLYPH_BBOX_PIXELS )
494 acbox->xMin >>= 6;
495 acbox->yMin >>= 6;
496 acbox->xMax >>= 6;
497 acbox->yMax >>= 6;
501 return;
505 /* documentation is in ftglyph.h */
507 FT_EXPORT_DEF( FT_Error )
508 FT_Glyph_To_Bitmap( FT_Glyph* the_glyph,
509 FT_Render_Mode render_mode,
510 FT_Vector* origin,
511 FT_Bool destroy )
513 FT_GlyphSlotRec dummy;
514 FT_GlyphSlot_InternalRec dummy_internal;
515 FT_Error error = FT_Err_Ok;
516 FT_Glyph glyph;
517 FT_BitmapGlyph bitmap = NULL;
519 const FT_Glyph_Class* clazz;
522 /* check argument */
523 if ( !the_glyph )
524 goto Bad;
526 /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
527 /* then calling FT_Render_Glyph_Internal() */
529 glyph = *the_glyph;
530 if ( !glyph )
531 goto Bad;
533 clazz = glyph->clazz;
535 /* when called with a bitmap glyph, do nothing and return successfully */
536 if ( clazz == &ft_bitmap_glyph_class )
537 goto Exit;
539 if ( !clazz || !clazz->glyph_prepare )
540 goto Bad;
542 FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
543 FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
544 dummy.internal = &dummy_internal;
545 dummy.library = glyph->library;
546 dummy.format = clazz->glyph_format;
548 /* create result bitmap glyph */
549 error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
550 (FT_Glyph*)(void*)&bitmap );
551 if ( error )
552 goto Exit;
554 #if 1
555 /* if `origin' is set, translate the glyph image */
556 if ( origin )
557 FT_Glyph_Transform( glyph, 0, origin );
558 #else
559 FT_UNUSED( origin );
560 #endif
562 /* prepare dummy slot for rendering */
563 error = clazz->glyph_prepare( glyph, &dummy );
564 if ( !error )
565 error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
567 #if 1
568 if ( !destroy && origin )
570 FT_Vector v;
573 v.x = -origin->x;
574 v.y = -origin->y;
575 FT_Glyph_Transform( glyph, 0, &v );
577 #endif
579 if ( error )
580 goto Exit;
582 /* in case of success, copy the bitmap to the glyph bitmap */
583 error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
584 if ( error )
585 goto Exit;
587 /* copy advance */
588 bitmap->root.advance = glyph->advance;
590 if ( destroy )
591 FT_Done_Glyph( glyph );
593 *the_glyph = FT_GLYPH( bitmap );
595 Exit:
596 if ( error && bitmap )
597 FT_Done_Glyph( FT_GLYPH( bitmap ) );
599 return error;
601 Bad:
602 error = FT_Err_Invalid_Argument;
603 goto Exit;
607 /* documentation is in ftglyph.h */
609 FT_EXPORT_DEF( void )
610 FT_Done_Glyph( FT_Glyph glyph )
612 if ( glyph )
614 FT_Memory memory = glyph->library->memory;
615 const FT_Glyph_Class* clazz = glyph->clazz;
618 if ( clazz->glyph_done )
619 clazz->glyph_done( glyph );
621 FT_FREE( glyph );
626 /* END */