ftglyph.c revision 41371e1e39c8528eb0c4bc40683c736e6683e60c
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, &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 )
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    const FT_Glyph_Class*     clazz;
516
517    /* FT_BITMAP_GLYPH_CLASS_GET derefers `library' in PIC mode */
518    FT_Library                library;
519
520
521    /* check argument */
522    if ( !the_glyph )
523      goto Bad;
524    glyph = *the_glyph;
525    if ( !glyph )
526      goto Bad;
527
528    clazz   = glyph->clazz;
529    library = glyph->library;
530    if ( !library || !clazz )
531      goto Bad;
532
533    /* when called with a bitmap glyph, do nothing and return successfully */
534    if ( clazz == FT_BITMAP_GLYPH_CLASS_GET )
535      goto Exit;
536
537    if ( !clazz->glyph_prepare )
538      goto Bad;
539
540    /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
541    /* then calling FT_Render_Glyph_Internal()                            */
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  = library;
547    dummy.format   = clazz->glyph_format;
548
549    /* create result bitmap glyph */
550    error = ft_new_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 */
628