forked from minhngoc25a/freetype2
[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.
This commit is contained in:
parent
ad696c07d3
commit
548bd3cf62
|
@ -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.
|
||||
|
|
|
@ -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,31 +2936,22 @@
|
|||
|
||||
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 */
|
||||
while ( relevant_list )
|
||||
{
|
||||
edge = relevant_list;
|
||||
relevant_list = relevant_list->next;
|
||||
|
||||
sdf_edge_done( memory, &edge );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
sdf_edge_done( memory, &temp );
|
||||
}
|
||||
|
||||
coarse_grid[i] = NULL;
|
||||
}
|
||||
|
||||
Exit:
|
||||
return error;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue