freetype-commit
[Top][All Lists]
Advanced

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

[freetype2] anuj-distance-field f95d181: [sdf] Optimize the coarse grid


From: Anuj Verma
Subject: [freetype2] anuj-distance-field f95d181: [sdf] Optimize the coarse grid optimization.
Date: Sun, 12 Jul 2020 07:17:38 -0400 (EDT)

branch: anuj-distance-field
commit f95d181521164c76e421066231f642b0f6f75fb8
Author: Anuj Verma <anujv@iitbhilai.ac.in>
Commit: Anuj Verma <anujv@iitbhilai.ac.in>

    [sdf] Optimize the coarse grid optimization.
    
    * src/sdf/ftsdf.c (sdf_generate_coarse_grid): Merge
      the relevant edge finding loop and shortest dist-
      ance search loop. We can find the relevant edges
      of a coarse grid and immediately use them to find
      the shortest distance of the points in the coarse
      grid. This drastically reduce memory usage and
      performance.
      Also, do the sign assignment of the edges which was
      missing.
---
 [GSoC]ChangeLog | 14 ++++++++++
 src/sdf/ftsdf.c | 87 ++++++++++++++++++++++++++++-----------------------------
 2 files changed, 56 insertions(+), 45 deletions(-)

diff --git a/[GSoC]ChangeLog b/[GSoC]ChangeLog
index ae1fee1..cc9de59 100644
--- a/[GSoC]ChangeLog
+++ b/[GSoC]ChangeLog
@@ -1,3 +1,17 @@
+2020-07-12  Anuj Verma  <anujv@iitbhilai.ac.in>
+
+       [sdf] Optimize the coarse grid optimization.
+
+       * src/sdf/ftsdf.c (sdf_generate_coarse_grid): Merge
+         the relevant edge finding loop and shortest dist-
+         ance search loop. We can find the relevant edges
+         of a coarse grid and immediately use them to find
+         the shortest distance of the points in the coarse
+         grid. This drastically reduce memory usage and 
+         performance.
+         Also, do the sign assignment of the edges which was
+         missing.
+
 2020-07-11  Anuj Verma  <anujv@iitbhilai.ac.in>
 
        * src/sdf/ftsdf.c (*): Fixed warnings.
diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c
index ab3aa08..458e745 100644
--- a/src/sdf/ftsdf.c
+++ b/src/sdf/ftsdf.c
@@ -2754,14 +2754,11 @@
     FT_UInt       c_width, c_rows; /* coarse grid dimensions              */
     FT_16D16      sp_sq;           /* max value to check                  */
     FT_16D16      cg_sq;           /* max value to check for coarse grid  */
-    FT_16D16      cg_max;
+    FT_16D16      cg_diagon;
 
     SDF_Contour*  contours;        /* list of all contours */
     FT_Short*     buffer;          /* the bitmap buffer    */
 
-    /* coarse grid to hold the list of edges */
-    SDF_Edge*     coarse_grid[ CG_DIMEN * CG_DIMEN ];
-
     if ( !shape || !bitmap )
     {
       error = FT_THROW( Invalid_Argument );
@@ -2794,19 +2791,20 @@
     c_width = width / CG_DIMEN + ( width % CG_DIMEN == 0 ? 0 : 1 );
     c_rows = rows / CG_DIMEN + ( rows % CG_DIMEN == 0 ? 0 : 1 );
 
-    cg_max = c_width > c_rows ? c_width : c_rows;
+    cg_diagon = FT_INT_16D16( c_width * c_width ) +
+                FT_INT_16D16( c_rows * c_rows );
 
     /* `cg_sq' is the max value for which we add an edge */
     /* to the coarse grid list.                          */
     if ( USE_SQUARED_DISTANCES )
     {
       sp_sq = FT_INT_16D16( spread * spread );
-      cg_sq = sp_sq + FT_INT_16D16( cg_max * cg_max ) / 4;
+      cg_sq = sp_sq + cg_diagon;
     }
     else
     {
       sp_sq = FT_INT_16D16( spread );
-      cg_sq = sp_sq + FT_INT_16D16( cg_max / 2 );
+      cg_sq = sp_sq + square_root( cg_diagon );
     }
 
     /* if the coarse grid is too small then simply */
@@ -2826,10 +2824,15 @@
         FT_Int        cindex  = j * CG_DIMEN + i;
         SDF_Contour*  cont    = contours;
         SDF_Edge*     edge;
+        SDF_Edge*     relevant_list;
         FT_26D6_Vec   cpoint;
+        FT_BBox       sample_region;
+        FT_Int        x, y;
+
+        SDF_Signed_Distance  min_cg_dist = max_sdf;
 
 
-        coarse_grid[cindex] = NULL;
+        relevant_list = NULL;
 
         /* we check from the center of the coarse grid */
         cpoint.x = FT_INT_26D6( i * c_width ) + FT_INT_26D6( c_width / 2 );
@@ -2855,32 +2858,25 @@
               FT_CALL( sdf_edge_new( memory, &temp ) );
               ft_memcpy( temp, edge, sizeof( *edge ) );
               
-              temp->next = coarse_grid[cindex];
-              coarse_grid[cindex] = temp;
+              temp->next = relevant_list;
+              relevant_list = temp;
             }
 
+            if ( dist.distance < min_cg_dist.distance )
+              min_cg_dist = dist;
+            else if ( FT_ABS( dist.distance - min_cg_dist.distance ) <
+                      CORNER_CHECK_EPSILON )
+              min_cg_dist = resolve_corner( min_cg_dist, dist );
+
             edge = edge->next;
           }
 
           cont = cont->next;
         }
-      }
-    }
-
-    /* Now that we have the list of edges relevant for the pixels */
-    /* inside a coarse grid, we only need to check those pixels   */
-    /* against the list of edges.                                 */
-
-    /* again loop through the coarse grid */
-    for ( j = 0; j < CG_DIMEN; j++ )
-    {
-      for ( i = 0; i < CG_DIMEN; i++ )
-      {
-        FT_BBox    sample_region;
-        FT_Int     x, y;
 
-
-        if ( !coarse_grid[j * CG_DIMEN + i] ) continue;
+        /* Now that we have the list of edges relevant for the pixels */
+        /* inside a coarse grid, we only need to check those pixels   */
+        /* against the list of edges.                                 */
 
         /* this gives the pixels inside the coarse grid */
         sample_region.xMin = i * c_width;
@@ -2888,7 +2884,6 @@
         sample_region.yMin = j * c_rows;
         sample_region.yMax = sample_region.yMin + c_rows;
 
-
         /* for all the pixes inside the coarse grid */
         for ( y = sample_region.yMin; y < sample_region.yMax; y++ )
         {
@@ -2896,12 +2891,20 @@
           {
             FT_26D6_Vec          current_pos;
             SDF_Signed_Distance  min_dist = max_sdf;
-            SDF_Edge*            edges = coarse_grid[j * CG_DIMEN + i];
+            SDF_Edge*            edges = relevant_list;
+            FT_Int               index = ( rows - y - 1 ) * width + x;
 
 
             if ( x < 0 || x >= width ) continue;
             if ( y < 0 || y >= rows )  continue;
 
+            /* If there is no relevant edge for the */
+            /* coarse grid then it's fare than the  */
+            /* `spread'. In that case simply assign */
+            /* `min_dist' = `min_cg_dist'.          */
+            if ( !relevant_list )
+              min_dist = min_cg_dist;
+
             /* we check from the center of a pixel */
             current_pos.x = FT_INT_26D6( x ) + FT_INT_26D6( 1 ) / 2;
             current_pos.y = FT_INT_26D6( y ) + FT_INT_26D6( 1 ) / 2;
@@ -2917,6 +2920,9 @@
 
               if ( dist.distance < min_dist.distance )
                 min_dist = dist;
+              else if ( FT_ABS( dist.distance - min_dist.distance ) <
+                        CORNER_CHECK_EPSILON )
+                min_dist = resolve_corner( min_dist, dist );
 
               edges = edges->next;
             }
@@ -2930,29 +2936,20 @@
 
             min_dist.distance /= 64;
 
-            buffer[( rows - y - 1 ) * width + x] = (FT_Short)min_dist.distance;
+            buffer[index] = (FT_Short)min_dist.distance * min_dist.sign;
 
           }
         }
-      }
-    }
-
-    /* release the allocated lists */
-    for ( i = 0; i < CG_DIMEN * CG_DIMEN; i++ )
-    {
-      SDF_Edge*  edge = coarse_grid[i];
-      SDF_Edge*  temp;
-
 
-      while ( edge )
-      {
-        temp = edge;
-        edge = edge->next;
+        /* release the allocated lists */
+        while ( relevant_list )
+        {
+          edge = relevant_list;
+          relevant_list = relevant_list->next;
 
-        sdf_edge_done( memory, &temp );
+          sdf_edge_done( memory, &edge );
+        }
       }
-
-      coarse_grid[i] = NULL;
     }
 
   Exit:



reply via email to

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