freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] master 3bb512b: [smooth] Introduce direct oversampling for o


From: Alexei Podtelezhnikov
Subject: [freetype2] master 3bb512b: [smooth] Introduce direct oversampling for overlaps.
Date: Fri, 3 Jul 2020 22:32:49 -0400 (EDT)

branch: master
commit 3bb512bc9f621e1329927292d9ee7ba764549cae
Author: Alexei Podtelezhnikov <apodtele@gmail.com>
Commit: Alexei Podtelezhnikov <apodtele@gmail.com>

    [smooth] Introduce direct oversampling for overlaps.
    
    This implements oversampling to metigate artifacts in pixels partially
    covered by overlapping contours.  It turns out that the 4x4
    oversampling is sufficient but, at least, quadruples the rendering
    time.  The outline has to set FT_OUTLINE_OVERLAP to use this method.
    
    * include/freetype/ftimage.h (FT_OUTLINE_OVERLAP): New flag.
    * src/smooth/ftsmooth.c (ft_smooth_render): Check it to...
    (ft_smooth_raster_overlap): ... inflate outline and set up direct
    rendering for oversampling with...
    (ft_smooth_overlap_spans): ... new span function that integrates them.
---
 ChangeLog                  |  15 +++++++
 include/freetype/ftimage.h |   8 ++++
 src/smooth/ftsmooth.c      | 104 ++++++++++++++++++++++++++++++++++++++++++---
 3 files changed, 121 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f5045de..a28694a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,20 @@
 2020-07-03  Alexei Podtelezhnikov  <apodtele@gmail.com>
 
+       [smooth] Introduce direct oversampling for overlaps.
+
+       This implements oversampling to metigate artifacts in pixels partially
+       covered by overlapping contours.  It turns out that the 4x4
+       oversampling is sufficient but, at least, quadruples the rendering
+       time.  The outline has to set FT_OUTLINE_OVERLAP to use this method.
+
+       * include/freetype/ftimage.h (FT_OUTLINE_OVERLAP): New flag.
+       * src/smooth/ftsmooth.c (ft_smooth_render): Check it to...
+       (ft_smooth_raster_overlap): ... inflate outline and set up direct
+       rendering for oversampling with...
+       (ft_smooth_overlap_spans): ... new span function that integrates them.
+
+2020-07-03  Alexei Podtelezhnikov  <apodtele@gmail.com>
+
        [smooth] Use direct rendering mode in Harmony.
 
        Instead of rendering 3 bitmaps side by side and reshuffling, we use
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index 9fecd1f..29b907a 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -400,6 +400,13 @@ FT_BEGIN_HEADER
    *     if @FT_OUTLINE_IGNORE_DROPOUTS is set.  See below for more
    *     information.
    *
+   *   FT_OUTLINE_OVERLAP ::
+   *     This flag indicates that this outline contains overlapping contrours
+   *     and the anti-aliased renderer should perform oversampling to
+   *     metigate possible artifacts.  This flag should _not_ be set for
+   *     well designed glyphs without overlaps because it quadruples the
+   *     rendering time.
+   *
    *   FT_OUTLINE_HIGH_PRECISION ::
    *     This flag indicates that the scan-line converter should try to
    *     convert this outline to bitmaps with the highest possible quality.
@@ -432,6 +439,7 @@ FT_BEGIN_HEADER
 #define FT_OUTLINE_SMART_DROPOUTS   0x10
 #define FT_OUTLINE_INCLUDE_STUBS    0x20
 
+#define FT_OUTLINE_OVERLAP          0x80
 #define FT_OUTLINE_HIGH_PRECISION   0x100
 #define FT_OUTLINE_SINGLE_PASS      0x200
 
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 1e0d0a3..b326292 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -333,7 +333,94 @@
 
 #endif  /* FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-  /* convert a slot's glyph image into a bitmap */
+/* Oversampling scale to be used in rendering overlaps */
+#define SCALE  ( 1 << 2 )
+
+  /* This function averages inflated spans in direct rendering mode */
+  static void
+  ft_smooth_overlap_spans( int             y,
+                           int             count,
+                           const FT_Span*  spans,
+                           TOrigin*        target )
+  {
+    unsigned char*  dst = target->origin - ( y / SCALE ) * target->pitch;
+    unsigned short  x;
+    unsigned int    cover, sum;
+
+
+    /* When accumulating the oversampled spans we need to assure that  */
+    /* fully covered pixels are equal to 255 and do not overflow.      */
+    /* It is important that the SCALE is a power of 2, each subpixel   */
+    /* cover can also reach a power of 2 after rounding, and the total */
+    /* is clamped to 255 when it adds up to 256.                       */
+    for ( ; count--; spans++ )
+    {
+      cover = ( spans->coverage + SCALE * SCALE / 2 ) / ( SCALE * SCALE );
+      for ( x = 0; x < spans->len; x++ )
+      {
+        sum = dst[ ( spans->x + x ) / SCALE ] + cover;
+        dst[ ( spans->x + x ) / SCALE ] = sum - ( sum >> 8 );
+      }
+    }
+  }
+
+
+  static FT_Error
+  ft_smooth_raster_overlap( FT_Renderer  render,
+                            FT_Outline*  outline,
+                            FT_Bitmap*   bitmap )
+  {
+    FT_Error    error      = FT_Err_Ok;
+    FT_Vector*  points     = outline->points;
+    FT_Vector*  points_end = FT_OFFSET( points, outline->n_points );
+    FT_Vector*  vec;
+
+    FT_Raster_Params   params;
+    TOrigin            target;
+
+
+    /* Set up direct rendering to average oversampled spans. */
+    params.target     = bitmap;
+    params.source     = outline;
+    params.flags      = FT_RASTER_FLAG_AA | FT_RASTER_FLAG_DIRECT;
+    params.gray_spans = (FT_SpanFunc)ft_smooth_overlap_spans;
+    params.user       = &target;
+
+    params.clip_box.xMin = 0;
+    params.clip_box.yMin = 0;
+    params.clip_box.xMax = bitmap->width * SCALE;
+    params.clip_box.yMax = bitmap->rows  * SCALE;
+
+    if ( bitmap->pitch < 0 )
+      target.origin = bitmap->buffer;
+    else
+      target.origin = bitmap->buffer
+                      + ( bitmap->rows - 1 ) * (unsigned int)bitmap->pitch;
+
+    target.pitch = bitmap->pitch;
+
+    /* inflate outline */
+    for ( vec = points; vec < points_end; vec++ )
+    {
+      vec->x *= SCALE;
+      vec->y *= SCALE;
+    }
+
+    /* render outline into the bitmap */
+    error = render->raster_render( render->raster, &params );
+
+    /* deflate outline */
+    for ( vec = points; vec < points_end; vec++ )
+    {
+      vec->x /= SCALE;
+      vec->y /= SCALE;
+    }
+
+    return error;
+  }
+
+#undef SCALE
+
   static FT_Error
   ft_smooth_render( FT_Renderer       render,
                     FT_GlyphSlot      slot,
@@ -407,14 +494,19 @@
     if ( mode == FT_RENDER_MODE_NORMAL ||
          mode == FT_RENDER_MODE_LIGHT  )
     {
-      FT_Raster_Params  params;
+      if ( outline->flags & FT_OUTLINE_OVERLAP )
+        error = ft_smooth_raster_overlap( render, outline, bitmap );
+      else
+      {
+        FT_Raster_Params  params;
 
 
-      params.target = bitmap;
-      params.source = outline;
-      params.flags  = FT_RASTER_FLAG_AA;
+        params.target = bitmap;
+        params.source = outline;
+        params.flags  = FT_RASTER_FLAG_AA;
 
-      error = render->raster_render( render->raster, &params );
+        error = render->raster_render( render->raster, &params );
+      }
     }
     else
     {



reply via email to

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