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