Updated to msdfgen 1.8, Skia geometry preprocessing, added -threads argument

This commit is contained in:
Chlumsky 2020-10-17 23:26:42 +02:00
parent 78142f6131
commit c42964a9ec
13 changed files with 136 additions and 87 deletions

View File

@ -100,9 +100,11 @@ Any subset of the following may be specified:
- `-angle <angle>` &ndash; sets the minimum angle between adjacent edges to be considered a corner. Append D for degrees (`msdf` / `mtsdf` only)
- `-errorcorrection <threshold>` &ndash; sets the threshold used to detect and correct potential artifacts. 0 disables error correction (`msdf` / `mtsdf` only)
- `-miterlimit <value>` &ndash; sets the miter limit that limits the extension of each glyph's bounding box due to very sharp corners (`psdf` / `msdf` / `mtsdf` only)
- `-nooverlap` &ndash; disables resolution of overlapping contours
- `-noscanline` &ndash; disables the scanline pass, which corrects the distance field's signs according to the non-zero fill rule
- `-overlap` &ndash; switches to distance field generator with support for overlapping contours
- `-nopreprocess` &ndash; disables path preprocessing which resolves self-intersections and overlapping contours
- `-scanline` &ndash; performs an additional scanline pass to fix the signs of the distances
- `-seed <N>` &ndash; sets the initial seed for the edge coloring heuristic
- `-threads <N>` &ndash; sets the number of threads for the parallel computation (0 = auto)
## Character set specification syntax

@ -1 +1 @@
Subproject commit 185eb7a3ab3913fa09173739de152935d3e4399e
Subproject commit 00ac3d8f964ec00a836c2bb5aeb126235ac98234

BIN
msdf-atlas-gen.aps Normal file

Binary file not shown.

Binary file not shown.

View File

@ -161,12 +161,12 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>freetype.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win32;msdfgen\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Library|Win32'">
@ -176,7 +176,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@ -185,6 +185,7 @@
</Link>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\debug;msdfgen\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -194,12 +195,12 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>freetype.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win64;msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug Library|x64'">
@ -209,13 +210,16 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>freetype.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\msdfgen\freetype\win64;$(SolutionDir)$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Lib>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\debug;msdfgen\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@ -226,14 +230,16 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DebugInformationFormat>None</DebugInformationFormat>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>freetype.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win32;msdfgen\bin;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\bin;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Library|Win32'">
@ -245,7 +251,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -256,6 +262,7 @@
</Link>
<Lib>
<TargetMachine>MachineX86</TargetMachine>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\release;msdfgen\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -267,14 +274,16 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DebugInformationFormat>None</DebugInformationFormat>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>freetype.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win64;msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>false</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release Library|x64'">
@ -286,7 +295,7 @@
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
@ -295,6 +304,9 @@
<AdditionalDependencies>freetype.lib;msdfgen.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\msdfgen\freetype\win64;$(SolutionDir)$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
<Lib>
<AdditionalLibraryDirectories>msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\release;msdfgen\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Lib>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="msdf-atlas-gen\artery-font-export.cpp" />

View File

@ -31,8 +31,8 @@ public:
/// Configuration of signed distance field generator
struct GeneratorAttributes {
bool overlapSupport = true;
bool scanlinePass = true;
bool overlapSupport = false;
bool scanlinePass = false;
double errorCorrectionThreshold = MSDFGEN_DEFAULT_ERROR_CORRECTION_THRESHOLD;
};

View File

@ -2,30 +2,32 @@
#include "GlyphGeometry.h"
#include <cmath>
#include <core/ShapeDistanceFinder.h>
namespace msdf_atlas {
GlyphGeometry::GlyphGeometry() : codepoint(), bounds(), reverseWinding(), advance(), box() { }
GlyphGeometry::GlyphGeometry() : codepoint(), bounds(), advance(), box() { }
double GlyphGeometry::simpleSignedDistance(const msdfgen::Point2 &p) const {
double dummy;
msdfgen::SignedDistance minDistance;
for (const msdfgen::Contour &contour : shape.contours)
for (const msdfgen::EdgeHolder &edge : contour.edges) {
msdfgen::SignedDistance distance = edge->signedDistance(p, dummy);
if (distance < minDistance)
minDistance = distance;
}
return minDistance.distance;
}
bool GlyphGeometry::load(msdfgen::FontHandle *font, unicode_t codepoint) {
bool GlyphGeometry::load(msdfgen::FontHandle *font, unicode_t codepoint, bool preprocessGeometry) {
if (font && msdfgen::loadGlyph(shape, font, codepoint, &advance) && shape.validate()) {
this->codepoint = codepoint;
#ifdef MSDFGEN_USE_SKIA
if (preprocessGeometry)
msdfgen::resolveShapeGeometry(shape);
#endif
shape.normalize();
bounds = shape.getBounds();
msdfgen::Point2 outerPoint(bounds.l-(bounds.r-bounds.l)-1, bounds.b-(bounds.t-bounds.b)-1);
reverseWinding = simpleSignedDistance(outerPoint) > 0;
#ifdef MSDFGEN_USE_SKIA
if (!preprocessGeometry)
#endif
{
// Determine if shape is winded incorrectly and reverse it in that case
msdfgen::Point2 outerPoint(bounds.l-(bounds.r-bounds.l)-1, bounds.b-(bounds.t-bounds.b)-1);
if (msdfgen::SimpleTrueShapeDistanceFinder::oneShotDistance(shape, outerPoint) > 0) {
for (msdfgen::Contour &contour : shape.contours)
contour.reverse();
}
}
return true;
}
return false;
@ -43,7 +45,7 @@ void GlyphGeometry::wrapBox(double scale, double range, double miterLimit) {
l -= .5*range, b -= .5*range;
r += .5*range, t += .5*range;
if (miterLimit > 0)
shape.boundMiters(l, b, r, t, .5*range, miterLimit, reverseWinding ? -1 : +1);
shape.boundMiters(l, b, r, t, .5*range, miterLimit, 1);
double w = scale*(r-l);
double h = scale*(t-b);
box.rect.w = (int) ceil(w)+1;
@ -72,10 +74,6 @@ double GlyphGeometry::getAdvance() const {
return advance;
}
bool GlyphGeometry::isWindingReverse() const {
return reverseWinding;
}
void GlyphGeometry::getBoxRect(int &x, int &y, int &w, int &h) const {
x = box.rect.x, y = box.rect.y;
w = box.rect.w, h = box.rect.h;

View File

@ -14,7 +14,7 @@ class GlyphGeometry {
public:
GlyphGeometry();
/// Loads glyph geometry from font
bool load(msdfgen::FontHandle *font, unicode_t codepoint);
bool load(msdfgen::FontHandle *font, unicode_t codepoint, bool preprocessGeometry = true);
/// Applies edge coloring to glyph shape
void edgeColoring(double angleThreshold, unsigned long long seed);
/// Computes the dimensions of the glyph's box as well as the transformation for the generator function
@ -27,8 +27,6 @@ public:
const msdfgen::Shape & getShape() const;
/// Returns the glyph's advance
double getAdvance() const;
/// Returns true if the shape has reverse winding
bool isWindingReverse() const;
/// Outputs the position and dimensions of the glyph's box in the atlas
void getBoxRect(int &x, int &y, int &w, int &h) const;
/// Outputs the dimensions of the glyph's box in the atlas
@ -52,7 +50,6 @@ private:
unicode_t codepoint;
msdfgen::Shape shape;
msdfgen::Shape::Bounds bounds;
bool reverseWinding;
double advance;
struct {
struct {
@ -63,9 +60,6 @@ private:
msdfgen::Vector2 translate;
} box;
/// Computes the signed distance from point p in a naive way
double simpleSignedDistance(const msdfgen::Point2 &p) const;
};
}

View File

@ -4,6 +4,7 @@
#include <vector>
#include <thread>
#include <atomic>
#include <algorithm>
namespace msdf_atlas {
@ -42,7 +43,7 @@ bool Workload::finish(int threadCount) {
if (threadCount == 1 || chunks == 1)
return finishSequential();
if (threadCount > 1)
return finishParallel(threadCount);
return finishParallel(std::min(threadCount, chunks));
return false;
}

View File

@ -3,51 +3,38 @@
namespace msdf_atlas {
template <int N>
static void invertColor(const msdfgen::BitmapRef<float, N> &bitmap) {
const float *end = bitmap.pixels+N*bitmap.width*bitmap.height;
for (float *p = bitmap.pixels; p < end; ++p)
*p = 1.f-*p;
}
void scanlineGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::rasterize(output, glyph.getShape(), glyph.getBoxScale(), glyph.getBoxTranslate(), MSDF_ATLAS_GLYPH_FILL_RULE);
}
void sdfGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::generateSDF(output, glyph.getShape(), glyph.getBoxRange(), glyph.getBoxScale(), glyph.getBoxTranslate(), attribs.overlapSupport);
if (glyph.isWindingReverse())
invertColor(output);
if (attribs.scanlinePass)
msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxScale(), glyph.getBoxTranslate(), MSDF_ATLAS_GLYPH_FILL_RULE);
}
void psdfGenerator(const msdfgen::BitmapRef<float, 1> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::generatePseudoSDF(output, glyph.getShape(), glyph.getBoxRange(), glyph.getBoxScale(), glyph.getBoxTranslate(), attribs.overlapSupport);
if (glyph.isWindingReverse())
invertColor(output);
if (attribs.scanlinePass)
msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxScale(), glyph.getBoxTranslate(), MSDF_ATLAS_GLYPH_FILL_RULE);
}
void msdfGenerator(const msdfgen::BitmapRef<float, 3> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::generateMSDF(output, glyph.getShape(), glyph.getBoxRange(), glyph.getBoxScale(), glyph.getBoxTranslate(), 0, attribs.overlapSupport);
if (glyph.isWindingReverse())
invertColor(output);
if (attribs.scanlinePass)
msdfgen::generateMSDF(output, glyph.getShape(), glyph.getBoxRange(), glyph.getBoxScale(), glyph.getBoxTranslate(), attribs.errorCorrectionThreshold, attribs.overlapSupport);
if (attribs.scanlinePass) {
msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxScale(), glyph.getBoxTranslate(), MSDF_ATLAS_GLYPH_FILL_RULE);
if (attribs.errorCorrectionThreshold > 0)
msdfgen::msdfErrorCorrection(output, attribs.errorCorrectionThreshold/(glyph.getBoxScale()*glyph.getBoxRange()));
if (attribs.errorCorrectionThreshold > 0)
msdfgen::msdfErrorCorrection(output, attribs.errorCorrectionThreshold/(glyph.getBoxScale()*glyph.getBoxRange()));
}
}
void mtsdfGenerator(const msdfgen::BitmapRef<float, 4> &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) {
msdfgen::generateMTSDF(output, glyph.getShape(), glyph.getBoxRange(), glyph.getBoxScale(), glyph.getBoxTranslate(), 0, attribs.overlapSupport);
if (glyph.isWindingReverse())
invertColor(output);
if (attribs.scanlinePass)
msdfgen::generateMTSDF(output, glyph.getShape(), glyph.getBoxRange(), glyph.getBoxScale(), glyph.getBoxTranslate(), attribs.errorCorrectionThreshold, attribs.overlapSupport);
if (attribs.scanlinePass) {
msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxScale(), glyph.getBoxTranslate(), MSDF_ATLAS_GLYPH_FILL_RULE);
if (attribs.errorCorrectionThreshold > 0)
msdfgen::msdfErrorCorrection(output, attribs.errorCorrectionThreshold/(glyph.getBoxScale()*glyph.getBoxRange()));
if (attribs.errorCorrectionThreshold > 0)
msdfgen::msdfErrorCorrection(output, attribs.errorCorrectionThreshold/(glyph.getBoxScale()*glyph.getBoxRange()));
}
}
}

View File

@ -1,6 +1,6 @@
/*
* MULTI-CHANNEL SIGNED DISTANCE FIELD ATLAS GENERATOR v1.0 (2020-03-08) - standalone console program
* MULTI-CHANNEL SIGNED DISTANCE FIELD ATLAS GENERATOR v1.1 (2020-10-18) - standalone console program
* --------------------------------------------------------------------------------------------------
* A utility by Viktor Chlumsky, (c) 2020
*
@ -27,9 +27,17 @@ using namespace msdf_atlas;
#define GLYPH_FILL_RULE msdfgen::FILL_NONZERO
#define MCG_MULTIPLIER 6364136223846793005ull
#ifdef MSDFGEN_USE_SKIA
#define TITLE_SUFFIX " & Skia"
#define EXTRA_UNDERLINE "-------"
#else
#define TITLE_SUFFIX
#define EXTRA_UNDERLINE
#endif
static const char * const helpText = R"(
MSDF Atlas Generator by Viktor Chlumsky v)" MSDF_ATLAS_VERSION R"( (with MSDFGEN v)" MSDFGEN_VERSION R"()
----------------------------------------------------------------
MSDF Atlas Generator by Viktor Chlumsky v)" MSDF_ATLAS_VERSION R"( (with MSDFGEN v)" MSDFGEN_VERSION TITLE_SUFFIX R"()
----------------------------------------------------------------)" EXTRA_UNDERLINE R"(
INPUT SPECIFICATION
-font <filename.ttf/otf>
@ -76,13 +84,27 @@ DISTANCE FIELD GENERATOR SETTINGS
-errorcorrection <threshold>
Changes the threshold used to detect and correct potential artifacts. 0 disables error correction. (msdf / mtsdf only)
-miterlimit <value>
Sets the miter limit that limits the extension of each glyph's bounding box due to very sharp corners. (psdf / msdf / mtsdf only)
Sets the miter limit that limits the extension of each glyph's bounding box due to very sharp corners. (psdf / msdf / mtsdf only))"
#ifdef MSDFGEN_USE_SKIA
R"(
-overlap
Switches to distance field generator with support for overlapping contours.
-nopreprocess
Disables path preprocessing which resolves self-intersections and overlapping contours.
-scanline
Performs an additional scanline pass to fix the signs of the distances.)"
#else
R"(
-nooverlap
Disables resolution of overlapping contours.
-noscanline
Disables the scanline pass, which corrects the distance field's signs according to the non-zero fill rule.
Disables the scanline pass, which corrects the distance field's signs according to the non-zero fill rule.)"
#endif
R"(
-seed <N>
Sets the initial seed for the edge coloring heuristic.
-threads <N>
Sets the number of threads for the parallel computation. (0 = auto)
)";
static char toupper(char c) {
@ -123,12 +145,12 @@ static bool cmpExtension(const char *path, const char *ext) {
return true;
}
static void loadGlyphs(std::vector<GlyphGeometry> &glyphs, msdfgen::FontHandle *font, const Charset &charset) {
static void loadGlyphs(std::vector<GlyphGeometry> &glyphs, msdfgen::FontHandle *font, const Charset &charset, bool preprocessGeometry) {
glyphs.clear();
glyphs.reserve(charset.size());
for (unicode_t cp : charset) {
GlyphGeometry glyph;
if (glyph.load(font, cp))
if (glyph.load(font, cp, preprocessGeometry))
glyphs.push_back((GlyphGeometry &&) glyph);
else
printf("Glyph for codepoint 0x%X missing\n", cp);
@ -145,6 +167,7 @@ struct Configuration {
double miterLimit;
unsigned long long coloringSeed;
GeneratorAttributes generatorAttributes;
bool preprocessGeometry;
int threadCount;
const char *arteryFontFilename;
const char *imageFilename;
@ -196,8 +219,15 @@ int main(int argc, const char * const *argv) {
config.imageFormat = ImageFormat::UNSPECIFIED;
const char *imageFormatName = nullptr;
int fixedWidth = -1, fixedHeight = -1;
config.generatorAttributes.overlapSupport = true;
config.generatorAttributes.scanlinePass = true;
config.preprocessGeometry = (
#ifdef MSDFGEN_USE_SKIA
true
#else
false
#endif
);
config.generatorAttributes.overlapSupport = !config.preprocessGeometry;
config.generatorAttributes.scanlinePass = !config.preprocessGeometry;
config.generatorAttributes.errorCorrectionThreshold = MSDFGEN_DEFAULT_ERROR_CORRECTION_THRESHOLD;
double minEmSize = 0;
enum {
@ -210,7 +240,7 @@ int main(int argc, const char * const *argv) {
TightAtlasPacker::DimensionsConstraint atlasSizeConstraint = TightAtlasPacker::DimensionsConstraint::MULTIPLE_OF_FOUR_SQUARE;
config.angleThreshold = DEFAULT_ANGLE_THRESHOLD;
config.miterLimit = DEFAULT_MITER_LIMIT;
config.threadCount = std::max((int) std::thread::hardware_concurrency(), 1);
config.threadCount = 0;
// Parse command line
int argPos = 1;
@ -394,11 +424,26 @@ int main(int argc, const char * const *argv) {
++argPos;
continue;
}
ARG_CASE("-nopreprocess", 0) {
config.preprocessGeometry = false;
argPos += 1;
continue;
}
ARG_CASE("-preprocess", 0) {
config.preprocessGeometry = true;
argPos += 1;
continue;
}
ARG_CASE("-nooverlap", 0) {
config.generatorAttributes.overlapSupport = false;
argPos += 1;
continue;
}
ARG_CASE("-overlap", 0) {
config.generatorAttributes.overlapSupport = true;
argPos += 1;
continue;
}
ARG_CASE("-noscanline", 0) {
config.generatorAttributes.scanlinePass = false;
argPos += 1;
@ -415,6 +460,14 @@ int main(int argc, const char * const *argv) {
argPos += 2;
continue;
}
ARG_CASE("-threads", 1) {
unsigned tc;
if (!parseUnsigned(tc, argv[argPos+1]) || (int) tc < 0)
ABORT("Invalid thread count. Use -threads <N> with N being a non-negative integer.");
config.threadCount = (int) tc;
argPos += 2;
continue;
}
ARG_CASE("-help", 0) {
puts(helpText);
return 0;
@ -462,6 +515,8 @@ int main(int argc, const char * const *argv) {
rangeMode = RANGE_PIXEL;
rangeValue = DEFAULT_PIXEL_RANGE;
}
if (config.threadCount <= 0)
config.threadCount = std::max((int) std::thread::hardware_concurrency(), 1);
// Finalize image format
ImageFormat imageExtension = ImageFormat::UNSPECIFIED;
@ -547,7 +602,7 @@ int main(int argc, const char * const *argv) {
// Load glyphs
std::vector<GlyphGeometry> glyphs;
loadGlyphs(glyphs, font, charset);
loadGlyphs(glyphs, font, charset, config.preprocessGeometry);
printf("Loaded geometry of %d out of %d characters.\n", (int) glyphs.size(), (int) charset.size());
// Determine final atlas dimensions, scale and range, pack glyphs

View File

@ -2,7 +2,7 @@
#pragma once
/*
* MULTI-CHANNEL SIGNED DISTANCE FIELD ATLAS GENERATOR v1.0 (2020-03-08)
* MULTI-CHANNEL SIGNED DISTANCE FIELD ATLAS GENERATOR v1.1 (2020-10-18)
* ---------------------------------------------------------------------
* A utility by Viktor Chlumsky, (c) 2020
*
@ -38,4 +38,4 @@
#include "json-export.h"
#include "shadron-preview-generator.h"
#define MSDF_ATLAS_VERSION "1.0"
#define MSDF_ATLAS_VERSION "1.1"

@ -1 +1 @@
Subproject commit 5b5272e7a8bd71a6c7f55951659df69a355486c8
Subproject commit 9d22335ea093422d7bf212d31bfaa6adcb9b89f0