fxft_ftglyph.c revision ee451cb395940862dad63c85adfe8f2fd55e864c
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, &copy );
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
632