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