Hello Alexei, Werner,

*> Since you and Alexei agree on 8bit being enough: Please change to >
8bit!*

I have made the relevant changes in both freetype and freetype-demos.
Please check the patches below. I have trimmed the 16bit 6.10 value to
normalized 8 bit values.

As for freetype-demos, I need to change a major part of it since most of it
is just hacks. I'm already rewriting the demo, it's going a bit slow due to
other
stuff I have in my hands right now. I'll send it as soon as I can.

Also, the demo programs are not compiling due to missing `gdiplus`
dependency.
Please add it as well:

---

diff --git a/graph/win32/rules.mk b/graph/win32/rules.mk
index 2dd0f14..6287345 100644
--- a/graph/win32/rules.mk
+++ b/graph/win32/rules.mk
@@ -28,19 +28,19 @@ ifeq ($(PLATFORM),windows)
   # now update COMPILE_GRAPH_LIB according to the compiler used on Win32
   #
   ifeq ($(firstword $(CC)),gcc)   # test for GCC
-    GRAPH_LINK += -luser32 -lgdi32
+    GRAPH_LINK += -luser32 -lgdi32 -lgdiplus
   endif

   ifeq ($(findstring $(CC),cl icl), $(CC))    # test for Visual C++ &
Intel C++
     COMPILE_GRAPH_LIB = lib /nologo /out:$(subst
/,$(COMPILER_SEP),$(GRAPH_LIB) $(GRAPH_OBJS))
     LINK              = cl /nologo /MD /Fe$(subst /,$(COMPILER_SEP),$@ $<
$(FTLIB))
-    GRAPH_LINK       += user32.lib gdi32.lib
+    GRAPH_LINK       += user32.lib gdi32.lib gdiplus.lib
   endif

   ifeq ($(CC),lcc)   # test for LCC-Win32
     COMPILE_GRAPH_LIB = lcclib /out:$(subst /,$(COMPILER_SEP),$(GRAPH_LIB)
$(GRAPH_OBJS))
     LINK              = lcclnk -o $(subst /,$(COMPILER_SEP),$@ $< $(FTLIB))
-    GRAPH_LINK       += user32.lib gdi32.lib
+    GRAPH_LINK       += user32.lib gdi32.lib gdiplus.lib
   endif

   ifeq ($(CC),bcc32) # test for Borland C++

Thanks,
Anuj
commit 623e66a142252b15ddfbd8f1c73874eae44a8f70
Author: Anuj Verma <an...@iitbhilai.ac.in>
Date:   Fri May 21 19:41:58 2021 +0530

    [ftsdf] Synchronize with the change made in the `sdf` renderer.
    
    * src/ftsdf.c (draw): Change logic to utilize 8bit SDF instead of 16.

diff --git a/src/ftsdf.c b/src/ftsdf.c
index a638c3e..796b737 100644
--- a/src/ftsdf.c
+++ b/src/ftsdf.c
@@ -436,7 +436,7 @@
     Box  sample_region;
 
     Vec2       center;
-    FT_Short*  buffer;
+    FT_Char*   buffer;
 
 
     if ( !bitmap || !bitmap->buffer )
@@ -496,7 +496,7 @@
       draw_region.xMax    = display->bitmap->width;
     }
 
-    buffer = (FT_Short*)bitmap->buffer;
+    buffer = (FT_Char*)bitmap->buffer;
 
     /* Finally loop over all pixels inside the draw region        */
     /* and copy pixels from the sample region to the draw region. */
@@ -516,12 +516,12 @@
         {
           FT_UInt   bitmap_index = ( y / status.scale ) * bitmap->width +
                                      x / status.scale;
-          FT_Short  pixel_value  = buffer[bitmap_index];
+          FT_Char   pixel_value  = buffer[bitmap_index];
 
 
           /* If nearest filtering then simply take the value of the */
           /* nearest sampling pixel.                                */
-          min_dist = (float)pixel_value / 1024.0f;
+          min_dist = (float)pixel_value / 128.0f;
         }
         else
         {
@@ -560,22 +560,22 @@
           indc[2] = (int)bi_y * width + (int)bi_x + 1;
           indc[3] = ( (int)bi_y + 1 ) * width + (int)bi_x + 1;
 
-          dist[0] = (float)buffer[indc[0]] / 1024.0f;
+          dist[0] = (float)buffer[indc[0]] / 128.0f;
 
           if ( indc[1] >= width * rows )
             dist[1] = -status.spread;
           else
-            dist[1] = (float)buffer[indc[1]] / 1024.0f;
+            dist[1] = (float)buffer[indc[1]] / 128.0f;
 
           if ( indc[2] >= width * rows )
             dist[2] = -status.spread;
           else
-            dist[2] = (float)buffer[indc[2]] / 1024.0f;
+            dist[2] = (float)buffer[indc[2]] / 128.0f;
 
           if ( indc[3] >= width * rows )
             dist[3] = -status.spread;
           else
-            dist[3] = (float)buffer[indc[3]] / 1024.0f;
+            dist[3] = (float)buffer[indc[3]] / 128.0f;
 
           m1 = dist[0] * ( 1.0f - nbi_y ) + dist[1] * nbi_y;
           m2 = dist[2] * ( 1.0f - nbi_y ) + dist[3] * nbi_y;
@@ -615,7 +615,6 @@
 
           /* normalize using `status.spread` */
           final_dist  = final_dist < 0 ? -final_dist : final_dist;
-          final_dist /= (float)status.spread;
 
           /* invert the values */
           final_dist  = 1.0f - final_dist;
@@ -686,12 +685,16 @@
       goto Exit;
     }
 
-#ifdef __linux__
+
     int  flip_y = 1;
 
+#ifdef __linux__
+    flip_y = 0;
+#endif
+
     FT_CALL( FT_Property_Set( handle->library, "sdf", "flip_y", &flip_y ) );
     FT_CALL( FT_Property_Set( handle->library, "bsdf", "flip_y", &flip_y ) );
-#endif
+
 
     grSetTitle( display->surface, "Signed Distance Field Viewer" );
     event_color_change();
commit 2b99e72ca36cf25e8df0d9341e1cd094987b461f
Author: Anuj Verma <an...@iitbhilai.ac.in>
Date:   Fri May 21 19:10:27 2021 +0530

    [sdf] Use 8 bits for final SDF output instead of 16bits.
    
    Since 8bits is enough to represent SDF data we no longer require 16bits for 
 this
    purpose. Also, we now normalize the output data to use the entire 8bit range
    efficiently. For example: if we use 3.5 format with a spread of 1 we 
basically only
    use the first 5 bits. By normalizing we can use the entire 8bit range.
    
    * include/freetype/freetype.h (FT_Render_Mode): Update the description for
      `FT_RENDER_MODE_SDF` regarding this change.
    
    * include/freetype/ftimage.h (FT_Pixel_Mode): Removed `FT_PIXEL_MODE_GRAY16`
      since no longer required.
    
    * include/freetype/fttypes.h (FT_F6Dot10): Removed since no longer required.
    
    * src/sdf/ftsdfrend.c (ft_sdf_render, ft_bsdf_render): Allocate 8bit bitmap 
instead of
      16bit buffer.
    
    * src/sdf/ftsdfcommon.h (map_fixed_to_sdf): Added function to convert 16.16
      distance value to our desired format.
    
    * src/sdf/ftsdf.c (sdf_generate_with_overlaps, sdf_generate_bounding_box):
      Modified to use the new `map_fixed_to_sdf` function and also use 8bit 
output
      buffer.
    
    * src/sdf/ftbsdf.c (finalize_sdf): Output to a 8bit buffer instead of 16bit 
buffer.

diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 03438b531..82e655cf8 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -3302,13 +3302,14 @@ FT_BEGIN_HEADER
    *     pixels and use the @FT_PIXEL_MODE_LCD_V mode.
    *
    *   FT_RENDER_MODE_SDF ::
-   *     This mode corresponds to 16-bit signed distance fields (SDF)
+   *     This mode corresponds to 8-bit signed distance fields (SDF)
    *     bitmaps.  Each pixel in a SDF bitmap contains information about the
    *     nearest edge of the glyph outline.  The distances are calculated
    *     from the center of the pixel and are positive if they are filled by
    *     the outline (i.e., inside the outline) and negative otherwise.  The
-   *     output bitmap buffer is represented as 6.10 fixed-point values; use
-   *     @FT_F6Dot10 and convert accordingly.
+   *     output bitmap buffer contains a normalized distance values (range
+   *     [-1.0, 1.0] in float).  To get the actual distances in pixels simply
+   *     multiply the values with the `spread` used.
    *
    * @note:
    *   The selected render mode only affects vector glyphs of a font.
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index e3cc68f6c..66a8b89aa 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -157,13 +157,6 @@ FT_BEGIN_HEADER
    *     in font files according to the OpenType specification.  We haven't
    *     found a single font using this format, however.
    *
-   *   FT_PIXEL_MODE_GRAY16 ::
-   *     A 16-bit per pixel bitmap used to represent signed distances in a
-   *     signed distance field bitmap as needed by @FT_RENDER_MODE_SDF.
-   *     Values are represented in a 6.10 fixed-point format; this means
-   *     that you have to divide by 1024 to get the actual data generated by
-   *     the SDF rasterizers.
-   *
    *   FT_PIXEL_MODE_LCD ::
    *     An 8-bit bitmap, representing RGB or BGR decimated glyph images used
    *     for display on LCD displays; the bitmap is three times wider than
@@ -194,7 +187,6 @@ FT_BEGIN_HEADER
     FT_PIXEL_MODE_LCD,
     FT_PIXEL_MODE_LCD_V,
     FT_PIXEL_MODE_BGRA,
-    FT_PIXEL_MODE_GRAY16,
 
     FT_PIXEL_MODE_MAX      /* do not remove */
 
diff --git a/include/freetype/fttypes.h b/include/freetype/fttypes.h
index 3e4a474bd..d5ca1c4f4 100644
--- a/include/freetype/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -78,7 +78,6 @@ FT_BEGIN_HEADER
    *   FT_FWord
    *   FT_UFWord
    *   FT_F2Dot14
-   *   FT_F6Dot10
    *   FT_UnitVector
    *   FT_F26Dot6
    *   FT_Data
@@ -265,17 +264,6 @@ FT_BEGIN_HEADER
   typedef signed short  FT_F2Dot14;
 
 
-  /**************************************************************************
-   *
-   * @type:
-   *   FT_F6Dot10
-   *
-   * @description:
-   *   A signed 6.10 fixed-point type used for signed distance values.
-   */
-  typedef signed short  FT_F6Dot10;
-
-
   /**************************************************************************
    *
    * @type:
diff --git a/src/sdf/ftbsdf.c b/src/sdf/ftbsdf.c
index af1e40382..6d1deb604 100644
--- a/src/sdf/ftbsdf.c
+++ b/src/sdf/ftbsdf.c
@@ -1089,12 +1089,12 @@
   finalize_sdf( BSDF_Worker*      worker,
                 const FT_Bitmap*  target )
   {
-    FT_Error  error = FT_Err_Ok;
+    FT_Error       error = FT_Err_Ok;
 
-    FT_Int    w, r;
-    FT_Int    i, j;
-    FT_6D10*  t_buffer;
-    FT_16D16  spread;
+    FT_Int         w, r;
+    FT_Int         i, j;
+    FT_SDFFormat*  t_buffer;
+    FT_16D16       spread;
 
 
     if ( !worker || !target )
@@ -1105,7 +1105,7 @@
 
     w        = target->width;
     r        = target->rows;
-    t_buffer = (FT_6D10*)target->buffer;
+    t_buffer = (FT_SDFFormat*)target->buffer;
 
     if ( w != worker->width ||
          r != worker->rows  )
@@ -1125,10 +1125,10 @@
     {
       for ( i = 0; i < w; i++ )
       {
-        FT_Int    index;
-        FT_16D16  dist;
-        FT_6D10   final_dist;
-        FT_Char   sign;
+        FT_Int       index;
+        FT_16D16     dist;
+        FT_SDFFormat final_dist;
+        FT_Char      sign;
 
 
         index = j * w + i;
@@ -1141,9 +1141,8 @@
         dist = square_root( dist );
 #endif
 
-        /* convert from 16.16 to 6.10 */
-        dist      /= 64;
-        final_dist = (FT_6D10)(dist & 0x0000FFFF);
+        /* concatenate from 16.16 to appropriate format */
+        final_dist = map_fixed_to_sdf( dist, spread );
 
         /* We assume that if the pixel is inside a contour */
         /* its coverage value must be > 127.               */
diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c
index a58d1448f..36efd67f6 100644
--- a/src/sdf/ftsdf.c
+++ b/src/sdf/ftsdf.c
@@ -2978,6 +2978,10 @@
   }
 
 
+  /* Might fix this later if this generate faster than the subdivision */
+  /* method. But currently I don't see any use for this.               */
+  #error "do not use `sdf_generate` as it outputs 16bit instead of 8bit data"
+
   /**************************************************************************
    *
    * @Function:
@@ -3190,10 +3194,10 @@
     FT_Memory  memory = NULL;
 
     FT_Int  width, rows, i, j;
-    FT_Int  sp_sq;            /* max value to check   */
+    FT_Int  sp_sq;            /* max value to check       */
 
-    SDF_Contour*  contours;   /* list of all contours */
-    FT_Short*     buffer;     /* the bitmap buffer    */
+    SDF_Contour*   contours;   /* list of all contours    */
+    FT_SDFFormat*  buffer;     /* the bitmap buffer       */
 
     /* This buffer has the same size in indices as the    */
     /* bitmap buffer.  When we check a pixel position for */
@@ -3202,6 +3206,8 @@
     /* and also determine the signs properly.             */
     SDF_Signed_Distance*  dists = NULL;
 
+    const FT_16D16 fixed_spread = FT_INT_16D16( spread );
+
 
     if ( !shape || !bitmap )
     {
@@ -3225,15 +3231,15 @@
     contours = shape->contours;
     width    = (FT_Int)bitmap->width;
     rows     = (FT_Int)bitmap->rows;
-    buffer   = (FT_Short*)bitmap->buffer;
+    buffer   = (FT_SDFFormat*)bitmap->buffer;
 
     if ( FT_ALLOC( dists, width * rows * sizeof ( *dists ) ) )
       goto Exit;
 
     if ( USE_SQUARED_DISTANCES )
-      sp_sq = FT_INT_16D16( spread * spread );
+      sp_sq = fixed_spread * fixed_spread;
     else
-      sp_sq = FT_INT_16D16( spread );
+      sp_sq = fixed_spread;
 
     if ( width == 0 || rows == 0 )
     {
@@ -3346,21 +3352,20 @@
         /* if the pixel is not set                     */
         /* its shortest distance is more than `spread` */
         if ( dists[index].sign == 0 )
-          dists[index].distance = FT_INT_16D16( spread );
+          dists[index].distance = fixed_spread;
         else
           current_sign = dists[index].sign;
 
         /* clamp the values */
-        if ( dists[index].distance > (FT_Int)FT_INT_16D16( spread ) )
-          dists[index].distance = FT_INT_16D16( spread );
-
-        /* convert from 16.16 to 6.10 */
-        dists[index].distance /= 64;
+        if ( dists[index].distance > (FT_Int)fixed_spread )
+          dists[index].distance = fixed_spread;
 
         if ( internal_params.flip_sign )
-          buffer[index] = (FT_Short)dists[index].distance * -current_sign;
+          dists[index].distance *= -current_sign;
         else
-          buffer[index] = (FT_Short)dists[index].distance * current_sign;
+          dists[index].distance *=  current_sign;
+
+        buffer[index] = map_fixed_to_sdf( dists[index].distance, fixed_spread 
);
       }
     }
 
@@ -3497,9 +3502,9 @@
     SDF_Contour*  head;              /* head of the contour list      */
     SDF_Shape     temp_shape;        /* temporary shape               */
 
-    FT_Memory  memory;               /* to allocate memory            */
-    FT_6D10*   t;                    /* target bitmap buffer          */
-    FT_Bool    flip_sign;            /* filp sign?                    */
+    FT_Memory      memory;           /* to allocate memory            */
+    FT_SDFFormat*  t;                /* target bitmap buffer          */
+    FT_Bool        flip_sign;        /* filp sign?                    */
 
     /* orientation of all the separate contours */
     SDF_Contour_Orientation*  orientations;
@@ -3617,7 +3622,7 @@
     shape->contours = head;
 
     /* cast the output bitmap buffer */
-    t = (FT_6D10*)bitmap->buffer;
+    t = (FT_SDFFormat*)bitmap->buffer;
 
     /* Iterate over all pixels and combine all separate    */
     /* contours.  These are the rules for combining:       */
@@ -3635,15 +3640,15 @@
         FT_Int   id = j * width + i;         /* index of current pixel    */
         FT_Int   c;                          /* contour iterator          */
 
-        FT_6D10  val_c  = SHRT_MIN;          /* max clockwise value       */
-        FT_6D10  val_ac = SHRT_MAX;          /* min counter-clockwise val */
+        FT_SDFFormat  val_c  = SCHAR_MIN;     /* max clockwise value       */
+        FT_SDFFormat  val_ac = SCHAR_MAX;     /* min counter-clockwise val */
 
 
         /* iterate through all the contours */
         for ( c = 0; c < num_contours; c++ )
         {
           /* current contour value */
-          FT_6D10  temp = ((FT_6D10*)bitmaps[c].buffer)[id];
+          FT_SDFFormat  temp = ( (FT_SDFFormat*)bitmaps[c].buffer )[id];
 
 
           if ( orientations[c] == SDF_ORIENTATION_CW )
diff --git a/src/sdf/ftsdfcommon.h b/src/sdf/ftsdfcommon.h
index 7c5581762..d81202245 100644
--- a/src/sdf/ftsdfcommon.h
+++ b/src/sdf/ftsdfcommon.h
@@ -43,7 +43,7 @@ FT_BEGIN_HEADER
    */
 
   /* default spread value */
-#define DEFAULT_SPREAD  8
+#define DEFAULT_SPREAD  2
   /* minimum spread supported by the renderer */
 #define MIN_SPREAD      2
   /* maximum spread supported by the renderer */
@@ -117,6 +117,8 @@ FT_BEGIN_HEADER
   typedef FT_Fixed  FT_26D6;       /* 26.6 fixed-point representation   */
   typedef FT_Short  FT_6D10;       /* 6.10 fixed-point representation   */
 
+  typedef FT_Char   FT_SDFFormat;  /* format to represent SDF data      */
+
   typedef FT_BBox   FT_CBox;       /* control box of a curve            */
 
 
@@ -163,6 +165,46 @@ FT_BEGIN_HEADER
   }
 
 
+  /*
+   * Convert 16.16 fixed point value to the desired output format.
+   * In this case we reduce 16.16 fixed point value to normalized
+   * 8 bit values.
+   * The `max_value` in the parameter is the maximum value in the
+   * distance field map and is equal to the spread.  We normalize
+   * the distances using this value instead of computing the maximum
+   * value for the entire bitmap.
+   */
+  static FT_SDFFormat
+  map_fixed_to_sdf( FT_16D16 dist, FT_16D16 max_value )
+  {
+    FT_SDFFormat  out;
+    FT_16D16      udist;
+
+
+    /* normalize the distance values */
+    dist = FT_DivFix( dist, max_value );
+
+    udist = dist < 0 ? -dist : dist;
+
+    /* Reduce the distance values to 8 bits, +1/-1 in   */
+    /* 16.16 takes the 16th bit.  So we right shift the */
+    /* number by 9 to make it fit in the 7 bit range.   */
+    /* 1 bit is reserved for the sign.                  */
+    udist >>= 9;
+
+    /* Since char can only store max positive value */
+    /* of 127 we need to make sure it does not wrap */
+    /* around and give a negative value.            */
+    if ( udist == 128 && dist > 0 )
+      udist = 127;
+
+    /* output the data */
+    out = dist < 0 ? (FT_SDFFormat)udist * -1
+                   : (FT_SDFFormat)udist;
+
+    return out;
+  }
+
 FT_END_HEADER
 
 #endif /* FTSDFCOMMON_H_ */
diff --git a/src/sdf/ftsdfrend.c b/src/sdf/ftsdfrend.c
index 3226bdc9d..d96db8190 100644
--- a/src/sdf/ftsdfrend.c
+++ b/src/sdf/ftsdfrend.c
@@ -313,9 +313,9 @@
     bitmap->width += x_pad * 2;
 
     /* ignore the pitch, pixel mode and set custom */
-    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY16;
-    bitmap->pitch      = bitmap->width * 2;
-    bitmap->num_grays  = 65535;
+    bitmap->pixel_mode = FT_PIXEL_MODE_GRAY;
+    bitmap->pitch      = bitmap->width;
+    bitmap->num_grays  = 255;
 
     /* allocate new buffer */
     if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
@@ -524,9 +524,9 @@
     target.width = bitmap->width + x_pad * 2;
 
     /* set up the target bitmap */
-    target.pixel_mode = FT_PIXEL_MODE_GRAY16;
-    target.pitch      = target.width * 2;
-    target.num_grays  = 65535;
+    target.pixel_mode = FT_PIXEL_MODE_GRAY;
+    target.pitch      = target.width;
+    target.num_grays  = 255;
 
     if ( FT_ALLOC_MULT( target.buffer, target.rows, target.pitch ) )
       goto Exit;

Reply via email to