source: trunk/poppler/freetype-2.1.10/src/base/ftglyph.c @ 2

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

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