summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnuj Verma <anujv@iitbhilai.ac.in>2020-08-19 12:56:58 +0530
committerAnuj Verma <anujv@iitbhilai.ac.in>2020-08-19 12:56:58 +0530
commit596bcfd34086d30c39093d0287e95781857fa575 (patch)
tree4d6994026d66f539d5996d8498d80166146ab957
parent75182d8ad1134bf2527056aaafe902edae42f7c2 (diff)
downloadfreetype2-596bcfd34086d30c39093d0287e95781857fa575.tar.gz
[sdf] Added function to generate SDF.
* src/sdf/ftsdf.c (sdf_generate): Added function to generate SDF. This one doesn't use any optimization, it simply check all grid point against all contours.
-rw-r--r--src/sdf/ftsdf.c152
1 files changed, 152 insertions, 0 deletions
diff --git a/src/sdf/ftsdf.c b/src/sdf/ftsdf.c
index 1b2eefbad..6d2552dcf 100644
--- a/src/sdf/ftsdf.c
+++ b/src/sdf/ftsdf.c
@@ -2647,6 +2647,158 @@
return error;
}
+ /**************************************************************************
+ *
+ * @Function:
+ * sdf_generate
+ *
+ * @Description:
+ * This is the main function that is responsible for generating
+ * signed distance fields. The function will not align or compute
+ * the size of the `bitmap', therefore setup the `bitmap' properly
+ * and transform the `shape' appropriately before calling this
+ * function.
+ * Currently we check all the pixels against all the contours and
+ * all the edges.
+ *
+ * @Input:
+ * internal_params ::
+ * Internal parameters and properties required by the rasterizer.
+ * See `SDF_Params' for the actual parameters.
+ *
+ * shape ::
+ * A complete shape which is used to generate SDF.
+ *
+ * spread ::
+ * Maximum distances to be allowed inthe output bitmap.
+ *
+ * @Return
+ * bitmap ::
+ * The output bitmap which will contain the SDF information.
+ *
+ * FT_Error ::
+ * FreeType error, 0 means success.
+ *
+ */
+ static FT_Error
+ sdf_generate( const SDF_Params internal_params,
+ const SDF_Shape* shape,
+ FT_UInt spread,
+ const FT_Bitmap* bitmap )
+ {
+ FT_Error error = FT_Err_Ok;
+ FT_UInt width = 0;
+ FT_UInt rows = 0;
+ FT_UInt x = 0; /* used to loop in x direction i.e. width */
+ FT_UInt y = 0; /* used to loop in y direction i.e. rows */
+ FT_UInt sp_sq = 0; /* `spread' * `spread' int 16.16 fixed */
+
+ FT_Short* buffer;
+
+ if ( !shape || !bitmap )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ if ( spread < MIN_SPREAD || spread > MAX_SPREAD )
+ {
+ error = FT_THROW( Invalid_Argument );
+ goto Exit;
+ }
+
+ width = bitmap->width;
+ rows = bitmap->rows;
+ buffer = (FT_Short*)bitmap->buffer;
+
+ if ( USE_SQUARED_DISTANCES )
+ sp_sq = FT_INT_16D16( spread * spread );
+ else
+ sp_sq = FT_INT_16D16( spread );
+
+ if ( width == 0 || rows == 0 )
+ {
+ FT_TRACE0(( "[sdf] sdf_generate:\n"
+ " Cannot render glyph with width/height == 0\n"
+ " (width, height provided [%d, %d])", width, rows ));
+ error = FT_THROW( Cannot_Render_Glyph );
+ goto Exit;
+ }
+
+ /* loop through all the rows */
+ for ( y = 0; y < rows; y++ )
+ {
+ /* loop through all the pixels of a row */
+ for ( x = 0; x < width; x++ )
+ {
+ /* `grid_point' is the current pixel position */
+ /* our task is to find the shortest distance */
+ /* from this point to the entire shape. */
+ FT_26D6_Vec grid_point = zero_vector;
+ SDF_Signed_Distance min_dist = max_sdf;
+ SDF_Contour* contour_list;
+ FT_UInt index;
+ FT_Short value;
+
+
+ grid_point.x = FT_INT_26D6( x );
+ grid_point.y = FT_INT_26D6( y );
+
+ /* This `grid_point' is at the corner, but we */
+ /* use the center of the pixel. */
+ grid_point.x += FT_INT_26D6( 1 ) / 2;
+ grid_point.y += FT_INT_26D6( 1 ) / 2;
+
+ contour_list = shape->contours;
+
+ /* iterate through all the contours manually */
+ while ( contour_list ) {
+ SDF_Signed_Distance current_dist = max_sdf;
+
+
+ FT_CALL( sdf_contour_get_min_distance(
+ contour_list,
+ grid_point, &current_dist ) );
+
+ if ( current_dist.distance < min_dist.distance )
+ min_dist = current_dist;
+
+ contour_list = contour_list->next;
+ }
+
+ /* [OPTIMIZATION]: if (min_dist > sp_sq) then simply clamp */
+ /* the value to spread to avoid square_root */
+
+ /* clamp the values to spread */
+ if ( min_dist.distance > sp_sq )
+ min_dist.distance = sp_sq;
+
+ /* square_root the values and fit in a 6.10 fixed point */
+ if ( USE_SQUARED_DISTANCES )
+ min_dist.distance = square_root( min_dist.distance );
+
+ if ( internal_params.orientation == FT_ORIENTATION_FILL_LEFT )
+ min_dist.sign = -min_dist.sign;
+ if ( internal_params.flip_sign )
+ min_dist.sign = -min_dist.sign;
+
+ min_dist.distance /= 64; /* convert from 16.16 to 22.10 */
+ value = min_dist.distance & 0x0000FFFF; /* truncate to 6.10 */
+ value *= min_dist.sign;
+
+ if ( internal_params.flip_y )
+ index = y * width + x;
+ else
+ index = ( rows - y - 1 ) * width + x;
+
+ buffer[index] = value;
+ }
+ }
+
+ Exit:
+ return error;
+ }
+
#endif
/* END */