1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftglyph.c                                                              */
4 /*                                                                         */
5 /*    FreeType convenience functions to handle glyphs (body).              */
6 /*                                                                         */
7 /*  Copyright 1996-2016 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_INTERNAL_DEBUG_H
33 
34 #include FT_GLYPH_H
35 #include FT_OUTLINE_H
36 #include FT_BITMAP_H
37 #include FT_INTERNAL_OBJECTS_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 )
ft_bitmap_glyph_init(FT_Glyph bitmap_glyph,FT_GlyphSlot slot)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_Init( &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 )
ft_bitmap_glyph_copy(FT_Glyph bitmap_source,FT_Glyph bitmap_target)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 )
ft_bitmap_glyph_done(FT_Glyph bitmap_glyph)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 )
ft_bitmap_glyph_bbox(FT_Glyph bitmap_glyph,FT_BBox * cbox)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 * 64;
129     cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 );
130     cbox->yMax = glyph->top * 64;
131     cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 );
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 
FT_CALLBACK_DEF(FT_Error)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,
177                             (FT_UInt)source->n_points,
178                             source->n_contours,
179                             &glyph->outline );
180     if ( error )
181       goto Exit;
182 
183     FT_Outline_Copy( source, target );
184 
185   Exit:
186     return error;
187   }
188 
189 
190   FT_CALLBACK_DEF( void )
ft_outline_glyph_done(FT_Glyph outline_glyph)191   ft_outline_glyph_done( FT_Glyph  outline_glyph )
192   {
193     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
194 
195 
196     FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
197   }
198 
199 
200   FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_copy(FT_Glyph outline_source,FT_Glyph outline_target)201   ft_outline_glyph_copy( FT_Glyph  outline_source,
202                          FT_Glyph  outline_target )
203   {
204     FT_OutlineGlyph  source  = (FT_OutlineGlyph)outline_source;
205     FT_OutlineGlyph  target  = (FT_OutlineGlyph)outline_target;
206     FT_Error         error;
207     FT_Library       library = FT_GLYPH( source )->library;
208 
209 
210     error = FT_Outline_New( library,
211                             (FT_UInt)source->outline.n_points,
212                             source->outline.n_contours,
213                             &target->outline );
214     if ( !error )
215       FT_Outline_Copy( &source->outline, &target->outline );
216 
217     return error;
218   }
219 
220 
221   FT_CALLBACK_DEF( void )
ft_outline_glyph_transform(FT_Glyph outline_glyph,const FT_Matrix * matrix,const FT_Vector * delta)222   ft_outline_glyph_transform( FT_Glyph          outline_glyph,
223                               const FT_Matrix*  matrix,
224                               const FT_Vector*  delta )
225   {
226     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
227 
228 
229     if ( matrix )
230       FT_Outline_Transform( &glyph->outline, matrix );
231 
232     if ( delta )
233       FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
234   }
235 
236 
237   FT_CALLBACK_DEF( void )
ft_outline_glyph_bbox(FT_Glyph outline_glyph,FT_BBox * bbox)238   ft_outline_glyph_bbox( FT_Glyph  outline_glyph,
239                          FT_BBox*  bbox )
240   {
241     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
242 
243 
244     FT_Outline_Get_CBox( &glyph->outline, bbox );
245   }
246 
247 
248   FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_prepare(FT_Glyph outline_glyph,FT_GlyphSlot slot)249   ft_outline_glyph_prepare( FT_Glyph      outline_glyph,
250                             FT_GlyphSlot  slot )
251   {
252     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
253 
254 
255     slot->format         = FT_GLYPH_FORMAT_OUTLINE;
256     slot->outline        = glyph->outline;
257     slot->outline.flags &= ~FT_OUTLINE_OWNER;
258 
259     return FT_Err_Ok;
260   }
261 
262 
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)263   FT_DEFINE_GLYPH( ft_outline_glyph_class,
264     sizeof ( FT_OutlineGlyphRec ),
265     FT_GLYPH_FORMAT_OUTLINE,
266 
267     ft_outline_glyph_init,
268     ft_outline_glyph_done,
269     ft_outline_glyph_copy,
270     ft_outline_glyph_transform,
271     ft_outline_glyph_bbox,
272     ft_outline_glyph_prepare
273   )
274 
275 
276   /*************************************************************************/
277   /*************************************************************************/
278   /****                                                                 ****/
279   /****   FT_Glyph class and API                                        ****/
280   /****                                                                 ****/
281   /*************************************************************************/
282   /*************************************************************************/
283 
284    static FT_Error
285    ft_new_glyph( FT_Library             library,
286                  const FT_Glyph_Class*  clazz,
287                  FT_Glyph*              aglyph )
288    {
289      FT_Memory  memory = library->memory;
290      FT_Error   error;
291      FT_Glyph   glyph  = NULL;
292 
293 
294      *aglyph = NULL;
295 
296      if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
297      {
298        glyph->library = library;
299        glyph->clazz   = clazz;
300        glyph->format  = clazz->glyph_format;
301 
302        *aglyph = glyph;
303      }
304 
305      return error;
306    }
307 
308 
309   /* documentation is in ftglyph.h */
310 
311   FT_EXPORT_DEF( FT_Error )
FT_Glyph_Copy(FT_Glyph source,FT_Glyph * target)312   FT_Glyph_Copy( FT_Glyph   source,
313                  FT_Glyph  *target )
314   {
315     FT_Glyph               copy;
316     FT_Error               error;
317     const FT_Glyph_Class*  clazz;
318 
319 
320     /* check arguments */
321     if ( !target || !source || !source->clazz )
322     {
323       error = FT_THROW( Invalid_Argument );
324       goto Exit;
325     }
326 
327     *target = NULL;
328 
329     if ( !source || !source->clazz )
330     {
331       error = FT_THROW( Invalid_Argument );
332       goto Exit;
333     }
334 
335     clazz = source->clazz;
336     error = ft_new_glyph( source->library, clazz, &copy );
337     if ( error )
338       goto Exit;
339 
340     copy->advance = source->advance;
341     copy->format  = source->format;
342 
343     if ( clazz->glyph_copy )
344       error = clazz->glyph_copy( source, copy );
345 
346     if ( error )
347       FT_Done_Glyph( copy );
348     else
349       *target = copy;
350 
351   Exit:
352     return error;
353   }
354 
355 
356   /* documentation is in ftglyph.h */
357 
358   FT_EXPORT_DEF( FT_Error )
FT_Get_Glyph(FT_GlyphSlot slot,FT_Glyph * aglyph)359   FT_Get_Glyph( FT_GlyphSlot  slot,
360                 FT_Glyph     *aglyph )
361   {
362     FT_Library  library;
363     FT_Error    error;
364     FT_Glyph    glyph;
365 
366     const FT_Glyph_Class*  clazz = NULL;
367 
368 
369     if ( !slot )
370       return FT_THROW( Invalid_Slot_Handle );
371 
372     library = slot->library;
373 
374     if ( !aglyph )
375       return FT_THROW( Invalid_Argument );
376 
377     /* if it is a bitmap, that's easy :-) */
378     if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
379       clazz = FT_BITMAP_GLYPH_CLASS_GET;
380 
381     /* if it is an outline */
382     else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
383       clazz = FT_OUTLINE_GLYPH_CLASS_GET;
384 
385     else
386     {
387       /* try to find a renderer that supports the glyph image format */
388       FT_Renderer  render = FT_Lookup_Renderer( library, slot->format, 0 );
389 
390 
391       if ( render )
392         clazz = &render->glyph_class;
393     }
394 
395     if ( !clazz )
396     {
397       error = FT_THROW( Invalid_Glyph_Format );
398       goto Exit;
399     }
400 
401     /* create FT_Glyph object */
402     error = ft_new_glyph( library, clazz, &glyph );
403     if ( error )
404       goto Exit;
405 
406     /* copy advance while converting 26.6 to 16.16 format */
407     glyph->advance.x = slot->advance.x * 1024;
408     glyph->advance.y = slot->advance.y * 1024;
409 
410     /* now import the image from the glyph slot */
411     error = clazz->glyph_init( glyph, slot );
412 
413     /* if an error occurred, destroy the glyph */
414     if ( error )
415       FT_Done_Glyph( glyph );
416     else
417       *aglyph = glyph;
418 
419   Exit:
420     return error;
421   }
422 
423 
424   /* documentation is in ftglyph.h */
425 
426   FT_EXPORT_DEF( FT_Error )
FT_Glyph_Transform(FT_Glyph glyph,FT_Matrix * matrix,FT_Vector * delta)427   FT_Glyph_Transform( FT_Glyph    glyph,
428                       FT_Matrix*  matrix,
429                       FT_Vector*  delta )
430   {
431     FT_Error  error = FT_Err_Ok;
432 
433 
434     if ( !glyph || !glyph->clazz )
435       error = FT_THROW( Invalid_Argument );
436     else
437     {
438       const FT_Glyph_Class*  clazz = glyph->clazz;
439 
440 
441       if ( clazz->glyph_transform )
442       {
443         /* transform glyph image */
444         clazz->glyph_transform( glyph, matrix, delta );
445 
446         /* transform advance vector */
447         if ( matrix )
448           FT_Vector_Transform( &glyph->advance, matrix );
449       }
450       else
451         error = FT_THROW( Invalid_Glyph_Format );
452     }
453     return error;
454   }
455 
456 
457   /* documentation is in ftglyph.h */
458 
459   FT_EXPORT_DEF( void )
FT_Glyph_Get_CBox(FT_Glyph glyph,FT_UInt bbox_mode,FT_BBox * acbox)460   FT_Glyph_Get_CBox( FT_Glyph  glyph,
461                      FT_UInt   bbox_mode,
462                      FT_BBox  *acbox )
463   {
464     const FT_Glyph_Class*  clazz;
465 
466 
467     if ( !acbox )
468       return;
469 
470     acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
471 
472     if ( !glyph || !glyph->clazz )
473       return;
474 
475     clazz = glyph->clazz;
476     if ( !clazz->glyph_bbox )
477       return;
478 
479     /* retrieve bbox in 26.6 coordinates */
480     clazz->glyph_bbox( glyph, acbox );
481 
482     /* perform grid fitting if needed */
483     if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
484          bbox_mode == FT_GLYPH_BBOX_PIXELS  )
485     {
486       acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
487       acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
488       acbox->xMax = FT_PIX_CEIL( acbox->xMax );
489       acbox->yMax = FT_PIX_CEIL( acbox->yMax );
490     }
491 
492     /* convert to integer pixels if needed */
493     if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
494          bbox_mode == FT_GLYPH_BBOX_PIXELS   )
495     {
496       acbox->xMin >>= 6;
497       acbox->yMin >>= 6;
498       acbox->xMax >>= 6;
499       acbox->yMax >>= 6;
500     }
501   }
502 
503 
504   /* documentation is in ftglyph.h */
505 
506   FT_EXPORT_DEF( FT_Error )
FT_Glyph_To_Bitmap(FT_Glyph * the_glyph,FT_Render_Mode render_mode,FT_Vector * origin,FT_Bool destroy)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 dereferences `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 )
FT_Done_Glyph(FT_Glyph glyph)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