branch update for HEAD-2003021201
[reactos.git] / subsys / win32k / freetype / src / base / ftglyph.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ftglyph.c                                                              */
4 /*                                                                         */
5 /*    FreeType convenience functions to handle glyphs (body).              */
6 /*                                                                         */
7 /*  Copyright 1996-2000 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/ftglyph.h>
32 #include <freetype/ftoutln.h>
33 #include <freetype/internal/ftobjs.h>
34
35
36   /*************************************************************************/
37   /*                                                                       */
38   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
39   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
40   /* messages during execution.                                            */
41   /*                                                                       */
42 #undef  FT_COMPONENT
43 #define FT_COMPONENT  trace_glyph
44
45
46   /*************************************************************************/
47   /*************************************************************************/
48   /****                                                                 ****/
49   /****   Convenience functions                                         ****/
50   /****                                                                 ****/
51   /*************************************************************************/
52   /*************************************************************************/
53
54
55   /*************************************************************************/
56   /*                                                                       */
57   /* <Function>                                                            */
58   /*    FT_Matrix_Multiply                                                 */
59   /*                                                                       */
60   /* <Description>                                                         */
61   /*    Performs the matrix operation `b = a*b'.                           */
62   /*                                                                       */
63   /* <Input>                                                               */
64   /*    a :: A pointer to matrix `a'.                                      */
65   /*                                                                       */
66   /* <InOut>                                                               */
67   /*    b :: A pointer to matrix `b'.                                      */
68   /*                                                                       */
69   /* <MT-Note>                                                             */
70   /*    Yes.                                                               */
71   /*                                                                       */
72   /* <Note>                                                                */
73   /*    The result is undefined if either `a' or `b' is zero.              */
74   /*                                                                       */
75   FT_EXPORT_FUNC( void )  FT_Matrix_Multiply( FT_Matrix*  a,
76                                               FT_Matrix*  b )
77   {
78     FT_Fixed  xx, xy, yx, yy;
79
80
81     if ( !a || !b )
82       return;
83
84     xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
85     xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
86     yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
87     yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
88
89     b->xx = xx;  b->xy = xy;
90     b->yx = yx;  b->yy = yy;
91   }
92
93
94   /*************************************************************************/
95   /*                                                                       */
96   /* <Function>                                                            */
97   /*    FT_Matrix_Invert                                                   */
98   /*                                                                       */
99   /* <Description>                                                         */
100   /*    Inverts a 2x2 matrix.  Returns an error if it can't be inverted.   */
101   /*                                                                       */
102   /* <InOut>                                                               */
103   /*    matrix :: A pointer to the target matrix.  Remains untouched in    */
104   /*              case of error.                                           */
105   /*                                                                       */
106   /* <Return>                                                              */
107   /*    FreeType error code.  0 means success.                             */
108   /*                                                                       */
109   /* <MT-Note>                                                             */
110   /*    Yes.                                                               */
111   /*                                                                       */
112   FT_EXPORT_FUNC( FT_Error )  FT_Matrix_Invert( FT_Matrix*  matrix )
113   {
114     FT_Pos  delta, xx, yy;
115
116
117     if ( !matrix )
118       return FT_Err_Invalid_Argument;
119
120     /* compute discriminant */
121     delta = FT_MulFix( matrix->xx, matrix->yy ) -
122             FT_MulFix( matrix->xy, matrix->yx );
123
124     if ( !delta )
125       return FT_Err_Invalid_Argument;  /* matrix can't be inverted */
126
127     matrix->xy = - FT_DivFix( matrix->xy, delta );
128     matrix->yx = - FT_DivFix( matrix->yx, delta );
129
130     xx = matrix->xx;
131     yy = matrix->yy;
132
133     matrix->xx = FT_DivFix( yy, delta );
134     matrix->yy = FT_DivFix( xx, delta );
135
136     return FT_Err_Ok;
137   }
138
139
140   /*************************************************************************/
141   /*************************************************************************/
142   /****                                                                 ****/
143   /****   FT_BitmapGlyph support                                        ****/
144   /****                                                                 ****/
145   /*************************************************************************/
146   /*************************************************************************/
147
148   static
149   FT_Error  ft_bitmap_copy( FT_Memory   memory,
150                             FT_Bitmap*  source,
151                             FT_Bitmap*  target )
152   {
153     FT_Error  error;
154     FT_Int    pitch = source->pitch;
155     FT_ULong  size;
156
157
158     *target = *source;
159
160     if ( pitch < 0 )
161       pitch = -pitch;
162
163     size = (FT_ULong)( pitch * source->rows );
164
165     if ( !ALLOC( target->buffer, size ) )
166       MEM_Copy( source->buffer, target->buffer, size );
167
168     return error;
169   }
170
171
172   static
173   FT_Error  ft_bitmap_glyph_init( FT_BitmapGlyph  glyph,
174                                   FT_GlyphSlot    slot )
175   {
176     FT_Error    error   = FT_Err_Ok;
177     FT_Library  library = FT_GLYPH(glyph)->library;
178     FT_Memory   memory  = library->memory;
179
180
181     if ( slot->format != ft_glyph_format_bitmap )
182     {
183       error = FT_Err_Invalid_Glyph_Format;
184       goto Exit;
185     }
186
187     /* grab the bitmap in the slot - do lazy copying whenever possible */
188     glyph->bitmap = slot->bitmap;
189     glyph->left   = slot->bitmap_left;
190     glyph->top    = slot->bitmap_top;
191
192     if ( slot->flags & ft_glyph_own_bitmap )
193       slot->flags &= ~ft_glyph_own_bitmap;
194     else
195     {
196       /* copy the bitmap into a new buffer */
197       error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap );
198     }
199
200   Exit:
201     return error;
202   }
203
204
205   static
206   FT_Error  ft_bitmap_glyph_copy( FT_BitmapGlyph  source,
207                                   FT_BitmapGlyph  target )
208   {
209     FT_Memory  memory = source->root.library->memory;
210
211
212     target->left = source->left;
213     target->top  = source->top;
214
215     return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap );
216   }
217
218
219   static
220   void  ft_bitmap_glyph_done( FT_BitmapGlyph  glyph )
221   {
222     FT_Memory  memory = FT_GLYPH(glyph)->library->memory;
223
224
225     FREE( glyph->bitmap.buffer );
226   }
227
228
229   static
230   void  ft_bitmap_glyph_bbox( FT_BitmapGlyph  glyph,
231                               FT_BBox*        cbox )
232   {
233     cbox->xMin = glyph->left << 6;
234     cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
235     cbox->yMax = glyph->top << 6;
236     cbox->yMin = cbox->xMax - ( glyph->bitmap.rows << 6 );
237   }
238
239
240   const FT_Glyph_Class  ft_bitmap_glyph_class =
241   {
242     sizeof( FT_BitmapGlyphRec ),
243     ft_glyph_format_bitmap,
244
245     (FT_Glyph_Init_Func)     ft_bitmap_glyph_init,
246     (FT_Glyph_Done_Func)     ft_bitmap_glyph_done,
247     (FT_Glyph_Copy_Func)     ft_bitmap_glyph_copy,
248     (FT_Glyph_Transform_Func)0,
249     (FT_Glyph_BBox_Func)     ft_bitmap_glyph_bbox,
250     (FT_Glyph_Prepare_Func)  0
251   };
252
253
254   /*************************************************************************/
255   /*************************************************************************/
256   /****                                                                 ****/
257   /****   FT_OutlineGlyph support                                       ****/
258   /****                                                                 ****/
259   /*************************************************************************/
260   /*************************************************************************/
261
262
263   static
264   FT_Error  ft_outline_glyph_init( FT_OutlineGlyph  glyph,
265                                    FT_GlyphSlot     slot )
266   {
267     FT_Error     error   = FT_Err_Ok;
268     FT_Library   library = FT_GLYPH(glyph)->library;
269     FT_Outline*  source  = &slot->outline;
270     FT_Outline*  target  = &glyph->outline;
271
272
273     /* check format in glyph slot */
274     if ( slot->format != ft_glyph_format_outline )
275     {
276       error = FT_Err_Invalid_Glyph_Format;
277       goto Exit;
278     }
279
280     /* allocate new outline */
281     error = FT_Outline_New( library, source->n_points, source->n_contours,
282                             &glyph->outline );
283     if ( error )
284       goto Exit;
285
286     /* copy it */
287     MEM_Copy( target->points, source->points,
288               source->n_points * sizeof ( FT_Vector ) );
289
290     MEM_Copy( target->tags, source->tags,
291               source->n_points * sizeof ( FT_Byte ) );
292
293     MEM_Copy( target->contours, source->contours,
294               source->n_contours * sizeof ( FT_Short ) );
295
296     /* copy all flags, except the `ft_outline_owner' one */
297     target->flags = source->flags | ft_outline_owner;
298
299   Exit:
300     return error;
301   }
302
303
304   static
305   void  ft_outline_glyph_done( FT_OutlineGlyph  glyph )
306   {
307     FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
308   }
309
310
311   static
312   FT_Error  ft_outline_glyph_copy( FT_OutlineGlyph  source,
313                                    FT_OutlineGlyph  target )
314   {
315     FT_Error    error;
316     FT_Library  library = FT_GLYPH( source )->library;
317
318
319     error = FT_Outline_New( library, source->outline.n_points,
320                             source->outline.n_contours, &target->outline );
321     if ( !error )
322       FT_Outline_Copy( &source->outline, &target->outline );
323
324     return error;
325   }
326
327
328   static
329   void  ft_outline_glyph_transform( FT_OutlineGlyph  glyph,
330                                     FT_Matrix*       matrix,
331                                     FT_Vector*       delta )
332   {
333     if ( matrix )
334       FT_Outline_Transform( &glyph->outline, matrix );
335
336     if ( delta )
337       FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
338   }
339
340
341   static
342   void  ft_outline_glyph_bbox( FT_OutlineGlyph  glyph,
343                                FT_BBox*         bbox )
344   {
345     FT_Outline_Get_CBox( &glyph->outline, bbox );
346   }
347
348
349   static
350   FT_Error  ft_outline_glyph_prepare( FT_OutlineGlyph  glyph,
351                                       FT_GlyphSlot     slot )
352   {
353     slot->format         = ft_glyph_format_outline;
354     slot->outline        = glyph->outline;
355     slot->outline.flags &= ~ft_outline_owner;
356
357     return FT_Err_Ok;
358   }
359
360
361   const FT_Glyph_Class  ft_outline_glyph_class =
362   {
363     sizeof( FT_OutlineGlyphRec ),
364     ft_glyph_format_outline,
365
366     (FT_Glyph_Init_Func)     ft_outline_glyph_init,
367     (FT_Glyph_Done_Func)     ft_outline_glyph_done,
368     (FT_Glyph_Copy_Func)     ft_outline_glyph_copy,
369     (FT_Glyph_Transform_Func)ft_outline_glyph_transform,
370     (FT_Glyph_BBox_Func)     ft_outline_glyph_bbox,
371     (FT_Glyph_Prepare_Func)  ft_outline_glyph_prepare
372   };
373
374
375   /*************************************************************************/
376   /*************************************************************************/
377   /****                                                                 ****/
378   /****   FT_Glyph class and API                                        ****/
379   /****                                                                 ****/
380   /*************************************************************************/
381   /*************************************************************************/
382
383    static
384    FT_Error  ft_new_glyph( FT_Library             library,
385                            const FT_Glyph_Class*  clazz,
386                            FT_Glyph*              aglyph )
387    {
388      FT_Memory  memory = library->memory;
389      FT_Error   error;
390      FT_Glyph   glyph;
391
392
393      *aglyph = 0;
394
395      if ( !ALLOC( glyph, clazz->glyph_size ) )
396      {
397        glyph->library = library;
398        glyph->clazz   = clazz;
399        glyph->format  = clazz->glyph_format;
400
401        *aglyph = glyph;
402      }
403
404      return error;
405    }
406
407
408   /*************************************************************************/
409   /*                                                                       */
410   /* <Function>                                                            */
411   /*    FT_Glyph_Copy                                                      */
412   /*                                                                       */
413   /* <Description>                                                         */
414   /*    A function used to copy a glyph image.                             */
415   /*                                                                       */
416   /* <Input>                                                               */
417   /*    source :: A handle to the source glyph object.                     */
418   /*                                                                       */
419   /* <Output>                                                              */
420   /*    target :: A handle to the target glyph object.  0 in case of       */
421   /*              error.                                                   */
422   /*                                                                       */
423   /* <Return>                                                              */
424   /*    FreeType error code.  0 means success.                             */
425   /*                                                                       */
426   FT_EXPORT_FUNC( FT_Error )  FT_Glyph_Copy( FT_Glyph   source,
427                                              FT_Glyph*  target )
428   {
429     FT_Glyph               copy;
430     FT_Error               error;
431     const FT_Glyph_Class*  clazz;
432
433
434     /* check arguments */
435     if ( !target || !source || !source->clazz )
436     {
437       error = FT_Err_Invalid_Argument;
438       goto Exit;
439     }
440
441     *target = 0;
442
443     clazz = source->clazz;
444     error = ft_new_glyph( source->library, clazz, &copy );
445     if ( error )
446       goto Exit;
447
448     if ( clazz->glyph_copy )
449       error = clazz->glyph_copy( source, copy );
450
451     if ( error )
452       FT_Done_Glyph( copy );
453     else
454       *target = copy;
455
456   Exit:
457     return error;
458   }
459
460
461   /*************************************************************************/
462   /*                                                                       */
463   /* <Function>                                                            */
464   /*    FT_Get_Glyph                                                       */
465   /*                                                                       */
466   /* <Description>                                                         */
467   /*    A function used to extract a glyph image from a slot.              */
468   /*                                                                       */
469   /* <Input>                                                               */
470   /*    slot   :: A handle to the source glyph slot.                       */
471   /*                                                                       */
472   /* <Output>                                                              */
473   /*    aglyph :: A handle to the glyph object.                            */
474   /*                                                                       */
475   /* <Return>                                                              */
476   /*    FreeType error code.  0 means success.                             */
477   /*                                                                       */
478   FT_EXPORT_FUNC( FT_Error )  FT_Get_Glyph( FT_GlyphSlot  slot,
479                                             FT_Glyph*     aglyph )
480   {
481     FT_Library  library = slot->library;
482     FT_Error    error;
483     FT_Glyph    glyph;
484
485     const FT_Glyph_Class*  clazz = 0;
486
487
488     if ( !slot )
489       return FT_Err_Invalid_Slot_Handle;
490
491     if ( !aglyph )
492       return FT_Err_Invalid_Argument;
493
494     /* if it is a bitmap, that's easy :-) */
495     if ( slot->format == ft_glyph_format_bitmap )
496       clazz = &ft_bitmap_glyph_class;
497
498     /* it it is an outline too */
499     else if ( slot->format == ft_glyph_format_outline )
500       clazz = &ft_outline_glyph_class;
501
502     else
503     {
504       /* try to find a renderer that supports the glyph image format */
505       FT_Renderer  render = FT_Lookup_Renderer( library, slot->format, 0 );
506
507
508       if ( render )
509         clazz = &render->glyph_class;
510     }
511
512     if ( !clazz )
513     {
514       error = FT_Err_Invalid_Glyph_Format;
515       goto Exit;
516     }
517
518     /* create FT_Glyph object */
519     error = ft_new_glyph( library, clazz, &glyph );
520     if ( error )
521       goto Exit;
522
523     /* copy advance while converting it to 16.16 format */
524     glyph->advance.x = slot->advance.x << 10;
525     glyph->advance.y = slot->advance.y << 10;
526
527     /* now import the image from the glyph slot */
528     error = clazz->glyph_init( glyph, slot );
529
530     /* if an error occurred, destroy the glyph */
531     if ( error )
532       FT_Done_Glyph( glyph );
533     else
534       *aglyph = glyph;
535
536   Exit:
537     return error;
538   }
539
540
541   /*************************************************************************/
542   /*                                                                       */
543   /* <Function>                                                            */
544   /*    FT_Glyph_Transform                                                 */
545   /*                                                                       */
546   /* <Description>                                                         */
547   /*    Transforms a glyph image if its format is scalable.                */
548   /*                                                                       */
549   /* <Input>                                                               */
550   /*    glyph  :: A handle to the target glyph object.                     */
551   /*                                                                       */
552   /*    matrix :: A pointer to a 2x2 matrix to apply.                      */
553   /*                                                                       */
554   /*    delta  :: A pointer to a 2d vector to apply.  Coordinates are      */
555   /*              expressed in 1/64th of a pixel.                          */
556   /*                                                                       */
557   /* <Return>                                                              */
558   /*    FreeType error code (the glyph format is not scalable if it is     */
559   /*    not zero).                                                         */
560   /*                                                                       */
561   /* <Note>                                                                */
562   /*    The 2x2 transformation matrix is also applied to the glyph's       */
563   /*    advance vector.                                                    */
564   /*                                                                       */
565   FT_EXPORT_FUNC( FT_Error )  FT_Glyph_Transform( FT_Glyph    glyph,
566                                                   FT_Matrix*  matrix,
567                                                   FT_Vector*  delta )
568   {
569     const FT_Glyph_Class*  clazz;
570     FT_Error               error = FT_Err_Ok;
571
572
573     if ( !glyph || !glyph->clazz )
574       error = FT_Err_Invalid_Argument;
575     else
576     {
577       clazz = glyph->clazz;
578       if ( clazz->glyph_transform )
579       {
580         /* transform glyph image */
581         clazz->glyph_transform( glyph, matrix, delta );
582
583         /* transform advance vector */
584         if ( matrix )
585           FT_Vector_Transform( &glyph->advance, matrix );
586       }
587       else
588         error = FT_Err_Invalid_Glyph_Format;
589     }
590     return error;
591   }
592
593
594   /*************************************************************************/
595   /*                                                                       */
596   /* <Function>                                                            */
597   /*    FT_Glyph_Get_CBox                                                  */
598   /*                                                                       */
599   /* <Description>                                                         */
600   /*    Returns the glyph image's bounding box.                            */
601   /*                                                                       */
602   /* <Input>                                                               */
603   /*    glyph :: A handle to the source glyph object.                      */
604   /*                                                                       */
605   /*    mode  :: A set of bit flags that indicate how to interpret the     */
606   /*             returned bounding box values.                             */
607   /*                                                                       */
608   /* <Output>                                                              */
609   /*    box   :: The glyph bounding box.  Coordinates are expressed in     */
610   /*             1/64th of pixels if it is grid-fitted.                    */
611   /*                                                                       */
612   /* <Note>                                                                */
613   /*    Coordinates are relative to the glyph origin, using the Y-upwards  */
614   /*    convention.                                                        */
615   /*                                                                       */
616   /*    If `ft_glyph_bbox_subpixels' is set in `mode', the bbox            */
617   /*    coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels).   */
618   /*    Otherwise, coordinates are expressed in integer pixels.            */
619   /*                                                                       */
620   /*    Note that the maximum coordinates are exclusive, which means that  */
621   /*    one can compute the width and height of the glyph image (be it in  */
622   /*    integer or 26.6 pixels) as:                                        */
623   /*                                                                       */
624   /*      width  = bbox.xMax - bbox.xMin;                                  */
625   /*      height = bbox.yMax - bbox.yMin;                                  */
626   /*                                                                       */
627   /*    Note also that for 26.6 coordinates, if the                        */
628   /*    `ft_glyph_bbox_gridfit' flag is set in `mode;, the coordinates     */
629   /*    will also be grid-fitted, which corresponds to:                    */
630   /*                                                                       */
631   /*      bbox.xMin = FLOOR(bbox.xMin);                                    */
632   /*      bbox.yMin = FLOOR(bbox.yMin);                                    */
633   /*      bbox.xMax = CEILING(bbox.xMax);                                  */
634   /*      bbox.yMax = CEILING(bbox.yMax);                                  */
635   /*                                                                       */
636   /*    The default value (0) for `bbox_mode' is `ft_glyph_bbox_pixels'.   */
637   /*                                                                       */
638   FT_EXPORT_FUNC( void )  FT_Glyph_Get_CBox( FT_Glyph  glyph,
639                                              FT_UInt   bbox_mode,
640                                              FT_BBox*  cbox )
641   {
642     const FT_Glyph_Class*  clazz;
643     FT_Error               error = FT_Err_Ok;
644
645
646     if ( !cbox || !glyph || !glyph->clazz )
647       error = FT_Err_Invalid_Argument;
648     else
649     {
650       clazz = glyph->clazz;
651       if ( !clazz->glyph_bbox )
652         error = FT_Err_Invalid_Glyph_Format;
653       else
654       {
655         /* retrieve bbox in 26.6 coordinates */
656         clazz->glyph_bbox( glyph, cbox );
657
658         /* perform grid fitting if needed */
659         if ( bbox_mode & ft_glyph_bbox_gridfit )
660         {
661           cbox->xMin &= -64;
662           cbox->yMin &= -64;
663           cbox->xMax  = ( cbox->xMax + 63 ) & -64;
664           cbox->yMax  = ( cbox->yMax + 63 ) & -64;
665         }
666
667         /* convert to integer pixels if needed */
668         if ( !( bbox_mode & ft_glyph_bbox_subpixels ) )
669         {
670           cbox->xMin >>= 6;
671           cbox->yMin >>= 6;
672           cbox->xMax >>= 6;
673           cbox->yMax >>= 6;
674         }
675       }
676     }
677     return;
678   }
679
680
681   /*************************************************************************/
682   /*                                                                       */
683   /* <Function>                                                            */
684   /*    FT_Glyph_To_Bitmap                                                 */
685   /*                                                                       */
686   /* <Description>                                                         */
687   /*    Converts a given glyph object to a bitmap glyph object.            */
688   /*                                                                       */
689   /* <InOut>                                                               */
690   /*    glyph       :: A pointer to a handle to the target glyph.          */
691   /*                                                                       */
692   /* <Input>                                                               */
693   /*    render_mode :: A set of bit flags that describe how the data is    */
694   /*                                                                       */
695   /*                                                                       */
696   /*    origin      :: A pointer to a vector used to translate the glyph   */
697   /*                   image before rendering.  Can be 0 (if no            */
698   /*                   translation).  The origin is expressed in           */
699   /*                   26.6 pixels.                                        */
700   /*                                                                       */
701   /*    destroy     :: A boolean that indicates that the original glyph    */
702   /*                   image should be destroyed by this function.  It is  */
703   /*                   never destroyed in case of error.                   */
704   /*                                                                       */
705   /* <Return>                                                              */
706   /*    FreeType error code.  0 means success.                             */
707   /*                                                                       */
708   /* <Note>                                                                */
709   /*    The glyph image is translated with the `origin' vector before      */
710   /*    rendering.  In case of error, it it translated back to its         */
711   /*    original position and the glyph is left untouched.                 */
712   /*                                                                       */
713   /*    The first parameter is a pointer to a FT_Glyph handle, that will   */
714   /*    be replaced by this function.  Typically, you would use (omitting  */
715   /*    error handling):                                                   */
716   /*                                                                       */
717   /*                                                                       */
718   /*      {                                                                */
719   /*        FT_Glyph        glyph;                                         */
720   /*        FT_BitmapGlyph  glyph_bitmap;                                  */
721   /*                                                                       */
722   /*                                                                       */
723   /*        // load glyph                                                  */
724   /*        error = FT_Load_Char( face, glyph_index, FT_LOAD_DEFAUT );     */
725   /*                                                                       */
726   /*        // extract glyph image                                         */
727   /*        error = FT_Get_Glyph( face->glyph, &glyph );                   */
728   /*                                                                       */
729   /*        // convert to a bitmap (default render mode + destroy old)     */
730   /*        if ( glyph->format != ft_glyph_format_bitmap )                 */
731   /*        {                                                              */
732   /*          error = FT_Glyph_To_Bitmap( &glyph, ft_render_mode_default,  */
733   /*                                      0, 1 );                          */
734   /*          if ( error ) // glyph unchanged                              */
735   /*            ...                                                        */
736   /*        }                                                              */
737   /*                                                                       */
738   /*        // access bitmap content by typecasting                        */
739   /*        glyph_bitmap = (FT_BitmapGlyph)glyph;                          */
740   /*                                                                       */
741   /*        // do funny stuff with it, like blitting/drawing               */
742   /*        ...                                                            */
743   /*                                                                       */
744   /*        // discard glyph image (bitmap or not)                         */
745   /*        FT_Done_Glyph( glyph );                                        */
746   /*      }                                                                */
747   /*                                                                       */
748   /*                                                                       */
749   /*    This function will always fail if the glyph's format isn't         */
750   /*    scalable.                                                          */
751   /*                                                                       */
752   FT_EXPORT_FUNC( FT_Error )  FT_Glyph_To_Bitmap( FT_Glyph*   the_glyph,
753                                                   FT_ULong    render_mode,
754                                                   FT_Vector*  origin,
755                                                   FT_Bool     destroy )
756   {
757     FT_GlyphSlotRec  dummy;
758     FT_Error         error;
759     FT_Glyph         glyph;
760     FT_BitmapGlyph   bitmap;
761
762     const FT_Glyph_Class*  clazz;
763
764
765     /* check argument */
766     if ( !the_glyph )
767       goto Bad;
768
769     /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
770     /* then calling FT_Render_Glyph_Internal()                            */
771
772     glyph = *the_glyph;
773     if ( !glyph )
774       goto Bad;
775
776     clazz = glyph->clazz;
777     if ( !clazz || !clazz->glyph_prepare )
778       goto Bad;
779
780     MEM_Set( &dummy, 0, sizeof ( dummy ) );
781     dummy.library = glyph->library;
782     dummy.format  = clazz->glyph_format;
783
784     /* if `origin' is set, translate the glyph image */
785     if ( origin )
786       FT_Glyph_Transform( glyph, 0, origin );
787
788     /* create result bitmap glyph */
789     error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
790                           (FT_Glyph*)&bitmap );
791     if ( error )
792       goto Exit;
793
794     /* prepare dummy slot for rendering */
795     error = clazz->glyph_prepare( glyph, &dummy ) ||
796             FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
797
798     if ( !destroy && origin )
799     {
800       FT_Vector  v;
801
802
803       v.x = -origin->x;
804       v.y = -origin->y;
805       FT_Glyph_Transform( glyph, 0, &v );
806     }
807
808     /* in case of succes, copy the bitmap to the glyph bitmap */
809     if ( !error )
810     {
811       error = ft_bitmap_glyph_init( bitmap, &dummy );
812       if ( error )
813       {
814         /* this should never happen, but let's be safe */
815         FT_Done_Glyph( FT_GLYPH( bitmap ) );
816         goto Exit;
817       }
818
819       if ( destroy )
820         FT_Done_Glyph( glyph );
821
822       *the_glyph = FT_GLYPH( bitmap );
823     }
824
825   Exit:
826     return error;
827
828   Bad:
829     error = FT_Err_Invalid_Argument;
830     goto Exit;
831   }
832
833
834   /*************************************************************************/
835   /*                                                                       */
836   /* <Function>                                                            */
837   /*    FT_Done_Glyph                                                      */
838   /*                                                                       */
839   /* <Description>                                                         */
840   /*    Destroys a given glyph.                                            */
841   /*                                                                       */
842   /* <Input>                                                               */
843   /*    glyph :: A handle to the target glyph object.                      */
844   /*                                                                       */
845   FT_EXPORT_FUNC( void )  FT_Done_Glyph( FT_Glyph  glyph )
846   {
847     if ( glyph )
848     {
849       FT_Memory              memory = glyph->library->memory;
850       const FT_Glyph_Class*  clazz  = glyph->clazz;
851
852
853       if ( clazz->glyph_done )
854         clazz->glyph_done( glyph );
855
856       FREE( glyph );
857     }
858   }
859
860
861 #if 0
862
863   /*************************************************************************/
864   /*************************************************************************/
865   /****                                                                 ****/
866   /****   EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT                    ****/
867   /****                                                                 ****/
868   /*************************************************************************/
869   /*************************************************************************/
870
871   /* Compute the norm of a vector */
872
873 #ifdef FT_CONFIG_OPTION_OLD_CALCS
874
875   static
876   FT_Pos  ft_norm( FT_Vector*  vec )
877   {
878     FT_Int64  t1, t2;
879
880
881     MUL_64( vec->x, vec->x, t1 );
882     MUL_64( vec->y, vec->y, t2 );
883     ADD_64( t1, t2, t1 );
884
885     return (FT_Pos)SQRT_64( t1 );
886   }
887
888 #else /* FT_CONFIG_OPTION_OLD_CALCS */
889
890   static
891   FT_Pos  ft_norm( FT_Vector*  vec )
892   {
893     FT_F26Dot6  u, v, d;
894     FT_Int      shift;
895     FT_ULong    H, L, L2, hi, lo, med;
896
897
898     u = vec->x; if ( u < 0 ) u = -u;
899     v = vec->y; if ( v < 0 ) v = -v;
900
901     if ( u < v )
902     {
903       d = u;
904       u = v;
905       v = d;
906     }
907
908     /* check that we are not trying to normalize zero! */
909     if ( u == 0 )
910       return 0;
911
912     /* compute (u*u + v*v) on 64 bits with two 32-bit registers [H:L] */
913     hi  = (FT_ULong)u >> 16;
914     lo  = (FT_ULong)u & 0xFFFF;
915     med = hi * lo;
916
917     H     = hi * hi + ( med >> 15 );
918     med <<= 17;
919     L     = lo * lo + med;
920     if ( L < med )
921       H++;
922
923     hi  = (FT_ULong)v >> 16;
924     lo  = (FT_ULong)v & 0xFFFF;
925     med = hi * lo;
926
927     H    += hi * hi + ( med >> 15 );
928     med <<= 17;
929     L2    = lo * lo + med;
930     if ( L2 < med )
931       H++;
932
933     L += L2;
934     if ( L < L2 )
935       H++;
936
937     /* if the value is smaller than 32 bits */
938     shift = 0;
939     if ( H == 0 )
940     {
941       while ( ( L & 0xC0000000UL ) == 0 )
942       {
943         L <<= 2;
944         shift++;
945       }
946       return ( FT_Sqrt32( L ) >> shift );
947     }
948     else
949     {
950       while ( H )
951       {
952         L   = ( L >> 2 ) | ( H << 30 );
953         H >>= 2;
954         shift++;
955       }
956       return ( FT_Sqrt32( L ) << shift );
957     }
958   }
959
960 #endif /* FT_CONFIG_OPTION_OLD_CALCS */
961
962
963   static
964   int  ft_test_extrema( FT_Outline*  outline,
965                         int          n )
966   {
967     FT_Vector  *prev, *cur, *next;
968     FT_Pos      product;
969     FT_Int      first, last;
970
971
972     /* we need to compute the `previous' and `next' point */
973     /* for these extrema.                                 */
974     cur   = outline->points + n;
975     prev  = cur - 1;
976     next  = cur + 1;
977
978     first = 0;
979     for ( c = 0; c < outline->n_contours; c++ )
980     {
981       last  = outline->contours[c];
982
983       if ( n == first )
984         prev = outline->points + last;
985
986       if ( n == last )
987         next = outline->points + first;
988
989       first = last + 1;
990     }
991
992     product = FT_MulDiv( cur->x - prev->x,   /* in.x  */
993                          next->y - cur->y,   /* out.y */
994                          0x40 )
995               -
996               FT_MulDiv( cur->y - prev->y,   /* in.y  */
997                          next->x - cur->x,   /* out.x */
998                          0x40 );
999
1000     if ( product )
1001       product = product > 0 ? 1 : -1;
1002
1003     return product;
1004   }
1005
1006
1007   /* Compute the orientation of path filling.  It differs between TrueType */
1008   /* and Type1 formats.  We could use the `ft_outline_reverse_fill' flag,  */
1009   /* but it is better to re-compute it directly (it seems that this flag   */
1010   /* isn't correctly set for some weird composite glyphs currently).       */
1011   /*                                                                       */
1012   /* We do this by computing bounding box points, and computing their      */
1013   /* curvature.                                                            */
1014   /*                                                                       */
1015   /* The function returns either 1 or -1.                                  */
1016   /*                                                                       */
1017   static
1018   int  ft_get_orientation( FT_Outline*  outline )
1019   {
1020     FT_BBox  box;
1021     FT_BBox  indices;
1022     int      n, last;
1023
1024
1025     indices.xMin = -1;
1026     indices.yMin = -1;
1027     indices.xMax = -1;
1028     indices.yMax = -1;
1029
1030     box.xMin = box.yMin = 32767;
1031     box.xMax = box.yMax = -32768;
1032
1033     /* is it empty ? */
1034     if ( outline->n_contours < 1 )
1035       return 1;
1036
1037     last = outline->contours[outline->n_contours - 1];
1038
1039     for ( n = 0; n <= last; n++ )
1040     {
1041       FT_Pos  x, y;
1042
1043
1044       x = outline->points[n].x;
1045       if ( x < box.xMin )
1046       {
1047         box.xMin     = x;
1048         indices.xMin = n;
1049       }
1050       if ( x > box.xMax )
1051       {
1052         box.xMax     = x;
1053         indices.xMax = n;
1054       }
1055
1056       y = outline->points[n].y;
1057       if ( y < box.yMin )
1058       {
1059         box.yMin     = y;
1060         indices.yMin = n;
1061       }
1062       if ( y > box.yMax )
1063       {
1064         box.yMax     = y;
1065         indices.yMax = n;
1066       }
1067     }
1068
1069     /* test orientation of the xmin */
1070     return ft_test_extrema( outline, indices.xMin ) ||
1071            ft_test_extrema( outline, indices.yMin ) ||
1072            ft_test_extrema( outline, indices.xMax ) ||
1073            ft_test_extrema( outline, indices.yMax ) ||
1074            1;  /* this is an empty glyph? */
1075   }
1076
1077
1078   static
1079   FT_Error  ft_embolden( FT_Face      original,
1080                          FT_Outline*  outline,
1081                          FT_Pos*      advance )
1082   {
1083     FT_Vector  u, v;
1084     FT_Vector* points;
1085     FT_Vector  cur, prev, next;
1086     FT_Pos     distance;
1087     int        c, n, first, orientation;
1088
1089     FT_UNUSED( advance );
1090
1091
1092     /* compute control distance */
1093     distance = FT_MulFix( original->em_size / 60,
1094                           original->size->metrics.y_scale );
1095
1096     orientation = ft_get_orientation( &original->glyph->outline );
1097
1098     points = original->glyph->outline.points;
1099
1100     first = 0;
1101     for ( c = 0; c < outline->n_contours; c++ )
1102     {
1103       int  last = outline->contours[c];
1104
1105
1106       prev = points[last];
1107
1108       for ( n = first; n <= last; n++ )
1109       {
1110         FT_Pos     norm, delta, d;
1111         FT_Vector  in, out;
1112
1113
1114         cur = points[n];
1115         if ( n < last ) next = points[n + 1];
1116         else            next = points[first];
1117
1118         /* compute the in and out vectors */
1119         in.x  = cur.x - prev.x;
1120         in.y  = cur.y - prev.y;
1121
1122         out.x = next.x - cur.x;
1123         out.y = next.y - cur.y;
1124
1125         /* compute U and V */
1126         norm = ft_norm( &in );
1127         u.x = orientation *  FT_DivFix( in.y, norm );
1128         u.y = orientation * -FT_DivFix( in.x, norm );
1129
1130         norm = ft_norm( &out );
1131         v.x = orientation *  FT_DivFix( out.y, norm );
1132         v.y = orientation * -FT_DivFix( out.x, norm );
1133
1134         d = distance;
1135
1136         if ( ( outline->flags[n] & FT_Curve_Tag_On ) == 0 )
1137           d *= 2;
1138
1139         /* Check discriminant for parallel vectors */
1140         delta = FT_MulFix( u.x, v.y ) - FT_MulFix( u.y, v.x );
1141         if ( delta > FT_BOLD_THRESHOLD || delta < -FT_BOLD_THRESHOLD )
1142         {
1143           /* Move point -- compute A and B */
1144           FT_Pos  x, y, A, B;
1145
1146
1147           A = d + FT_MulFix( cur.x, u.x ) + FT_MulFix( cur.y, u.y );
1148           B = d + FT_MulFix( cur.x, v.x ) + FT_MulFix( cur.y, v.y );
1149
1150           x = FT_MulFix( A, v.y ) - FT_MulFix( B, u.y );
1151           y = FT_MulFix( B, u.x ) - FT_MulFix( A, v.x );
1152
1153           outline->points[n].x = distance + FT_DivFix( x, delta );
1154           outline->points[n].y = distance + FT_DivFix( y, delta );
1155         }
1156         else
1157         {
1158           /* Vectors are nearly parallel */
1159           FT_Pos  x, y;
1160
1161
1162           x = distance + cur.x + FT_MulFix( d, u.x + v.x ) / 2;
1163           y = distance + cur.y + FT_MulFix( d, u.y + v.y ) / 2;
1164
1165           outline->points[n].x = x;
1166           outline->points[n].y = y;
1167         }
1168
1169         prev = cur;
1170       }
1171
1172       first = last + 1;
1173     }
1174
1175     if ( advance )
1176       *advance = ( *advance + distance * 4 ) & -64;
1177
1178     return 0;
1179   }
1180
1181 #endif /* 0 -- EXPERIMENTAL STUFF! */
1182
1183
1184 /* END */