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