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, 2010 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 = NULL; |
|
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, © ); |
|
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 */ |
|