freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[freetype2] master 61d1818: Bitmap metrics presetting [1/2].


From: Alexei Podtelezhnikov
Subject: [freetype2] master 61d1818: Bitmap metrics presetting [1/2].
Date: Thu, 28 Sep 2017 00:22:09 -0400 (EDT)

branch: master
commit 61d1818b5ef4fd9b014c4577f07cf5580ba67eee
Author: Alexei Podtelezhnikov <address@hidden>
Commit: Alexei Podtelezhnikov <address@hidden>

    Bitmap metrics presetting [1/2].
    
    This mainly just extracts the code for presetting the bitmap metrics
    from the monochrome, grayscale, and LCD renderers into a separate
    function.
    
    * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): New function that
    calculates prespective bitmap metrics for the given rendering mode.
    * include/freetype/internal/ftobjs.h (ft_glyphslot_preset_bitmap):
    Declare it.
    
    * src/base/ftlcdfil.c (ft_lcd_padding): New helper function that adds
    padding to CBox taking into account pecularities of LCD rendering.
    * include/freetype/ftlcdfil.h (ft_lcd_padding): Declare it.
    
    * src/raster/ftrend1.c (ft_raster1_render): Reworked to use
    `ft_glyphslot_preset_bitmap'.
    * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto.
    (ft_smooth_render_lcd, ft_smooth_render_lcd): The pixel_mode setting
    is moved to `ft_glyphslot_preset_bitmap'.
---
 ChangeLog                          |  23 +++++
 include/freetype/ftlcdfil.h        |  10 ++
 include/freetype/internal/ftobjs.h |   6 ++
 src/base/ftlcdfil.c                |  49 +++++++--
 src/base/ftobjs.c                  | 129 ++++++++++++++++++++++++
 src/raster/ftrend1.c               | 105 ++++++-------------
 src/smooth/ftsmooth.c              | 201 ++++++++++---------------------------
 7 files changed, 294 insertions(+), 229 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 03adef7..c1a9b32 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2017-09-28  Alexei Podtelezhnikov  <address@hidden>
+
+       Bitmap metrics presetting [1/2].
+
+       This mainly just extracts the code for presetting the bitmap metrics
+       from the monochrome, grayscale, and LCD renderers into a separate
+       function.
+
+       * src/base/ftobjs.c (ft_glyphslot_preset_bitmap): New function that
+       calculates prespective bitmap metrics for the given rendering mode.
+       * include/freetype/internal/ftobjs.h (ft_glyphslot_preset_bitmap):
+       Declare it.
+
+       * src/base/ftlcdfil.c (ft_lcd_padding): New helper function that adds
+       padding to CBox taking into account pecularities of LCD rendering.
+       * include/freetype/ftlcdfil.h (ft_lcd_padding): Declare it.
+
+       * src/raster/ftrend1.c (ft_raster1_render): Reworked to use
+       `ft_glyphslot_preset_bitmap'.
+       * src/smooth/ftsmooth.c (ft_smooth_render_generic): Ditto.
+       (ft_smooth_render_lcd, ft_smooth_render_lcd): The pixel_mode setting
+       is moved to `ft_glyphslot_preset_bitmap'.
+
 2017-09-28  Ewald Hew  <address@hidden>
 
        [psaux] Fix compiler warning.
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index 8c75141..df1d7cc 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -316,6 +316,14 @@ FT_BEGIN_HEADER
 
   typedef FT_Byte  FT_LcdFiveTapFilter[FT_LCD_FILTER_FIVE_TAPS];
 
+
+  FT_BASE( void )
+  ft_lcd_padding( FT_Pos*       Min,
+                  FT_Pos*       Max,
+                  FT_GlyphSlot  slot );
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+
   typedef void  (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap*      bitmap,
                                             FT_Render_Mode  render_mode,
                                             FT_Byte*        weights );
@@ -327,6 +335,8 @@ FT_BEGIN_HEADER
                      FT_Render_Mode       mode,
                      FT_LcdFiveTapFilter  weights );
 
+#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
+
 
   /* */
 
diff --git a/include/freetype/internal/ftobjs.h 
b/include/freetype/internal/ftobjs.h
index 25c328f..97c4e67 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -708,6 +708,12 @@ FT_BEGIN_HEADER
   ft_glyphslot_free_bitmap( FT_GlyphSlot  slot );
 
 
+  /* Preset bitmap metrics of an outline glyphslot prior to rendering.    */
+  FT_BASE( void )
+  ft_glyphslot_preset_bitmap( FT_GlyphSlot      slot,
+                              FT_Render_Mode    mode,
+                              const FT_Vector*  origin );
+
   /* Allocate a new bitmap buffer in a glyph slot. */
   FT_BASE( FT_Error )
   ft_glyphslot_alloc_bitmap( FT_GlyphSlot  slot,
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index ca781f3..4971f93 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -31,6 +31,39 @@
 
 #define FT_SHIFTCLAMP( x )  ( x >>= 8, (FT_Byte)( x > 255 ? 255 : x ) )
 
+
+  /* add padding according to filter weights */
+  FT_BASE_DEF (void)
+  ft_lcd_padding( FT_Pos*       Min,
+                  FT_Pos*       Max,
+                  FT_GlyphSlot  slot )
+  {
+    FT_Byte*                 lcd_weights;
+    FT_Bitmap_LcdFilterFunc  lcd_filter_func;
+
+
+    /* Per-face LCD filtering takes priority if set up. */
+    if ( slot->face && slot->face->internal->lcd_filter_func )
+    {
+      lcd_weights     = slot->face->internal->lcd_weights;
+      lcd_filter_func = slot->face->internal->lcd_filter_func;
+    }
+    else
+    {
+      lcd_weights     = slot->library->lcd_weights;
+      lcd_filter_func = slot->library->lcd_filter_func;
+    }
+
+    if ( lcd_filter_func == ft_lcd_filter_fir )
+    {
+      *Min -= lcd_weights[0] ? 43 :
+              lcd_weights[1] ? 22 : 0;
+      *Max += lcd_weights[4] ? 43 :
+              lcd_weights[3] ? 22 : 0;
+    }
+  }
+
+
   /* FIR filter used by the default and light filters */
   FT_BASE_DEF( void )
   ft_lcd_filter_fir( FT_Bitmap*           bitmap,
@@ -310,14 +343,16 @@
 
 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-  FT_BASE( void )
-  ft_lcd_filter_fir( FT_Bitmap*           bitmap,
-                     FT_Render_Mode       mode,
-                     FT_LcdFiveTapFilter  weights )
+  /* add padding according to accommodate outline shifts */
+  FT_BASE_DEF (void)
+  ft_lcd_padding( FT_Pos*       Min,
+                  FT_Pos*       Max,
+                  FT_GlyphSlot  slot )
   {
-    FT_UNUSED( bitmap );
-    FT_UNUSED( mode );
-    FT_UNUSED( weights );
+    FT_UNUSED( slot );
+
+    *Min -= 21;
+    *Max += 21;
   }
 
 
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index aedb1f3..42ec58e 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -328,6 +328,135 @@
 
 
   FT_BASE_DEF( void )
+  ft_glyphslot_preset_bitmap( FT_GlyphSlot      slot,
+                              FT_Render_Mode    mode,
+                              const FT_Vector*  origin )
+  {
+    FT_Outline*  outline = &slot->outline;
+    FT_Bitmap*   bitmap  = &slot->bitmap;
+
+    FT_Pixel_Mode  pixel_mode;
+
+    FT_BBox      cbox;
+    FT_Pos       x_shift = 0;
+    FT_Pos       y_shift = 0;
+    FT_Pos       x_left, y_top;
+    FT_Pos       width, height, pitch;
+
+
+    if ( slot->internal && ( slot->internal->flags & FT_GLYPH_OWN_BITMAP ) )
+      return;
+
+    if ( origin )
+    {
+      x_shift = origin->x;
+      y_shift = origin->y;
+    }
+
+    /* compute the control box, and grid fit it */
+    /* taking into account the origin shift     */
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    cbox.xMin += x_shift;
+    cbox.yMin += y_shift;
+    cbox.xMax += x_shift;
+    cbox.yMax += y_shift;
+
+    switch ( mode )
+    {
+    case FT_RENDER_MODE_MONO:
+      pixel_mode = FT_PIXEL_MODE_MONO;
+#if 1
+      /* undocumented but confirmed: bbox values get rounded    */
+      /* unless the rounded box can collapse for a narrow glyph */
+      if ( cbox.xMax - cbox.xMin < 64 )
+      {
+        cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+        cbox.xMax = FT_PIX_CEIL( cbox.xMax );
+      }
+      else
+      {
+        cbox.xMin = FT_PIX_ROUND( cbox.xMin );
+        cbox.xMax = FT_PIX_ROUND( cbox.xMax );
+      }
+
+      if ( cbox.yMax - cbox.yMin < 64 )
+      {
+        cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+        cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+      }
+      else
+      {
+        cbox.yMin = FT_PIX_ROUND( cbox.yMin );
+        cbox.yMax = FT_PIX_ROUND( cbox.yMax );
+      }
+#else
+      cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+      cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+      cbox.xMax = FT_PIX_CEIL( cbox.xMax );
+      cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+#endif
+      break;
+
+    case FT_RENDER_MODE_LCD:
+      pixel_mode = FT_PIXEL_MODE_LCD;
+      ft_lcd_padding( &cbox.xMin, &cbox.xMax, slot );
+      goto Round;
+
+    case FT_RENDER_MODE_LCD_V:
+      pixel_mode = FT_PIXEL_MODE_LCD_V;
+      ft_lcd_padding( &cbox.yMin, &cbox.yMax, slot );
+      goto Round;
+
+    case FT_RENDER_MODE_NORMAL:
+    case FT_RENDER_MODE_LIGHT:
+    default:
+      pixel_mode = FT_PIXEL_MODE_GRAY;
+    Round:
+      cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
+      cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
+      cbox.xMax = FT_PIX_CEIL( cbox.xMax );
+      cbox.yMax = FT_PIX_CEIL( cbox.yMax );
+    }
+
+    x_shift -= cbox.xMin;
+    y_shift -= cbox.yMin;
+
+    x_left  = cbox.xMin >> 6;
+    y_top   = cbox.yMax >> 6;
+
+    width  = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
+    height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
+
+    switch ( pixel_mode )
+    {
+    case FT_PIXEL_MODE_MONO:
+      pitch  = ( ( width + 15 ) >> 4 ) << 1;
+      break;
+    case FT_PIXEL_MODE_LCD:
+      width *= 3;
+      pitch  = FT_PAD_CEIL( width, 4 );
+      break;
+    case FT_PIXEL_MODE_LCD_V:
+      height *= 3;
+      /* fall through */
+    case FT_PIXEL_MODE_GRAY:
+    default:
+      pitch = width;
+    }
+
+    slot->bitmap_left = (FT_Int)x_left;
+    slot->bitmap_top  = (FT_Int)y_top;
+
+    bitmap->pixel_mode = pixel_mode;
+    bitmap->num_grays  = 256;
+    bitmap->width      = (unsigned int)width;
+    bitmap->rows       = (unsigned int)height;
+    bitmap->pitch      = pitch;
+  }
+
+
+  FT_BASE_DEF( void )
   ft_glyphslot_set_bitmap( FT_GlyphSlot  slot,
                            FT_Byte*      buffer )
   {
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index 185a7f6..a5b8153 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -98,11 +98,11 @@
                      const FT_Vector*  origin )
   {
     FT_Error     error;
-    FT_Outline*  outline;
-    FT_BBox      cbox, cbox0;
-    FT_UInt      width, height, pitch;
-    FT_Bitmap*   bitmap;
-    FT_Memory    memory;
+    FT_Outline*  outline = &slot->outline;
+    FT_Bitmap*   bitmap  = &slot->bitmap;
+    FT_Memory    memory  = render->root.memory;
+    FT_Pos       x_shift = 0;
+    FT_Pos       y_shift = 0;
 
     FT_Raster_Params  params;
 
@@ -121,60 +121,6 @@
       return FT_THROW( Cannot_Render_Glyph );
     }
 
-    outline = &slot->outline;
-
-    /* translate the outline to the new origin if needed */
-    if ( origin )
-      FT_Outline_Translate( outline, origin->x, origin->y );
-
-    /* compute the control box, and grid fit it */
-    FT_Outline_Get_CBox( outline, &cbox0 );
-
-    /* undocumented but confirmed: bbox values get rounded */
-#if 1
-    cbox.xMin = FT_PIX_ROUND( cbox0.xMin );
-    cbox.yMin = FT_PIX_ROUND( cbox0.yMin );
-    cbox.xMax = FT_PIX_ROUND( cbox0.xMax );
-    cbox.yMax = FT_PIX_ROUND( cbox0.yMax );
-#else
-    cbox.xMin = FT_PIX_FLOOR( cbox.xMin );
-    cbox.yMin = FT_PIX_FLOOR( cbox.yMin );
-    cbox.xMax = FT_PIX_CEIL( cbox.xMax );
-    cbox.yMax = FT_PIX_CEIL( cbox.yMax );
-#endif
-
-    /* If either `width' or `height' round to 0, try    */
-    /* explicitly rounding up/down.  In the case of     */
-    /* glyphs containing only one very narrow feature,  */
-    /* this gives the drop-out compensation in the scan */
-    /* conversion code a chance to do its stuff.        */
-    width  = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
-    if ( width == 0 )
-    {
-      cbox.xMin = FT_PIX_FLOOR( cbox0.xMin );
-      cbox.xMax = FT_PIX_CEIL( cbox0.xMax );
-
-      width = (FT_UInt)( ( cbox.xMax - cbox.xMin ) >> 6 );
-    }
-
-    height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
-    if ( height == 0 )
-    {
-      cbox.yMin = FT_PIX_FLOOR( cbox0.yMin );
-      cbox.yMax = FT_PIX_CEIL( cbox0.yMax );
-
-      height = (FT_UInt)( ( cbox.yMax - cbox.yMin ) >> 6 );
-    }
-
-    if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX )
-    {
-      error = FT_THROW( Invalid_Argument );
-      goto Exit;
-    }
-
-    bitmap = &slot->bitmap;
-    memory = render->root.memory;
-
     /* release old bitmap buffer */
     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
     {
@@ -182,20 +128,26 @@
       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
     }
 
-    pitch              = ( ( width + 15 ) >> 4 ) << 1;
-    bitmap->pixel_mode = FT_PIXEL_MODE_MONO;
-
-    bitmap->width = width;
-    bitmap->rows  = height;
-    bitmap->pitch = (int)pitch;
+    ft_glyphslot_preset_bitmap( slot, mode, origin );
 
-    if ( FT_ALLOC_MULT( bitmap->buffer, height, pitch ) )
+    /* allocate new one */
+    if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
       goto Exit;
 
     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
+    x_shift = -slot->bitmap_left * 64;
+    y_shift = ( bitmap->rows - slot->bitmap_top ) * 64;
+
+    if ( origin )
+    {
+      x_shift += origin->x;
+      y_shift += origin->y;
+    }
+
     /* translate outline to render it into the bitmap */
-    FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
+    if ( x_shift || y_shift )
+      FT_Outline_Translate( outline, x_shift, y_shift );
 
     /* set up parameters */
     params.target = bitmap;
@@ -204,17 +156,24 @@
 
     /* render outline into the bitmap */
     error = render->raster_render( render->raster, &params );
-
-    FT_Outline_Translate( outline, cbox.xMin, cbox.yMin );
-
     if ( error )
       goto Exit;
 
-    slot->format      = FT_GLYPH_FORMAT_BITMAP;
-    slot->bitmap_left = (FT_Int)( cbox.xMin >> 6 );
-    slot->bitmap_top  = (FT_Int)( cbox.yMax >> 6 );
+    /* everything is fine; the glyph is now officially a bitmap */
+    slot->format = FT_GLYPH_FORMAT_BITMAP;
+
+    error = FT_Err_Ok;
 
   Exit:
+    if ( x_shift || y_shift )
+      FT_Outline_Translate( outline, -x_shift, -y_shift );
+    if ( slot->format != FT_GLYPH_FORMAT_BITMAP      &&
+         slot->internal->flags & FT_GLYPH_OWN_BITMAP )
+    {
+      FT_FREE( bitmap->buffer );
+      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+    }
+
     return error;
   }
 
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 99a9883..50ce44b 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -101,36 +101,13 @@
     FT_Outline*  outline = &slot->outline;
     FT_Bitmap*   bitmap  = &slot->bitmap;
     FT_Memory    memory  = render->root.memory;
-    FT_BBox      cbox;
     FT_Pos       x_shift = 0;
     FT_Pos       y_shift = 0;
-    FT_Pos       x_left, y_top;
-    FT_Pos       width, height, pitch;
     FT_Int       hmul    = ( mode == FT_RENDER_MODE_LCD );
     FT_Int       vmul    = ( mode == FT_RENDER_MODE_LCD_V );
 
     FT_Raster_Params  params;
 
-    FT_Bool  have_outline_shifted = FALSE;
-    FT_Bool  have_buffer          = FALSE;
-
-#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-    FT_Byte*                 lcd_weights;
-    FT_Bitmap_LcdFilterFunc  lcd_filter_func;
-
-
-    /* Per-face LCD filtering takes priority if set up. */
-    if ( slot->face && slot->face->internal->lcd_filter_func )
-    {
-      lcd_weights     = slot->face->internal->lcd_weights;
-      lcd_filter_func = slot->face->internal->lcd_filter_func;
-    }
-    else
-    {
-      lcd_weights     = slot->library->lcd_weights;
-      lcd_filter_func = slot->library->lcd_filter_func;
-    }
-#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
     /* check glyph image format */
     if ( slot->format != render->glyph_format )
@@ -146,100 +123,6 @@
       goto Exit;
     }
 
-    if ( origin )
-    {
-      x_shift = origin->x;
-      y_shift = origin->y;
-    }
-
-    /* compute the control box, and grid fit it */
-    /* taking into account the origin shift     */
-    FT_Outline_Get_CBox( outline, &cbox );
-
-#ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
-
-    /* add minimal padding for LCD rendering */
-    if ( hmul )
-    {
-      cbox.xMax += 21;
-      cbox.xMin -= 21;
-    }
-
-    if ( vmul )
-    {
-      cbox.yMax += 21;
-      cbox.yMin -= 21;
-    }
-
-#else /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
-
-    /* add minimal padding for LCD filter depending on specific weights */
-    if ( lcd_filter_func == ft_lcd_filter_fir )
-    {
-      if ( hmul )
-      {
-        cbox.xMax += lcd_weights[4] ? 43
-                                    : lcd_weights[3] ? 22 : 0;
-        cbox.xMin -= lcd_weights[0] ? 43
-                                    : lcd_weights[1] ? 22 : 0;
-      }
-
-      if ( vmul )
-      {
-        cbox.yMax += lcd_weights[4] ? 43
-                                    : lcd_weights[3] ? 22 : 0;
-        cbox.yMin -= lcd_weights[0] ? 43
-                                    : lcd_weights[1] ? 22 : 0;
-      }
-    }
-
-#endif /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
-
-    cbox.xMin = FT_PIX_FLOOR( cbox.xMin + x_shift );
-    cbox.yMin = FT_PIX_FLOOR( cbox.yMin + y_shift );
-    cbox.xMax = FT_PIX_CEIL( cbox.xMax + x_shift );
-    cbox.yMax = FT_PIX_CEIL( cbox.yMax + y_shift );
-
-    x_shift -= cbox.xMin;
-    y_shift -= cbox.yMin;
-
-    x_left  = cbox.xMin >> 6;
-    y_top   = cbox.yMax >> 6;
-
-    width  = (FT_ULong)( cbox.xMax - cbox.xMin ) >> 6;
-    height = (FT_ULong)( cbox.yMax - cbox.yMin ) >> 6;
-
-    pitch = width;
-    if ( hmul )
-    {
-      width *= 3;
-      pitch  = FT_PAD_CEIL( width, 4 );
-    }
-
-    if ( vmul )
-      height *= 3;
-
-    /*
-     * XXX: on 16bit system, we return an error for huge bitmap
-     * to prevent an overflow.
-     */
-    if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX ||
-         x_left < FT_INT_MIN || y_top < FT_INT_MIN )
-    {
-      error = FT_THROW( Invalid_Pixel_Size );
-      goto Exit;
-    }
-
-    /* Required check is (pitch * height < FT_ULONG_MAX),        */
-    /* but we care realistic cases only.  Always pitch <= width. */
-    if ( width > 0x7FFF || height > 0x7FFF )
-    {
-      FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
-                 width, height ));
-      error = FT_THROW( Raster_Overflow );
-      goto Exit;
-    }
-
     /* release old bitmap buffer */
     if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
     {
@@ -247,30 +130,30 @@
       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
     }
 
+    ft_glyphslot_preset_bitmap( slot, mode, origin );
+
     /* allocate new one */
-    if ( FT_ALLOC( bitmap->buffer, (FT_ULong)( pitch * height ) ) )
+    if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
       goto Exit;
-    else
-      have_buffer = TRUE;
 
     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
-    slot->format      = FT_GLYPH_FORMAT_BITMAP;
-    slot->bitmap_left = (FT_Int)x_left;
-    slot->bitmap_top  = (FT_Int)y_top;
+    x_shift = 64 * -slot->bitmap_left;
+    y_shift = 64 * -slot->bitmap_top;
+    if ( bitmap->pixel_mode == FT_PIXEL_MODE_LCD_V )
+      y_shift += 64 * bitmap->rows / 3;
+    else
+      y_shift += 64 * bitmap->rows;
 
-    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
-    bitmap->num_grays  = 256;
-    bitmap->width      = (unsigned int)width;
-    bitmap->rows       = (unsigned int)height;
-    bitmap->pitch      = pitch;
+    if ( origin )
+    {
+      x_shift += origin->x;
+      y_shift += origin->y;
+    }
 
     /* translate outline to render it into the bitmap */
     if ( x_shift || y_shift )
-    {
       FT_Outline_Translate( outline, x_shift, y_shift );
-      have_outline_shifted = TRUE;
-    }
 
     /* set up parameters */
     params.target = bitmap;
@@ -317,8 +200,28 @@
     if ( error )
       goto Exit;
 
-    if ( lcd_filter_func )
-      lcd_filter_func( bitmap, mode, lcd_weights );
+    /* finally apply filtering */
+    if ( hmul || vmul )
+    {
+      FT_Byte*                 lcd_weights;
+      FT_Bitmap_LcdFilterFunc  lcd_filter_func;
+
+
+      /* Per-face LCD filtering takes priority if set up. */
+      if ( slot->face && slot->face->internal->lcd_filter_func )
+      {
+        lcd_weights     = slot->face->internal->lcd_weights;
+        lcd_filter_func = slot->face->internal->lcd_filter_func;
+      }
+      else
+      {
+        lcd_weights     = slot->library->lcd_weights;
+        lcd_filter_func = slot->library->lcd_filter_func;
+      }
+
+      if ( lcd_filter_func )
+        lcd_filter_func( bitmap, mode, lcd_weights );
+    }
 
 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
@@ -328,6 +231,10 @@
       FT_Byte*  temp;
       FT_Int    i, j;
 
+      unsigned int    height = bitmap->rows;
+      unsigned int    width  = bitmap->width;
+      int             pitch  = bitmap->pitch;
+
 
       /* Render 3 separate monochrome bitmaps, shifting the outline  */
       /* by 1/3 pixel.                                               */
@@ -378,6 +285,9 @@
     }
     else if ( vmul )  /* lcd_v */
     {
+      int             pitch  = bitmap->pitch;
+
+
       /* Render 3 separate monochrome bitmaps, shifting the outline  */
       /* by 1/3 pixel. Triple the pitch to render on each third row. */
       bitmap->pitch *= 3;
@@ -418,15 +328,16 @@
 
 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-    /* everything is fine; don't deallocate buffer */
-    have_buffer = FALSE;
+    /* everything is fine; the glyph is now officially a bitmap */
+    slot->format = FT_GLYPH_FORMAT_BITMAP;
 
     error = FT_Err_Ok;
 
   Exit:
-    if ( have_outline_shifted )
+    if ( x_shift || y_shift )
       FT_Outline_Translate( outline, -x_shift, -y_shift );
-    if ( have_buffer )
+    if ( slot->format != FT_GLYPH_FORMAT_BITMAP      &&
+         slot->internal->flags & FT_GLYPH_OWN_BITMAP )
     {
       FT_FREE( bitmap->buffer );
       slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
@@ -460,12 +371,8 @@
   {
     FT_Error  error;
 
-    error = ft_smooth_render_generic( render, slot, mode, origin,
-                                      FT_RENDER_MODE_LCD );
-    if ( !error )
-      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
-
-    return error;
+    return ft_smooth_render_generic( render, slot, mode, origin,
+                                     FT_RENDER_MODE_LCD );
   }
 
 
@@ -478,12 +385,8 @@
   {
     FT_Error  error;
 
-    error = ft_smooth_render_generic( render, slot, mode, origin,
-                                      FT_RENDER_MODE_LCD_V );
-    if ( !error )
-      slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;
-
-    return error;
+    return ft_smooth_render_generic( render, slot, mode, origin,
+                                     FT_RENDER_MODE_LCD_V );
   }
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]