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 )
ft_bitmap_glyph_init(FT_Glyph bitmap_glyph,FT_GlyphSlot slot)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 )
ft_bitmap_glyph_copy(FT_Glyph bitmap_source,FT_Glyph bitmap_target)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 )
ft_bitmap_glyph_done(FT_Glyph bitmap_glyph)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 )
ft_bitmap_glyph_bbox(FT_Glyph bitmap_glyph,FT_BBox * cbox)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 
FT_CALLBACK_DEF(FT_Error)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 )
ft_outline_glyph_done(FT_Glyph outline_glyph)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 )
ft_outline_glyph_copy(FT_Glyph outline_source,FT_Glyph outline_target)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 )
ft_outline_glyph_transform(FT_Glyph outline_glyph,const FT_Matrix * matrix,const FT_Vector * delta)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 )
ft_outline_glyph_bbox(FT_Glyph outline_glyph,FT_BBox * bbox)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 )
ft_outline_glyph_prepare(FT_Glyph outline_glyph,FT_GlyphSlot slot)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 
FT_DEFINE_GLYPH(ft_outline_glyph_class,sizeof (FT_OutlineGlyphRec),FT_GLYPH_FORMAT_OUTLINE,ft_outline_glyph_init,ft_outline_glyph_done,ft_outline_glyph_copy,ft_outline_glyph_transform,ft_outline_glyph_bbox,ft_outline_glyph_prepare)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 )
FT_Glyph_Copy(FT_Glyph source,FT_Glyph * target)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 )
FT_Get_Glyph(FT_GlyphSlot slot,FT_Glyph * aglyph)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 )
FT_Glyph_Transform(FT_Glyph glyph,FT_Matrix * matrix,FT_Vector * delta)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 )
FT_Glyph_Get_CBox(FT_Glyph glyph,FT_UInt bbox_mode,FT_BBox * acbox)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 )
FT_Glyph_To_Bitmap(FT_Glyph * the_glyph,FT_Render_Mode render_mode,FT_Vector * origin,FT_Bool destroy)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 )
FT_Done_Glyph(FT_Glyph glyph)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 */
628