ftbsdf.c |
A brief technical overview of how the BSDF rasterizer works
-----------------------------------------------------------
[Notes]:
* SDF stands for Signed Distance Field everywhere.
* BSDF stands for Bitmap to Signed Distance Field rasterizer.
* This renderer converts rasterized bitmaps to SDF. There is another
renderer called 'sdf', which generates SDF directly from outlines;
see file `ftsdf.c` for more.
* The idea of generating SDF from bitmaps is taken from two research
papers, where one is dependent on the other:
- Per-Erik Danielsson: Euclidean Distance Mapping
http://webstaff.itn.liu.se/~stegu/JFA/Danielsson.pdf
From this paper we use the eight-point sequential Euclidean
distance mapping (8SED). This is the heart of the process used
in this rasterizer.
- Stefan Gustavson, Robin Strand: Anti-aliased Euclidean distance transform.
http://weber.itn.liu.se/~stegu/aadist/edtaa_preprint.pdf
The original 8SED algorithm discards the pixels' alpha values,
which can contain information about the actual outline of the
glyph. This paper takes advantage of those alpha values and
approximates outline pretty accurately.
* This rasterizer also works for monochrome bitmaps. However, the
result is not as accurate since we don't have any way to
approximate outlines from binary bitmaps.
========================================================================
Generating SDF from bitmap is done in several steps.
(1) The only information we have is the bitmap itself. It can
be monochrome or anti-aliased. If it is anti-aliased, pixel values
are nothing but coverage values. These coverage values can be used
to extract information about the outline of the image. For
example, if the pixel's alpha value is 0.5, then we can safely
assume that the outline passes through the center of the pixel.
(2) Find edge pixels in the bitmap (see `bsdf_is_edge` for more). For
all edge pixels we use the Anti-aliased Euclidean distance
transform algorithm and compute approximate edge distances (see
`compute_edge_distance` and/or the second paper for more).
(3) Now that we have computed approximate distances for edge pixels we
use the 8SED algorithm to basically sweep the entire bitmap and
compute distances for the rest of the pixels. (Since the algorithm
is pretty convoluted it is only explained briefly in a comment to
function `edt8`. To see the actual algorithm refer to the first
paper.)
(4) Finally, compute the sign for each pixel. This is done in function
`finalize_sdf`. The basic idea is that if a pixel's original
alpha/coverage value is greater than 0.5 then it is 'inside' (and
'outside' otherwise).
Pseudo Code:
```
b = source bitmap;
t = target bitmap;
dm = list of distances; // dimension equal to b
foreach grid_point (x, y) in b:
{
if (is_edge(x, y)):
dm = approximate_edge_distance(b, x, y);
// do the 8SED on the distances
edt8(dm);
// determine the signs
determine_signs(dm):
// copy SDF data to the target bitmap
copy(dm to t);
}
|
38453 |
ftsdf.c |
A brief technical overview of how the SDF rasterizer works
----------------------------------------------------------
[Notes]:
* SDF stands for Signed Distance Field everywhere.
* This renderer generates SDF directly from outlines. There is
another renderer called 'bsdf', which converts bitmaps to SDF; see
file `ftbsdf.c` for more.
* The basic idea of generating the SDF is taken from Viktor Chlumsky's
research paper. The paper explains both single and multi-channel
SDF, however, this implementation only generates single-channel SDF.
Chlumsky, Viktor: Shape Decomposition for Multi-channel Distance
Fields. Master's thesis. Czech Technical University in Prague,
Faculty of InformationTechnology, 2015.
For more information: https://github.com/Chlumsky/msdfgen
========================================================================
Generating SDF from outlines is pretty straightforward.
(1) We have a set of contours that make the outline of a shape/glyph.
Each contour comprises of several edges, with three types of edges.
* line segments
* conic Bezier curves
* cubic Bezier curves
(2) Apart from the outlines we also have a two-dimensional grid, namely
the bitmap that is used to represent the final SDF data.
(3) In order to generate SDF, our task is to find shortest signed
distance from each grid point to the outline. The 'signed
distance' means that if the grid point is filled by any contour
then its sign is positive, otherwise it is negative. The pseudo
code is as follows.
```
foreach grid_point (x, y):
{
int min_dist = INT_MAX;
foreach contour in outline:
{
foreach edge in contour:
{
// get shortest distance from point (x, y) to the edge
d = get_min_dist(x, y, edge);
if (d < min_dist)
min_dist = d;
}
bitmap[x, y] = min_dist;
}
}
```
(4) After running this algorithm the bitmap contains information about
the shortest distance from each point to the outline of the shape.
Of course, while this is the most straightforward way of generating
SDF, we use various optimizations in our implementation. See the
`sdf_generate_*' functions in this file for all details.
The optimization currently used by default is subdivision; see
function `sdf_generate_subdivision` for more.
Also, to see how we compute the shortest distance from a point to
each type of edge, check out the `get_min_distance_*' functions.
|
112098 |
ftsdf.h |
common properties and function |
2914 |
ftsdfcommon.c |
format and sign manipulating functions
|
3485 |
ftsdfcommon.h |
This file contains common functions and properties
for both the 'sdf' and 'bsdf' renderers.
|
4021 |
ftsdferrs.h |
FTSDFERRS_H_ |
848 |
ftsdfrend.c |
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.
|
16209 |
ftsdfrend.h |
@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 that 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 renderer.
`spread` defines the maximum unsigned value that is present in the
final SDF output. For the default value check file
`ftsdfcommon.h`.
flip_sign ::
By default positive values indicate positions inside of contours,
i.e., filled by a contour. If this property is true then that
output will be the opposite of the default, i.e., negative values
indicate positions inside of contours.
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 glyphs that do not
have self-intersecting contours. Also, removing overlaps require a
considerable amount of extra memory; additionally, it will not work
if generating SDF from bitmap.
@note:
All properties except `overlaps` are valid for both the 'sdf' and
'bsdf' renderers.
|
3386 |
module.mk |
|
924 |
rules.mk |
|
1901 |
sdf.c |
END |
735 |