Edit

kc3-lang/freetype/src/base/ftglyph.c

Branch :

  • Show log

    Commit

  • Author : Werner Lemberg
    Date : 2004-05-17 09:25:04
    Hash : e260d253
    Message : * src/cache/ftcbasic.c (ftc_basic_family_compare, ftc_basic_family_init, ftc_basic_family_get_count, ftc_basic_family_load_bitmap, ftc_basic_family_load_glyph, ftc_basic_gnode_compare_faceid): Adjust parameters and return types to prototypes given in header files from include/freetype/cache. Use casts to proper types locally. (ftc_basic_image_family_class, ftc_basic_image_cache_class, ftc_basic_sbit_family_class, ftc_basic_sbit_cache_class): Remove casts. * src/cache/ftccback.h: Adjust parameters and return types to prototypes given in header files from include/freetype/cache. * src/cache/ftcimage.c (ftc_inode_free, ftc_inode_new, ftc_inode_weight): Adjust parameters and return types to prototypes given in header files from include/freetype/cache. Use casts to proper types locally. * src/cache/ftcsbits.c (ftc_snode_free, ftc_snode_new, ftc_snode_weight, ftc_snode_compare): Adjust parameters and return types to prototypes given in header files from include/freetype/cache. Use casts to proper types locally. * src/cache/ftccmap.c (ftc_cmap_node_free, ftc_cmap_node_new, ftc_cmap_node_weight, ftc_cmap_node_compare, ftc_cmap_node_remove_faceid): Adjust parameters and return types to prototypes given in header files from include/freetype/cache. Use casts to proper types locally. (ftc_cmap_cache_class): Remove casts. * src/cache/ftcglyph.c (ftc_gnode_compare, ftc_gcache_init, ftc_gcache_done): Adjust parameters and return types to prototypes given in header files from include/freetype/cache. Use casts to proper types locally. * src/cache/ftcmanag.c (ftc_size_node_done, ftc_size_node_compare, ftc_size_node_init, ftc_size_node_reset, ftc_size_node_compare_faceid, ftc_face_node_init, ftc_face_node_done, ftc_face_node_compare: Adjust parameters and return types to prototypes given in header files from include/freetype/cache. Use casts to proper types locally. (ftc_size_list_class, ftc_face_list_class): Remove casts. * src/autohint/ahmodule.c (ft_autohinter_init, ft_autohinter_done): Use FT_Module as parameter and do a cast to FT_AutoHinter locally. (autohint_module_class): Remove casts. * src/base/ftglyph.c (ft_bitmap_glyph_init, ft_bitmap_glyph_copy, ft_bitmap_glyph_done, ft_bitmap_glyph_bbox, ft_outline_glyph_init, ft_outline_glyph_done, ft_outline_glyph_copy, ft_outline_glyph_transform, ft_outline_glyph_bbox, ft_outline_glyph_prepare): Use FT_Glyph as parameter and do a cast to FT_XXXGlyph locally. Use FT_CALLBACK_DEF throughout. (ft_bitmap_glyph_class, ft_outline_glyph_class): Remove casts. * src/bdf/bdfdrivr.c (bdf_cmap_init, bdf_cmap_done, bdf_cmap_char_index, bdf_cmap_char_next): Use FT_CMap as parameter and do a cast to BDF_CMap locally. (bdf_cmap_class): Remove casts.

  • src/base/ftglyph.c
  • /***************************************************************************/
    /*                                                                         */
    /*  ftglyph.c                                                              */
    /*                                                                         */
    /*    FreeType convenience functions to handle glyphs (body).              */
    /*                                                                         */
    /*  Copyright 1996-2001, 2002, 2003, 2004 by                               */
    /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
    /*                                                                         */
    /*  This file is part of the FreeType project, and may only be used,       */
    /*  modified, and distributed under the terms of the FreeType project      */
    /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
    /*  this file you indicate that you have read the license and              */
    /*  understand and accept it fully.                                        */
    /*                                                                         */
    /***************************************************************************/
    
      /*************************************************************************/
      /*                                                                       */
      /*  This file contains the definition of several convenience functions   */
      /*  that can be used by client applications to easily retrieve glyph     */
      /*  bitmaps and outlines from a given face.                              */
      /*                                                                       */
      /*  These functions should be optional if you are writing a font server  */
      /*  or text layout engine on top of FreeType.  However, they are pretty  */
      /*  handy for many other simple uses of the library.                     */
      /*                                                                       */
      /*************************************************************************/
    
    
    #include <ft2build.h>
    #include FT_GLYPH_H
    #include FT_OUTLINE_H
    #include FT_INTERNAL_OBJECTS_H
    
    
      /*************************************************************************/
      /*                                                                       */
      /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
      /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
      /* messages during execution.                                            */
      /*                                                                       */
    #undef  FT_COMPONENT
    #define FT_COMPONENT  trace_glyph
    
    
      /*************************************************************************/
      /*************************************************************************/
      /****                                                                 ****/
      /****   Convenience functions                                         ****/
      /****                                                                 ****/
      /*************************************************************************/
      /*************************************************************************/
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( void )
      FT_Matrix_Multiply( const FT_Matrix*  a,
                          FT_Matrix        *b )
      {
        FT_Fixed  xx, xy, yx, yy;
    
    
        if ( !a || !b )
          return;
    
        xx = FT_MulFix( a->xx, b->xx ) + FT_MulFix( a->xy, b->yx );
        xy = FT_MulFix( a->xx, b->xy ) + FT_MulFix( a->xy, b->yy );
        yx = FT_MulFix( a->yx, b->xx ) + FT_MulFix( a->yy, b->yx );
        yy = FT_MulFix( a->yx, b->xy ) + FT_MulFix( a->yy, b->yy );
    
        b->xx = xx;  b->xy = xy;
        b->yx = yx;  b->yy = yy;
      }
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( FT_Error )
      FT_Matrix_Invert( FT_Matrix*  matrix )
      {
        FT_Pos  delta, xx, yy;
    
    
        if ( !matrix )
          return FT_Err_Invalid_Argument;
    
        /* compute discriminant */
        delta = FT_MulFix( matrix->xx, matrix->yy ) -
                FT_MulFix( matrix->xy, matrix->yx );
    
        if ( !delta )
          return FT_Err_Invalid_Argument;  /* matrix can't be inverted */
    
        matrix->xy = - FT_DivFix( matrix->xy, delta );
        matrix->yx = - FT_DivFix( matrix->yx, delta );
    
        xx = matrix->xx;
        yy = matrix->yy;
    
        matrix->xx = FT_DivFix( yy, delta );
        matrix->yy = FT_DivFix( xx, delta );
    
        return FT_Err_Ok;
      }
    
    
      /*************************************************************************/
      /*************************************************************************/
      /****                                                                 ****/
      /****   FT_BitmapGlyph support                                        ****/
      /****                                                                 ****/
      /*************************************************************************/
      /*************************************************************************/
    
      static FT_Error
      ft_bitmap_copy( FT_Memory   memory,
                      FT_Bitmap*  source,
                      FT_Bitmap*  target )
      {
        FT_Error  error;
        FT_Int    pitch = source->pitch;
        FT_ULong  size;
    
    
        *target = *source;
    
        if ( pitch < 0 )
          pitch = -pitch;
    
        size = (FT_ULong)( pitch * source->rows );
    
        if ( !FT_ALLOC( target->buffer, size ) )
          FT_MEM_COPY( target->buffer, source->buffer, size );
    
        return error;
      }
    
    
      FT_CALLBACK_DEF( FT_Error )
      ft_bitmap_glyph_init( FT_Glyph      bitmap_glyph,
                            FT_GlyphSlot  slot )
      {
        FT_BitmapGlyph  glyph   = (FT_BitmapGlyph)bitmap_glyph;
        FT_Error        error   = FT_Err_Ok;
        FT_Library      library = FT_GLYPH( glyph )->library;
        FT_Memory       memory  = library->memory;
    
    
        if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
        {
          error = FT_Err_Invalid_Glyph_Format;
          goto Exit;
        }
    
        /* grab the bitmap in the slot - do lazy copying whenever possible */
        glyph->bitmap = slot->bitmap;
        glyph->left   = slot->bitmap_left;
        glyph->top    = slot->bitmap_top;
    
        if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
          slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
        else
        {
          /* copy the bitmap into a new buffer */
          error = ft_bitmap_copy( memory, &slot->bitmap, &glyph->bitmap );
        }
    
      Exit:
        return error;
      }
    
    
      FT_CALLBACK_DEF( FT_Error )
      ft_bitmap_glyph_copy( FT_Glyph  bitmap_source,
                            FT_Glyph  bitmap_target )
      {
        FT_BitmapGlyph  source = (FT_BitmapGlyph)bitmap_source;
        FT_BitmapGlyph  target = (FT_BitmapGlyph)bitmap_target;
        FT_Memory       memory = bitmap_source->library->memory;
    
    
        target->left = source->left;
        target->top  = source->top;
    
        return ft_bitmap_copy( memory, &source->bitmap, &target->bitmap );
      }
    
    
      FT_CALLBACK_DEF( void )
      ft_bitmap_glyph_done( FT_Glyph  bitmap_glyph )
      {
        FT_BitmapGlyph  glyph  = (FT_BitmapGlyph)bitmap_glyph;
        FT_Memory       memory = FT_GLYPH( glyph )->library->memory;
    
    
        FT_FREE( glyph->bitmap.buffer );
      }
    
    
      FT_CALLBACK_DEF( void )
      ft_bitmap_glyph_bbox( FT_Glyph  bitmap_glyph,
                            FT_BBox*  cbox )
      {
        FT_BitmapGlyph  glyph = (FT_BitmapGlyph)bitmap_glyph;
    
    
        cbox->xMin = glyph->left << 6;
        cbox->xMax = cbox->xMin + ( glyph->bitmap.width << 6 );
        cbox->yMax = glyph->top << 6;
        cbox->yMin = cbox->yMax - ( glyph->bitmap.rows << 6 );
      }
    
    
      FT_CALLBACK_TABLE_DEF
      const FT_Glyph_Class  ft_bitmap_glyph_class =
      {
        sizeof ( FT_BitmapGlyphRec ),
        FT_GLYPH_FORMAT_BITMAP,
    
        ft_bitmap_glyph_init,
        ft_bitmap_glyph_done,
        ft_bitmap_glyph_copy,
        0,                          /* FT_Glyph_TransformFunc */
        ft_bitmap_glyph_bbox,
        0                           /* FT_Glyph_PrepareFunc   */
      };
    
    
      /*************************************************************************/
      /*************************************************************************/
      /****                                                                 ****/
      /****   FT_OutlineGlyph support                                       ****/
      /****                                                                 ****/
      /*************************************************************************/
      /*************************************************************************/
    
    
      FT_CALLBACK_DEF( FT_Error )
      ft_outline_glyph_init( FT_Glyph      outline_glyph,
                             FT_GlyphSlot  slot )
      {
        FT_OutlineGlyph  glyph   = (FT_OutlineGlyph)outline_glyph;
        FT_Error         error   = FT_Err_Ok;
        FT_Library       library = FT_GLYPH( glyph )->library;
        FT_Outline*      source  = &slot->outline;
        FT_Outline*      target  = &glyph->outline;
    
    
        /* check format in glyph slot */
        if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
        {
          error = FT_Err_Invalid_Glyph_Format;
          goto Exit;
        }
    
        /* allocate new outline */
        error = FT_Outline_New( library, source->n_points, source->n_contours,
                                &glyph->outline );
        if ( error )
          goto Exit;
    
        /* copy it */
        FT_ARRAY_COPY( target->points, source->points, source->n_points );
    
        FT_ARRAY_COPY( target->tags, source->tags, source->n_points );
    
        FT_ARRAY_COPY( target->contours, source->contours, source->n_contours );
    
        /* copy all flags, except the `FT_OUTLINE_OWNER' one */
        target->flags = source->flags | FT_OUTLINE_OWNER;
    
      Exit:
        return error;
      }
    
    
      FT_CALLBACK_DEF( void )
      ft_outline_glyph_done( FT_Glyph  outline_glyph )
      {
        FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
    
    
        FT_Outline_Done( FT_GLYPH( glyph )->library, &glyph->outline );
      }
    
    
      FT_CALLBACK_DEF( FT_Error )
      ft_outline_glyph_copy( FT_Glyph  outline_source,
                             FT_Glyph  outline_target )
      {
        FT_OutlineGlyph  source  = (FT_OutlineGlyph)outline_source;
        FT_OutlineGlyph  target  = (FT_OutlineGlyph)outline_target;
        FT_Error         error;
        FT_Library       library = FT_GLYPH( source )->library;
    
    
        error = FT_Outline_New( library, source->outline.n_points,
                                source->outline.n_contours, &target->outline );
        if ( !error )
          FT_Outline_Copy( &source->outline, &target->outline );
    
        return error;
      }
    
    
      FT_CALLBACK_DEF( void )
      ft_outline_glyph_transform( FT_Glyph    outline_glyph,
                                  FT_Matrix*  matrix,
                                  FT_Vector*  delta )
      {
        FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
    
    
        if ( matrix )
          FT_Outline_Transform( &glyph->outline, matrix );
    
        if ( delta )
          FT_Outline_Translate( &glyph->outline, delta->x, delta->y );
      }
    
    
      FT_CALLBACK_DEF( void )
      ft_outline_glyph_bbox( FT_Glyph  outline_glyph,
                             FT_BBox*  bbox )
      {
        FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
    
    
        FT_Outline_Get_CBox( &glyph->outline, bbox );
      }
    
    
      FT_CALLBACK_DEF( FT_Error )
      ft_outline_glyph_prepare( FT_Glyph      outline_glyph,
                                FT_GlyphSlot  slot )
      {
        FT_OutlineGlyph  glyph = (FT_OutlineGlyph)outline_glyph;
    
    
        slot->format         = FT_GLYPH_FORMAT_OUTLINE;
        slot->outline        = glyph->outline;
        slot->outline.flags &= ~FT_OUTLINE_OWNER;
    
        return FT_Err_Ok;
      }
    
    
      FT_CALLBACK_TABLE_DEF
      const FT_Glyph_Class  ft_outline_glyph_class =
      {
        sizeof ( FT_OutlineGlyphRec ),
        FT_GLYPH_FORMAT_OUTLINE,
    
        ft_outline_glyph_init,
        ft_outline_glyph_done,
        ft_outline_glyph_copy,
        ft_outline_glyph_transform,
        ft_outline_glyph_bbox,
        ft_outline_glyph_prepare
      };
    
    
      /*************************************************************************/
      /*************************************************************************/
      /****                                                                 ****/
      /****   FT_Glyph class and API                                        ****/
      /****                                                                 ****/
      /*************************************************************************/
      /*************************************************************************/
    
       static FT_Error
       ft_new_glyph( FT_Library             library,
                     const FT_Glyph_Class*  clazz,
                     FT_Glyph*              aglyph )
       {
         FT_Memory  memory = library->memory;
         FT_Error   error;
         FT_Glyph   glyph;
    
    
         *aglyph = 0;
    
         if ( !FT_ALLOC( glyph, clazz->glyph_size ) )
         {
           glyph->library = library;
           glyph->clazz   = clazz;
           glyph->format  = clazz->glyph_format;
    
           *aglyph = glyph;
         }
    
         return error;
       }
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( FT_Error )
      FT_Glyph_Copy( FT_Glyph   source,
                     FT_Glyph  *target )
      {
        FT_Glyph               copy;
        FT_Error               error;
        const FT_Glyph_Class*  clazz;
    
    
        /* check arguments */
        if ( !target || !source || !source->clazz )
        {
          error = FT_Err_Invalid_Argument;
          goto Exit;
        }
    
        *target = 0;
    
        clazz = source->clazz;
        error = ft_new_glyph( source->library, clazz, &copy );
        if ( error )
          goto Exit;
    
        copy->advance = source->advance;
        copy->format  = source->format;
    
        if ( clazz->glyph_copy )
          error = clazz->glyph_copy( source, copy );
    
        if ( error )
          FT_Done_Glyph( copy );
        else
          *target = copy;
    
      Exit:
        return error;
      }
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( FT_Error )
      FT_Get_Glyph( FT_GlyphSlot  slot,
                    FT_Glyph     *aglyph )
      {
        FT_Library  library;
        FT_Error    error;
        FT_Glyph    glyph;
    
        const FT_Glyph_Class*  clazz = 0;
    
    
        if ( !slot )
          return FT_Err_Invalid_Slot_Handle;
    
        library = slot->library;
    
        if ( !aglyph )
          return FT_Err_Invalid_Argument;
    
        /* if it is a bitmap, that's easy :-) */
        if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
          clazz = &ft_bitmap_glyph_class;
    
        /* it it is an outline too */
        else if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
          clazz = &ft_outline_glyph_class;
    
        else
        {
          /* try to find a renderer that supports the glyph image format */
          FT_Renderer  render = FT_Lookup_Renderer( library, slot->format, 0 );
    
    
          if ( render )
            clazz = &render->glyph_class;
        }
    
        if ( !clazz )
        {
          error = FT_Err_Invalid_Glyph_Format;
          goto Exit;
        }
    
        /* create FT_Glyph object */
        error = ft_new_glyph( library, clazz, &glyph );
        if ( error )
          goto Exit;
    
        /* copy advance while converting it to 16.16 format */
        glyph->advance.x = slot->advance.x << 10;
        glyph->advance.y = slot->advance.y << 10;
    
        /* now import the image from the glyph slot */
        error = clazz->glyph_init( glyph, slot );
    
        /* if an error occurred, destroy the glyph */
        if ( error )
          FT_Done_Glyph( glyph );
        else
          *aglyph = glyph;
    
      Exit:
        return error;
      }
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( FT_Error )
      FT_Glyph_Transform( FT_Glyph    glyph,
                          FT_Matrix*  matrix,
                          FT_Vector*  delta )
      {
        const FT_Glyph_Class*  clazz;
        FT_Error               error = FT_Err_Ok;
    
    
        if ( !glyph || !glyph->clazz )
          error = FT_Err_Invalid_Argument;
        else
        {
          clazz = glyph->clazz;
          if ( clazz->glyph_transform )
          {
            /* transform glyph image */
            clazz->glyph_transform( glyph, matrix, delta );
    
            /* transform advance vector */
            if ( matrix )
              FT_Vector_Transform( &glyph->advance, matrix );
          }
          else
            error = FT_Err_Invalid_Glyph_Format;
        }
        return error;
      }
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( void )
      FT_Glyph_Get_CBox( FT_Glyph  glyph,
                         FT_UInt   bbox_mode,
                         FT_BBox  *acbox )
      {
        const FT_Glyph_Class*  clazz;
    
    
        if ( !acbox )
          return;
    
        acbox->xMin = acbox->yMin = acbox->xMax = acbox->yMax = 0;
    
        if ( !glyph || !glyph->clazz )
          return;
        else
        {
          clazz = glyph->clazz;
          if ( !clazz->glyph_bbox )
            return;
          else
          {
            /* retrieve bbox in 26.6 coordinates */
            clazz->glyph_bbox( glyph, acbox );
    
            /* perform grid fitting if needed */
            if ( bbox_mode == FT_GLYPH_BBOX_GRIDFIT ||
                 bbox_mode == FT_GLYPH_BBOX_PIXELS  )
            {
              acbox->xMin = FT_PIX_FLOOR( acbox->xMin );
              acbox->yMin = FT_PIX_FLOOR( acbox->yMin );
              acbox->xMax = FT_PIX_CEIL( acbox->xMax );
              acbox->yMax = FT_PIX_CEIL( acbox->yMax );
            }
    
            /* convert to integer pixels if needed */
            if ( bbox_mode == FT_GLYPH_BBOX_TRUNCATE ||
                 bbox_mode == FT_GLYPH_BBOX_PIXELS   )
            {
              acbox->xMin >>= 6;
              acbox->yMin >>= 6;
              acbox->xMax >>= 6;
              acbox->yMax >>= 6;
            }
          }
        }
        return;
      }
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( FT_Error )
      FT_Glyph_To_Bitmap( FT_Glyph*       the_glyph,
                          FT_Render_Mode  render_mode,
                          FT_Vector*      origin,
                          FT_Bool         destroy )
      {
        FT_GlyphSlotRec           dummy;
        FT_GlyphSlot_InternalRec  dummy_internal;
        FT_Error                  error = FT_Err_Ok;
        FT_Glyph                  glyph;
        FT_BitmapGlyph            bitmap = NULL;
    
        const FT_Glyph_Class*     clazz;
    
    
        /* check argument */
        if ( !the_glyph )
          goto Bad;
    
        /* we render the glyph into a glyph bitmap using a `dummy' glyph slot */
        /* then calling FT_Render_Glyph_Internal()                            */
    
        glyph = *the_glyph;
        if ( !glyph )
          goto Bad;
    
        clazz = glyph->clazz;
    
        /* when called with a bitmap glyph, do nothing and return successfully */
        if ( clazz == &ft_bitmap_glyph_class )
          goto Exit;
    
        if ( !clazz || !clazz->glyph_prepare )
          goto Bad;
    
        FT_MEM_ZERO( &dummy, sizeof ( dummy ) );
        FT_MEM_ZERO( &dummy_internal, sizeof ( dummy_internal ) );
        dummy.internal = &dummy_internal;
        dummy.library  = glyph->library;
        dummy.format   = clazz->glyph_format;
    
        /* create result bitmap glyph */
        error = ft_new_glyph( glyph->library, &ft_bitmap_glyph_class,
                              (FT_Glyph*)&bitmap );
        if ( error )
          goto Exit;
    
    #if 1
        /* if `origin' is set, translate the glyph image */
        if ( origin )
          FT_Glyph_Transform( glyph, 0, origin );
    #else
        FT_UNUSED( origin );
    #endif
    
        /* prepare dummy slot for rendering */
        error = clazz->glyph_prepare( glyph, &dummy );
        if ( !error )
          error = FT_Render_Glyph_Internal( glyph->library, &dummy, render_mode );
    
    #if 1
        if ( !destroy && origin )
        {
          FT_Vector  v;
    
    
          v.x = -origin->x;
          v.y = -origin->y;
          FT_Glyph_Transform( glyph, 0, &v );
        }
    #endif
    
        if ( error )
          goto Exit;
    
        /* in case of success, copy the bitmap to the glyph bitmap */
        error = ft_bitmap_glyph_init( (FT_Glyph)bitmap, &dummy );
        if ( error )
          goto Exit;
    
        /* copy advance */
        bitmap->root.advance = glyph->advance;
    
        if ( destroy )
          FT_Done_Glyph( glyph );
    
        *the_glyph = FT_GLYPH( bitmap );
    
      Exit:
        if ( error && bitmap )
          FT_Done_Glyph( FT_GLYPH( bitmap ) );
    
        return error;
    
      Bad:
        error = FT_Err_Invalid_Argument;
        goto Exit;
      }
    
    
      /* documentation is in ftglyph.h */
    
      FT_EXPORT_DEF( void )
      FT_Done_Glyph( FT_Glyph  glyph )
      {
        if ( glyph )
        {
          FT_Memory              memory = glyph->library->memory;
          const FT_Glyph_Class*  clazz  = glyph->clazz;
    
    
          if ( clazz->glyph_done )
            clazz->glyph_done( glyph );
    
          FT_FREE( glyph );
        }
      }
    
    
    /* END */