Commit 8a317cf7ab1a13f9b4b7fbf678454c92c21cfddf

David Turner 2006-09-27T07:52:48

* include/freetype/freetype.h: bumping FT_FREETYPE_PATCH to 2 for an upcoming 2.2.2 release * include/freetype/ftlcdfil.h, src/freetype/ftlcdfil.c: added a new API to support color filtering of subpixel glyph bitmaps. In default build, the function FT_Library_SetLcdFilter returns FT_Err_Unimplemented_Feature; you need to #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in ftoption.h to compile the real implementation * src/smooth/ftsmooth.c: adding support for sub-pixel color filtering; simplifying a few function calls * include/freetype/config/ftheader.h: adding FT_LCD_FILTER_H macro that points to <freetype/ftlcdfil.h>

diff --git a/ChangeLog b/ChangeLog
index 1887e73..20e6000 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2006-09-27  David Turner  <david@freetype.org>
+
+        * include/freetype/freetype.h: bumping FT_FREETYPE_PATCH to 2
+        for an upcoming 2.2.2 release
+
+        * include/freetype/ftlcdfil.h, src/freetype/ftlcdfil.c:
+        added a new API to support color filtering of subpixel glyph
+        bitmaps. In default build, the function FT_Library_SetLcdFilter
+        returns FT_Err_Unimplemented_Feature; you need to #define
+        FT_CONFIG_OPTION_SUBPIXEL_RENDERING in ftoption.h to compile
+        the real implementation
+
+        * src/smooth/ftsmooth.c: adding support for sub-pixel color
+        filtering; simplifying a few function calls
+
+        * include/freetype/config/ftheader.h: adding FT_LCD_FILTER_H
+        macro that points to <freetype/ftlcdfil.h>
+
 2006-09-26  David Bustin
 
 	* src/pfr/pfrobjs.c (pfr_face_get_kerning): Skip adjustment bytes
diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h
index 7d663d9..097ff66 100644
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -665,6 +665,17 @@
    */
 #define FT_TRIGONOMETRY_H  <freetype/fttrigon.h>
 
+  /*************************************************************************
+   *
+   * @macro:
+   *   FT_LCD_FILTER_H
+   *
+   * @description:
+   *   A macro used in #include statements to name the file containing the
+   *   FreeType 2 API used to perform color filtering for subpixel rendering
+   */
+#define FT_LCD_FILTER_H    <freetype/ftlcdfil.h>
+
   /* */
 
 #define FT_ERROR_DEFINITIONS_H  <freetype/fterrdef.h>
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 5e6b6c3..6344b6c 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -3311,7 +3311,7 @@ FT_BEGIN_HEADER
    */
 #define FREETYPE_MAJOR  2
 #define FREETYPE_MINOR  2
-#define FREETYPE_PATCH  1
+#define FREETYPE_PATCH  2
 
 
   /*************************************************************************/
@@ -3349,7 +3349,6 @@ FT_BEGIN_HEADER
                       FT_Int      *aminor,
                       FT_Int      *apatch );
 
-
   /* */
 
 
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index 38eef7b..2e7c895 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -650,6 +650,10 @@ FT_BEGIN_HEADER
 #define FT_DEBUG_HOOK_UNPATENTED_HINTING  1
 
 
+  typedef void  (*FT_Bitmap_LcdFilterFunc)( FT_Bitmap*      bitmap,
+                                            FT_Render_Mode  render_mode,
+                                            FT_Byte*        weights );
+
   /*************************************************************************/
   /*                                                                       */
   /* <Struct>                                                              */
@@ -723,6 +727,11 @@ FT_BEGIN_HEADER
 
     FT_DebugHook_Func  debug_hooks[4];
 
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+    FT_Byte                  lcd_filter_weights[5];
+    FT_Bitmap_LcdFilterFunc  lcd_filter;
+#endif
+
   } FT_LibraryRec;
 
 
diff --git a/src/base/Jamfile b/src/base/Jamfile
index 2c486d1..8999a22 100644
--- a/src/base/Jamfile
+++ b/src/base/Jamfile
@@ -34,7 +34,7 @@ SubDir  FT2_TOP $(FT2_SRC_DIR) base ;
   local  _sources =  system  init    glyph  mm      bdf
                      bbox    debug   xf86   type1   pfr
                      stroke  winfnt  otval  bitmap  synth
-                     gxval
+                     gxval   lcdfil
                      ;
 
   Library  $(FT2_LIB) : ft$(_sources).c ;
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 3045a75..f17f1a6 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -98,9 +98,7 @@
                             FT_GlyphSlot      slot,
                             FT_Render_Mode    mode,
                             const FT_Vector*  origin,
-                            FT_Render_Mode    required_mode,
-                            FT_Int            hmul,
-                            FT_Int            vmul )
+                            FT_Render_Mode    required_mode )
   {
     FT_Error     error;
     FT_Outline*  outline = NULL;
@@ -108,6 +106,9 @@
     FT_UInt      width, height, height_org, width_org, pitch;
     FT_Bitmap*   bitmap;
     FT_Memory    memory;
+    FT_Int       hmul = (mode == FT_RENDER_MODE_LCD);
+    FT_Int       vmul = (mode == FT_RENDER_MODE_LCD_V);
+    FT_Pos       x_shift, y_shift, x_left, y_top;
 
     FT_Raster_Params  params;
 
@@ -156,12 +157,36 @@
     pitch = width;
     if ( hmul )
     {
-      width = width * hmul;
+      width = width * 3;
       pitch = FT_PAD_CEIL( width, 4 );
     }
 
     if ( vmul )
-      height *= vmul;
+      height *= 3;
+
+    x_shift = (FT_Int) cbox.xMin;
+    y_shift = (FT_Int) cbox.yMin;
+    x_left  = (FT_Int)( cbox.xMin >> 6 );
+    y_top   = (FT_Int)( cbox.yMax >> 6 );
+
+#ifdef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
+    if ( slot->library->lcd_filter )
+    {
+      if ( hmul )
+      {
+        x_shift -= 64;
+        width   += 6;
+        pitch    = FT_PAD_CEIL( width, 4 );
+        x_left  -= 1;
+      }
+      if ( vmul )
+      {
+        y_shift -= 64;
+        height  += 6;
+        y_top   += 1;
+      }
+    }
+#endif
 
     bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
     bitmap->num_grays  = 256;
@@ -169,14 +194,14 @@
     bitmap->rows       = height;
     bitmap->pitch      = pitch;
 
+    /* translate outline to render it into the bitmap */
+    FT_Outline_Translate( outline, -x_shift, -y_shift );
+
     if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
       goto Exit;
 
     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
-    /* translate outline to render it into the bitmap */
-    FT_Outline_Translate( outline, -cbox.xMin, -cbox.yMin );
-
     /* set up parameters */
     params.target = bitmap;
     params.source = outline;
@@ -194,13 +219,13 @@
         for ( vec = outline->points, n = 0;
               n < outline->n_points;
               n++, vec++ )
-          vec->x *= hmul;
+          vec->x *= 3;
 
       if ( vmul )
         for ( vec = outline->points, n = 0;
               n < outline->n_points;
               n++, vec++ )
-          vec->y *= vmul;
+          vec->y *= 3;
     }
 
     /* render outline into the bitmap */
@@ -216,22 +241,26 @@
         for ( vec = outline->points, n = 0;
               n < outline->n_points;
               n++, vec++ )
-          vec->x /= hmul;
+          vec->x /= 3;
 
       if ( vmul )
         for ( vec = outline->points, n = 0;
               n < outline->n_points;
               n++, vec++ )
-          vec->y /= vmul;
+          vec->y /= 3;
     }
 
+    if ( slot->library->lcd_filter )
+      slot->library->lcd_filter( bitmap, mode,
+                                 slot->library->lcd_filter_weights );
+
 #else /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
     /* render outline into bitmap */
     error = render->raster_render( render->raster, &params );
 
     /* expand it horizontally */
-    if ( hmul > 1 )
+    if ( hmul )
     {
       FT_Byte*  line = bitmap->buffer + ( height - height_org ) * pitch;
       FT_UInt   hh;
@@ -246,19 +275,18 @@
         for ( xx = width_org; xx > 0; xx-- )
         {
           FT_UInt  pixel = line[xx-1];
-          FT_UInt  count = hmul;
-
 
-          for ( count = hmul; count > 0; count-- )
-            end[-count] = (FT_Byte)pixel;
 
-          end -= hmul;
+          end[-3] = (FT_Byte)pixel;
+          end[-2] = (FT_Byte)pixel;
+          end[-1] = (FT_Byte)pixel;
+          end    -= 3;
         }
       }
     }
 
     /* expand it vertically */
-    if ( vmul > 1 )
+    if ( vmul )
     {
       FT_Byte*  read  = bitmap->buffer + ( height - height_org ) * pitch;
       FT_Byte*  write = bitmap->buffer;
@@ -267,28 +295,28 @@
 
       for ( hh = height_org; hh > 0; hh-- )
       {
-        FT_UInt  count = vmul;
+        memcpy( write, read, pitch );
+        write += pitch;
 
+        memcpy( write, read, pitch );
+        write += pitch;
 
-        for ( count = vmul; count > 0; count-- )
-        {
-          memcpy( write, read, pitch );
-          write += pitch;
-        }
-        read += pitch;
+        memcpy( write, read, pitch );
+        write += pitch;
+        read  += pitch;
       }
     }
 
 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-    FT_Outline_Translate( outline, cbox.xMin, cbox.yMin );
+    FT_Outline_Translate( outline, x_shift, y_shift );
 
     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 );
+    slot->bitmap_left = x_left;
+    slot->bitmap_top  = y_top;
 
   Exit:
     if ( outline && origin )
@@ -309,8 +337,7 @@
       mode = FT_RENDER_MODE_NORMAL;
 
     return ft_smooth_render_generic( render, slot, mode, origin,
-                                     FT_RENDER_MODE_NORMAL,
-                                     0, 0 );
+                                     FT_RENDER_MODE_NORMAL );
   }
 
 
@@ -324,8 +351,7 @@
     FT_Error  error;
 
     error = ft_smooth_render_generic( render, slot, mode, origin,
-                                      FT_RENDER_MODE_LCD,
-                                      3, 0 );
+                                      FT_RENDER_MODE_LCD );
     if ( !error )
       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD;
 
@@ -343,8 +369,7 @@
     FT_Error  error;
 
     error = ft_smooth_render_generic( render, slot, mode, origin,
-                                      FT_RENDER_MODE_LCD_V,
-                                      0, 3 );
+                                      FT_RENDER_MODE_LCD_V );
     if ( !error )
       slot->bitmap.pixel_mode = FT_PIXEL_MODE_LCD_V;