Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftglyph.c                                                              */
  4. /*                                                                         */
  5. /*    FreeType convenience functions to handle glyphs (body).              */
  6. /*                                                                         */
  7. /*  Copyright 1996-2005, 2007, 2008, 2010, 2012, 2013 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_INTERNAL_DEBUG_H
  33.  
  34. #include FT_GLYPH_H
  35. #include FT_OUTLINE_H
  36. #include FT_BITMAP_H
  37. #include FT_INTERNAL_OBJECTS_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.