source: trunk/poppler/freetype2/src/base/ftglyph.c @ 251

Last change on this file since 251 was 251, checked in by Eugene Romanenko, 13 years ago

PDF plugin: freetype library updated to version 2.3.5

File size: 17.6 KB
Line 
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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 )
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
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 )
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 )
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 )
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 )
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 )
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 )
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 */
Note: See TracBrowser for help on using the repository browser.