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