OLD | NEW |
| (Empty) |
1 #if !defined(_FXFT_VERSION_) || _FXFT_VERSION_ == 2501 | |
2 /***************************************************************************/ | |
3 /* */ | |
4 /* ftglyph.c */ | |
5 /* */ | |
6 /* FreeType convenience functions to handle glyphs (body). */ | |
7 /* */ | |
8 /* Copyright 1996-2005, 2007, 2008, 2010, 2012, 2013 by */ | |
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | |
10 /* */ | |
11 /* This file is part of the FreeType project, and may only be used, */ | |
12 /* modified, and distributed under the terms of the FreeType project */ | |
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | |
14 /* this file you indicate that you have read the license and */ | |
15 /* understand and accept it fully. */ | |
16 /* */ | |
17 /***************************************************************************/ | |
18 | |
19 /*************************************************************************/ | |
20 /* */ | |
21 /* This file contains the definition of several convenience functions */ | |
22 /* that can be used by client applications to easily retrieve glyph */ | |
23 /* bitmaps and outlines from a given face. */ | |
24 /* */ | |
25 /* These functions should be optional if you are writing a font server */ | |
26 /* or text layout engine on top of FreeType. However, they are pretty */ | |
27 /* handy for many other simple uses of the library. */ | |
28 /* */ | |
29 /*************************************************************************/ | |
30 | |
31 #define FT2_BUILD_LIBRARY | |
32 #include "../../include/ft2build.h" | |
33 #include "../../include/freetype/internal/ftdebug.h" | |
34 #include "../../include/freetype/ftglyph.h" | |
35 #include "../../include/freetype/ftoutln.h" | |
36 #include "../../include/freetype/ftbitmap.h" | |
37 #include "../../include/freetype/internal/ftobjs.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 0 /* FT_Glyph_PrepareFunc */ | |
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 */ | |
630 #endif | |
631 | |
OLD | NEW |