Compare commits

...

35 Commits

Author SHA1 Message Date
Anuj Verma 6218c942ad [sdf] Fix compiler warnings.
* src/sdf/ftsdf.c (get_control_box): Use goto instead of letting the next case statement
  execute to avoid compiler warning [-Wimplicit-fallthrough=].

* src/sdf/ftsdf.c (sdf_generate_bounding_box): Fix compiler warning due to signed
  unsigned mismatch.

* src/sdf/ftsdfrend.c (ft_sdf_done): The function must have a return type of `void'
  to match the signature of `FT_Module_Destructor'.
2020-08-24 09:40:46 +05:30
Anuj Verma d2d939098d [sdf, bsdf] Fix compiler warnings.
* src/sdf/ftsdf.c, src/sdf/ftbsdf.c (*): Fix compiler warnings caused due to signed
  unsigned mismatch (-Wsign-compare).
2020-08-23 18:03:39 +05:30
Anuj Verma 8cce50b9b8 Be more explicit about the output of the SDF rasterizers.
* include/freetype/fttypes.h (FT_F6Dot10): Add a new data type which can be\
  used to convert the output buffer appropriately.

* include/freetype/freetype.h (FT_Render_Mode): Add information about the
  output while using `FT_RENDER_MODE_SDF'.

* include/freetype/ftimage.h (FT_Pixel_Mode): Add more information about the
  `FT_PIXEL_MODE_GRAY16' pixel mode.
2020-08-23 05:35:46 +05:30
Anuj Verma 7c2a64b709 [sdf] Added debugging function.
* src/sdf/ftsdf.c (sdf_shape_dump): Added a debugging function which can be used
  to debug issues with the outline, contours, edges etc.
2020-08-21 04:59:08 -07:00
Anuj Verma ed49facfe0 [sdf] Bug fix.
* src/sdf/ftsdf.c (*): Only track memory when `FT_DEBUG_MEMORY' is defined. Some
  variables used internally by the freetype memory debugger are only defined when
  we are tracking memory. If `FT_DEBUG_MEMORY' is not defined those variable
  are not defined and we get undefined reference error.
2020-08-21 04:55:15 -07:00
Anuj Verma 644a6c24fd [sdf] Added brief technical overview of both the rasterizers.
* src/sdf/ftsdf.c (*): Added a technical overview of the working of the `sdf' rasterizer.

* src/sdf/ftbsdf,c (*) : Added a technical overview of the working of the `bsdf'
  rasterizer.
2020-08-21 03:59:23 -07:00
Anuj Verma 56e4100aad [sdf] Added the `bsdf' renderer to the `sdf' module.
* src/sdf/ftsdfrend.c (ft_bsdf_render): Added the `bsdf' renderer, render function 
  which is essentially what is called from the FreeType core to render a glyph.

* src/sdf/ftsdfrend.c (ft_bitmap_sdf_renderer_class): Added the `bsdf' renderer
  definition.
2020-08-20 21:57:43 -07:00
Anuj Verma 67652386e2 [bsdf] Added forward declaration of the `bsdf' rasterizer.
* src/sdf/ftsdf.h (ft_bitmap_sdf_raster): Added forward declaration of the rasterizer
  so that it can be added to the renderer.
2020-08-20 21:27:59 -07:00
Anuj Verma d1e95d734c [bsdf] Added the interface functions for the `bsdf' rasterizer.
* src/sdf/ftsdf.c (bsdf_raster_): Added interface functions which are called from the
  FreeType core library to rasterize and do various other stuff with the rasterizer.
2020-08-20 21:25:46 -07:00
Anuj Verma f2545feda9 [bsdf] Added function to copy the SDF data into the output bitmap.
* src/sdf/ftbsdf.c (finalize_sdf): The function uses the final data present in the 
  distance map and copies is to the output bitmap. It also converts our data into the
  desired format.
2020-08-20 21:21:33 -07:00
Anuj Verma c6b4053a76 [bsdf] Added the 8SED algorithm.
* src/sdf/ftbsdf.c (edt8): Added function to do the euclidean transform to the 
  distance map. The function basically does the 8SED algorithm on the distance map 
  to compute the distance transform of the bitmap.

* src/sdf/ftbsdf.c (first_pass, second_pass): The first and the second pass of the 8SED
  algorithm.

* src/sdf/ftbsdf.c (compare_neighbor): Helper function to compare the neighbor of
  a pixel which is required in the 8SED algorithm.
2020-08-20 21:19:32 -07:00
Anuj Verma 461d693c29 [bsdf] Added function to copy source bitmap to the distance map.
* src/sdf/ftbsdf.c (bsdf_init_distance_map): The function copies the source bitmap to
  the intermediate distance map which is present within the `worker'.
2020-08-20 21:09:23 -07:00
Anuj Verma e883c6dc50 [bsdf] Added function to approximate edge distances.
* src/sdf/ftbsdf.c (compute_edge_distance): Added function to approximate edges 
  given only the array of alpha values representing pixel coverage. This function uses
  the Gustavson's algorithm for approximating.

* src/sdf/ftbsdf.c (bsdf_approximate_edge): This function loops through the entire
  bitmap and for edge pixel (found using `bsdf_is_edge') compute approximate edge
  distances (using `compute_edge_distance').
2020-08-20 09:25:15 +05:30
Anuj Verma 44e9d12f0f [bsdf] Added function to find edge pixels given a grid of alpha values.
* src/sdf/ftbsdf.c (bsdf_is_edge): The function find the edge pixel in a distance map
  which is basically a 2D array of alpha values which represent coverage in the
  original input bitmap.
2020-08-20 09:20:26 +05:30
Anuj Verma 2aeee74c0c [bsdf] Added essential structures required by the `bsdf' rasterizer.
* src/sdf/ftbsdf.c (*): Added all the essential structures required internally by the
  `bsdf' rasterizer as well as the initializer for the `ED' struct.
2020-08-20 09:17:38 +05:30
Anuj Verma 1df094bd7a [sdf] Added `sdf' module to non gnumake build systems.
* include/freetype/config/ftmodule.h (*): Add both the renderers to the list of 
  modules. This allows build systems other than GNU Make to use the renderers.

* CMakeLists.txt (BASE_SRCS): Add the `sdf' module single object to the list of source
  files.
2020-08-20 08:28:14 +05:30
Anuj Verma d5397730b4 [sdf] Added basic overlapping contour support.
* src/sdf/ftsdf.c (sdf_generate_with_overlaps): Added another `sdf_generate_' 
  function which can generate SDF for glyphs with overlapping contour. Note that
  it cannot generate proper SDF for glyphs with self intersecting contours.
2020-08-20 07:54:13 +05:30
Anuj Verma a538f17928 [sdf] Add the `sdf' module to `modules.cg' and fix makefiles.
* src/sdf/module.mk, src/sdf/rules.mk: Fix file names, they were reversed.

* include/freetype/ftmoderr.h (FT_MODERRDEF): Add error definition for the `sdf'
  module.

* include/freetype/internal/fttrace.h (FT_TRACE_DEF): Add trace definition for the 
  `sdf' module.

* modules.cfg (RASTER_MODULES): Add the `sdf' module to the list of rasterizers.
2020-08-19 17:30:44 +05:30
Anuj Verma c76b653829 [sdf] Added makefiles to build the `sdf' module.
* src/sdf/ftsdf.c (module.mk, rules.mk): Added makefiled to build the `sdf' module.

* src/sdf/ftsdf.c (ft_sdf_raster): Added forward declaration of the `sdf' rasterizer.
2020-08-19 16:57:38 +05:30
Anuj Verma 8359cb3501 [sdf] Added the interface functions for the `sdf' rasterizer.
* src/sdf/ftsdf.c (sdf_raster_): Added interface functions which are called from the
  FreeType core library to rasterize and do various other stuff with the rasterizer.
2020-08-19 16:29:51 +05:30
Anuj Verma 5cee930937 [sdf] Added the subdivision and bounding box optimization.
* src/sdf/ftsdf.c (sdf_generate_bounding_box): Added function to generate SDF by
  only checking grid point around the bounding box of any edge.

* src/sdf/ftsdf.c (sdf_generate_subdivision): Added function to generate SDF by 
  splitting the shape into a number of line segments and then only checking grid
  points around the neighborhood of the lines.
2020-08-19 16:25:08 +05:30
Anuj Verma 596bcfd340 [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.
2020-08-19 12:56:58 +05:30
Anuj Verma 75182d8ad1 [sdf] Added functions to get shortest distance from any edge/contour.
* src/sdf/ftsdf,c (sdf_edge_get_min_distance): Added function to get shortest distance
  from any arbitary edge.

* src/sdf/ftsdf.c (sdf_contour_get_min_distance): Added function to get shortest
  distance from a contour. It basically returns the shortest distance from the nearest
  edge.
2020-08-19 12:22:34 +05:30
Anuj Verma c39b5dd849 [sdf] Added shortest distance finding functions.
* src/sdf/ftsdf.c (get_min_distance_): Added function to find the closest distance
  from a point to a curves of all three different types (i.e. line segment, conic
  bezier and cubic bezier).
2020-08-18 17:49:56 +05:30
Anuj Verma 68032a77e3 [sdf] Added function to resolve corner distances.
* src/sdf/ftsdf.c (resolve_corner): Added function to resolve corner distances
  because at corner two equal distance can have opposite sign.
2020-08-18 10:28:16 +05:30
Anuj Verma 0fcd73fb4a [sdf] Added essential math functions.
* src/sdf/ftsdf.c (cube_root, arc_cos): Added functions to compute cube root and
  cosine inverse of a 16.16 fixed point number.

* src/sdf/ftsdf.c (solve_quadratic_equation, solve_cubic_equation): Added
  functions to find roots of quadratic and cubic polynomial equations.
2020-08-18 10:17:46 +05:30
Anuj Verma 4dc90dc8d0 [sdf] Added utility functions for contours.
* src/sdf/ftsdf.c (get_control_box, get_contour_orientation): Added functions to
  get control box and orientation of any `SDF_Contour'.

* src/sdf/ftsdf.c (split_sdf_shape): Added function to split a complete shape (i.e.
  a collection of contours) into a number of small lines.
2020-08-18 10:14:20 +05:30
Anuj Verma e4e81c0168 [sdf] Added functions to decompose `FT_Outline'.
* src/sdf/ftsdf.c (sdf_outline_decompose): Added a function which decompose
  a `FT_Outline' using `FT_Outline_Decompose' and adds the outline data to a
  `SDF_Shape' for easier handling later on.
2020-08-17 16:36:30 +05:30
Anuj Verma 286fc7e42c [sdf] Added essential structs, enums and macros for `sdf' rasterizer.
* src/sdf/ftsdf.c (SDF_): Added the essential structures and enums which will
  be used internally by the `sdf' rasterizer. Also added allocator and deallocator
  functions for the structs.

* src/sdf/ftsdf.c (SDF_MemoryUser): Added a custom memory allocator which
  is used to track intermediate memory usage while generate SDF.

* src/sdf/ftsdf.c (definations): Added various definitions which can be used to
  modify the `sdf' rasterizer and also added a few helper macros.
2020-08-17 16:24:39 +05:30
Anuj Verma b8f4ab8304 [sdf] Added raster params struct.
* src/sdf/ftsdf.h (SDF_Raster_Params): Added struct which is used to pass 
  params to both `sdf' and `bsdf' rasterizer.

* src/sdf/sdf.c (*): Include source files in order to make a single object of the
  module.

* src/sdf/ftsdfrend.h (SDF_Renderer_Module): Add a '*' to make the comment
  similar to the rest in the module.
2020-08-17 16:11:56 +05:30
Anuj Verma ed7d2f5789 [sdf] Added the `sdf' renderer.
* src/sdf/ftsdf.c (*): Added `sdf' renderer along with
  it's interface functions and functions to set and get
  properties.
2020-08-17 11:47:26 +05:30
Anuj Verma e087e937e8 [sdf] Added common elements for `sdf' and `bsdf' renderers.
* src/sdf/ftsdfrend.c (*): Added common renderer struct and
  declaration of both the renderers.

* src/sdf/ftsdfcommon.h (*): Added common properties, typedefs,
  macros etc.

* src/sdf/ftsdferrs.h (*): Error definitions for the module.
2020-08-17 11:40:57 +05:30
Anuj Verma 29de1ff668 [sdf] Added all the necessary filed required by the module.
Added the necessary files required by the `sdf' module. These include files
for both the `sdf' and the `bsdf' renderers. Here is breakdown of what the
specific files will contain:

* src/sdf/ftsdfrend.*: Both the renderers.

* src/sdf/ftsdf.*: The rasterizer for the `sdf' renderer.

* src/sdf/ftbsdf.c: The rasterizer for the `bsdf' renderer.

* src/sdf/ftsdfcommon.h: Commmon properties and functions for both the
  rasterizers.

* src/sdf/ftsdferrs.h: Common error define.

* src/sdf/sdf.c: For building a single object of the entire module.
2020-08-16 17:09:22 +05:30
Anuj Verma 6b81c538ed Added render mode and data type required for the `sdf' module.
* include/freetype/freetype.h (FT_Render_Mode): Added a new render mode
  `FT_RENDER_MODE_SDF', which will be used to generate SDF.

* include/freetype/ftimage.h (FT_Pixel_Mode): Added a new pixel mode
  `FT_PIXEL_MODE_GRAY16', which will be the output of the `sdf' module.

* include/freetype/ftimage.h (FT_RASTER_FLAG_SDF): Added a new raster flag
  to be used internally by the `sdf' module.
2020-08-16 10:47:41 +05:30
Anuj Verma 6ed3c34a0e [base] Make necessary changes to allow renderers of different formats.
* src/base/ftobjs.c (FT_Render_Glyph_Internal): Do not return if the glyph's slot
  format is `FT_GLYPH_FORMAT_BITMAP'. The `bsdf' renderer will require bitmaps 
  for processing.

* src/base/ftobjs.c (ft_add_renderer, ft_remove_renderer): Remove renderer's glyph
  format check before adding and removing them. The `bsdf' renderer will have a
  format of `FT_GLYPH_FORMAT_BITMAP'. So, if we do not remove this check it will
  not get initialized and will not work.
2020-08-16 09:06:59 +05:30
19 changed files with 6019 additions and 11 deletions

View File

@ -353,6 +353,7 @@ set(BASE_SRCS
src/type1/type1.c
src/type42/type42.c
src/winfonts/winfnt.c
src/sdf/sdf.c
)
if (UNIX)

View File

@ -26,5 +26,7 @@ FT_USE_MODULE( FT_Renderer_Class, ft_raster1_renderer_class )
FT_USE_MODULE( FT_Module_Class, sfnt_module_class )
FT_USE_MODULE( FT_Renderer_Class, ft_smooth_renderer_class )
FT_USE_MODULE( FT_Driver_ClassRec, bdf_driver_class )
FT_USE_MODULE( FT_Renderer_Class, ft_sdf_renderer_class )
FT_USE_MODULE( FT_Renderer_Class, ft_bitmap_sdf_renderer_class )
/* EOF */

View File

@ -3208,10 +3208,14 @@ FT_BEGIN_HEADER
* in the @FT_GlyphSlotRec structure gives the format of the returned
* bitmap.
*
* All modes except @FT_RENDER_MODE_MONO use 256 levels of opacity,
* indicating pixel coverage. Use linear alpha blending and gamma
* correction to correctly render non-monochrome glyph bitmaps onto a
* surface; see @FT_Render_Glyph.
* All modes except @FT_RENDER_MODE_MONO and @FT_RENDER_MODE_SDF use
* 256 levels of opacity, indicating pixel coverage. Use linear alpha
* blending and gamma correction to correctly render non-monochrome glyph
* bitmaps onto a surface; see @FT_Render_Glyph.
*
* The @FT_RENDER_MODE_SDF is s special render mode which uses as much
* 65536 distance values, indicating the signed distance from the grid
* position to the nearest outline.
*
* @values:
* FT_RENDER_MODE_NORMAL ::
@ -3238,6 +3242,15 @@ FT_BEGIN_HEADER
* bitmaps that are 3~times the height of the original glyph outline in
* pixels and use the @FT_PIXEL_MODE_LCD_V mode.
*
* FT_RENDER_MODE_SDF ::
* This mode corresponds to 16-bit signed distance fields bitmap. 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_6Dot10 and convert
* accordingly.
*
* @note:
* The selected render mode only affects vector glyphs of a font.
* Embedded bitmaps often have a different pixel mode like
@ -3251,6 +3264,7 @@ FT_BEGIN_HEADER
FT_RENDER_MODE_MONO,
FT_RENDER_MODE_LCD,
FT_RENDER_MODE_LCD_V,
FT_RENDER_MODE_SDF,
FT_RENDER_MODE_MAX

View File

@ -157,6 +157,14 @@ 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. This is currently only used while
* rendering using @FT_RENDER_MODE_SDF. One Impotant Note:
* This pixel format is represented as 6.10 fixed point format. That
* means you have to divide the values by 1024.0F in order to get
* actual data that is outputted 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
@ -184,6 +192,7 @@ FT_BEGIN_HEADER
FT_PIXEL_MODE_GRAY,
FT_PIXEL_MODE_GRAY2,
FT_PIXEL_MODE_GRAY4,
FT_PIXEL_MODE_GRAY16,
FT_PIXEL_MODE_LCD,
FT_PIXEL_MODE_LCD_V,
FT_PIXEL_MODE_BGRA,
@ -962,11 +971,17 @@ FT_BEGIN_HEADER
* will be clipped to a box specified in the `clip_box` field of the
* @FT_Raster_Params structure. Otherwise, the `clip_box` is
* effectively set to the bounding box and all spans are generated.
*
* FT_RASTER_FLAG_SDF ::
* This flag is set to indicate that a signed distance field glyph
* image should be generated. This is only used while rendering with
* `FT_RENDER_MODE_SDF' render mode.
*/
#define FT_RASTER_FLAG_DEFAULT 0x0
#define FT_RASTER_FLAG_AA 0x1
#define FT_RASTER_FLAG_DIRECT 0x2
#define FT_RASTER_FLAG_CLIP 0x4
#define FT_RASTER_FLAG_SDF 0x8
/* these constants are deprecated; use the corresponding */
/* `FT_RASTER_FLAG_XXX` values instead */

View File

@ -171,6 +171,7 @@
FT_MODERRDEF( Type42, 0x1400, "Type 42 module" )
FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" )
FT_MODERRDEF( GXvalid, 0x1600, "GX validation module" )
FT_MODERRDEF( Sdf, 0x1700, "Signed distance field raster module" )
#ifdef FT_MODERR_END_LIST

View File

@ -78,6 +78,7 @@ FT_BEGIN_HEADER
* FT_FWord
* FT_UFWord
* FT_F2Dot14
* FT_F6Dot10
* FT_UnitVector
* FT_F26Dot6
* FT_Data
@ -264,6 +265,17 @@ 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:

View File

@ -40,6 +40,7 @@ FT_TRACE_DEF( psprops ) /* PS driver properties (ftpsprop.c) */
FT_TRACE_DEF( raccess ) /* resource fork accessor (ftrfork.c) */
FT_TRACE_DEF( raster ) /* monochrome rasterizer (ftraster.c) */
FT_TRACE_DEF( smooth ) /* anti-aliasing raster (ftgrays.c) */
FT_TRACE_DEF( sdf ) /* signed distance raster (ftsdf.c) */
FT_TRACE_DEF( synth ) /* bold/slant synthesizer (ftsynth.c) */
/* Cache sub-system */

View File

@ -99,6 +99,9 @@ RASTER_MODULES += raster
# Anti-aliasing rasterizer.
RASTER_MODULES += smooth
# Signed distance field rasterizer.
RASTER_MODULES += sdf
####
#### auxiliary modules

View File

@ -4393,8 +4393,7 @@
render->glyph_format = clazz->glyph_format;
/* allocate raster object if needed */
if ( clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
clazz->raster_class->raster_new )
if ( clazz->raster_class->raster_new )
{
error = clazz->raster_class->raster_new( memory, &render->raster );
if ( error )
@ -4441,8 +4440,7 @@
/* release raster object, if any */
if ( render->clazz->glyph_format == FT_GLYPH_FORMAT_OUTLINE &&
render->raster )
if ( render->raster )
render->clazz->raster_class->raster_done( render->raster );
/* remove from list */
@ -4537,9 +4535,6 @@
switch ( slot->format )
{
case FT_GLYPH_FORMAT_BITMAP: /* already a bitmap, don't do anything */
break;
default:
if ( slot->internal->load_flags & FT_LOAD_COLOR )
{

1293
src/sdf/ftbsdf.c Normal file

File diff suppressed because it is too large Load Diff

3715
src/sdf/ftsdf.c Normal file

File diff suppressed because it is too large Load Diff

77
src/sdf/ftsdf.h Normal file
View File

@ -0,0 +1,77 @@
#ifndef FTSDF_H_
#define FTSDF_H_
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include <freetype/ftimage.h>
/* common properties and function */
#include "ftsdfcommon.h"
FT_BEGIN_HEADER
/**************************************************************************
*
* @struct:
* SDF_Raster_Params
*
* @description:
* This struct must be passed to the raster render function
* `FT_Raster_Render_Func' instead of `FT_Raster_Params' because
* the rasterizer require some addition information to render properly.
* So, this struct is used to pass additional parameter to the
* rasterizer.
*
* @fields:
* root ::
* The native raster params struct.
*
* spread ::
* This is and essential parameter/property required by the
* rendere. `spread' defines the maximum unsigned value that
* will be present in the final SDF output. For default value
* check `ftsdfcommon.h'.
*
* flip_sign ::
* By default the position values are inside the contours i.e.
* filled by a contour. If this property is true then that output
* will be opposite from the default i.e. negative will be filled
* by a contour.
*
* flip_y ::
* Setting this parameter to true maked the output image flipped
* along the y-axis.
*
* overlaps ::
* Set this to true to generate SDF for glyphs having overlapping
* contours. The overlapping support is limited to glyph which do
* not have self intersecting contours. Also, removing overlaps
* require a considerable amount of extra memory and this is not
* valid while generating SDF from bitmap.
*
* @note:
* It is valid for both `sdf' and `bsdf' renderer.
*
*/
typedef struct SDF_Raster_Params_
{
FT_Raster_Params root;
FT_UInt spread;
FT_Bool flip_sign;
FT_Bool flip_y;
FT_Bool overlaps;
} SDF_Raster_Params;
/* rasterizer to convert outline to SDF */
FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_sdf_raster;
/* rasterizer to convert bitmap to SDF */
FT_EXPORT_VAR( const FT_Raster_Funcs ) ft_bitmap_sdf_raster;
FT_END_HEADER
#endif /* FTSDF_H_ */
/* END */

137
src/sdf/ftsdfcommon.h Normal file
View File

@ -0,0 +1,137 @@
/****************************************************
*
* This file contain common function and properties
* for both `sdf' and `bsdf' renderer.
*
*/
#ifndef FTSDFCOMMON_H_
#define FTSDFCOMMON_H_
#include <ft2build.h>
#include FT_CONFIG_CONFIG_H
#include <freetype/freetype.h>
FT_BEGIN_HEADER
/**************************************************************************
*
* default values (cannot be set individually for each renderer)
*
*/
/* default spread value */
#define DEFAULT_SPREAD 8
/* minimum spread supported by the renderer. */
#define MIN_SPREAD 2
/* maximum spread supported by the renderer. */
#define MAX_SPREAD 32
/**************************************************************************
*
* common definitions (cannot be set individually for each renderer)
*
*/
/* If it is defined to 1 then the rasterizer will use squared distances */
/* for computation. It can greatly improve the performance but there is */
/* a chance of overflow and artifacts. You can safely use it upto a */
/* pixel size of 128. */
#ifndef USE_SQUARED_DISTANCES
# define USE_SQUARED_DISTANCES 0
#endif
/**************************************************************************
*
* common macros
*
*/
/* convert int to 26.6 fixed point */
#define FT_INT_26D6( x ) ( x * 64 )
/* convert int to 16.16 fixed point */
#define FT_INT_16D16( x ) ( x * 65536 )
/* convert 26.6 to 16.16 fixed point */
#define FT_26D6_16D16( x ) ( x * 1024 )
/* Convenient macro which calls the function */
/* and returns if any error occurs. */
#define FT_CALL( x ) do \
{ \
error = ( x ); \
if ( error != FT_Err_Ok ) \
goto Exit; \
} while ( 0 )
/* [IMPORTANT]: The macro `VECTOR_LENGTH_16D16' is not always the same */
/* and must not be used anywhere except a few places. This macro is */
/* controlled by the `USE_SQUARED_DISTANCES' macro. It compute squared */
/* distance or actual distance based on `USE_SQUARED_DISTANCES' value. */
/* By using squared distances the performance can be greatly improved */
/* but there is a risk of overflow. Use it wisely. */
#if USE_SQUARED_DISTANCES
# define VECTOR_LENGTH_16D16( v ) ( FT_MulFix( v.x, v.x ) + \
FT_MulFix( v.y, v.y ) )
#else
# define VECTOR_LENGTH_16D16( v ) FT_Vector_Length( &v )
#endif
/**************************************************************************
*
* common typedefs
*
*/
typedef FT_Vector FT_26D6_Vec; /* with 26.6 fixed point components */
typedef FT_Vector FT_16D16_Vec; /* with 16.16 fixed point components */
typedef FT_Fixed FT_16D16; /* 16.16 fixed point representation */
typedef FT_Fixed FT_26D6; /* 26.6 fixed point representation */
typedef FT_Short FT_6D10; /* 6.10 fixed point representation */
typedef FT_BBox FT_CBox; /* control box of a curve */
/**************************************************************************
*
* common functions
*
*/
/* Original Algorithm: https://github.com/chmike/fpsqrt */
/* Use this to compute the square root of a 16.16 fixed */
/* point number. */
static FT_16D16
square_root( FT_16D16 val )
{
FT_ULong t, q, b, r;
r = val;
b = 0x40000000;
q = 0;
while( b > 0x40 )
{
t = q + b;
if( r >= t )
{
r -= t;
q = t + b;
}
r <<= 1;
b >>= 1;
}
q >>= 8;
return q;
}
FT_END_HEADER
#endif /* FTSDFCOMMON_H_ */
/* END */

17
src/sdf/ftsdferrs.h Normal file
View File

@ -0,0 +1,17 @@
#ifndef FTSDFERRS_H_
#define FTSDFERRS_H_
#include <freetype/ftmoderr.h>
#undef FTERRORS_H_
#undef FT_ERR_PREFIX
#define FT_ERR_PREFIX Sdf_Err_
#define FT_ERR_BASE FT_Mod_Err_Sdf
#include <freetype/fterrors.h>
#endif /* FTSDFERRS_H_ */
/* END */

540
src/sdf/ftsdfrend.c Normal file
View File

@ -0,0 +1,540 @@
#include <freetype/internal/ftdebug.h>
#include <freetype/internal/ftobjs.h>
#include <freetype/internal/services/svprop.h>
#include <freetype/ftoutln.h>
#include <freetype/ftbitmap.h>
#include "ftsdfrend.h"
#include "ftsdf.h"
#include "ftsdferrs.h"
/**************************************************************************
*
* The macro FT_COMPONENT is used in trace mode. It is an implicit
* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
* messages during execution.
*/
#undef FT_COMPONENT
#define FT_COMPONENT sdf
/**************************************************************************
*
* macros and default property values
*
*/
#define SDF_RENDERER( rend ) ( (SDF_Renderer)rend )
/**************************************************************************
*
* for setting properties
*
*/
/* property setter function */
static FT_Error
sdf_property_set( FT_Module module,
const char* property_name,
const void* value,
FT_Bool value_is_string )
{
FT_Error error = FT_Err_Ok;
SDF_Renderer render = SDF_RENDERER( FT_RENDERER( module ) );
FT_UNUSED( value_is_string );
if ( ft_strcmp( property_name, "spread" ) == 0 )
{
FT_Int val = *(const FT_Int*)value;
if ( val > MAX_SPREAD || val < MIN_SPREAD )
{
FT_TRACE0(( "[sdf] sdf_property_set: "
"the `spread' property can have a "
"value within range [%d, %d] (value provided %d)\n",
MIN_SPREAD, MAX_SPREAD, val ));
error = FT_THROW( Invalid_Argument );
goto Exit;
}
render->spread = (FT_UInt)val;
FT_TRACE7(( "[sdf] sdf_property_set: "
"updated property `spread' to %d\n", val ));
}
else if ( ft_strcmp( property_name, "flip_sign" ) == 0 )
{
FT_Int val = *(const FT_Int*)value;
render->flip_sign = val ? 1 : 0;
FT_TRACE7(( "[sdf] sdf_property_set: "
"updated property `flip_sign' to %d\n", val ));
}
else if ( ft_strcmp( property_name, "flip_y" ) == 0 )
{
FT_Int val = *(const FT_Int*)value;
render->flip_y = val ? 1 : 0;
FT_TRACE7(( "[sdf] sdf_property_set: "
"updated property `flip_y' to %d\n", val ));
}
else if ( ft_strcmp( property_name, "overlaps" ) == 0 )
{
FT_Int val = *(const FT_Int*)value;
render->overlaps = val;
FT_TRACE7(( "[sdf] sdf_property_set: "
"updated property `overlaps' to %d\n", val ));
}
else
{
FT_TRACE0(( "[sdf] sdf_property_set: "
"missing property `%s'\n", property_name ));
error = FT_THROW( Missing_Property );
}
Exit:
return error;
}
/* property getter function */
static FT_Error
sdf_property_get( FT_Module module,
const char* property_name,
void* value )
{
FT_Error error = FT_Err_Ok;
SDF_Renderer render = SDF_RENDERER( FT_RENDERER( module ) );
if ( ft_strcmp( property_name, "spread" ) == 0 )
{
FT_Int* val = (FT_Int*)value;
*val = render->spread;
}
else if ( ft_strcmp( property_name, "flip_sign" ) == 0 )
{
FT_Int* val = (FT_Int*)value;
*val = render->flip_sign;
}
else if ( ft_strcmp( property_name, "flip_y" ) == 0 )
{
FT_Int* val = (FT_Int*)value;
*val = render->flip_y;
}
else if ( ft_strcmp( property_name, "overlaps" ) == 0 )
{
FT_Int* val = (FT_Int*)value;
*val = render->overlaps;
}
else
{
FT_TRACE0(( "[sdf] sdf_property_get: "
"missing property `%s'\n", property_name ));
error = FT_THROW( Missing_Property );
}
return error;
}
FT_DEFINE_SERVICE_PROPERTIESREC(
sdf_service_properties,
(FT_Properties_SetFunc)sdf_property_set, /* set_property */
(FT_Properties_GetFunc)sdf_property_get ) /* get_property */
FT_DEFINE_SERVICEDESCREC1(
sdf_services,
FT_SERVICE_ID_PROPERTIES, &sdf_service_properties )
static FT_Module_Interface
ft_sdf_requester( FT_Renderer render,
const char* module_interface )
{
FT_UNUSED( render );
return ft_service_list_lookup( sdf_services, module_interface );
}
/**************************************************************************
*
* interface functions
*
*/
static FT_Error
ft_sdf_init( FT_Renderer render )
{
SDF_Renderer sdf_render = SDF_RENDERER( render );
sdf_render->spread = DEFAULT_SPREAD;
sdf_render->flip_sign = 0;
sdf_render->flip_y = 0;
sdf_render->overlaps = 0;
return FT_Err_Ok;
}
static void
ft_sdf_done( FT_Renderer render )
{
FT_UNUSED( render );
}
/* generate signed distance field from a glyph's slot image */
static FT_Error
ft_sdf_render( FT_Renderer module,
FT_GlyphSlot slot,
FT_Render_Mode mode,
const FT_Vector* origin )
{
FT_Error error = FT_Err_Ok;
FT_Outline* outline = &slot->outline;
FT_Bitmap* bitmap = &slot->bitmap;
FT_Memory memory = NULL;
FT_Renderer render = NULL;
FT_Pos x_shift = 0;
FT_Pos y_shift = 0;
FT_Pos x_pad = 0;
FT_Pos y_pad = 0;
SDF_Raster_Params params;
SDF_Renderer sdf_module = SDF_RENDERER( module );
render = &sdf_module->root;
memory = render->root.memory;
/* check if slot format is correct before rendering */
if ( slot->format != render->glyph_format )
{
error = FT_THROW( Invalid_Glyph_Format );
goto Exit;
}
/* check if render mode is correct */
if ( mode != FT_RENDER_MODE_SDF )
{
FT_ERROR(( "[sdf] ft_sdf_render: "
"sdf module only render when "
"using `FT_RENDER_MODE_SDF'\n" ));
error = FT_THROW( Cannot_Render_Glyph );
goto Exit;
}
/* deallocate the previously allocated bitmap */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
FT_FREE( bitmap->buffer );
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
/* preset the bitmap using the glyph's outline; */
/* the sdf bitmap is similar to an antialiased bitmap */
/* with a slightly bigger size and different pixel mode */
if ( ft_glyphslot_preset_bitmap( slot, FT_RENDER_MODE_NORMAL, origin ) )
{
error = FT_THROW( Raster_Overflow );
goto Exit;
}
if ( !bitmap->rows || !bitmap->pitch )
goto Exit;
/* the padding will simply be equal to the `spread' */
x_pad = sdf_module->spread;
y_pad = sdf_module->spread;
/* apply the padding, will be in all the directions */
bitmap->rows += y_pad * 2;
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;
/* allocate new buffer */
if ( FT_ALLOC_MULT( bitmap->buffer, bitmap->rows, bitmap->pitch ) )
goto Exit;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
x_shift = 64 * -( slot->bitmap_left - x_pad );
y_shift = 64 * -( slot->bitmap_top + y_pad );
y_shift += 64 * (FT_Int)bitmap->rows;
if ( origin )
{
x_shift += origin->x;
y_shift += origin->y;
}
/* translate outline to render it into the bitmap */
if ( x_shift || y_shift )
FT_Outline_Translate( outline, x_shift, y_shift );
/* set up parameters */
params.root.target = bitmap;
params.root.source = outline;
params.root.flags = FT_RASTER_FLAG_SDF;
params.spread = sdf_module->spread;
params.flip_sign = sdf_module->flip_sign;
params.flip_y = sdf_module->flip_y;
params.overlaps = sdf_module->overlaps;
/* render the outline */
error = render->raster_render( render->raster, (const FT_Raster_Params*)&params );
Exit:
if ( !error )
{
/* the glyph is successfully rendered to a bitmap */
slot->format = FT_GLYPH_FORMAT_BITMAP;
}
else if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
FT_FREE( bitmap->buffer );
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
if ( x_shift || y_shift )
FT_Outline_Translate( outline, -x_shift, -y_shift );
return error;
}
/* transform the glyph using matrix and/or delta */
static FT_Error
ft_sdf_transform( FT_Renderer render,
FT_GlyphSlot slot,
const FT_Matrix* matrix,
const FT_Vector* delta )
{
FT_Error error = FT_Err_Ok;
if ( slot->format != render->glyph_format )
{
error = FT_THROW( Invalid_Argument );
goto Exit;
}
if ( matrix )
FT_Outline_Transform( &slot->outline, matrix );
if ( delta )
FT_Outline_Translate( &slot->outline, delta->x, delta->y );
Exit:
return error;
}
/* returns the control box of glyph's outline */
static void
ft_sdf_get_cbox( FT_Renderer render,
FT_GlyphSlot slot,
FT_BBox* cbox )
{
FT_ZERO( cbox );
if ( slot->format == render->glyph_format )
FT_Outline_Get_CBox( &slot->outline, cbox );
}
/* set render specific modes or attributes */
static FT_Error
ft_sdf_set_mode( FT_Renderer render,
FT_ULong mode_tag,
FT_Pointer data )
{
/* pass it to the rasterizer */
return render->clazz->raster_class->raster_set_mode( render->raster,
mode_tag,
data );
}
FT_DEFINE_RENDERER(
ft_sdf_renderer_class,
FT_MODULE_RENDERER,
sizeof( SDF_Renderer_Module ),
"sdf",
0x10000L,
0x20000L,
NULL,
(FT_Module_Constructor) ft_sdf_init,
(FT_Module_Destructor) ft_sdf_done,
(FT_Module_Requester) ft_sdf_requester,
FT_GLYPH_FORMAT_OUTLINE,
(FT_Renderer_RenderFunc) ft_sdf_render, /* render_glyph */
(FT_Renderer_TransformFunc) ft_sdf_transform, /* transform_glyph */
(FT_Renderer_GetCBoxFunc) ft_sdf_get_cbox, /* get_glyph_cbox */
(FT_Renderer_SetModeFunc) ft_sdf_set_mode, /* set_mode */
(FT_Raster_Funcs*)&ft_sdf_raster /* raster_class */
)
/*************************************************************************/
/*************************************************************************/
/** **/
/** BITMAP TO SDF CONVERTER **/
/** **/
/*************************************************************************/
/*************************************************************************/
/* generate signed distance field from glyph's bitmap */
static FT_Error
ft_bsdf_render( FT_Renderer module,
FT_GlyphSlot slot,
FT_Render_Mode mode,
const FT_Vector* origin )
{
FT_Error error = FT_Err_Ok;
FT_Bitmap* bitmap = &slot->bitmap;
FT_Memory memory = NULL;
FT_Renderer render = NULL;
FT_Bitmap target;
FT_Pos x_pad = 0;
FT_Pos y_pad = 0;
SDF_Raster_Params params;
SDF_Renderer sdf_module = SDF_RENDERER( module );
/* initialize the bitmap in case any error occurs */
FT_Bitmap_Init( &target );
render = &sdf_module->root;
memory = render->root.memory;
/* check if slot format is correct before rendering */
if ( slot->format != render->glyph_format )
{
FT_ERROR(( "[bsdf] ft_bsdf_render: "
"bsdf renderer require the slot "
"format to be a bitmap\n" ));
error = FT_THROW( Invalid_Glyph_Format );
goto Exit;
}
/* check if render mode is correct */
if ( mode != FT_RENDER_MODE_SDF )
{
FT_ERROR(( "[bsdf] ft_bsdf_render: "
"sdf module only render when "
"using `FT_RENDER_MODE_SDF'\n" ));
error = FT_THROW( Cannot_Render_Glyph );
goto Exit;
}
if ( origin )
{
FT_ERROR(( "[bsdf] ft_bsdf_render: "
"bsdf renderer can't translate "
"the bitmap\n" ));
error = FT_THROW( Unimplemented_Feature );
goto Exit;
}
if ( !bitmap->rows || !bitmap->pitch )
goto Exit;
FT_Bitmap_New( &target );
/* the padding will simply be equal to the `spread' */
x_pad = sdf_module->spread;
y_pad = sdf_module->spread;
/* apply the padding, will be in all the directions */
target.rows = bitmap->rows + y_pad * 2;
target.width = bitmap->width + x_pad * 2;
/* setup the target bitmap */
target.pixel_mode = FT_PIXEL_MODE_GRAY16;
target.pitch = target.width * 2;
target.num_grays = 65535;
if ( FT_ALLOC_MULT( target.buffer, target.rows, target.pitch ) )
goto Exit;
/* set up parameters */
params.root.target = &target;
params.root.source = bitmap;
params.root.flags = FT_RASTER_FLAG_SDF;
params.spread = sdf_module->spread;
params.flip_sign = sdf_module->flip_sign;
params.flip_y = sdf_module->flip_y;
error = render->raster_render( render->raster,
(const FT_Raster_Params*)&params );
Exit:
if ( !error )
{
/* the glyph is successfully converted to a SDF */
if ( slot->internal->flags & FT_GLYPH_OWN_BITMAP )
{
FT_FREE( bitmap->buffer );
slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
}
slot->bitmap = target;
slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
}
else if ( target.buffer )
{
FT_FREE( target.buffer );
}
return error;
}
FT_DEFINE_RENDERER(
ft_bitmap_sdf_renderer_class,
FT_MODULE_RENDERER,
sizeof( SDF_Renderer_Module ),
"bsdf",
0x10000L,
0x20000L,
NULL,
(FT_Module_Constructor) ft_sdf_init,
(FT_Module_Destructor) ft_sdf_done,
(FT_Module_Requester) ft_sdf_requester,
FT_GLYPH_FORMAT_BITMAP,
(FT_Renderer_RenderFunc) ft_bsdf_render, /* render_glyph */
(FT_Renderer_TransformFunc) ft_sdf_transform, /* transform_glyph */
(FT_Renderer_GetCBoxFunc) ft_sdf_get_cbox, /* get_glyph_cbox */
(FT_Renderer_SetModeFunc) ft_sdf_set_mode, /* set_mode */
(FT_Raster_Funcs*)&ft_bitmap_sdf_raster /* raster_class */
)
/* END */

98
src/sdf/ftsdfrend.h Normal file
View File

@ -0,0 +1,98 @@
#ifndef FTSDFREND_H_
#define FTSDFREND_H_
#include <freetype/ftrender.h>
#include <freetype/ftmodapi.h>
#include <freetype/internal/ftobjs.h>
FT_BEGIN_HEADER
/**************************************************************************
*
* @struct:
* SDF_Renderer_Module
*
* @description:
* This struct extends the native renderer struct `FT_RendererRec'.
* It is basically used to store various parameters required by the
* renderer and some additional parameters which can be used to
* tweak the output of the renderer.
*
* @fields:
* root ::
* The native rendere struct.
*
* spread ::
* This is an essential parameter/property required by the
* rendere. `spread' defines the maximum unsigned value that
* will be present in the final SDF output. For default value
* check `ftsdfcommon.h'.
*
* flip_sign ::
* By default the position values are inside the contours i.e.
* filled by a contour. If this property is true then that output
* will be opposite from the default i.e. negative will be filled
* by a contour.
*
* flip_y ::
* Setting this parameter to true makes the output image flipped
* along the y-axis.
*
* overlaps ::
* Set this to true to generate SDF for glyphs having overlapping
* contours. The overlapping support is limited to glyph which do
* not have self intersecting contours. Also, removing overlaps
* require a considerable amount of extra memory and this is not
* valid while generating SDF from bitmap.
*
* @note:
* All properties except `overlaps' is valid for both `sdf' and
* `bsdf' renderer.
*
*/
typedef struct SDF_Renderer_Module_
{
FT_RendererRec root;
FT_UInt spread;
FT_Bool flip_sign;
FT_Bool flip_y;
FT_Bool overlaps;
} SDF_Renderer_Module, *SDF_Renderer;
/**************************************************************************
*
* @renderer:
* ft_sdf_renderer_class
*
* @description:
* Renderer to convert `FT_Outline' to signed distance fields.
*
*/
FT_DECLARE_RENDERER( ft_sdf_renderer_class )
/**************************************************************************
*
* @renderer:
* ft_bitmap_sdf_renderer_class
*
* @description:
* This is not exactly a renderer, it's just a converter which
* convert bitmaps to signed distance fields.
*
* @note:
* This is not a separate module, it is a part of the `sdf' module.
*
*/
FT_DECLARE_RENDERER( ft_bitmap_sdf_renderer_class )
FT_END_HEADER
#endif /* FTSDFREND_H_ */
/* END */

16
src/sdf/module.mk Normal file
View File

@ -0,0 +1,16 @@
FTMODULE_H_COMMANDS += SDF_RENDERER
FTMODULE_H_COMMANDS += BSDF_RENDERER
define SDF_RENDERER
$(OPEN_DRIVER) FT_Renderer_Class, ft_sdf_renderer_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)sdf $(ECHO_DRIVER_DESC)signed distance field renderer$(ECHO_DRIVER_DONE)
endef
define BSDF_RENDERER
$(OPEN_DRIVER) FT_Renderer_Class, ft_bitmap_sdf_renderer_class $(CLOSE_DRIVER)
$(ECHO_DRIVER)bsdf $(ECHO_DRIVER_DESC)bitmap to signed distance field converter$(ECHO_DRIVER_DONE)
endef
#EOF

63
src/sdf/rules.mk Normal file
View File

@ -0,0 +1,63 @@
# sdf driver directory
#
SDF_DIR := $(SRC_DIR)/sdf
# compilation flags for the driver
#
SDF_COMPILE := $(CC) $(ANSIFLAGS) \
$I$(subst /,$(COMPILER_SEP),$(SDF_DIR)) \
$(INCLUDE_FLAGS) \
$(FT_CFLAGS)
# sdf driver sources (i.e., C files)
#
SDF_DRV_SRC := $(SDF_DIR)/ftsdfrend.c \
$(SDF_DIR)/ftsdf.c \
$(SDF_DIR)/ftbsdf.c
# sdf driver headers
#
SDF_DRV_H := $(SDF_DIR)/ftsdfrend.h \
$(SDF_DIR)/ftsdf.h \
$(SDF_DIR)/ftsdferrs.h \
$(SDF_DIR)/ftsdfcommon.h
# sdf driver object(s)
#
# SDF_DRV_OBJ_M is used during `multi' builds.
# SDF_DRV_OBJ_S is used during `single' builds.
#
SDF_DRV_OBJ_M := $(SDF_DRV_SRC:$(SDF_DIR)/%.c=$(OBJ_DIR)/%.$O)
SDF_DRV_OBJ_S := $(OBJ_DIR)/sdf.$O
# sdf driver source file for single build
#
SDF_DRV_SRC_S := $(SDF_DIR)/sdf.c
# sdf driver - single object
#
$(SDF_DRV_OBJ_S): $(SDF_DRV_SRC_S) $(SDF_DRV_SRC) \
$(FREETYPE_H) $(SDF_DRV_H)
$(SDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $(SDF_DRV_SRC_S))
# sdf driver - multiple objects
#
$(OBJ_DIR)/%.$O: $(SDF_DIR)/%.c $(FREETYPE_H) $(SDF_DRV_H)
$(SDF_COMPILE) $T$(subst /,$(COMPILER_SEP),$@ $<)
# update main driver list
#
DRV_OBJS_S += $(SDF_DRV_OBJ_S)
DRV_OBJS_M += $(SDF_DRV_OBJ_M)
# EOF

8
src/sdf/sdf.c Normal file
View File

@ -0,0 +1,8 @@
#define FT_MAKE_OPTION_SINGLE_OBJECT
#include "ftsdfrend.c"
#include "ftbsdf.c"
#include "ftsdf.c"
/* END */