[sdf] Remove use of `FT_List'.

Simply use a `next' pointer inside `SDF_Edge' and
`SDF_Contour' to create a linked list. This reduces
the number of allocations due to `FT_ListNode', also
we don't need a doubly linked list.

* src/sdf/ftsdf.c (SDF_Edge, SDF_Contour): Remove the
  `FT_List' and use a `next' pointer to create the
  linked list.

* src/sdf/ftsdf.c(sdf_edge_destructor, sdf_contour_destructor):
  Removed, not needed any more.

* src/sdf/ftsdf.c (*): Remove the use of `FT_List_'
  functions wherever necessary and sync with the new
  list.
This commit is contained in:
Anuj Verma 2020-07-10 09:15:58 +05:30 committed by anujverma
parent 8bf9da21e0
commit d9eeac807e
2 changed files with 139 additions and 163 deletions

View File

@ -1,8 +1,28 @@
2020-07-10 Anuj Verma <anujv@iitbhilai.ac.in>
[sdf] Remove use of `FT_List'.
Simply use a `next' pointer inside `SDF_Edge' and
`SDF_Contour' to create a linked list. This reduces
the number of allocations due to `FT_ListNode', also
we don't need a doubly linked list.
* src/sdf/ftsdf.c (SDF_Edge, SDF_Contour): Remove the
`FT_List' and use a `next' pointer to create the
linked list.
* src/sdf/ftsdf.c(sdf_edge_destructor, sdf_contour_destructor):
Removed, not needed any more.
* src/sdf/ftsdf.c (*): Remove the use of `FT_List_'
functions wherever necessary and sync with the new
list.
2020-07-09 Anuj Verma <anujv@iitbhilai.ac.in> 2020-07-09 Anuj Verma <anujv@iitbhilai.ac.in>
[sdf] Added subdivision optimization. [sdf] Added subdivision optimization.
* src/sdf/ftsdfrend.c (sdf_generate_subdivision): The * src/sdf/ftsdf.c (sdf_generate_subdivision): The
function generate SDF just like the `sdf_generate' function generate SDF just like the `sdf_generate'
function, but subdivide the curve into a number of function, but subdivide the curve into a number of
lines and then use the `sdf_generate_bounding_box' lines and then use the `sdf_generate_bounding_box'

View File

@ -1,7 +1,6 @@
#include <freetype/internal/ftobjs.h> #include <freetype/internal/ftobjs.h>
#include <freetype/internal/ftdebug.h> #include <freetype/internal/ftdebug.h>
#include <freetype/ftlist.h>
#include <freetype/fttrigon.h> #include <freetype/fttrigon.h>
#include "ftsdf.h" #include "ftsdf.h"
@ -18,7 +17,7 @@
/* a chance of overflow and artifacts. You can safely use it upto a */ /* a chance of overflow and artifacts. You can safely use it upto a */
/* pixel size of 128. */ /* pixel size of 128. */
#ifndef USE_SQUARED_DISTANCES #ifndef USE_SQUARED_DISTANCES
# define USE_SQUARED_DISTANCES 1 # define USE_SQUARED_DISTANCES 0
#endif #endif
/* If it is defined to 1 then the rasterizer will use Newton-Raphson's */ /* If it is defined to 1 then the rasterizer will use Newton-Raphson's */
@ -134,14 +133,18 @@
SDF_Edge_Type edge_type; /* edge identifier */ SDF_Edge_Type edge_type; /* edge identifier */
struct SDF_Edge_* next; /* to create linked list */
} SDF_Edge; } SDF_Edge;
/* A contour represent a set of edges which make a closed */ /* A contour represent a set of edges which make a closed */
/* loop. */ /* loop. */
typedef struct SDF_Contour_ typedef struct SDF_Contour_
{ {
FT_26D6_Vec last_pos; /* end position of the last edge */ FT_26D6_Vec last_pos; /* end position of the last edge */
FT_ListRec edges; /* list of all edges in the contour */ SDF_Edge* edges; /* list of all edges in the contour */
struct SDF_Contour_* next; /* to create linked list */
} SDF_Contour; } SDF_Contour;
@ -149,8 +152,8 @@
/* glyph outline. */ /* glyph outline. */
typedef struct SDF_Shape_ typedef struct SDF_Shape_
{ {
FT_Memory memory; /* used internally to allocate memory */ FT_Memory memory; /* used internally to allocate memory */
FT_ListRec contours; /* list of all contours in the outline */ SDF_Contour* contours; /* list of all contours in the outline */
} SDF_Shape; } SDF_Shape;
@ -188,13 +191,13 @@
static static
const SDF_Edge null_edge = { { 0, 0 }, { 0, 0 }, const SDF_Edge null_edge = { { 0, 0 }, { 0, 0 },
{ 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 },
SDF_EDGE_UNDEFINED }; SDF_EDGE_UNDEFINED, NULL };
static static
const SDF_Contour null_contour = { { 0, 0 }, { NULL, NULL } }; const SDF_Contour null_contour = { { 0, 0 }, NULL, NULL };
static static
const SDF_Shape null_shape = { NULL, { NULL, NULL } }; const SDF_Shape null_shape = { NULL, NULL };
static static
const SDF_Signed_Distance max_sdf = { INT_MAX, 0, 0 }; const SDF_Signed_Distance max_sdf = { INT_MAX, 0, 0 };
@ -236,18 +239,6 @@
FT_FREE( *edge ); FT_FREE( *edge );
} }
/* Used in `FT_List_Finalize'. */
static void
sdf_edge_destructor( FT_Memory memory,
void* data,
void* user )
{
SDF_Edge* edge = (SDF_Edge*)data;
sdf_edge_done( memory, &edge );
}
/* Creates a new `SDF_Contour' on the heap and assigns */ /* Creates a new `SDF_Contour' on the heap and assigns */
/* the `contour' pointer to the newly allocated memory. */ /* the `contour' pointer to the newly allocated memory. */
static FT_Error static FT_Error
@ -280,28 +271,26 @@
sdf_contour_done( FT_Memory memory, sdf_contour_done( FT_Memory memory,
SDF_Contour** contour ) SDF_Contour** contour )
{ {
SDF_Edge* edges;
SDF_Edge* temp;
if ( !memory || !contour || !*contour ) if ( !memory || !contour || !*contour )
return; return;
/* */ edges = (*contour)->edges;
FT_List_Finalize( &(*contour)->edges, sdf_edge_destructor,
memory, NULL ); /* release all the edges */
while ( edges )
{
temp = edges;
edges = edges->next;
sdf_edge_done( memory, &temp );
}
FT_FREE( *contour ); FT_FREE( *contour );
} }
/* Used in `FT_List_Finalize'. */
static void
sdf_contour_destructor( FT_Memory memory,
void* data,
void* user )
{
SDF_Contour* contour = (SDF_Contour*)data;
sdf_contour_done( memory, &contour );
}
/* Creates a new `SDF_Shape' on the heap and assigns */ /* Creates a new `SDF_Shape' on the heap and assigns */
/* the `shape' pointer to the newly allocated memory. */ /* the `shape' pointer to the newly allocated memory. */
static FT_Error static FT_Error
@ -334,20 +323,28 @@
static void static void
sdf_shape_done( SDF_Shape** shape ) sdf_shape_done( SDF_Shape** shape )
{ {
FT_Memory memory; FT_Memory memory;
SDF_Contour* contours;
SDF_Contour* temp;
if ( !shape || !*shape ) if ( !shape || !*shape )
return; return;
memory = (*shape)->memory; memory = (*shape)->memory;
contours = (*shape)->contours;
if ( !memory ) if ( !memory )
return; return;
/* release the list of contours */ /* release all the contours */
FT_List_Finalize( &(*shape)->contours, sdf_contour_destructor, while ( contours )
memory, NULL ); {
temp = contours;
contours = contours->next;
sdf_contour_done( memory, &temp );
}
/* release the allocated shape struct */ /* release the allocated shape struct */
FT_FREE( *shape ); FT_FREE( *shape );
@ -368,7 +365,6 @@
{ {
SDF_Shape* shape = ( SDF_Shape* )user; SDF_Shape* shape = ( SDF_Shape* )user;
SDF_Contour* contour = NULL; SDF_Contour* contour = NULL;
FT_ListNode node = NULL;
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_Memory memory = shape->memory; FT_Memory memory = shape->memory;
@ -380,17 +376,11 @@
goto Exit; goto Exit;
} }
error = sdf_contour_new( memory, &contour ); FT_CALL( sdf_contour_new( memory, &contour ) );
if ( error != FT_Err_Ok )
goto Exit;
if ( FT_QNEW( node ) )
goto Exit;
contour->last_pos = *to; contour->last_pos = *to;
contour->next = shape->contours;
node->data = contour; shape->contours = contour;
FT_List_Add( &shape->contours, node );
Exit: Exit:
return error; return error;
@ -403,7 +393,6 @@
SDF_Shape* shape = ( SDF_Shape* )user; SDF_Shape* shape = ( SDF_Shape* )user;
SDF_Edge* edge = NULL; SDF_Edge* edge = NULL;
SDF_Contour* contour = NULL; SDF_Contour* contour = NULL;
FT_ListNode node = NULL;
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_Memory memory = shape->memory; FT_Memory memory = shape->memory;
@ -415,28 +404,22 @@
goto Exit; goto Exit;
} }
contour = ( SDF_Contour* )shape->contours.tail->data; contour = shape->contours;
if ( contour->last_pos.x == to->x && if ( contour->last_pos.x == to->x &&
contour->last_pos.y == to->y ) contour->last_pos.y == to->y )
goto Exit; goto Exit;
error = sdf_edge_new( memory, &edge ); FT_CALL( sdf_edge_new( memory, &edge ) );
if ( error != FT_Err_Ok )
goto Exit;
if ( FT_QNEW( node ) )
goto Exit;
edge->edge_type = SDF_EDGE_LINE; edge->edge_type = SDF_EDGE_LINE;
edge->start_pos = contour->last_pos; edge->start_pos = contour->last_pos;
edge->end_pos = *to; edge->end_pos = *to;
edge->next = contour->edges;
contour->edges = edge;
contour->last_pos = *to; contour->last_pos = *to;
node->data = edge;
FT_List_Add( &contour->edges, node );
Exit: Exit:
return error; return error;
} }
@ -449,7 +432,6 @@
SDF_Shape* shape = ( SDF_Shape* )user; SDF_Shape* shape = ( SDF_Shape* )user;
SDF_Edge* edge = NULL; SDF_Edge* edge = NULL;
SDF_Contour* contour = NULL; SDF_Contour* contour = NULL;
FT_ListNode node = NULL;
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_Memory memory = shape->memory; FT_Memory memory = shape->memory;
@ -461,25 +443,19 @@
goto Exit; goto Exit;
} }
contour = ( SDF_Contour* )shape->contours.tail->data; contour = shape->contours;
error = sdf_edge_new( memory, &edge ); FT_CALL( sdf_edge_new( memory, &edge ) );
if ( error != FT_Err_Ok )
goto Exit;
if ( FT_QNEW( node ) )
goto Exit;
edge->edge_type = SDF_EDGE_CONIC; edge->edge_type = SDF_EDGE_CONIC;
edge->start_pos = contour->last_pos; edge->start_pos = contour->last_pos;
edge->control_a = *control_1; edge->control_a = *control_1;
edge->end_pos = *to; edge->end_pos = *to;
edge->next = contour->edges;
contour->edges = edge;
contour->last_pos = *to; contour->last_pos = *to;
node->data = edge;
FT_List_Add( &contour->edges, node );
Exit: Exit:
return error; return error;
} }
@ -493,7 +469,6 @@
SDF_Shape* shape = ( SDF_Shape* )user; SDF_Shape* shape = ( SDF_Shape* )user;
SDF_Edge* edge = NULL; SDF_Edge* edge = NULL;
SDF_Contour* contour = NULL; SDF_Contour* contour = NULL;
FT_ListNode node = NULL;
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_Memory memory = shape->memory; FT_Memory memory = shape->memory;
@ -505,14 +480,9 @@
goto Exit; goto Exit;
} }
contour = ( SDF_Contour* )shape->contours.tail->data; contour = shape->contours;
error = sdf_edge_new( memory, &edge ); FT_CALL( sdf_edge_new( memory, &edge ) );
if ( error != FT_Err_Ok )
goto Exit;
if ( FT_QNEW( node ) )
goto Exit;
edge->edge_type = SDF_EDGE_CUBIC; edge->edge_type = SDF_EDGE_CUBIC;
edge->start_pos = contour->last_pos; edge->start_pos = contour->last_pos;
@ -520,11 +490,10 @@
edge->control_b = *control_2; edge->control_b = *control_2;
edge->end_pos = *to; edge->end_pos = *to;
edge->next = contour->edges;
contour->edges = edge;
contour->last_pos = *to; contour->last_pos = *to;
node->data = edge;
FT_List_Add( &contour->edges, node );
Exit: Exit:
return error; return error;
} }
@ -721,12 +690,11 @@
split_sdf_conic( FT_Memory memory, split_sdf_conic( FT_Memory memory,
FT_26D6_Vec* control_points, FT_26D6_Vec* control_points,
FT_Int max_splits, FT_Int max_splits,
FT_List out ) SDF_Edge** out )
{ {
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_26D6_Vec cpos[5]; FT_26D6_Vec cpos[5];
SDF_Edge* left,* right; SDF_Edge* left,* right;
FT_ListNode n1, n2;
if ( !memory || !out ) if ( !memory || !out )
@ -766,9 +734,6 @@
FT_CALL( sdf_edge_new( memory, &left) ); FT_CALL( sdf_edge_new( memory, &left) );
FT_CALL( sdf_edge_new( memory, &right) ); FT_CALL( sdf_edge_new( memory, &right) );
if ( FT_QNEW( n1 ) || FT_QNEW( n2 ) )
goto Exit;
left->start_pos = cpos[0]; left->start_pos = cpos[0];
left->end_pos = cpos[2]; left->end_pos = cpos[2];
left->edge_type = SDF_EDGE_LINE; left->edge_type = SDF_EDGE_LINE;
@ -777,11 +742,9 @@
right->end_pos = cpos[4]; right->end_pos = cpos[4];
right->edge_type = SDF_EDGE_LINE; right->edge_type = SDF_EDGE_LINE;
n1->data = left; left->next = right;
n2->data = right; right->next = (*out);
*out = left;
FT_List_Add( out, n1 );
FT_List_Add( out, n2 );
Exit: Exit:
return error; return error;
@ -796,12 +759,11 @@
split_sdf_cubic( FT_Memory memory, split_sdf_cubic( FT_Memory memory,
FT_26D6_Vec* control_points, FT_26D6_Vec* control_points,
FT_Int max_splits, FT_Int max_splits,
FT_List out ) SDF_Edge** out )
{ {
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_26D6_Vec cpos[7]; FT_26D6_Vec cpos[7];
SDF_Edge* left,* right; SDF_Edge* left,* right;
FT_ListNode n1, n2;
if ( !memory || !out ) if ( !memory || !out )
@ -842,9 +804,6 @@
FT_CALL( sdf_edge_new( memory, &left) ); FT_CALL( sdf_edge_new( memory, &left) );
FT_CALL( sdf_edge_new( memory, &right) ); FT_CALL( sdf_edge_new( memory, &right) );
if ( FT_QNEW( n1 ) || FT_QNEW( n2 ) )
goto Exit;
left->start_pos = cpos[0]; left->start_pos = cpos[0];
left->end_pos = cpos[3]; left->end_pos = cpos[3];
left->edge_type = SDF_EDGE_LINE; left->edge_type = SDF_EDGE_LINE;
@ -853,11 +812,9 @@
right->end_pos = cpos[6]; right->end_pos = cpos[6];
right->edge_type = SDF_EDGE_LINE; right->edge_type = SDF_EDGE_LINE;
n1->data = left; left->next = right;
n2->data = right; right->next = (*out);
*out = left;
FT_List_Add( out, n1 );
FT_List_Add( out, n2 );
Exit: Exit:
return error; return error;
@ -870,11 +827,12 @@
static FT_Error static FT_Error
split_sdf_shape( SDF_Shape* shape ) split_sdf_shape( SDF_Shape* shape )
{ {
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_ListRec contours; FT_Memory memory = shape->memory;
FT_ListRec edges;
FT_ListRec new_edges = { NULL, NULL }; SDF_Contour* contours;
FT_Memory memory = shape->memory; SDF_Contour* new_contours = NULL;
if ( !shape ) if ( !shape )
@ -886,15 +844,17 @@
contours = shape->contours; contours = shape->contours;
/* for each contour */ /* for each contour */
while ( contours.head ) while ( contours )
{ {
edges = ((SDF_Contour*)contours.head->data)->edges; SDF_Edge* edges = contours->edges;
SDF_Edge* new_edges = NULL;
SDF_Contour* tempc;
/* for each edge */ /* for each edge */
while ( edges.head ) while ( edges )
{ {
SDF_Edge* edge = (SDF_Edge*)edges.head->data; SDF_Edge* edge = edges;
FT_ListNode node;
SDF_Edge* temp; SDF_Edge* temp;
switch ( edge->edge_type ) switch ( edge->edge_type )
@ -903,18 +863,12 @@
{ {
/* Just create a duplicate edge in case */ /* Just create a duplicate edge in case */
/* it is a line. We can use the same edge */ /* it is a line. We can use the same edge */
/* but then `FT_List_Finalize' will have */
/* to be changed. */
FT_CALL( sdf_edge_new( memory, &temp ) ); FT_CALL( sdf_edge_new( memory, &temp ) );
if ( FT_QNEW( node ) )
goto Exit;
ft_memcpy( temp, edge, sizeof( *edge ) ); ft_memcpy( temp, edge, sizeof( *edge ) );
node->data = temp; temp->next = new_edges;
new_edges = temp;
FT_List_Add( &new_edges, node );
node = NULL;
break; break;
} }
case SDF_EDGE_CONIC: case SDF_EDGE_CONIC:
@ -947,21 +901,25 @@
goto Exit; goto Exit;
} }
edges.head = edges.head->next; edges = edges->next;
} }
edges = ((SDF_Contour*)contours.head->data)->edges; /* add to the contours list */
FT_CALL( sdf_contour_new( memory, &tempc ) );
tempc->next = new_contours;
tempc->edges = new_edges;
new_contours = tempc;
new_edges = NULL;
/* Deallocate the previous list of edges and */ /* deallocate the contour */
/* assign the newly created list to the contour. */ tempc = contours;
FT_List_Finalize( &edges, sdf_edge_destructor, memory, NULL ); contours = contours->next;
((SDF_Contour*)contours.head->data)->edges = new_edges;
new_edges.head = NULL;
new_edges.tail = NULL;
contours.head = contours.head->next; sdf_contour_done( memory, &tempc );
} }
shape->contours = new_contours;
Exit: Exit:
return error; return error;
} }
@ -982,8 +940,8 @@
FT_UInt total_lines = 0; FT_UInt total_lines = 0;
FT_UInt total_conic = 0; FT_UInt total_conic = 0;
FT_UInt total_cubic = 0; FT_UInt total_cubic = 0;
FT_ListRec contour_list;
SDF_Contour* contour_list;
if ( !shape ) if ( !shape )
{ {
@ -996,19 +954,19 @@
FT_TRACE5(( "-------------------------------------------------\n" )); FT_TRACE5(( "-------------------------------------------------\n" ));
FT_TRACE5(( "[sdf] sdf_shape_dump:\n" )); FT_TRACE5(( "[sdf] sdf_shape_dump:\n" ));
while ( contour_list.head != NULL ) while ( contour_list )
{ {
FT_UInt num_edges = 0; FT_UInt num_edges = 0;
FT_ListRec edge_list; SDF_Edge* edge_list;
SDF_Contour* contour = (SDF_Contour*)contour_list.head->data; SDF_Contour* contour = contour_list;
edge_list = contour->edges; edge_list = contour->edges;
FT_TRACE5(( "Contour %d\n", num_contours )); FT_TRACE5(( "Contour %d\n", num_contours ));
while ( edge_list.head != NULL ) while ( edge_list )
{ {
SDF_Edge* edge = (SDF_Edge*)edge_list.head->data; SDF_Edge* edge = edge_list;
FT_TRACE5(( " Edge %d\n", num_edges )); FT_TRACE5(( " Edge %d\n", num_edges ));
@ -1053,11 +1011,11 @@
num_edges++; num_edges++;
total_edges++; total_edges++;
edge_list.head = edge_list.head->next; edge_list = edge_list->next;
} }
num_contours++; num_contours++;
contour_list.head = contour_list.head->next; contour_list = contour_list->next;
} }
FT_TRACE5(( "\n" )); FT_TRACE5(( "\n" ));
@ -2353,7 +2311,7 @@
{ {
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
SDF_Signed_Distance min_dist = max_sdf; SDF_Signed_Distance min_dist = max_sdf;
FT_ListRec edge_list; SDF_Edge* edge_list;
if ( !contour || !out ) if ( !contour || !out )
@ -2365,13 +2323,13 @@
edge_list = contour->edges; edge_list = contour->edges;
/* iterate through all the edges manually */ /* iterate through all the edges manually */
while ( edge_list.head ) { while ( edge_list ) {
SDF_Signed_Distance current_dist = max_sdf; SDF_Signed_Distance current_dist = max_sdf;
FT_16D16 diff; FT_16D16 diff;
FT_CALL( sdf_edge_get_min_distance( FT_CALL( sdf_edge_get_min_distance(
(SDF_Edge*)edge_list.head->data, edge_list,
point, &current_dist ) ); point, &current_dist ) );
if ( current_dist.distance >= 0 ) if ( current_dist.distance >= 0 )
@ -2389,7 +2347,7 @@
FT_TRACE0(( "sdf_contour_get_min_distance: Overflowed.\n" )); FT_TRACE0(( "sdf_contour_get_min_distance: Overflowed.\n" ));
} }
edge_list.head = edge_list.head->next; edge_list = edge_list->next;
} }
*out = min_dist; *out = min_dist;
@ -2472,7 +2430,7 @@
/* from this point to the entire shape. */ /* from this point to the entire shape. */
FT_26D6_Vec grid_point = zero_vector; FT_26D6_Vec grid_point = zero_vector;
SDF_Signed_Distance min_dist = max_sdf; SDF_Signed_Distance min_dist = max_sdf;
FT_ListRec contour_list; SDF_Contour* contour_list;
FT_UInt index; FT_UInt index;
FT_Short value; FT_Short value;
@ -2490,18 +2448,18 @@
index = ( rows - y - 1 ) * width + x; index = ( rows - y - 1 ) * width + x;
/* iterate through all the contours manually */ /* iterate through all the contours manually */
while ( contour_list.head ) { while ( contour_list ) {
SDF_Signed_Distance current_dist = max_sdf; SDF_Signed_Distance current_dist = max_sdf;
FT_CALL( sdf_contour_get_min_distance( FT_CALL( sdf_contour_get_min_distance(
(SDF_Contour*)contour_list.head->data, contour_list,
grid_point, &current_dist ) ); grid_point, &current_dist ) );
if ( current_dist.distance < min_dist.distance ) if ( current_dist.distance < min_dist.distance )
min_dist = current_dist; min_dist = current_dist;
contour_list.head = contour_list.head->next; contour_list = contour_list->next;
} }
/* [OPTIMIZATION]: if (min_dist > sp_sq) then simply clamp */ /* [OPTIMIZATION]: if (min_dist > sp_sq) then simply clamp */
@ -2558,14 +2516,14 @@
FT_UInt spread, FT_UInt spread,
const FT_Bitmap* bitmap ) const FT_Bitmap* bitmap )
{ {
FT_Error error = FT_Err_Ok; FT_Error error = FT_Err_Ok;
FT_Memory memory; FT_Memory memory;
FT_UInt width, rows, i, j; FT_UInt width, rows, i, j;
FT_ListRec contours; /* list of all contours */ FT_UInt sp_sq; /* max value to check */
FT_UInt sp_sq; /* max value to check */
FT_Short* buffer; /* the bitmap buffer */ SDF_Contour* contours; /* list of all contours */
FT_Short* buffer; /* the bitmap buffer */
/* This buffer has the same size in indices as the */ /* This buffer has the same size in indices as the */
/* bitmap buffer. When we check a pixel position for */ /* bitmap buffer. When we check a pixel position for */
@ -2613,20 +2571,18 @@
} }
/* loop through all the contours */ /* loop through all the contours */
while ( contours.head ) { while ( contours ) {
SDF_Contour* current_contour = (SDF_Contour*)contours.head->data; SDF_Edge* edges = contours->edges;
FT_ListRec edges = current_contour->edges;
/* loop through all the edges */ /* loop through all the edges */
while ( edges.head ) while ( edges )
{ {
SDF_Edge* current_edge = (SDF_Edge*)edges.head->data;
FT_CBox cbox; FT_CBox cbox;
FT_Int x, y; FT_Int x, y;
/* get the control box and increase by `spread' */ /* get the control box and increase by `spread' */
cbox = get_control_box( *current_edge ); cbox = get_control_box( *edges );
cbox.xMin = ( cbox.xMin - 63 ) / 64 - ( FT_Pos )spread; cbox.xMin = ( cbox.xMin - 63 ) / 64 - ( FT_Pos )spread;
cbox.xMax = ( cbox.xMax + 63 ) / 64 + ( FT_Pos )spread; cbox.xMax = ( cbox.xMax + 63 ) / 64 + ( FT_Pos )spread;
cbox.yMin = ( cbox.yMin - 63 ) / 64 - ( FT_Pos )spread; cbox.yMin = ( cbox.yMin - 63 ) / 64 - ( FT_Pos )spread;
@ -2656,7 +2612,7 @@
index = ( rows - y - 1 ) * width + x; index = ( rows - y - 1 ) * width + x;
FT_CALL( sdf_edge_get_min_distance( current_edge, FT_CALL( sdf_edge_get_min_distance( edges,
grid_point, grid_point,
&dist ) ); &dist ) );
@ -2681,10 +2637,10 @@
} }
} }
edges.head = edges.head->next; edges = edges->next;
} }
contours.head = contours.head->next; contours = contours->next;
} }
/* final pass */ /* final pass */
@ -2872,7 +2828,7 @@
FT_CALL( sdf_outline_decompose( outline, shape ) ); FT_CALL( sdf_outline_decompose( outline, shape ) );
FT_CALL( sdf_generate_subdivision( shape, sdf_params->spread, FT_CALL( sdf_generate_subdivision( shape, sdf_params->spread,
sdf_params->root.target ) ); sdf_params->root.target ) );
Exit: Exit: