From c42964a9ec32899047c894582c4ddd184eb60da4 Mon Sep 17 00:00:00 2001 From: Chlumsky Date: Sat, 17 Oct 2020 23:26:42 +0200 Subject: [PATCH] Updated to msdfgen 1.8, Skia geometry preprocessing, added -threads argument --- README.md | 6 ++- artery-font-format | 2 +- msdf-atlas-gen.aps | Bin 0 -> 35252 bytes msdf-atlas-gen.rc | Bin 3250 -> 5274 bytes msdf-atlas-gen.vcxproj | 44 ++++++++++------ msdf-atlas-gen/AtlasGenerator.h | 4 +- msdf-atlas-gen/GlyphGeometry.cpp | 40 +++++++-------- msdf-atlas-gen/GlyphGeometry.h | 8 +-- msdf-atlas-gen/Workload.cpp | 3 +- msdf-atlas-gen/glyph-generators.cpp | 33 ++++-------- msdf-atlas-gen/main.cpp | 77 ++++++++++++++++++++++++---- msdf-atlas-gen/msdf-atlas-gen.h | 4 +- msdfgen | 2 +- 13 files changed, 136 insertions(+), 87 deletions(-) create mode 100644 msdf-atlas-gen.aps diff --git a/README.md b/README.md index 3d2f5f5..496ae34 100644 --- a/README.md +++ b/README.md @@ -100,9 +100,11 @@ Any subset of the following may be specified: - `-angle ` – sets the minimum angle between adjacent edges to be considered a corner. Append D for degrees (`msdf` / `mtsdf` only) - `-errorcorrection ` – sets the threshold used to detect and correct potential artifacts. 0 disables error correction (`msdf` / `mtsdf` only) - `-miterlimit ` – sets the miter limit that limits the extension of each glyph's bounding box due to very sharp corners (`psdf` / `msdf` / `mtsdf` only) -- `-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 +- `-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 - `-seed ` – sets the initial seed for the edge coloring heuristic +- `-threads ` – sets the number of threads for the parallel computation (0 = auto) ## Character set specification syntax diff --git a/artery-font-format b/artery-font-format index 185eb7a..00ac3d8 160000 --- a/artery-font-format +++ b/artery-font-format @@ -1 +1 @@ -Subproject commit 185eb7a3ab3913fa09173739de152935d3e4399e +Subproject commit 00ac3d8f964ec00a836c2bb5aeb126235ac98234 diff --git a/msdf-atlas-gen.aps b/msdf-atlas-gen.aps new file mode 100644 index 0000000000000000000000000000000000000000..2e23cf822981600cdc849c394a5addb9366e68bd GIT binary patch literal 35252 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 L;lhc9yefAUSLRl7dhQG!otw)& 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 Zsy621eNkMGeE07Q^!KM!zWe_E{{hTu9OM81 literal 0 HcmV?d00001 diff --git a/msdf-atlas-gen.rc b/msdf-atlas-gen.rc index dde4932826ef0f39b4c7fdd8e3ea67b838b75b6f..dba59c3f798b38593a8111345dc7584b4cd5ec9a 100644 GIT binary patch literal 5274 zcmd6rTW=ay5Xa}aQoq9%zcgy%OOls7+CV5O7|USPR+g;9x1e$pmo}~P)zkL(KZjv= zVWBnh16nO-_net?X8vrkeXu@nW&43Eu}8bN zA@_v&8RH#u6GrjPdAj8};Z3{sYz)nzeQV!v%25~(m>sg(hx#time%+W?UR)PwKxv~ z-9zBh-luk9ZR^;TRjh6;yRl2FGF##K+#2=^Gi`pGcE(JDXFp#u?BC_m`IuM@TvjoD z0Hu))(0>Lx!l8rKKl58h>oR%@k1F%8xmPXn-!}Lo;2Zh!`0pQLE>ZN3IatY)9?*L? z-*Du8-~Ae0I>q2$=y{9%6Z<~*cFFvhi26ueDUx3l_`oz1QN4iHce%*AW6x82k59#j zY7;$I#8w%vy1};^T-x^wSF(|_!ycD-@C|&5!WZGx2D9hPUNP2!m->w8er2X?KiW(7 zZ9{X$Ns(UXR*~tH*#^EYETYw=!Dg!~Cc4P~6Wo=+v0paLO5^tRaZ_abx<=h6ptUIn zX#EV`Yau)6Em>T}+4kCw7a6w-auG3cDVOYWMp2e8*?NvC*)_T9nh1{hK9zElL~nMK z=&9!%5K+o2F;b#jvRYA&S@$+!r#oxs{d#ukd`$3^TPn}fx&&45$%1wUXA%%rhoP#IKsgQ^%3ta&dO?~bXU6ROdl1Dt+wa=xFDKv%aIk~$9ruh}07k2_h zo!nksp-HgD%Wxkv9tW>X==?6(uR=8_lb7;FpcC zyK+`qQ)1;gUz82Nzv+1 zTQ5K@FGIQ>>u8?JPcE(us=6(36*46xm|<^4*drF|q1iol8iLShC07^k=5dhUHEQ!N zX!McaeAZ8SiYk|{`q;&e>UxDi3AxoBkBRpok$%oNK;ly9DN1-s&wfLr5jv@l`h-4n zD5lJQ-5^ErIgUkz-LqdgF)sYPCiqprP1Rz?Ss$SFzCPxw0jEn=Wk&UE>h}|5Qr^@1 z3@wV$*)CT;PF44|{GbE;x4tx^t@A zYz_G)^L^%fV6X21d6GORRytv(H~E%27*$14#BX!eVNq%|wcF~Ky&~l)w#&=An-`|N zr~BjjOg^7<(O|N)$u9XRpG7+CCZwj|llCAnic~G$g?w@nyv%D-lr@z!eNtB6+($mg z*PPeu{Trow_Kwwc+n4%!7rlR4xkS=T&pvu?&;Kv>|NpbmSIzeSY#d9MVE;x*xY^r> QWHWW;>;KTK+g&^T3tqo}&Hw-a delta 16 XcmbQGxk++E73X9rcB#!Zf^y6NF_{GM diff --git a/msdf-atlas-gen.vcxproj b/msdf-atlas-gen.vcxproj index 92cfd35..bb7c6a5 100644 --- a/msdf-atlas-gen.vcxproj +++ b/msdf-atlas-gen.vcxproj @@ -161,12 +161,12 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreadedDebug - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) Console - freetype.lib;msdfgen.lib;%(AdditionalDependencies) - msdfgen\freetype\win32;msdfgen\$(Configuration) Library;%(AdditionalLibraryDirectories) + freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies) + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\$(Configuration) Library;%(AdditionalLibraryDirectories) @@ -176,7 +176,7 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreadedDebug - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions) Console @@ -185,6 +185,7 @@ MachineX86 + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\debug;msdfgen\$(Configuration);%(AdditionalLibraryDirectories) @@ -194,12 +195,12 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreadedDebug - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) Console - freetype.lib;msdfgen.lib;%(AdditionalDependencies) - msdfgen\freetype\win64;msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories) + freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies) + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories) @@ -209,13 +210,16 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreadedDebug - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions) Console freetype.lib;msdfgen.lib;%(AdditionalDependencies) ..\msdfgen\freetype\win64;$(SolutionDir)$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories) + + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\debug;msdfgen\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + @@ -226,14 +230,16 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreaded - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) + None true true Console - freetype.lib;msdfgen.lib;%(AdditionalDependencies) - msdfgen\freetype\win32;msdfgen\bin;%(AdditionalLibraryDirectories) + freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies) + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\bin;%(AdditionalLibraryDirectories) + false @@ -245,7 +251,7 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreaded - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions) true @@ -256,6 +262,7 @@ MachineX86 + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\release;msdfgen\$(Configuration);%(AdditionalLibraryDirectories) @@ -267,14 +274,16 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreaded - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;MSDF_ATLAS_STANDALONE;%(PreprocessorDefinitions) + None true true Console - freetype.lib;msdfgen.lib;%(AdditionalDependencies) - msdfgen\freetype\win64;msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories) + freetype.lib;skia.lib;msdfgen.lib;%(AdditionalDependencies) + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\$(Configuration);msdfgen\$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories) + false @@ -286,7 +295,7 @@ true msdfgen\include;msdfgen\freetype\include;msdfgen;artery-font-format;%(AdditionalIncludeDirectories) MultiThreaded - _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;MSDFGEN_USE_CPP11;MSDFGEN_USE_SKIA;%(PreprocessorDefinitions) true @@ -295,6 +304,9 @@ freetype.lib;msdfgen.lib;%(AdditionalDependencies) ..\msdfgen\freetype\win64;$(SolutionDir)$(Platform)\$(Configuration) Library;%(AdditionalLibraryDirectories) + + msdfgen\freetype\win$(PlatformArchitecture);msdfgen\skia\win$(PlatformArchitecture)\release;msdfgen\$(Platform)\$(Configuration);%(AdditionalLibraryDirectories) + diff --git a/msdf-atlas-gen/AtlasGenerator.h b/msdf-atlas-gen/AtlasGenerator.h index 71e5513..8a587c8 100644 --- a/msdf-atlas-gen/AtlasGenerator.h +++ b/msdf-atlas-gen/AtlasGenerator.h @@ -31,8 +31,8 @@ class AtlasGenerator { /// 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; }; diff --git a/msdf-atlas-gen/GlyphGeometry.cpp b/msdf-atlas-gen/GlyphGeometry.cpp index e6a8a67..39a70f2 100644 --- a/msdf-atlas-gen/GlyphGeometry.cpp +++ b/msdf-atlas-gen/GlyphGeometry.cpp @@ -2,30 +2,32 @@ #include "GlyphGeometry.h" #include +#include 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; diff --git a/msdf-atlas-gen/GlyphGeometry.h b/msdf-atlas-gen/GlyphGeometry.h index a0f3dda..eea6dd5 100644 --- a/msdf-atlas-gen/GlyphGeometry.h +++ b/msdf-atlas-gen/GlyphGeometry.h @@ -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 @@ class GlyphGeometry { 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 @@ class GlyphGeometry { unicode_t codepoint; msdfgen::Shape shape; msdfgen::Shape::Bounds bounds; - bool reverseWinding; double advance; struct { struct { @@ -63,9 +60,6 @@ class GlyphGeometry { msdfgen::Vector2 translate; } box; - /// Computes the signed distance from point p in a naive way - double simpleSignedDistance(const msdfgen::Point2 &p) const; - }; } diff --git a/msdf-atlas-gen/Workload.cpp b/msdf-atlas-gen/Workload.cpp index e9cd5d4..6050bd0 100644 --- a/msdf-atlas-gen/Workload.cpp +++ b/msdf-atlas-gen/Workload.cpp @@ -4,6 +4,7 @@ #include #include #include +#include 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; } diff --git a/msdf-atlas-gen/glyph-generators.cpp b/msdf-atlas-gen/glyph-generators.cpp index 430c0bc..a4ea4f7 100644 --- a/msdf-atlas-gen/glyph-generators.cpp +++ b/msdf-atlas-gen/glyph-generators.cpp @@ -3,51 +3,38 @@ namespace msdf_atlas { -template -static void invertColor(const msdfgen::BitmapRef &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 &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 &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 &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 &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 &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())); + } } } diff --git a/msdf-atlas-gen/main.cpp b/msdf-atlas-gen/main.cpp index 1cc4731..65c0ae9 100644 --- a/msdf-atlas-gen/main.cpp +++ b/msdf-atlas-gen/main.cpp @@ -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 @@ -76,13 +84,27 @@ DISTANCE FIELD GENERATOR SETTINGS -errorcorrection Changes the threshold used to detect and correct potential artifacts. 0 disables error correction. (msdf / mtsdf only) -miterlimit - 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 Sets the initial seed for the edge coloring heuristic. + -threads + 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 &glyphs, msdfgen::FontHandle *font, const Charset &charset) { +static void loadGlyphs(std::vector &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 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 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 diff --git a/msdf-atlas-gen/msdf-atlas-gen.h b/msdf-atlas-gen/msdf-atlas-gen.h index 6c9ebb5..244c9b9 100644 --- a/msdf-atlas-gen/msdf-atlas-gen.h +++ b/msdf-atlas-gen/msdf-atlas-gen.h @@ -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" diff --git a/msdfgen b/msdfgen index 5b5272e..9d22335 160000 --- a/msdfgen +++ b/msdfgen @@ -1 +1 @@ -Subproject commit 5b5272e7a8bd71a6c7f55951659df69a355486c8 +Subproject commit 9d22335ea093422d7bf212d31bfaa6adcb9b89f0