• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /****************************************************************************
2  *
3  * ftglyph.c
4  *
5  *   FreeType convenience functions to handle glyphs (body).
6  *
7  * Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h>
32 
33 #include <freetype/ftglyph.h>
34 #include <freetype/ftoutln.h>
35 #include <freetype/ftbitmap.h>
36 #include <freetype/internal/ftobjs.h>
37 #include <freetype/otsvg.h>
38 
39 #include "ftbase.h"
40 
41 
42   /**************************************************************************
43    *
44    * The macro FT_COMPONENT is used in trace mode.  It is an implicit
45    * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
46    * messages during execution.
47    */
48 #undef  FT_COMPONENT
49 #define FT_COMPONENT  glyph
50 
51 
52   /*************************************************************************/
53   /*************************************************************************/
54   /****                                                                 ****/
55   /****   FT_BitmapGlyph support                                        ****/
56   /****                                                                 ****/
57   /*************************************************************************/
58   /*************************************************************************/
59 
60   FT_CALLBACK_DEF( FT_Error )
ft_bitmap_glyph_init(FT_Glyph bitmap_glyph,FT_GlyphSlot slot)61   ft_bitmap_glyph_init( FT_Glyph      bitmap_glyph,
62                         FT_GlyphSlot  slot )
63   {
64     FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
65     FT_Error        error   = FT_Err_Ok;
66     FT_Library      library = FT_GLYPH( glyph )->library;
67 
68 
69     if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
70     {
71       error = FT_THROW( Invalid_Glyph_Format );
72       goto Exit;
73     }
74 
75     glyph->left = slot->bitmap_left;
76     glyph->top  = slot->bitmap_top;
77 
78     /* do lazy copying whenever possible */
79     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
80     {
81       glyph->bitmap          = slot->bitmap;
82       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
83     }
84     else
85     {
86       FT_Bitmap_Init( &glyph->bitmap );
87       error = FT_Bitmap_Copy( library, &slot->bitmap, &glyph->bitmap );
88     }
89 
90   Exit:
91     return error;
92   }
93 
94 
95   FT_CALLBACK_DEF( FT_Error )
ft_bitmap_glyph_copy(FT_Glyph bitmap_source,FT_Glyph bitmap_target)96   ft_bitmap_glyph_copy( FT_Glyph  bitmap_source,
97                         FT_Glyph  bitmap_target )
98   {
99     FT_Library      library = bitmap_source->library;
100     FT_BitmapGlyph  source  = (FT_BitmapGlyph)bitmap_source;
101     FT_BitmapGlyph  target  = (FT_BitmapGlyph)bitmap_target;
102 
103 
104     target->left = source->left;
105     target->top  = source->top;
106 
107     return FT_Bitmap_Copy( library, &source->bitmap, &target->bitmap );
108   }
109 
110 
111   FT_CALLBACK_DEF( void )
ft_bitmap_glyph_done(FT_Glyph bitmap_glyph)112   ft_bitmap_glyph_done( FT_Glyph  bitmap_glyph )
113   {
114     FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
115     FT_Library      library = FT_GLYPH( glyph )->library;
116 
117 
118     FT_Bitmap_Done( library, &glyph->bitmap );
119   }
120 
121 
122   FT_CALLBACK_DEF( void )
ft_bitmap_glyph_bbox(FT_Glyph bitmap_glyph,FT_BBox * cbox)123   ft_bitmap_glyph_bbox( FT_Glyph  bitmap_glyph,
124                         FT_BBox*  cbox )
125   {
126     FT_BitmapGlyph  glyph = (FT_BitmapGlyph)bitmap_glyph;
127 
128 
129     cbox->xMin = glyph->left * 64;
130     cbox->xMax = cbox->xMin + (FT_Pos)( glyph->bitmap.width * 64 );
131     cbox->yMax = glyph->top * 64;
132     cbox->yMin = cbox->yMax - (FT_Pos)( glyph->bitmap.rows * 64 );
133   }
134 
135 
FT_DEFINE_GLYPH(ft_bitmap_glyph_class,sizeof (FT_BitmapGlyphRec),FT_GLYPH_FORMAT_BITMAP,ft_bitmap_glyph_init,ft_bitmap_glyph_done,ft_bitmap_glyph_copy,NULL,ft_bitmap_glyph_bbox,NULL)136   FT_DEFINE_GLYPH(
137     ft_bitmap_glyph_class,
138 
139     sizeof ( FT_BitmapGlyphRec ),
140     FT_GLYPH_FORMAT_BITMAP,
141 
142     ft_bitmap_glyph_init,    /* FT_Glyph_InitFunc       glyph_init      */
143     ft_bitmap_glyph_done,    /* FT_Glyph_DoneFunc       glyph_done      */
144     ft_bitmap_glyph_copy,    /* FT_Glyph_CopyFunc       glyph_copy      */
145     NULL,                    /* FT_Glyph_TransformFunc  glyph_transform */
146     ft_bitmap_glyph_bbox,    /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
147     NULL                     /* FT_Glyph_PrepareFunc    glyph_prepare   */
148   )
149 
150 
151   /*************************************************************************/
152   /*************************************************************************/
153   /****                                                                 ****/
154   /****   FT_OutlineGlyph support                                       ****/
155   /****                                                                 ****/
156   /*************************************************************************/
157   /*************************************************************************/
158 
159 
160   FT_CALLBACK_DEF( FT_Error )
161   ft_outline_glyph_init( FT_Glyph      outline_glyph,
162                          FT_GlyphSlot  slot )
163   {
164     FT_OutlineGlyph  glyph   = (FT_OutlineGlyph)outline_glyph;
165     FT_Error         error   = FT_Err_Ok;
166     FT_Library       library = FT_GLYPH( glyph )->library;
167     FT_Outline*      source  = &slot->outline;
168     FT_Outline*      target  = &glyph->outline;
169 
170 
171     /* check format in glyph slot */
172     if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
173     {
174       error = FT_THROW( Invalid_Glyph_Format );
175       goto Exit;
176     }
177 
178     /* allocate new outline */
179     error = FT_Outline_New( library,
180                             (FT_UInt)source->n_points,
181                             source->n_contours,
182                             &glyph->outline );
183     if ( error )
184       goto Exit;
185 
186     FT_Outline_Copy( source, target );
187 
188   Exit:
189     return error;
190   }
191 
192 
193   FT_CALLBACK_DEF( void )
ft_outline_glyph_done(FT_Glyph outline_glyph)194   ft_outline_glyph_done( FT_Glyph  outline_glyph )
195   {
196     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
197 
198 
199     FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
200   }
201 
202 
203   FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_copy(FT_Glyph outline_source,FT_Glyph outline_target)204   ft_outline_glyph_copy( FT_Glyph  outline_source,
205                          FT_Glyph  outline_target )
206   {
207     FT_OutlineGlyph  source  = (FT_OutlineGlyph)outline_source;
208     FT_OutlineGlyph  target  = (FT_OutlineGlyph)outline_target;
209     FT_Error         error;
210     FT_Library       library = FT_GLYPH( source )->library;
211 
212 
213     error = FT_Outline_New( library,
214                             (FT_UInt)source->outline.n_points,
215                             source->outline.n_contours,
216                             &target->outline );
217     if ( !error )
218       FT_Outline_Copy( &source->outline, &target->outline );
219 
220     return error;
221   }
222 
223 
224   FT_CALLBACK_DEF( void )
ft_outline_glyph_transform(FT_Glyph outline_glyph,const FT_Matrix * matrix,const FT_Vector * delta)225   ft_outline_glyph_transform( FT_Glyph          outline_glyph,
226                               const FT_Matrix*  matrix,
227                               const FT_Vector*  delta )
228   {
229     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
230 
231 
232     if ( matrix )
233       FT_Outline_Transform( &glyph->outline, matrix );
234 
235     if ( delta )
236       FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
237   }
238 
239 
240   FT_CALLBACK_DEF( void )
ft_outline_glyph_bbox(FT_Glyph outline_glyph,FT_BBox * bbox)241   ft_outline_glyph_bbox( FT_Glyph  outline_glyph,
242                          FT_BBox*  bbox )
243   {
244     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
245 
246 
247     FT_Outline_Get_CBox( &glyph->outline, bbox );
248   }
249 
250 
251   FT_CALLBACK_DEF( FT_Error )
ft_outline_glyph_prepare(FT_Glyph outline_glyph,FT_GlyphSlot slot)252   ft_outline_glyph_prepare( FT_Glyph      outline_glyph,
253                             FT_GlyphSlot  slot )
254   {
255     FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
256 
257 
258     slot->format         = FT_GLYPH_FORMAT_OUTLINE;
259     slot->outline        = glyph->outline;
260     slot->outline.flags &= ~FT_OUTLINE_OWNER;
261 
262     return FT_Err_Ok;
263   }
264 
265 
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)266   FT_DEFINE_GLYPH(
267     ft_outline_glyph_class,
268 
269     sizeof ( FT_OutlineGlyphRec ),
270     FT_GLYPH_FORMAT_OUTLINE,
271 
272     ft_outline_glyph_init,      /* FT_Glyph_InitFunc       glyph_init      */
273     ft_outline_glyph_done,      /* FT_Glyph_DoneFunc       glyph_done      */
274     ft_outline_glyph_copy,      /* FT_Glyph_CopyFunc       glyph_copy      */
275     ft_outline_glyph_transform, /* FT_Glyph_TransformFunc  glyph_transform */
276     ft_outline_glyph_bbox,      /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
277     ft_outline_glyph_prepare    /* FT_Glyph_PrepareFunc    glyph_prepare   */
278   )
279 
280 
281 #ifdef FT_CONFIG_OPTION_SVG
282 
283   /*************************************************************************/
284   /*************************************************************************/
285   /****                                                                 ****/
286   /****   FT_SvgGlyph support                                           ****/
287   /****                                                                 ****/
288   /*************************************************************************/
289   /*************************************************************************/
290 
291 
292   FT_CALLBACK_DEF( FT_Error )
293   ft_svg_glyph_init( FT_Glyph      svg_glyph,
294                      FT_GlyphSlot  slot )
295   {
296     FT_ULong         doc_length;
297     FT_SVG_Document  document;
298     FT_SvgGlyph      glyph = (FT_SvgGlyph)svg_glyph;
299 
300     FT_Error   error  = FT_Err_Ok;
301     FT_Memory  memory = FT_GLYPH( glyph )->library->memory;
302 
303 
304     if ( slot->format != FT_GLYPH_FORMAT_SVG )
305     {
306       error = FT_THROW( Invalid_Glyph_Format );
307       goto Exit;
308     }
309 
310     if ( slot->other == NULL )
311     {
312       error = FT_THROW( Invalid_Slot_Handle );
313       goto Exit;
314     }
315 
316     document = (FT_SVG_Document)slot->other;
317 
318     if ( document->svg_document_length == 0 )
319     {
320       error = FT_THROW( Invalid_Slot_Handle );
321       goto Exit;
322     }
323 
324     /* allocate a new document */
325     doc_length = document->svg_document_length;
326     if ( FT_QALLOC( glyph->svg_document, doc_length ) )
327       goto Exit;
328     glyph->svg_document_length = doc_length;
329 
330     glyph->glyph_index = slot->glyph_index;
331 
332     glyph->metrics      = document->metrics;
333     glyph->units_per_EM = document->units_per_EM;
334 
335     glyph->start_glyph_id = document->start_glyph_id;
336     glyph->end_glyph_id   = document->end_glyph_id;
337 
338     glyph->transform = document->transform;
339     glyph->delta     = document->delta;
340 
341     /* copy the document into glyph */
342     FT_MEM_COPY( glyph->svg_document, document->svg_document, doc_length );
343 
344   Exit:
345     return error;
346   }
347 
348 
349   FT_CALLBACK_DEF( void )
ft_svg_glyph_done(FT_Glyph svg_glyph)350   ft_svg_glyph_done( FT_Glyph  svg_glyph )
351   {
352     FT_SvgGlyph  glyph  = (FT_SvgGlyph)svg_glyph;
353     FT_Memory    memory = svg_glyph->library->memory;
354 
355 
356     /* just free the memory */
357     FT_FREE( glyph->svg_document );
358   }
359 
360 
361   FT_CALLBACK_DEF( FT_Error )
ft_svg_glyph_copy(FT_Glyph svg_source,FT_Glyph svg_target)362   ft_svg_glyph_copy( FT_Glyph  svg_source,
363                      FT_Glyph  svg_target )
364   {
365     FT_SvgGlyph  source = (FT_SvgGlyph)svg_source;
366     FT_SvgGlyph  target = (FT_SvgGlyph)svg_target;
367 
368     FT_Error   error  = FT_Err_Ok;
369     FT_Memory  memory = FT_GLYPH( source )->library->memory;
370 
371 
372     if ( svg_source->format != FT_GLYPH_FORMAT_SVG )
373     {
374       error = FT_THROW( Invalid_Glyph_Format );
375       goto Exit;
376     }
377 
378     if ( source->svg_document_length == 0 )
379     {
380       error = FT_THROW( Invalid_Slot_Handle );
381       goto Exit;
382     }
383 
384     target->glyph_index = source->glyph_index;
385 
386     target->svg_document_length = source->svg_document_length;
387 
388     target->metrics      = source->metrics;
389     target->units_per_EM = source->units_per_EM;
390 
391     target->start_glyph_id = source->start_glyph_id;
392     target->end_glyph_id   = source->end_glyph_id;
393 
394     target->transform = source->transform;
395     target->delta     = source->delta;
396 
397     /* allocate space for the SVG document */
398     if ( FT_QALLOC( target->svg_document, target->svg_document_length ) )
399       goto Exit;
400 
401     /* copy the document */
402     FT_MEM_COPY( target->svg_document,
403                  source->svg_document,
404                  target->svg_document_length );
405 
406   Exit:
407     return error;
408   }
409 
410 
411   FT_CALLBACK_DEF( void )
ft_svg_glyph_transform(FT_Glyph svg_glyph,const FT_Matrix * _matrix,const FT_Vector * _delta)412   ft_svg_glyph_transform( FT_Glyph          svg_glyph,
413                           const FT_Matrix*  _matrix,
414                           const FT_Vector*  _delta )
415   {
416     FT_SvgGlyph  glyph  = (FT_SvgGlyph)svg_glyph;
417     FT_Matrix*   matrix = (FT_Matrix*)_matrix;
418     FT_Vector*   delta  = (FT_Vector*)_delta;
419 
420     FT_Matrix  tmp_matrix;
421     FT_Vector  tmp_delta;
422 
423     FT_Matrix  a, b;
424     FT_Pos     x, y;
425 
426 
427     if ( !matrix )
428     {
429       tmp_matrix.xx = 0x10000;
430       tmp_matrix.xy = 0;
431       tmp_matrix.yx = 0;
432       tmp_matrix.yy = 0x10000;
433 
434       matrix = &tmp_matrix;
435     }
436 
437     if ( !delta )
438     {
439       tmp_delta.x = 0;
440       tmp_delta.y = 0;
441 
442       delta = &tmp_delta;
443     }
444 
445     a = glyph->transform;
446     b = *matrix;
447     FT_Matrix_Multiply( &b, &a );
448 
449     x = ADD_LONG( ADD_LONG( FT_MulFix( matrix->xx, glyph->delta.x ),
450                             FT_MulFix( matrix->xy, glyph->delta.y ) ),
451                   delta->x );
452     y = ADD_LONG( ADD_LONG( FT_MulFix( matrix->yx, glyph->delta.x ),
453                             FT_MulFix( matrix->yy, glyph->delta.y ) ),
454                   delta->y );
455 
456     glyph->delta.x = x;
457     glyph->delta.y = y;
458 
459     glyph->transform = a;
460   }
461 
462 
463   FT_CALLBACK_DEF( FT_Error )
ft_svg_glyph_prepare(FT_Glyph svg_glyph,FT_GlyphSlot slot)464   ft_svg_glyph_prepare( FT_Glyph      svg_glyph,
465                         FT_GlyphSlot  slot )
466   {
467     FT_SvgGlyph  glyph = (FT_SvgGlyph)svg_glyph;
468 
469     FT_Error   error  = FT_Err_Ok;
470     FT_Memory  memory = svg_glyph->library->memory;
471 
472     FT_SVG_Document  document = NULL;
473 
474 
475     if ( FT_NEW( document ) )
476       return error;
477 
478     document->svg_document        = glyph->svg_document;
479     document->svg_document_length = glyph->svg_document_length;
480 
481     document->metrics      = glyph->metrics;
482     document->units_per_EM = glyph->units_per_EM;
483 
484     document->start_glyph_id = glyph->start_glyph_id;
485     document->end_glyph_id   = glyph->end_glyph_id;
486 
487     document->transform = glyph->transform;
488     document->delta     = glyph->delta;
489 
490     slot->format      = FT_GLYPH_FORMAT_SVG;
491     slot->glyph_index = glyph->glyph_index;
492     slot->other       = document;
493 
494     return error;
495   }
496 
497 
FT_DEFINE_GLYPH(ft_svg_glyph_class,sizeof (FT_SvgGlyphRec),FT_GLYPH_FORMAT_SVG,ft_svg_glyph_init,ft_svg_glyph_done,ft_svg_glyph_copy,ft_svg_glyph_transform,NULL,ft_svg_glyph_prepare)498   FT_DEFINE_GLYPH(
499     ft_svg_glyph_class,
500 
501     sizeof ( FT_SvgGlyphRec ),
502     FT_GLYPH_FORMAT_SVG,
503 
504     ft_svg_glyph_init,      /* FT_Glyph_InitFunc       glyph_init      */
505     ft_svg_glyph_done,      /* FT_Glyph_DoneFunc       glyph_done      */
506     ft_svg_glyph_copy,      /* FT_Glyph_CopyFunc       glyph_copy      */
507     ft_svg_glyph_transform, /* FT_Glyph_TransformFunc  glyph_transform */
508     NULL,                   /* FT_Glyph_GetBBoxFunc    glyph_bbox      */
509     ft_svg_glyph_prepare    /* FT_Glyph_PrepareFunc    glyph_prepare   */
510   )
511 
512 #endif /* FT_CONFIG_OPTION_SVG */
513 
514 
515   /*************************************************************************/
516   /*************************************************************************/
517   /****                                                                 ****/
518   /****   FT_Glyph class and API                                        ****/
519   /****                                                                 ****/
520   /*************************************************************************/
521   /*************************************************************************/
522 
523    static FT_Error
524    ft_new_glyph( FT_Library             library,
525                  const FT_Glyph_Class*  clazz,
526                  FT_Glyph*              aglyph )
527    {
528      FT_Memory  memory = library->memory;
529      FT_Error   error;
530      FT_Glyph   glyph  = NULL;
531 
532 
533      *aglyph = NULL;
534 
535      if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
536      {
537        glyph->library = library;
538        glyph->clazz   = clazz;
539        glyph->format  = clazz->glyph_format;
540 
541        *aglyph = glyph;
542      }
543 
544      return error;
545    }
546 
547 
548   /* documentation is in ftglyph.h */
549 
550   FT_EXPORT_DEF( FT_Error )
FT_Glyph_Copy(FT_Glyph source,FT_Glyph * target)551   FT_Glyph_Copy( FT_Glyph   source,
552                  FT_Glyph  *target )
553   {
554     FT_Glyph               copy;
555     FT_Error               error;
556     const FT_Glyph_Class*  clazz;
557 
558 
559     /* check arguments */
560     if ( !target || !source || !source->clazz )
561     {
562       error = FT_THROW( Invalid_Argument );
563       goto Exit;
564     }
565 
566     *target = NULL;
567 
568     if ( !source || !source->clazz )
569     {
570       error = FT_THROW( Invalid_Argument );
571       goto Exit;
572     }
573 
574     clazz = source->clazz;
575     error = ft_new_glyph( source->library, clazz, &copy );
576     if ( error )
577       goto Exit;
578 
579     copy->advance = source->advance;
580     copy->format  = source->format;
581 
582     if ( clazz->glyph_copy )
583       error = clazz->glyph_copy( source, copy );
584 
585     if ( error )
586       FT_Done_Glyph( copy );
587     else
588       *target = copy;
589 
590   Exit:
591     return error;
592   }
593 
594 
595   /* documentation is in ftglyph.h */
596 
597   FT_EXPORT( FT_Error )
FT_New_Glyph(FT_Library library,FT_Glyph_Format format,FT_Glyph * aglyph)598   FT_New_Glyph( FT_Library       library,
599                 FT_Glyph_Format  format,
600                 FT_Glyph        *aglyph )
601   {
602     const FT_Glyph_Class*  clazz = NULL;
603 
604     if ( !library || !aglyph )
605       return FT_THROW( Invalid_Argument );
606 
607     /* if it is a bitmap, that's easy :-) */
608     if ( format == FT_GLYPH_FORMAT_BITMAP )
609       clazz = &ft_bitmap_glyph_class;
610 
611     /* if it is an outline */
612     else if ( format == FT_GLYPH_FORMAT_OUTLINE )
613       clazz = &ft_outline_glyph_class;
614 
615 #ifdef FT_CONFIG_OPTION_SVG
616     /* if it is an SVG glyph */
617     else if ( format == FT_GLYPH_FORMAT_SVG )
618       clazz = &ft_svg_glyph_class;
619 #endif
620 
621     else
622     {
623       /* try to find a renderer that supports the glyph image format */
624       FT_Renderer  render = FT_Lookup_Renderer( library, format, 0 );
625 
626 
627       if ( render )
628         clazz = &render->glyph_class;
629     }
630 
631     if ( !clazz )
632       return FT_THROW( Invalid_Glyph_Format );
633 
634     /* create FT_Glyph object */
635     return ft_new_glyph( library, clazz, aglyph );
636   }
637 
638 
639   /* documentation is in ftglyph.h */
640 
641   FT_EXPORT_DEF( FT_Error )
FT_Get_Glyph(FT_GlyphSlot slot,FT_Glyph * aglyph)642   FT_Get_Glyph( FT_GlyphSlot  slot,
643                 FT_Glyph     *aglyph )
644   {
645     FT_Error  error;
646     FT_Glyph  glyph;
647 
648 
649     if ( !slot )
650       return FT_THROW( Invalid_Slot_Handle );
651 
652     if ( !aglyph )
653       return FT_THROW( Invalid_Argument );
654 
655     /* create FT_Glyph object */
656     error = FT_New_Glyph( slot->library, slot->format, &glyph );
657     if ( error )
658       goto Exit;
659 
660     /* copy advance while converting 26.6 to 16.16 format */
661     if ( slot->advance.x >=  0x8000L * 64 ||
662          slot->advance.x <= -0x8000L * 64 )
663     {
664       FT_ERROR(( "FT_Get_Glyph: advance width too large\n" ));
665       error = FT_THROW( Invalid_Argument );
666       goto Exit2;
667     }
668     if ( slot->advance.y >=  0x8000L * 64 ||
669          slot->advance.y <= -0x8000L * 64 )
670     {
671       FT_ERROR(( "FT_Get_Glyph: advance height too large\n" ));
672       error = FT_THROW( Invalid_Argument );
673       goto Exit2;
674     }
675 
676     glyph->advance.x = slot->advance.x * 1024;
677     glyph->advance.y = slot->advance.y * 1024;
678 
679     /* now import the image from the glyph slot */
680     error = glyph->clazz->glyph_init( glyph, slot );
681 
682   Exit2:
683     /* if an error occurred, destroy the glyph */
684     if ( error )
685     {
686       FT_Done_Glyph( glyph );
687       *aglyph = NULL;
688     }
689     else
690       *aglyph = glyph;
691 
692   Exit:
693     return error;
694   }
695 
696 
697   /* documentation is in ftglyph.h */
698 
699   FT_EXPORT_DEF( FT_Error )
FT_Glyph_Transform(FT_Glyph glyph,const FT_Matrix * matrix,const FT_Vector * delta)700   FT_Glyph_Transform( FT_Glyph          glyph,
701                       const FT_Matrix*  matrix,
702                       const FT_Vector*  delta )
703   {
704     FT_Error  error = FT_Err_Ok;
705 
706 
707     if ( !glyph || !glyph->clazz )
708       error = FT_THROW( Invalid_Argument );
709     else
710     {
711       const FT_Glyph_Class*  clazz = glyph->clazz;
712 
713 
714       if ( clazz->glyph_transform )
715       {
716         /* transform glyph image */
717         clazz->glyph_transform( glyph, matrix, delta );
718 
719         /* transform advance vector */
720         if ( matrix )
721           FT_Vector_Transform( &glyph->advance, matrix );
722       }
723       else
724         error = FT_THROW( Invalid_Glyph_Format );
725     }
726     return error;
727   }
728 
729 
730   /* documentation is in ftglyph.h */
731 
732   FT_EXPORT_DEF( void )
FT_Glyph_Get_CBox(FT_Glyph glyph,FT_UInt bbox_mode,FT_BBox * acbox)733   FT_Glyph_Get_CBox( FT_Glyph  glyph,
734                      FT_UInt   bbox_mode,
735                      FT_BBox  *acbox )
736   {
737     const FT_Glyph_Class*  clazz;
738 
739 
740     if ( !acbox )
741       return;
742 
743     acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
744 
745     if ( !glyph || !glyph->clazz )
746       return;
747 
748     clazz = glyph->clazz;
749     if ( !clazz->glyph_bbox )
750       return;
751 
752     /* retrieve bbox in 26.6 coordinates */
753     clazz->glyph_bbox( glyph, acbox );
754 
755     /* perform grid fitting if needed */
756     if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
757          bbox_mode == FT_GLYPH_BBOX_PIXELS  )
758     {
759       acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
760       acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
761       acbox->xMax = FT_PIX_CEIL_LONG( acbox->xMax );
762       acbox->yMax = FT_PIX_CEIL_LONG( acbox->yMax );
763     }
764 
765     /* convert to integer pixels if needed */
766     if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
767          bbox_mode == FT_GLYPH_BBOX_PIXELS   )
768     {
769       acbox->xMin >>= 6;
770       acbox->yMin >>= 6;
771       acbox->xMax >>= 6;
772       acbox->yMax >>= 6;
773     }
774   }
775 
776 
777   /* documentation is in ftglyph.h */
778 
779   FT_EXPORT_DEF( FT_Error )
FT_Glyph_To_Bitmap(FT_Glyph * the_glyph,FT_Render_Mode render_mode,const FT_Vector * origin,FT_Bool destroy)780   FT_Glyph_To_Bitmap( FT_Glyph*         the_glyph,
781                       FT_Render_Mode    render_mode,
782                       const FT_Vector*  origin,
783                       FT_Bool           destroy )
784   {
785     FT_GlyphSlotRec           dummy;
786     FT_GlyphSlot_InternalRec  dummy_internal;
787     FT_Error                  error = FT_Err_Ok;
788     FT_Glyph                  b, glyph;
789     FT_BitmapGlyph            bitmap = NULL;
790     const FT_Glyph_Class*     clazz;
791 
792     FT_Library                library;
793 
794 
795     /* check argument */
796     if ( !the_glyph )
797       goto Bad;
798     glyph = *the_glyph;
799     if ( !glyph )
800       goto Bad;
801 
802     clazz   = glyph->clazz;
803     library = glyph->library;
804     if ( !library || !clazz )
805       goto Bad;
806 
807     /* when called with a bitmap glyph, do nothing and return successfully */
808     if ( clazz == &ft_bitmap_glyph_class )
809       goto Exit;
810 
811     if ( !clazz->glyph_prepare )
812       goto Bad;
813 
814     /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
815     /* then calling FT_Render_Glyph_Internal()                            */
816 
817     FT_ZERO( &dummy );
818     FT_ZERO( &dummy_internal );
819     dummy.internal = &dummy_internal;
820     dummy.library  = library;
821     dummy.format   = clazz->glyph_format;
822 
823     /* create result bitmap glyph */
824     error = ft_new_glyph( library, &ft_bitmap_glyph_class, &b );
825     if ( error )
826       goto Exit;
827     bitmap = (FT_BitmapGlyph)b;
828 
829 #if 1
830     /* if `origin' is set, translate the glyph image */
831     if ( origin )
832       FT_Glyph_Transform( glyph, NULL, origin );
833 #else
834     FT_UNUSED( origin );
835 #endif
836 
837     /* prepare dummy slot for rendering */
838     error = clazz->glyph_prepare( glyph, &dummy );
839     if ( !error )
840       error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
841 
842 #ifdef FT_CONFIG_OPTION_SVG
843     if ( clazz == &ft_svg_glyph_class )
844     {
845       FT_Memory  memory = library->memory;
846 
847 
848       FT_FREE( dummy.other );
849     }
850 #endif
851 
852 #if 1
853     if ( !destroy && origin )
854     {
855       FT_Vector  v;
856 
857 
858       v.x = -origin->x;
859       v.y = -origin->y;
860       FT_Glyph_Transform( glyph, NULL, &v );
861     }
862 #endif
863 
864     if ( error )
865       goto Exit;
866 
867     /* in case of success, copy the bitmap to the glyph bitmap */
868     error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
869     if ( error )
870       goto Exit;
871 
872     /* copy advance */
873     bitmap->root.advance = glyph->advance;
874 
875     if ( destroy )
876       FT_Done_Glyph( glyph );
877 
878     *the_glyph = FT_GLYPH( bitmap );
879 
880   Exit:
881     if ( error && bitmap )
882       FT_Done_Glyph( FT_GLYPH( bitmap ) );
883 
884     return error;
885 
886   Bad:
887     error = FT_THROW( Invalid_Argument );
888     goto Exit;
889   }
890 
891 
892   /* documentation is in ftglyph.h */
893 
894   FT_EXPORT_DEF( void )
FT_Done_Glyph(FT_Glyph glyph)895   FT_Done_Glyph( FT_Glyph  glyph )
896   {
897     if ( glyph )
898     {
899       FT_Memory              memory = glyph->library->memory;
900       const FT_Glyph_Class*  clazz  = glyph->clazz;
901 
902 
903       if ( clazz->glyph_done )
904         clazz->glyph_done( glyph );
905 
906       FT_FREE( glyph );
907     }
908   }
909 
910 
911 /* END */
912