XFA: merge patch from CL 817753002
[pdfium.git] / core / src / fxge / fx_freetype / fxft2.5.01 / src / base / fxft_ftglyph.c
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