diff --git a/Nuake/src/Rendering/Textures/Texture.cpp b/Nuake/src/Rendering/Textures/Texture.cpp index ee6ea54d..df337820 100644 --- a/Nuake/src/Rendering/Textures/Texture.cpp +++ b/Nuake/src/Rendering/Textures/Texture.cpp @@ -95,22 +95,6 @@ namespace Nuake } } - Texture::Texture(Vector2 size, msdfgen::BitmapConstRef& bitmap, bool t) - { - m_RendererId = 0; - m_Width = size.x; - m_Height = size.y; - - glGenTextures(1, &m_RendererId); - glBindTexture(GL_TEXTURE_2D, m_RendererId); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - auto pixel = bitmap(0, bitmap.height - 0 - 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_Width, m_Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (unsigned char*)bitmap.pixels); - } - void Texture::Resize(glm::vec2 size) { diff --git a/Nuake/src/Rendering/Textures/Texture.h b/Nuake/src/Rendering/Textures/Texture.h index 150cab56..28557b01 100644 --- a/Nuake/src/Rendering/Textures/Texture.h +++ b/Nuake/src/Rendering/Textures/Texture.h @@ -4,7 +4,6 @@ #include "src/Resource/Serializable.h" #include "stb_image/stb_image.h" -#include "msdfgen/core/BitmapRef.hpp" #include @@ -31,7 +30,6 @@ namespace Nuake Texture(unsigned char* data, int len); // Used to load texture from a memory buffer Texture(Vector2 size, GLenum format, GLenum format2 = 0, GLenum format3 = 0, void* data = 0); // Used to load texture from memeory with known size - Texture(Vector2 size, msdfgen::BitmapConstRef& bitmap, bool t); // Used internally for MSDF fonts ~Texture(); void Resize(glm::vec2 size); diff --git a/Nuake/src/Scripting/ScriptingEngineNet.cpp b/Nuake/src/Scripting/ScriptingEngineNet.cpp index 868ae71d..8e8308fc 100644 --- a/Nuake/src/Scripting/ScriptingEngineNet.cpp +++ b/Nuake/src/Scripting/ScriptingEngineNet.cpp @@ -335,7 +335,7 @@ namespace Nuake int32_t handle; }; - exposedVar.Value = classInstance.GetFieldValue(varName).id; + //exposedVar.Value = classInstance.GetFieldValue(varName).id; break; } } @@ -371,7 +371,6 @@ namespace Nuake auto newEntity = m_BaseEntityType.CreateInstance(); newEntity.SetPropertyValue("ECSHandle", scriptEntity.GetHandle()); newEntity.SetPropertyValue("ID", scriptEntity.GetID()); - classInstance.SetFieldValue(exposedVarUserValue.Name, newEntity); } } diff --git a/Nuake/src/Vendors/msdf-atlas-gen/.gitignore b/Nuake/src/Vendors/msdf-atlas-gen/.gitignore deleted file mode 100644 index 28420b94..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/.gitignore +++ /dev/null @@ -1,20 +0,0 @@ -Debug/ -Release/ -Debug Library/ -Release Library/ -x86/ -x64/ -*.exe -*.user -*.sdf -*.pdb -*.ipdb -*.iobj -*.suo -*.VC.opendb -*.VC.db -bin/msdf-atlas-gen -bin/*.lib -output.png -out/ -build/ diff --git a/Nuake/src/Vendors/msdf-atlas-gen/.gitmodules b/Nuake/src/Vendors/msdf-atlas-gen/.gitmodules deleted file mode 100644 index 64238d0d..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/.gitmodules +++ /dev/null @@ -1,6 +0,0 @@ -[submodule "msdfgen"] - path = msdfgen - url = https://github.com/Chlumsky/msdfgen -[submodule "artery-font-format"] - path = artery-font-format - url = https://github.com/Chlumsky/artery-font-format diff --git a/Nuake/src/Vendors/msdf-atlas-gen/AtlasGenerator.h b/Nuake/src/Vendors/msdf-atlas-gen/AtlasGenerator.h deleted file mode 100644 index c15f78f3..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/AtlasGenerator.h +++ /dev/null @@ -1,42 +0,0 @@ - -#pragma once - -#include "msdfgen.h" -#include "Remap.h" -#include "GlyphGeometry.h" - -namespace msdf_atlas { - -namespace { - -/** Prototype of an atlas generator class. - * An atlas generator maintains the atlas bitmap (AtlasStorage) and its layout and facilitates - * generation of bitmap representation of glyphs. The layout of the atlas is given by the caller. - */ -class AtlasGenerator { - -public: - AtlasGenerator(); - AtlasGenerator(int width, int height); - /// Generates bitmap representation for the supplied array of glyphs - void generate(const GlyphGeometry *glyphs, int count); - /// Resizes the atlas and rearranges the generated pixels according to the remapping array - void rearrange(int width, int height, const Remap *remapping, int count); - /// Resizes the atlas and keeps the generated pixels in place - void resize(int width, int height); - -}; - -} - -/// Configuration of signed distance field generator -struct GeneratorAttributes { - msdfgen::MSDFGeneratorConfig config; - bool scanlinePass = false; -}; - -/// A function that generates the bitmap for a single glyph -template -using GeneratorFunction = void (*)(const msdfgen::BitmapRef &, const GlyphGeometry &, const GeneratorAttributes &); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/AtlasStorage.h b/Nuake/src/Vendors/msdf-atlas-gen/AtlasStorage.h deleted file mode 100644 index a51f46a4..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/AtlasStorage.h +++ /dev/null @@ -1,37 +0,0 @@ - -#pragma once - -#include -#include "Remap.h" - -namespace msdf_atlas { - -namespace { - -/** Prototype of an atlas storage class. - * An atlas storage physically holds the pixels of the atlas - * and allows to read and write subsections represented as bitmaps. - * Can be implemented using a simple bitmap (BitmapAtlasStorage), - * as texture memory, or any other way. - */ -class AtlasStorage { - -public: - AtlasStorage(); - AtlasStorage(int width, int height); - /// Creates a copy with different dimensions - AtlasStorage(const AtlasStorage &orig, int width, int height); - /// Creates a copy with different dimensions and rearranges the pixels according to the remapping array - AtlasStorage(const AtlasStorage &orig, int width, int height, const Remap *remapping, int count); - /// Stores a subsection at x, y into the atlas storage. May be implemented for only some T, N - template - void put(int x, int y, const msdfgen::BitmapConstRef &subBitmap); - /// Retrieves a subsection at x, y from the atlas storage. May be implemented for only some T, N - template - void get(int x, int y, const msdfgen::BitmapRef &subBitmap) const; - -}; - -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/BitmapAtlasStorage.h b/Nuake/src/Vendors/msdf-atlas-gen/BitmapAtlasStorage.h deleted file mode 100644 index f0f7c99b..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/BitmapAtlasStorage.h +++ /dev/null @@ -1,33 +0,0 @@ - -#pragma once - -#include "AtlasStorage.h" - -namespace msdf_atlas { - -/// An implementation of AtlasStorage represented by a bitmap in memory (msdfgen::Bitmap) -template -class BitmapAtlasStorage { - -public: - BitmapAtlasStorage(); - BitmapAtlasStorage(int width, int height); - explicit BitmapAtlasStorage(const msdfgen::BitmapConstRef &bitmap); - explicit BitmapAtlasStorage(msdfgen::Bitmap &&bitmap); - BitmapAtlasStorage(const BitmapAtlasStorage &orig, int width, int height); - BitmapAtlasStorage(const BitmapAtlasStorage &orig, int width, int height, const Remap *remapping, int count); - operator msdfgen::BitmapConstRef() const; - operator msdfgen::BitmapRef(); - operator msdfgen::Bitmap() &&; - template - void put(int x, int y, const msdfgen::BitmapConstRef &subBitmap); - void get(int x, int y, const msdfgen::BitmapRef &subBitmap) const; - -private: - msdfgen::Bitmap bitmap; - -}; - -} - -#include "BitmapAtlasStorage.hpp" diff --git a/Nuake/src/Vendors/msdf-atlas-gen/BitmapAtlasStorage.hpp b/Nuake/src/Vendors/msdf-atlas-gen/BitmapAtlasStorage.hpp deleted file mode 100644 index fbfdc9b1..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/BitmapAtlasStorage.hpp +++ /dev/null @@ -1,65 +0,0 @@ - -#include "BitmapAtlasStorage.h" - -#include -#include -#include "bitmap-blit.h" - -namespace msdf_atlas { - -template -BitmapAtlasStorage::BitmapAtlasStorage() { } - -template -BitmapAtlasStorage::BitmapAtlasStorage(int width, int height) : bitmap(width, height) { - memset((T *) bitmap, 0, sizeof(T)*N*width*height); -} - -template -BitmapAtlasStorage::BitmapAtlasStorage(const msdfgen::BitmapConstRef &bitmap) : bitmap(bitmap) { } - -template -BitmapAtlasStorage::BitmapAtlasStorage(msdfgen::Bitmap &&bitmap) : bitmap((msdfgen::Bitmap &&) bitmap) { } - -template -BitmapAtlasStorage::BitmapAtlasStorage(const BitmapAtlasStorage &orig, int width, int height) : bitmap(width, height) { - memset((T *) bitmap, 0, sizeof(T)*N*width*height); - blit(bitmap, orig.bitmap, 0, 0, 0, 0, std::min(width, orig.bitmap.width()), std::min(height, orig.bitmap.height())); -} - -template -BitmapAtlasStorage::BitmapAtlasStorage(const BitmapAtlasStorage &orig, int width, int height, const Remap *remapping, int count) : bitmap(width, height) { - memset((T *) bitmap, 0, sizeof(T)*N*width*height); - for (int i = 0; i < count; ++i) { - const Remap &remap = remapping[i]; - blit(bitmap, orig.bitmap, remap.target.x, remap.target.y, remap.source.x, remap.source.y, remap.width, remap.height); - } -} - -template -BitmapAtlasStorage::operator msdfgen::BitmapConstRef() const { - return bitmap; -} - -template -BitmapAtlasStorage::operator msdfgen::BitmapRef() { - return bitmap; -} - -template -BitmapAtlasStorage::operator msdfgen::Bitmap() && { - return (msdfgen::Bitmap &&) bitmap; -} - -template -template -void BitmapAtlasStorage::put(int x, int y, const msdfgen::BitmapConstRef &subBitmap) { - blit(bitmap, subBitmap, x, y, 0, 0, subBitmap.width, subBitmap.height); -} - -template -void BitmapAtlasStorage::get(int x, int y, const msdfgen::BitmapRef &subBitmap) const { - blit(subBitmap, bitmap, 0, 0, x, y, subBitmap.width, subBitmap.height); -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/CHANGELOG.md b/Nuake/src/Vendors/msdf-atlas-gen/CHANGELOG.md deleted file mode 100644 index d7d4480a..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/CHANGELOG.md +++ /dev/null @@ -1,26 +0,0 @@ - -## Version 1.2 (2021-05-29) - -- Updated to MSDFgen 1.9. -- Multiple fonts or font sizes can now be compiled into a single atlas. -- Added `-yorigin` option to choose if Y-coordinates increase from bottom to top or from top to bottom. -- Added `-coloringstrategy` option to select MSDF edge coloring heuristic. -- Shadron preview now properly loads floating-point image outputs in full range mode. - -## Version 1.1 (2020-10-18) - -- Updated to MSDFgen 1.8. -- Glyph geometry is now preprocessed by Skia to resolve irregularities which were previously unsupported and caused artifacts. - - The scanline pass and overlapping contour mode is made obsolete by this step and has been disabled by default. The preprocess step can be disabled by the new `-nopreprocess` switch and the former enabled by `-scanline` and `-overlap` respectively. - - The project can be built without the Skia library, forgoing the geometry preprocessing feature. This is controlled by the macro definition `MSDFGEN_USE_SKIA`. -- Glyphs can now also be loaded by glyph index rather than Unicode values. In the standalone version, a set of glyphs can be passed by `-glyphset` in place of `-charset`. -- Glyphs not present in the font should now be correctly skipped instead of producing a placeholder symbol. -- Added `-threads` argument to set the number of concurrent threads used during distance field generation. - -### Version 1.0.1 (2020-03-09) - -- Updated to MSDFgen 1.7.1. - -## Version 1.0 (2020-03-08) - -- Initial release. diff --git a/Nuake/src/Vendors/msdf-atlas-gen/Charset.cpp b/Nuake/src/Vendors/msdf-atlas-gen/Charset.cpp deleted file mode 100644 index 69c93ee7..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/Charset.cpp +++ /dev/null @@ -1,39 +0,0 @@ - -#include "Charset.h" - -namespace msdf_atlas { - -static Charset createAsciiCharset() { - Charset ascii; - for (unicode_t cp = 0x20; cp < 0x7f; ++cp) - ascii.add(cp); - return ascii; -} - -const Charset Charset::ASCII = createAsciiCharset(); - -void Charset::add(unicode_t cp) { - codepoints.insert(cp); -} - -void Charset::remove(unicode_t cp) { - codepoints.erase(cp); -} - -size_t Charset::size() const { - return codepoints.size(); -} - -bool Charset::empty() const { - return codepoints.empty(); -} - -std::set::const_iterator Charset::begin() const { - return codepoints.begin(); -} - -std::set::const_iterator Charset::end() const { - return codepoints.end(); -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/Charset.h b/Nuake/src/Vendors/msdf-atlas-gen/Charset.h deleted file mode 100644 index d0cc7191..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/Charset.h +++ /dev/null @@ -1,35 +0,0 @@ - -#pragma once - -#include -#include -#include "types.h" - -namespace msdf_atlas { - -/// Represents a set of Unicode codepoints (characters) -class Charset { - -public: - /// The set of the 95 printable ASCII characters - static const Charset ASCII; - - /// Adds a codepoint - void add(unicode_t cp); - /// Removes a codepoint - void remove(unicode_t cp); - - size_t size() const; - bool empty() const; - std::set::const_iterator begin() const; - std::set::const_iterator end() const; - - /// Load character set from a text file with the correct syntax - bool load(const char *filename, bool disableCharLiterals = false); - -private: - std::set codepoints; - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/DynamicAtlas.h b/Nuake/src/Vendors/msdf-atlas-gen/DynamicAtlas.h deleted file mode 100644 index e1640977..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/DynamicAtlas.h +++ /dev/null @@ -1,43 +0,0 @@ - -#pragma once - -#include -#include "RectanglePacker.h" -#include "AtlasGenerator.h" - -namespace msdf_atlas { - -/** - * This class can be used to produce a dynamic atlas to which more glyphs are added over time. - * It takes care of laying out and enlarging the atlas as necessary and delegates the actual work - * to the specified AtlasGenerator, which may e.g. do the work asynchronously. - */ -template -class DynamicAtlas { - -public: - DynamicAtlas(); - /// Creates with a configured generator. The generator must not contain any prior glyphs! - explicit DynamicAtlas(AtlasGenerator &&generator); - /// Adds a batch of glyphs. Adding more than one glyph at a time may improve packing efficiency - void add(GlyphGeometry *glyphs, int count); - /// Allows access to generator. Do not add glyphs to the generator directly! - AtlasGenerator & atlasGenerator(); - const AtlasGenerator & atlasGenerator() const; - -private: - AtlasGenerator generator; - RectanglePacker packer; - int glyphCount; - int side; - std::vector rectangles; - std::vector remapBuffer; - int totalArea; - GeneratorAttributes genAttribs; - int padding; - -}; - -} - -#include "DynamicAtlas.hpp" diff --git a/Nuake/src/Vendors/msdf-atlas-gen/DynamicAtlas.hpp b/Nuake/src/Vendors/msdf-atlas-gen/DynamicAtlas.hpp deleted file mode 100644 index 51a712a8..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/DynamicAtlas.hpp +++ /dev/null @@ -1,69 +0,0 @@ - -#include "DynamicAtlas.h" - -namespace msdf_atlas { - -template -DynamicAtlas::DynamicAtlas() : glyphCount(0), side(0), totalArea(0), padding(0) { } - -template -DynamicAtlas::DynamicAtlas(AtlasGenerator &&generator) : generator((AtlasGenerator &&) generator), glyphCount(0), side(0), totalArea(0), padding(0) { } - -template -void DynamicAtlas::add(GlyphGeometry *glyphs, int count) { - int start = rectangles.size(); - for (int i = 0; i < count; ++i) { - if (!glyphs[i].isWhitespace()) { - int w, h; - glyphs[i].getBoxSize(w, h); - Rectangle rect = { 0, 0, w+padding, h+padding }; - rectangles.push_back(rect); - Remap remapEntry = { }; - remapEntry.index = glyphCount+i; - remapEntry.width = w; - remapEntry.height = h; - remapBuffer.push_back(remapEntry); - totalArea += (w+padding)*(h+padding); - } - } - if ((int) rectangles.size() > start) { - int oldSide = side; - int packerStart = start; - while (packer.pack(rectangles.data()+packerStart, rectangles.size()-packerStart) > 0) { - side = side+!side<<1; - while (side*side < totalArea) - side <<= 1; - packer = RectanglePacker(side+padding, side+padding); - packerStart = 0; - } - if (packerStart < start) { - for (int i = 0; i < start; ++i) { - Remap &remap = remapBuffer[i]; - remap.source = remap.target; - remap.target.x = rectangles[i].x; - remap.target.y = rectangles[i].y; - } - generator.rearrange(side, side, remapBuffer.data(), start); - } else if (side != oldSide) - generator.resize(side, side); - for (int i = start; i < (int) rectangles.size(); ++i) { - remapBuffer[i].target.x = rectangles[i].x; - remapBuffer[i].target.y = rectangles[i].y; - glyphs[remapBuffer[i].index-glyphCount].placeBox(rectangles[i].x, rectangles[i].y); - } - } - generator.generate(glyphs, count, genAttribs); - glyphCount += count; -} - -template -AtlasGenerator & DynamicAtlas::atlasGenerator() { - return generator; -} - -template -const AtlasGenerator & DynamicAtlas::atlasGenerator() const { - return generator; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/FontGeometry.cpp b/Nuake/src/Vendors/msdf-atlas-gen/FontGeometry.cpp deleted file mode 100644 index ad89d45f..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/FontGeometry.cpp +++ /dev/null @@ -1,185 +0,0 @@ - -#include "FontGeometry.h" - -namespace msdf_atlas { - -FontGeometry::GlyphRange::GlyphRange() : glyphs(), rangeStart(), rangeEnd() { } - -FontGeometry::GlyphRange::GlyphRange(const std::vector *glyphs, size_t rangeStart, size_t rangeEnd) : glyphs(glyphs), rangeStart(rangeStart), rangeEnd(rangeEnd) { } - -size_t FontGeometry::GlyphRange::size() const { - return glyphs->size(); -} - -bool FontGeometry::GlyphRange::empty() const { - return glyphs->empty(); -} - -const GlyphGeometry * FontGeometry::GlyphRange::begin() const { - return glyphs->data()+rangeStart; -} - -const GlyphGeometry * FontGeometry::GlyphRange::end() const { - return glyphs->data()+rangeEnd; -} - -FontGeometry::FontGeometry() : geometryScale(1), metrics(), preferredIdentifierType(GlyphIdentifierType::UNICODE_CODEPOINT), glyphs(&ownGlyphs), rangeStart(glyphs->size()), rangeEnd(glyphs->size()) { } - -FontGeometry::FontGeometry(std::vector *glyphStorage) : geometryScale(1), metrics(), preferredIdentifierType(GlyphIdentifierType::UNICODE_CODEPOINT), glyphs(glyphStorage), rangeStart(glyphs->size()), rangeEnd(glyphs->size()) { } - -int FontGeometry::loadGlyphset(msdfgen::FontHandle *font, double fontScale, const Charset &glyphset, bool preprocessGeometry, bool enableKerning) { - if (!(glyphs->size() == rangeEnd && loadMetrics(font, fontScale))) - return -1; - glyphs->reserve(glyphs->size()+glyphset.size()); - int loaded = 0; - for (unicode_t index : glyphset) { - GlyphGeometry glyph; - if (glyph.load(font, geometryScale, msdfgen::GlyphIndex(index), preprocessGeometry)) { - addGlyph((GlyphGeometry &&) glyph); - ++loaded; - } - } - if (enableKerning) - loadKerning(font); - preferredIdentifierType = GlyphIdentifierType::GLYPH_INDEX; - return loaded; -} - -int FontGeometry::loadCharset(msdfgen::FontHandle *font, double fontScale, const Charset &charset, bool preprocessGeometry, bool enableKerning) { - if (!(glyphs->size() == rangeEnd && loadMetrics(font, fontScale))) - return -1; - glyphs->reserve(glyphs->size()+charset.size()); - int loaded = 0; - for (unicode_t cp : charset) { - GlyphGeometry glyph; - if (glyph.load(font, geometryScale, cp, preprocessGeometry)) { - addGlyph((GlyphGeometry &&) glyph); - ++loaded; - } - } - if (enableKerning) - loadKerning(font); - preferredIdentifierType = GlyphIdentifierType::UNICODE_CODEPOINT; - return loaded; -} - -bool FontGeometry::loadMetrics(msdfgen::FontHandle *font, double fontScale) { - if (!msdfgen::getFontMetrics(metrics, font)) - return false; - if (metrics.emSize <= 0) - metrics.emSize = MSDF_ATLAS_DEFAULT_EM_SIZE; - geometryScale = fontScale/metrics.emSize; - metrics.emSize *= geometryScale; - metrics.ascenderY *= geometryScale; - metrics.descenderY *= geometryScale; - metrics.lineHeight *= geometryScale; - metrics.underlineY *= geometryScale; - metrics.underlineThickness *= geometryScale; - return true; -} - -bool FontGeometry::addGlyph(const GlyphGeometry &glyph) { - if (glyphs->size() != rangeEnd) - return false; - glyphsByIndex.insert(std::make_pair(glyph.getIndex(), rangeEnd)); - if (glyph.getCodepoint()) - glyphsByCodepoint.insert(std::make_pair(glyph.getCodepoint(), rangeEnd)); - glyphs->push_back(glyph); - ++rangeEnd; - return true; -} - -bool FontGeometry::addGlyph(GlyphGeometry &&glyph) { - if (glyphs->size() != rangeEnd) - return false; - glyphsByIndex.insert(std::make_pair(glyph.getIndex(), rangeEnd)); - if (glyph.getCodepoint()) - glyphsByCodepoint.insert(std::make_pair(glyph.getCodepoint(), rangeEnd)); - glyphs->push_back((GlyphGeometry &&) glyph); - ++rangeEnd; - return true; -} - -int FontGeometry::loadKerning(msdfgen::FontHandle *font) { - int loaded = 0; - for (size_t i = rangeStart; i < rangeEnd; ++i) - for (size_t j = rangeStart; j < rangeEnd; ++j) { - double advance; - if (msdfgen::getKerning(advance, font, (*glyphs)[i].getGlyphIndex(), (*glyphs)[j].getGlyphIndex()) && advance) { - kerning[std::make_pair((*glyphs)[i].getIndex(), (*glyphs)[j].getIndex())] = geometryScale*advance; - ++loaded; - } - } - return loaded; -} - -void FontGeometry::setName(const char *name) { - if (name) - this->name = name; - else - this->name.clear(); -} - -double FontGeometry::getGeometryScale() const { - return geometryScale; -} - -const msdfgen::FontMetrics & FontGeometry::getMetrics() const { - return metrics; -} - -GlyphIdentifierType FontGeometry::getPreferredIdentifierType() const { - return preferredIdentifierType; -} - -FontGeometry::GlyphRange FontGeometry::getGlyphs() const { - return GlyphRange(glyphs, rangeStart, rangeEnd); -} - -const GlyphGeometry * FontGeometry::getGlyph(msdfgen::GlyphIndex index) const { - std::map::const_iterator it = glyphsByIndex.find(index.getIndex()); - if (it != glyphsByIndex.end()) - return &(*glyphs)[it->second]; - return nullptr; -} - -const GlyphGeometry * FontGeometry::getGlyph(unicode_t codepoint) const { - std::map::const_iterator it = glyphsByCodepoint.find(codepoint); - if (it != glyphsByCodepoint.end()) - return &(*glyphs)[it->second]; - return nullptr; -} - -bool FontGeometry::getAdvance(double &advance, msdfgen::GlyphIndex index1, msdfgen::GlyphIndex index2) const { - const GlyphGeometry *glyph1 = getGlyph(index1); - if (!glyph1) - return false; - advance = glyph1->getAdvance(); - std::map, double>::const_iterator it = kerning.find(std::make_pair(index1.getIndex(), index2.getIndex())); - if (it != kerning.end()) - advance += it->second; - return true; -} - -bool FontGeometry::getAdvance(double &advance, unicode_t codepoint1, unicode_t codepoint2) const { - const GlyphGeometry *glyph1, *glyph2; - if (!((glyph1 = getGlyph(codepoint1)) && (glyph2 = getGlyph(codepoint2)))) - return false; - advance = glyph1->getAdvance(); - std::map, double>::const_iterator it = kerning.find(std::make_pair(glyph1->getIndex(), glyph2->getIndex())); - if (it != kerning.end()) - advance += it->second; - return true; -} - -const std::map, double> & FontGeometry::getKerning() const { - return kerning; -} - -const char * FontGeometry::getName() const { - if (name.empty()) - return nullptr; - return name.c_str(); -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/FontGeometry.h b/Nuake/src/Vendors/msdf-atlas-gen/FontGeometry.h deleted file mode 100644 index 4ac230e9..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/FontGeometry.h +++ /dev/null @@ -1,86 +0,0 @@ - -#pragma once - -#include -#include -#include -#include -#include -#include -#include "types.h" -#include "GlyphGeometry.h" -#include "Charset.h" - -#define MSDF_ATLAS_DEFAULT_EM_SIZE 32.0 - -namespace msdf_atlas { - -/// Represents the geometry of all glyphs of a given font or font variant -class FontGeometry { - -public: - class GlyphRange { - public: - GlyphRange(); - GlyphRange(const std::vector *glyphs, size_t rangeStart, size_t rangeEnd); - size_t size() const; - bool empty() const; - const GlyphGeometry * begin() const; - const GlyphGeometry * end() const; - private: - const std::vector *glyphs; - size_t rangeStart, rangeEnd; - }; - - FontGeometry(); - explicit FontGeometry(std::vector *glyphStorage); - - /// Loads all glyphs in a glyphset (Charset elements are glyph indices), returns the number of successfully loaded glyphs - int loadGlyphset(msdfgen::FontHandle *font, double fontScale, const Charset &glyphset, bool preprocessGeometry = true, bool enableKerning = true); - /// Loads all glyphs in a charset (Charset elements are Unicode codepoints), returns the number of successfully loaded glyphs - int loadCharset(msdfgen::FontHandle *font, double fontScale, const Charset &charset, bool preprocessGeometry = true, bool enableKerning = true); - - /// Only loads font metrics and geometry scale from font - bool loadMetrics(msdfgen::FontHandle *font, double fontScale); - /// Adds a loaded glyph - bool addGlyph(const GlyphGeometry &glyph); - bool addGlyph(GlyphGeometry &&glyph); - /// Loads kerning pairs for all glyphs that are currently present, returns the number of loaded kerning pairs - int loadKerning(msdfgen::FontHandle *font); - /// Sets a name to be associated with the font - void setName(const char *name); - - /// Returns the geometry scale to be used when loading glyphs - double getGeometryScale() const; - /// Returns the processed font metrics - const msdfgen::FontMetrics & getMetrics() const; - /// Returns the type of identifier that was used to load glyphs - GlyphIdentifierType getPreferredIdentifierType() const; - /// Returns the list of all glyphs - GlyphRange getGlyphs() const; - /// Finds a glyph by glyph index or Unicode codepoint, returns null if not found - const GlyphGeometry * getGlyph(msdfgen::GlyphIndex index) const; - const GlyphGeometry * getGlyph(unicode_t codepoint) const; - /// Outputs the advance between two glyphs with kerning taken into consideration, returns false on failure - bool getAdvance(double &advance, msdfgen::GlyphIndex index1, msdfgen::GlyphIndex index2) const; - bool getAdvance(double &advance, unicode_t codepoint1, unicode_t codepoint2) const; - /// Returns the complete mapping of kerning pairs (by glyph indices) and their respective advance values - const std::map, double> & getKerning() const; - /// Returns the name associated with the font or null if not set - const char * getName() const; - -private: - double geometryScale; - msdfgen::FontMetrics metrics; - GlyphIdentifierType preferredIdentifierType; - std::vector *glyphs; - size_t rangeStart, rangeEnd; - std::map glyphsByIndex; - std::map glyphsByCodepoint; - std::map, double> kerning; - std::vector ownGlyphs; - std::string name; - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/GlyphBox.h b/Nuake/src/Vendors/msdf-atlas-gen/GlyphBox.h deleted file mode 100644 index 83b8842c..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/GlyphBox.h +++ /dev/null @@ -1,19 +0,0 @@ - -#pragma once - -namespace msdf_atlas { - -/// The glyph box - its bounds in plane and atlas -struct GlyphBox { - int index; - double advance; - struct { - double l, b, r, t; - } bounds; - struct { - int x, y, w, h; - } rect; - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/GlyphGeometry.cpp b/Nuake/src/Vendors/msdf-atlas-gen/GlyphGeometry.cpp deleted file mode 100644 index 5ee557a9..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/GlyphGeometry.cpp +++ /dev/null @@ -1,170 +0,0 @@ - -#include "GlyphGeometry.h" - -#include -#include - -namespace msdf_atlas { - -GlyphGeometry::GlyphGeometry() : index(), codepoint(), geometryScale(), bounds(), advance(), box() { } - -bool GlyphGeometry::load(msdfgen::FontHandle *font, double geometryScale, msdfgen::GlyphIndex index, bool preprocessGeometry) { - if (font && msdfgen::loadGlyph(shape, font, index, &advance) && shape.validate()) { - this->index = index.getIndex(); - this->geometryScale = geometryScale; - codepoint = 0; - advance *= geometryScale; - #ifdef MSDFGEN_USE_SKIA - if (preprocessGeometry) - msdfgen::resolveShapeGeometry(shape); - #endif - shape.normalize(); - bounds = shape.getBounds(); - #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; -} - -bool GlyphGeometry::load(msdfgen::FontHandle *font, double geometryScale, unicode_t codepoint, bool preprocessGeometry) { - msdfgen::GlyphIndex index; - if (msdfgen::getGlyphIndex(index, font, codepoint)) { - if (load(font, geometryScale, index, preprocessGeometry)) { - this->codepoint = codepoint; - return true; - } - } - return false; -} - -void GlyphGeometry::edgeColoring(void (*fn)(msdfgen::Shape &, double, unsigned long long), double angleThreshold, unsigned long long seed) { - fn(shape, angleThreshold, seed); -} - -void GlyphGeometry::wrapBox(double scale, double range, double miterLimit) { - scale *= geometryScale; - range /= geometryScale; - box.range = range; - box.scale = scale; - if (bounds.l < bounds.r && bounds.b < bounds.t) { - double l = bounds.l, b = bounds.b, r = bounds.r, t = bounds.t; - l -= .5*range, b -= .5*range; - r += .5*range, t += .5*range; - if (miterLimit > 0) - 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; - box.rect.h = (int) ceil(h)+1; - box.translate.x = -l+.5*(box.rect.w-w)/scale; - box.translate.y = -b+.5*(box.rect.h-h)/scale; - } else { - box.rect.w = 0, box.rect.h = 0; - box.translate = msdfgen::Vector2(); - } -} - -void GlyphGeometry::placeBox(int x, int y) { - box.rect.x = x, box.rect.y = y; -} - -int GlyphGeometry::getIndex() const { - return index; -} - -msdfgen::GlyphIndex GlyphGeometry::getGlyphIndex() const { - return msdfgen::GlyphIndex(index); -} - -unicode_t GlyphGeometry::getCodepoint() const { - return codepoint; -} - -int GlyphGeometry::getIdentifier(GlyphIdentifierType type) const { - switch (type) { - case GlyphIdentifierType::GLYPH_INDEX: - return index; - case GlyphIdentifierType::UNICODE_CODEPOINT: - return (int) codepoint; - } - return 0; -} - -const msdfgen::Shape & GlyphGeometry::getShape() const { - return shape; -} - -double GlyphGeometry::getAdvance() const { - return advance; -} - -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; -} - -void GlyphGeometry::getBoxSize(int &w, int &h) const { - w = box.rect.w, h = box.rect.h; -} - -double GlyphGeometry::getBoxRange() const { - return box.range; -} - -msdfgen::Projection GlyphGeometry::getBoxProjection() const { - return msdfgen::Projection(msdfgen::Vector2(box.scale), box.translate); -} - -double GlyphGeometry::getBoxScale() const { - return box.scale; -} - -msdfgen::Vector2 GlyphGeometry::getBoxTranslate() const { - return box.translate; -} - -void GlyphGeometry::getQuadPlaneBounds(double &l, double &b, double &r, double &t) const { - if (box.rect.w > 0 && box.rect.h > 0) { - double invBoxScale = 1/box.scale; - l = geometryScale*(-box.translate.x+.5*invBoxScale); - b = geometryScale*(-box.translate.y+.5*invBoxScale); - r = geometryScale*(-box.translate.x+(box.rect.w-.5)*invBoxScale); - t = geometryScale*(-box.translate.y+(box.rect.h-.5)*invBoxScale); - } else - l = 0, b = 0, r = 0, t = 0; -} - -void GlyphGeometry::getQuadAtlasBounds(double &l, double &b, double &r, double &t) const { - if (box.rect.w > 0 && box.rect.h > 0) { - l = box.rect.x+.5; - b = box.rect.y+.5; - r = box.rect.x+box.rect.w-.5; - t = box.rect.y+box.rect.h-.5; - } else - l = 0, b = 0, r = 0, t = 0; -} - -bool GlyphGeometry::isWhitespace() const { - return shape.contours.empty(); -} - -GlyphGeometry::operator GlyphBox() const { - GlyphBox box; - box.index = index; - box.advance = advance; - getQuadPlaneBounds(box.bounds.l, box.bounds.b, box.bounds.r, box.bounds.t); - box.rect.x = this->box.rect.x, box.rect.y = this->box.rect.y, box.rect.w = this->box.rect.w, box.rect.h = this->box.rect.h; - return box; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/GlyphGeometry.h b/Nuake/src/Vendors/msdf-atlas-gen/GlyphGeometry.h deleted file mode 100644 index 748baed4..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/GlyphGeometry.h +++ /dev/null @@ -1,76 +0,0 @@ - -#pragma once - -#include -#include -#include "types.h" -#include "GlyphBox.h" - -namespace msdf_atlas { - -/// Represents the shape geometry of a single glyph as well as its configuration -class GlyphGeometry { - -public: - GlyphGeometry(); - /// Loads glyph geometry from font - bool load(msdfgen::FontHandle *font, double geometryScale, msdfgen::GlyphIndex index, bool preprocessGeometry = true); - bool load(msdfgen::FontHandle *font, double geometryScale, unicode_t codepoint, bool preprocessGeometry = true); - /// Applies edge coloring to glyph shape - void edgeColoring(void (*fn)(msdfgen::Shape &, double, unsigned long long), double angleThreshold, unsigned long long seed); - /// Computes the dimensions of the glyph's box as well as the transformation for the generator function - void wrapBox(double scale, double range, double miterLimit); - /// Sets the glyph's box's position in the atlas - void placeBox(int x, int y); - /// Returns the glyph's index within the font - int getIndex() const; - /// Returns the glyph's index as a msdfgen::GlyphIndex - msdfgen::GlyphIndex getGlyphIndex() const; - /// Returns the Unicode codepoint represented by the glyph or 0 if unknown - unicode_t getCodepoint() const; - /// Returns the glyph's identifier specified by the supplied identifier type - int getIdentifier(GlyphIdentifierType type) const; - /// Returns the glyph's shape - const msdfgen::Shape & getShape() const; - /// Returns the glyph's advance - double getAdvance() 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 - void getBoxSize(int &w, int &h) const; - /// Returns the range needed to generate the glyph's SDF - double getBoxRange() const; - /// Returns the projection needed to generate the glyph's bitmap - msdfgen::Projection getBoxProjection() const; - /// Returns the scale needed to generate the glyph's bitmap - double getBoxScale() const; - /// Returns the translation vector needed to generate the glyph's bitmap - msdfgen::Vector2 getBoxTranslate() const; - /// Outputs the bounding box of the glyph as it should be placed on the baseline - void getQuadPlaneBounds(double &l, double &b, double &r, double &t) const; - /// Outputs the bounding box of the glyph in the atlas - void getQuadAtlasBounds(double &l, double &b, double &r, double &t) const; - /// Returns true if the glyph is a whitespace and has no geometry - bool isWhitespace() const; - /// Simplifies to GlyphBox - operator GlyphBox() const; - -private: - int index; - unicode_t codepoint; - double geometryScale; - msdfgen::Shape shape; - msdfgen::Shape::Bounds bounds; - double advance; - struct { - struct { - int x, y, w, h; - } rect; - double range; - double scale; - msdfgen::Vector2 translate; - } box; - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/ImmediateAtlasGenerator.h b/Nuake/src/Vendors/msdf-atlas-gen/ImmediateAtlasGenerator.h deleted file mode 100644 index c627ab63..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/ImmediateAtlasGenerator.h +++ /dev/null @@ -1,45 +0,0 @@ - -#pragma once - -#include -#include "GlyphBox.h" -#include "Workload.h" -#include "AtlasGenerator.h" - -namespace msdf_atlas { - -/** - * An implementation of AtlasGenerator that uses the specified generator function - * and AtlasStorage class and generates glyph bitmaps immediately - * (does not return until all submitted work is finished), - * but may use multiple threads (setThreadCount). - */ -template GEN_FN, class AtlasStorage> -class ImmediateAtlasGenerator { - -public: - ImmediateAtlasGenerator(); - ImmediateAtlasGenerator(int width, int height); - void generate(const GlyphGeometry *glyphs, int count); - void rearrange(int width, int height, const Remap *remapping, int count); - void resize(int width, int height); - /// Sets attributes for the generator function - void setAttributes(const GeneratorAttributes &attributes); - /// Sets the number of threads to be run by generate - void setThreadCount(int threadCount); - /// Allows access to the underlying AtlasStorage - const AtlasStorage & atlasStorage() const; - -private: - AtlasStorage storage; - std::vector layout; - std::vector glyphBuffer; - std::vector errorCorrectionBuffer; - GeneratorAttributes attributes; - int threadCount; - -}; - -} - -#include "ImmediateAtlasGenerator.hpp" diff --git a/Nuake/src/Vendors/msdf-atlas-gen/ImmediateAtlasGenerator.hpp b/Nuake/src/Vendors/msdf-atlas-gen/ImmediateAtlasGenerator.hpp deleted file mode 100644 index 67351de9..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/ImmediateAtlasGenerator.hpp +++ /dev/null @@ -1,77 +0,0 @@ - -#include "ImmediateAtlasGenerator.h" - -#include - -namespace msdf_atlas { - -template GEN_FN, class AtlasStorage> -ImmediateAtlasGenerator::ImmediateAtlasGenerator() : threadCount(1) { } - -template GEN_FN, class AtlasStorage> -ImmediateAtlasGenerator::ImmediateAtlasGenerator(int width, int height) : storage(width, height), threadCount(1) { } - -template GEN_FN, class AtlasStorage> -void ImmediateAtlasGenerator::generate(const GlyphGeometry *glyphs, int count) { - int maxBoxArea = 0; - for (int i = 0; i < count; ++i) { - GlyphBox box = glyphs[i]; - maxBoxArea = std::max(maxBoxArea, box.rect.w*box.rect.h); - layout.push_back((GlyphBox &&) box); - } - int threadBufferSize = N*maxBoxArea; - if (threadCount*threadBufferSize > (int) glyphBuffer.size()) - glyphBuffer.resize(threadCount*threadBufferSize); - if (threadCount*maxBoxArea > (int) errorCorrectionBuffer.size()) - errorCorrectionBuffer.resize(threadCount*maxBoxArea); - std::vector threadAttributes(threadCount); - for (int i = 0; i < threadCount; ++i) { - threadAttributes[i] = attributes; - threadAttributes[i].config.errorCorrection.buffer = errorCorrectionBuffer.data()+i*maxBoxArea; - } - - Workload([this, glyphs, &threadAttributes, threadBufferSize](int i, int threadNo) -> bool { - const GlyphGeometry &glyph = glyphs[i]; - if (!glyph.isWhitespace()) { - int l, b, w, h; - glyph.getBoxRect(l, b, w, h); - msdfgen::BitmapRef glyphBitmap(glyphBuffer.data()+threadNo*threadBufferSize, w, h); - GEN_FN(glyphBitmap, glyph, threadAttributes[threadNo]); - storage.put(l, b, msdfgen::BitmapConstRef(glyphBitmap)); - } - return true; - }, count).finish(threadCount); -} - -template GEN_FN, class AtlasStorage> -void ImmediateAtlasGenerator::rearrange(int width, int height, const Remap *remapping, int count) { - for (int i = 0; i < count; ++i) { - layout[remapping[i].index].rect.x = remapping[i].target.x; - layout[remapping[i].index].rect.y = remapping[i].target.y; - } - AtlasStorage newStorage((AtlasStorage &&) storage, width, height, remapping, count); - storage = (AtlasStorage &&) newStorage; -} - -template GEN_FN, class AtlasStorage> -void ImmediateAtlasGenerator::resize(int width, int height) { - AtlasStorage newStorage((AtlasStorage &&) storage, width, height); - storage = (AtlasStorage &&) newStorage; -} - -template GEN_FN, class AtlasStorage> -void ImmediateAtlasGenerator::setAttributes(const GeneratorAttributes &attributes) { - this->attributes = attributes; -} - -template GEN_FN, class AtlasStorage> -void ImmediateAtlasGenerator::setThreadCount(int threadCount) { - this->threadCount = threadCount; -} - -template GEN_FN, class AtlasStorage> -const AtlasStorage & ImmediateAtlasGenerator::atlasStorage() const { - return storage; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/LICENSE.txt b/Nuake/src/Vendors/msdf-atlas-gen/LICENSE.txt deleted file mode 100644 index 83edc597..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2020 Viktor Chlumsky - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Nuake/src/Vendors/msdf-atlas-gen/README.md b/Nuake/src/Vendors/msdf-atlas-gen/README.md deleted file mode 100644 index c8c54ef6..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/README.md +++ /dev/null @@ -1,142 +0,0 @@ - -# Multi-channel signed distance field atlas generator - -This is a utility for generating compact font atlases using [MSDFgen](https://github.com/Chlumsky/msdfgen). - -The atlas generator loads a subset of glyphs from a TTF or OTF font file, generates a distance field for each of them, and tightly packs them into an atlas bitmap (example below). The finished atlas and/or its layout metadata can be exported as an [Artery Font](https://github.com/Chlumsky/artery-font-format) file, a plain image file, a CSV sheet or a structured JSON file. - -![Atlas example](https://user-images.githubusercontent.com/18639794/76163889-811f2e80-614a-11ea-9b28-1eed54dbb899.png) - -A font atlas is typically stored in texture memory and used to draw text in real-time rendering contexts such as video games. - -- See what's new in the [changelog](CHANGELOG.md). - -## Atlas types - -The atlas generator can generate the following six types of atlases. - -| |Hard mask|Soft mask|SDF|PSDF|MSDF|MTSDF| -|-|-|-|-|-|-|-| -| |![Hard mask](https://user-images.githubusercontent.com/18639794/76163903-9eec9380-614a-11ea-92cb-d49485bbad31.png)|![Soft mask](https://user-images.githubusercontent.com/18639794/76163904-a1e78400-614a-11ea-912a-b220fed081cb.png)|![SDF](https://user-images.githubusercontent.com/18639794/76163905-a4e27480-614a-11ea-93eb-c80819a44e6e.png)|![PSDF](https://user-images.githubusercontent.com/18639794/76163907-a6ac3800-614a-11ea-8d97-dafc1db6711d.png)|![MSDF](https://user-images.githubusercontent.com/18639794/76163909-a9a72880-614a-11ea-9726-e825ee0dde94.png)|![MTSDF](https://user-images.githubusercontent.com/18639794/76163910-ac098280-614a-11ea-8b6b-811d864cd584.png)| -|Channels:|1 (1-bit)|1|1|1|3|4| -|Anti-aliasing:|-|Yes|Yes|Yes|Yes|Yes| -|Scalability:|-|-|Yes|Yes|Yes|Yes| -|Sharp corners:|-|-|-|-|Yes|Yes| -|Soft effects:|-|-|Yes|-|-|Yes| -|Hard effects:|-|-|-|Yes|Yes|Yes| - -Notes: -- *Sharp corners* refers to preservation of corner sharpness when upscaled. -- *Soft effects* refers to the support of effects that use true distance, such as glows, rounded borders, or simplified shadows. -- *Hard effects* refers to the support of effects that use pseudo-distance, such as mitered borders or thickness adjustment. - -## Getting started - -This project can be used either as a library or as a standalone console program. -To start using the program immediately, there is a Windows binary available for download in the ["Releases" section](https://github.com/Chlumsky/msdf-atlas-gen/releases). -To build the project, you may use the included [Visual Studio solution](msdf-atlas-gen.sln) or the [Unix Makefile](Makefile). - -## Command line arguments - -Use the following command line arguments for the standalone version of the atlas generator. - -### Input - -- `-font ` (required) – sets the input font file. -- `-charset ` – sets the character set. The ASCII charset will be used if not specified. See [the syntax specification](#character-set-specification-syntax) of `charset.txt`. -- `-glyphset ` – sets the set of input glyphs using their indices within the font file. See [the syntax specification](#glyph-set-specification). -- `-fontscale ` – applies a scaling transformation to the font's glyphs. Mainly to be used to generate multiple sizes in a single atlas, otherwise use [`-size`](#glyph-configuration). -- `-fontname ` – sets a name for the font that will be stored in certain output files as metadata. -- `-and` – separates multiple inputs to be combined into a single atlas. - -### Bitmap atlas type - -`-type ` – see [Atlas types](#atlas-types) - -`` can be one of: - -- `hardmask` – a non-anti-aliased binary image -- `softmask` – an anti-aliased image -- `sdf` – a true signed distance field (SDF) -- `psdf` – a pseudo-distance field -- `msdf` (default) – a multi-channel signed distance field (MSDF) -- `mtsdf` – a combination of MSDF and true SDF in the alpha channel - -### Atlas image format - -`-format ` - -`` can be one of: - -- `png` – a compressed PNG image -- `bmp` – an uncompressed BMP image -- `tiff` – an uncompressed floating-point TIFF image -- `text` – a sequence of pixel values in plain text -- `textfloat` – a sequence of floating-point pixel values in plain text -- `bin` – a sequence of pixel values encoded as raw bytes of data -- `binfloat` – a sequence of pixel values encoded as raw 32-bit floating-point values - -### Atlas dimensions - -`-dimensions ` – sets fixed atlas dimensions - -Alternativelly, the minimum possible dimensions may be selected automatically if a dimensions constraint is set instead: - -- `-pots` – a power-of-two square -- `-potr` – a power-of-two square or rectangle (2:1) -- `-square` – any square dimensions -- `-square2` – square with even side length -- `-square4` (default) – square with side length divisible by four - -### Outputs - -Any non-empty subset of the following may be specified: - -- `-imageout ` – saves the atlas bitmap as a plain image file. Format matches `-format` -- `-json ` – writes the atlas's layout data as well as other metrics into a structured JSON file -- `-csv ` – writes the glyph layout data into a simple CSV file -- `-arfont ` – saves the atlas and its layout data as an [Artery Font](https://github.com/Chlumsky/artery-font-format) file -- `-shadronpreview ` – generates a [Shadron script](https://www.arteryengine.com/shadron/) that uses the generated atlas to draw a sample text as a preview - -### Glyph configuration - -- `-size ` – sets the size of the glyphs in the atlas in pixels per EM -- `-minsize ` – sets the minimum size. The largest possible size that fits the same atlas dimensions will be used -- `-emrange ` – sets the distance field range in EM's -- `-pxrange ` (default = 2) – sets the distance field range in output pixels - -### Distance field generator settings - -- `-angle ` – sets the minimum angle between adjacent edges to be considered a corner. Append D for degrees (`msdf` / `mtsdf` only) -- `-coloringstrategy ` – selects the edge coloring heuristic (`msdf` / `mtsdf` only) -- `-errorcorrection ` – selects the error correction algorithm. Use `help` as mode for more information (`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) -- `-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) - -Use `-help` for an exhaustive list of options. - -## Character set specification syntax - -The character set file is a text file with UTF-8 or ASCII encoding. -The characters can be denoted in the following ways: - -- Single character: `'A'` (UTF-8 encoded), `65` (decimal Unicode), `0x41` (hexadecimal Unicode) -- Range of characters: `['A', 'Z']`, `[65, 90]`, `[0x41, 0x5a]` -- String of characters: `"ABCDEFGHIJKLMNOPQRSTUVWXYZ"` (UTF-8 encoded) - -The entries should be separated by commas or whitespace. -In between quotation marks, backslash is used as the escape character (e.g. `'\''`, `'\\'`, `"!\"#"`). -The order in which characters appear is not taken into consideration. - -Additionally, the include directive can be used to include other charset files and combine character sets in a hierarchical way. -It must be written on a separate line: - -`@include "base-charset.txt"` - -### Glyph set specification - -The syntax of the glyph set specification is mostly the same as that of a character set, but only numeric values (decimal and hexadecimal) are allowed. diff --git a/Nuake/src/Vendors/msdf-atlas-gen/Rectangle.h b/Nuake/src/Vendors/msdf-atlas-gen/Rectangle.h deleted file mode 100644 index 8221be42..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/Rectangle.h +++ /dev/null @@ -1,14 +0,0 @@ - -#pragma once - -namespace msdf_atlas { - -struct Rectangle { - int x, y, w, h; -}; - -struct OrientedRectangle : Rectangle { - bool rotated; -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/RectanglePacker.cpp b/Nuake/src/Vendors/msdf-atlas-gen/RectanglePacker.cpp deleted file mode 100644 index b85d6975..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/RectanglePacker.cpp +++ /dev/null @@ -1,143 +0,0 @@ - -#include "RectanglePacker.h" - -#include - -namespace msdf_atlas { - -#define WORST_FIT 0x7fffffff - -template -static void removeFromUnorderedVector(std::vector &vector, size_t index) { - if (index != vector.size()-1) - std::swap(vector[index], vector.back()); - vector.pop_back(); -} - -int RectanglePacker::rateFit(int w, int h, int sw, int sh) { - return std::min(sw-w, sh-h); -} - -RectanglePacker::RectanglePacker() : RectanglePacker(0, 0) { } - -RectanglePacker::RectanglePacker(int width, int height) { - if (width > 0 && height > 0) - spaces.push_back(Rectangle { 0, 0, width, height }); -} - -void RectanglePacker::splitSpace(int index, int w, int h) { - Rectangle space = spaces[index]; - removeFromUnorderedVector(spaces, index); - Rectangle a = { space.x, space.y+h, w, space.h-h }; - Rectangle b = { space.x+w, space.y, space.w-w, h }; - if (w*(space.h-h) <= h*(space.w-w)) - a.w = space.w; - else - b.h = space.h; - if (a.w > 0 && a.h > 0) - spaces.push_back(a); - if (b.w > 0 && b.h > 0) - spaces.push_back(b); -} - -int RectanglePacker::pack(Rectangle *rectangles, int count) { - std::vector remainingRects(count); - for (int i = 0; i < count; ++i) - remainingRects[i] = i; - while (!remainingRects.empty()) { - int bestFit = WORST_FIT; - int bestSpace = -1; - int bestRect = -1; - for (size_t i = 0; i < spaces.size(); ++i) { - const Rectangle &space = spaces[i]; - for (size_t j = 0; j < remainingRects.size(); ++j) { - const Rectangle &rect = rectangles[remainingRects[j]]; - if (rect.w == space.w && rect.h == space.h) { - bestSpace = i; - bestRect = j; - goto BEST_FIT_FOUND; - } - if (rect.w <= space.w && rect.h <= space.h) { - int fit = rateFit(rect.w, rect.h, space.w, space.h); - if (fit < bestFit) { - bestSpace = i; - bestRect = j; - bestFit = fit; - } - } - } - } - if (bestSpace < 0 || bestRect < 0) - break; - BEST_FIT_FOUND: - Rectangle &rect = rectangles[remainingRects[bestRect]]; - rect.x = spaces[bestSpace].x; - rect.y = spaces[bestSpace].y; - splitSpace(bestSpace, rect.w, rect.h); - removeFromUnorderedVector(remainingRects, bestRect); - } - return (int) remainingRects.size(); -} - -int RectanglePacker::pack(OrientedRectangle *rectangles, int count) { - std::vector remainingRects(count); - for (int i = 0; i < count; ++i) - remainingRects[i] = i; - while (!remainingRects.empty()) { - int bestFit = WORST_FIT; - int bestSpace = -1; - int bestRect = -1; - bool bestRotated = false; - for (size_t i = 0; i < spaces.size(); ++i) { - const Rectangle &space = spaces[i]; - for (size_t j = 0; j < remainingRects.size(); ++j) { - const OrientedRectangle &rect = rectangles[remainingRects[j]]; - if (rect.w == space.w && rect.h == space.h) { - bestSpace = i; - bestRect = j; - bestRotated = false; - goto BEST_FIT_FOUND; - } - if (rect.h == space.w && rect.w == space.h) { - bestSpace = i; - bestRect = j; - bestRotated = true; - goto BEST_FIT_FOUND; - } - if (rect.w <= space.w && rect.h <= space.h) { - int fit = rateFit(rect.w, rect.h, space.w, space.h); - if (fit < bestFit) { - bestSpace = i; - bestRect = j; - bestRotated = false; - bestFit = fit; - } - } - if (rect.h <= space.w && rect.w <= space.h) { - int fit = rateFit(rect.h, rect.w, space.w, space.h); - if (fit < bestFit) { - bestSpace = i; - bestRect = j; - bestRotated = true; - bestFit = fit; - } - } - } - } - if (bestSpace < 0 || bestRect < 0) - break; - BEST_FIT_FOUND: - OrientedRectangle &rect = rectangles[remainingRects[bestRect]]; - rect.x = spaces[bestSpace].x; - rect.y = spaces[bestSpace].y; - rect.rotated = bestRotated; - if (bestRotated) - splitSpace(bestSpace, rect.h, rect.w); - else - splitSpace(bestSpace, rect.w, rect.h); - removeFromUnorderedVector(remainingRects, bestRect); - } - return (int) remainingRects.size(); -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/RectanglePacker.h b/Nuake/src/Vendors/msdf-atlas-gen/RectanglePacker.h deleted file mode 100644 index 10e4c194..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/RectanglePacker.h +++ /dev/null @@ -1,28 +0,0 @@ - -#pragma once - -#include -#include "Rectangle.h" - -namespace msdf_atlas { - -/// Guillotine 2D single bin packer -class RectanglePacker { - -public: - RectanglePacker(); - RectanglePacker(int width, int height); - /// Packs the rectangle array, returns how many didn't fit (0 on success) - int pack(Rectangle *rectangles, int count); - int pack(OrientedRectangle *rectangles, int count); - -private: - std::vector spaces; - - static int rateFit(int w, int h, int sw, int sh); - - void splitSpace(int index, int w, int h); - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/Remap.h b/Nuake/src/Vendors/msdf-atlas-gen/Remap.h deleted file mode 100644 index 4a698896..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/Remap.h +++ /dev/null @@ -1,15 +0,0 @@ - -#pragma once - -namespace msdf_atlas { - -/// Represents the repositioning of a subsection of the atlas -struct Remap { - int index; - struct { - int x, y; - } source, target; - int width, height; -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/TightAtlasPacker.cpp b/Nuake/src/Vendors/msdf-atlas-gen/TightAtlasPacker.cpp deleted file mode 100644 index 5c623eac..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/TightAtlasPacker.cpp +++ /dev/null @@ -1,168 +0,0 @@ - -#include "TightAtlasPacker.h" - -#include -#include "Rectangle.h" -#include "rectangle-packing.h" -#include "size-selectors.h" - -namespace msdf_atlas { - -int TightAtlasPacker::tryPack(GlyphGeometry *glyphs, int count, DimensionsConstraint dimensionsConstraint, int &width, int &height, int padding, double scale, double range, double miterLimit) { - // Wrap glyphs into boxes - std::vector rectangles; - std::vector rectangleGlyphs; - rectangles.reserve(count); - rectangleGlyphs.reserve(count); - for (GlyphGeometry *glyph = glyphs, *end = glyphs+count; glyph < end; ++glyph) { - if (!glyph->isWhitespace()) { - Rectangle rect = { }; - glyph->wrapBox(scale, range, miterLimit); - glyph->getBoxSize(rect.w, rect.h); - if (rect.w > 0 && rect.h > 0) { - rectangles.push_back(rect); - rectangleGlyphs.push_back(glyph); - } - } - } - // No non-zero size boxes? - if (rectangles.empty()) { - if (width < 0 || height < 0) - width = 0, height = 0; - return 0; - } - // Box rectangle packing - if (width < 0 || height < 0) { - std::pair dimensions = std::make_pair(width, height); - switch (dimensionsConstraint) { - case DimensionsConstraint::POWER_OF_TWO_SQUARE: - dimensions = packRectangles(rectangles.data(), rectangles.size(), padding); - break; - case DimensionsConstraint::POWER_OF_TWO_RECTANGLE: - dimensions = packRectangles(rectangles.data(), rectangles.size(), padding); - break; - case DimensionsConstraint::MULTIPLE_OF_FOUR_SQUARE: - dimensions = packRectangles >(rectangles.data(), rectangles.size(), padding); - break; - case DimensionsConstraint::EVEN_SQUARE: - dimensions = packRectangles >(rectangles.data(), rectangles.size(), padding); - break; - case DimensionsConstraint::SQUARE: - dimensions = packRectangles >(rectangles.data(), rectangles.size(), padding); - break; - } - if (!(dimensions.first > 0 && dimensions.second > 0)) - return -1; - width = dimensions.first, height = dimensions.second; - } else { - if (int result = packRectangles(rectangles.data(), rectangles.size(), width, height, padding)) - return result; - } - // Set glyph box placement - for (size_t i = 0; i < rectangles.size(); ++i) - rectangleGlyphs[i]->placeBox(rectangles[i].x, height-(rectangles[i].y+rectangles[i].h)); - return 0; -} - -double TightAtlasPacker::packAndScale(GlyphGeometry *glyphs, int count, int width, int height, int padding, double unitRange, double pxRange, double miterLimit, double tolerance) { - bool lastResult = false; - #define TRY_PACK(scale) (lastResult = !tryPack(glyphs, count, DimensionsConstraint(), width, height, padding, (scale), unitRange+pxRange/(scale), miterLimit)) - double minScale = 1, maxScale = 1; - if (TRY_PACK(1)) { - while (maxScale < 1e+32 && ((maxScale = 2*minScale), TRY_PACK(maxScale))) - minScale = maxScale; - } else { - while (minScale > 1e-32 && ((minScale = .5*maxScale), !TRY_PACK(minScale))) - maxScale = minScale; - } - if (minScale == maxScale) - return 0; - while (minScale/maxScale < 1-tolerance) { - double midScale = .5*(minScale+maxScale); - if (TRY_PACK(midScale)) - minScale = midScale; - else - maxScale = midScale; - } - if (!lastResult) - TRY_PACK(minScale); - return minScale; -} - -TightAtlasPacker::TightAtlasPacker() : - width(-1), height(-1), - padding(0), - dimensionsConstraint(DimensionsConstraint::POWER_OF_TWO_SQUARE), - scale(-1), - minScale(1), - unitRange(0), - pxRange(0), - miterLimit(0), - scaleMaximizationTolerance(.001) -{ } - -int TightAtlasPacker::pack(GlyphGeometry *glyphs, int count) { - double initialScale = scale > 0 ? scale : minScale; - if (initialScale > 0) { - if (int remaining = tryPack(glyphs, count, dimensionsConstraint, width, height, padding, initialScale, unitRange+pxRange/initialScale, miterLimit)) - return remaining; - } else if (width < 0 || height < 0) - return -1; - if (scale <= 0) - scale = packAndScale(glyphs, count, width, height, padding, unitRange, pxRange, miterLimit, scaleMaximizationTolerance); - if (scale <= 0) - return -1; - pxRange += scale*unitRange; - unitRange = 0; - return 0; -} - -void TightAtlasPacker::setDimensions(int width, int height) { - this->width = width, this->height = height; -} - -void TightAtlasPacker::unsetDimensions() { - width = -1, height = -1; -} - -void TightAtlasPacker::setDimensionsConstraint(DimensionsConstraint dimensionsConstraint) { - this->dimensionsConstraint = dimensionsConstraint; -} - -void TightAtlasPacker::setPadding(int padding) { - this->padding = padding; -} - -void TightAtlasPacker::setScale(double scale) { - this->scale = scale; -} - -void TightAtlasPacker::setMinimumScale(double minScale) { - this->minScale = minScale; -} - -void TightAtlasPacker::setUnitRange(double unitRange) { - this->unitRange = unitRange; -} - -void TightAtlasPacker::setPixelRange(double pxRange) { - this->pxRange = pxRange; -} - -void TightAtlasPacker::setMiterLimit(double miterLimit) { - this->miterLimit = miterLimit; -} - -void TightAtlasPacker::getDimensions(int &width, int &height) const { - width = this->width, height = this->height; -} - -double TightAtlasPacker::getScale() const { - return scale; -} - -double TightAtlasPacker::getPixelRange() const { - return pxRange; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/TightAtlasPacker.h b/Nuake/src/Vendors/msdf-atlas-gen/TightAtlasPacker.h deleted file mode 100644 index 35bb2a97..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/TightAtlasPacker.h +++ /dev/null @@ -1,71 +0,0 @@ - -#pragma once - -#include "GlyphGeometry.h" - -namespace msdf_atlas { - -/** - * This class computes the layout of a static atlas and may optionally - * also find the minimum required dimensions and/or the maximum glyph scale - */ -class TightAtlasPacker { - -public: - /// Constraints for the atlas's dimensions - see size selectors for more info - enum class DimensionsConstraint { - POWER_OF_TWO_SQUARE, - POWER_OF_TWO_RECTANGLE, - MULTIPLE_OF_FOUR_SQUARE, - EVEN_SQUARE, - SQUARE - }; - - TightAtlasPacker(); - - /// Computes the layout for the array of glyphs. Returns 0 on success - int pack(GlyphGeometry *glyphs, int count); - - /// Sets the atlas's dimensions to be fixed - void setDimensions(int width, int height); - /// Sets the atlas's dimensions to be determined during pack - void unsetDimensions(); - /// Sets the constraint to be used when determining dimensions - void setDimensionsConstraint(DimensionsConstraint dimensionsConstraint); - /// Sets the padding between glyph boxes - void setPadding(int padding); - /// Sets fixed glyph scale - void setScale(double scale); - /// Sets the minimum glyph scale - void setMinimumScale(double minScale); - /// Sets the unit component of the total distance range - void setUnitRange(double unitRange); - /// Sets the pixel component of the total distance range - void setPixelRange(double pxRange); - /// Sets the miter limit for bounds computation - void setMiterLimit(double miterLimit); - - /// Outputs the atlas's final dimensions - void getDimensions(int &width, int &height) const; - /// Returns the final glyph scale - double getScale() const; - /// Returns the final combined pixel range (including converted unit range) - double getPixelRange() const; - -private: - int width, height; - int padding; - DimensionsConstraint dimensionsConstraint; - double scale; - double minScale; - double unitRange; - double pxRange; - double miterLimit; - double scaleMaximizationTolerance; - - static int tryPack(GlyphGeometry *glyphs, int count, DimensionsConstraint dimensionsConstraint, int &width, int &height, int padding, double scale, double range, double miterLimit); - static double packAndScale(GlyphGeometry *glyphs, int count, int width, int height, int padding, double unitRange, double pxRange, double miterLimit, double tolerance); - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/Workload.cpp b/Nuake/src/Vendors/msdf-atlas-gen/Workload.cpp deleted file mode 100644 index 6050bd0c..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/Workload.cpp +++ /dev/null @@ -1,50 +0,0 @@ - -#include "Workload.h" - -#include -#include -#include -#include - -namespace msdf_atlas { - -Workload::Workload() : chunks(0) { } - -Workload::Workload(const std::function &workerFunction, int chunks) : workerFunction(workerFunction), chunks(chunks) { } - -bool Workload::finishSequential() { - for (int i = 0; i < chunks; ++i) - if (!workerFunction(i, 0)) - return false; - return true; -} - -bool Workload::finishParallel(int threadCount) { - bool result = true; - std::atomic next(0); - std::function threadWorker = [this, &result, &next](int threadNo) { - for (int i = next++; result && i < chunks; i = next++) { - if (!workerFunction(i, threadNo)) - result = false; - } - }; - std::vector threads; - threads.reserve(threadCount); - for (int i = 0; i < threadCount; ++i) - threads.emplace_back(threadWorker, i); - for (std::thread &thread : threads) - thread.join(); - return result; -} - -bool Workload::finish(int threadCount) { - if (!chunks) - return true; - if (threadCount == 1 || chunks == 1) - return finishSequential(); - if (threadCount > 1) - return finishParallel(std::min(threadCount, chunks)); - return false; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/Workload.h b/Nuake/src/Vendors/msdf-atlas-gen/Workload.h deleted file mode 100644 index cee0c9d7..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/Workload.h +++ /dev/null @@ -1,32 +0,0 @@ - -#pragma once - -#include - -namespace msdf_atlas { - -/** - * This function allows to split a workload into multiple threads. - * The worker function: - * bool FN(int chunk, int threadNo); - * should process the given chunk (out of chunks) and return true. - * If false is returned, the process is interrupted. - */ -class Workload { - -public: - Workload(); - Workload(const std::function &workerFunction, int chunks); - /// Runs the process and returns true if all chunks have been processed - bool finish(int threadCount); - -private: - std::function workerFunction; - int chunks; - - bool finishSequential(); - bool finishParallel(int threadCount); - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/artery-font-export.cpp b/Nuake/src/Vendors/msdf-atlas-gen/artery-font-export.cpp deleted file mode 100644 index 04a3f0ae..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/artery-font-export.cpp +++ /dev/null @@ -1,191 +0,0 @@ - -#include "artery-font-export.h" - -/*#include -#include -#include "GlyphGeometry.h" -#include "image-encode.h" - -namespace msdf_atlas { - -static artery_font::ImageType convertImageType(ImageType imageType) { - switch (imageType) { - case ImageType::HARD_MASK: - case ImageType::SOFT_MASK: - return artery_font::IMAGE_LINEAR_MASK; - case ImageType::SDF: - return artery_font::IMAGE_SDF; - case ImageType::PSDF: - return artery_font::IMAGE_PSDF; - case ImageType::MSDF: - return artery_font::IMAGE_MSDF; - case ImageType::MTSDF: - return artery_font::IMAGE_MTSDF; - } - return artery_font::IMAGE_NONE; -} - -static artery_font::CodepointType convertCodepointType(GlyphIdentifierType glyphIdentifierType) { - switch (glyphIdentifierType) { - case GlyphIdentifierType::GLYPH_INDEX: - return artery_font::CP_INDEXED; - case GlyphIdentifierType::UNICODE_CODEPOINT: - return artery_font::CP_UNICODE; - } - return artery_font::CP_UNSPECIFIED; -} - -template -static bool encodeTiff(std::vector &output, const msdfgen::BitmapConstRef &atlas) { - // TODO - return false; -} - -template -static artery_font::PixelFormat getPixelFormat(); - -template <> -artery_font::PixelFormat getPixelFormat() { - return artery_font::PIXEL_UNSIGNED8; -} -template <> -artery_font::PixelFormat getPixelFormat() { - return artery_font::PIXEL_FLOAT32; -} - -template -bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties) { - artery_font::StdArteryFont arfont = { }; - arfont.metadataFormat = artery_font::METADATA_NONE; - - for (int i = 0; i < fontCount; ++i) { - const FontGeometry &font = fonts[i]; - GlyphIdentifierType identifierType = font.getPreferredIdentifierType(); - const msdfgen::FontMetrics &fontMetrics = font.getMetrics(); - artery_font::StdFontVariant fontVariant = { }; - fontVariant.codepointType = convertCodepointType(identifierType); - fontVariant.imageType = convertImageType(properties.imageType); - fontVariant.metrics.fontSize = REAL(properties.fontSize*fontMetrics.emSize); - if (properties.imageType != ImageType::HARD_MASK) - fontVariant.metrics.distanceRange = REAL(properties.pxRange); - fontVariant.metrics.emSize = REAL(fontMetrics.emSize); - fontVariant.metrics.ascender = REAL(fontMetrics.ascenderY); - fontVariant.metrics.descender = REAL(fontMetrics.descenderY); - fontVariant.metrics.lineHeight = REAL(fontMetrics.lineHeight); - fontVariant.metrics.underlineY = REAL(fontMetrics.underlineY); - fontVariant.metrics.underlineThickness = REAL(fontMetrics.underlineThickness); - const char *name = font.getName(); - if (name) - fontVariant.name.string = name; - fontVariant.glyphs = artery_font::StdList >(font.getGlyphs().size()); - int j = 0; - for (const GlyphGeometry &glyphGeom : font.getGlyphs()) { - artery_font::Glyph &glyph = fontVariant.glyphs[j++]; - glyph.codepoint = glyphGeom.getIdentifier(identifierType); - glyph.image = 0; - double l, b, r, t; - glyphGeom.getQuadPlaneBounds(l, b, r, t); - glyph.planeBounds.l = REAL(l); - glyph.planeBounds.b = REAL(b); - glyph.planeBounds.r = REAL(r); - glyph.planeBounds.t = REAL(t); - glyphGeom.getQuadAtlasBounds(l, b, r, t); - glyph.imageBounds.l = REAL(l); - glyph.imageBounds.b = REAL(b); - glyph.imageBounds.r = REAL(r); - glyph.imageBounds.t = REAL(t); - glyph.advance.h = REAL(glyphGeom.getAdvance()); - glyph.advance.v = REAL(0); - } - switch (identifierType) { - case GlyphIdentifierType::GLYPH_INDEX: - for (const std::pair, double> &elem : font.getKerning()) { - artery_font::KernPair kernPair = { }; - kernPair.codepoint1 = elem.first.first; - kernPair.codepoint2 = elem.first.second; - kernPair.advance.h = REAL(elem.second); - fontVariant.kernPairs.vector.push_back((artery_font::KernPair &&) kernPair); - } - break; - case GlyphIdentifierType::UNICODE_CODEPOINT: - for (const std::pair, double> &elem : font.getKerning()) { - const GlyphGeometry *glyph1 = font.getGlyph(msdfgen::GlyphIndex(elem.first.first)); - const GlyphGeometry *glyph2 = font.getGlyph(msdfgen::GlyphIndex(elem.first.second)); - if (glyph1 && glyph2 && glyph1->getCodepoint() && glyph2->getCodepoint()) { - artery_font::KernPair kernPair = { }; - kernPair.codepoint1 = glyph1->getCodepoint(); - kernPair.codepoint2 = glyph2->getCodepoint(); - kernPair.advance.h = REAL(elem.second); - fontVariant.kernPairs.vector.push_back((artery_font::KernPair &&) kernPair); - } - } - break; - } - arfont.variants.vector.push_back((artery_font::StdFontVariant &&) fontVariant); - } - - { - artery_font::StdImage image = { }; - image.width = atlas.width; - image.height = atlas.height; - image.channels = N; - image.imageType = convertImageType(properties.imageType); - switch (properties.imageFormat) { - case ImageFormat::PNG: - image.encoding = artery_font::IMAGE_PNG; - image.pixelFormat = artery_font::PIXEL_UNSIGNED8; - if (!encodePng(image.data.vector, atlas)) - return false; - break; - case ImageFormat::TIFF: - image.encoding = artery_font::IMAGE_TIFF; - image.pixelFormat = artery_font::PIXEL_FLOAT32; - if (!encodeTiff(image.data.vector, atlas)) - return false; - break; - case ImageFormat::BINARY: - image.pixelFormat = artery_font::PIXEL_UNSIGNED8; - goto BINARY_EITHER; - case ImageFormat::BINARY_FLOAT: - image.pixelFormat = artery_font::PIXEL_FLOAT32; - goto BINARY_EITHER; - BINARY_EITHER: - if (image.pixelFormat != getPixelFormat()) - return false; - image.encoding = artery_font::IMAGE_RAW_BINARY; - image.rawBinaryFormat.rowLength = N*sizeof(T)*atlas.width; - image.data = artery_font::StdByteArray(N*sizeof(T)*atlas.width*atlas.height); - switch (properties.yDirection) { - case YDirection::BOTTOM_UP: - image.rawBinaryFormat.orientation = artery_font::ORIENTATION_BOTTOM_UP; - memcpy((byte *) image.data, atlas.pixels, N*sizeof(T)*atlas.width*atlas.height); - break; - case YDirection::TOP_DOWN: { - image.rawBinaryFormat.orientation = artery_font::ORIENTATION_TOP_DOWN; - byte *imageData = (byte *) image.data; - for (int y = atlas.height-1; y >= 0; --y) { - memcpy(imageData, atlas.pixels+N*atlas.width*y, N*sizeof(T)*atlas.width); - imageData += N*sizeof(T)*atlas.width; - } - break; - } - } - break; - default: - return false; - } - arfont.images.vector.push_back((artery_font::StdImage &&) image); - } - - return artery_font::writeFile(arfont, filename); -} - -template bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties); -template bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties); -template bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties); -template bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties); -template bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties); -template bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties); - -} -*/ diff --git a/Nuake/src/Vendors/msdf-atlas-gen/artery-font-export.h b/Nuake/src/Vendors/msdf-atlas-gen/artery-font-export.h deleted file mode 100644 index 593fe5cb..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/artery-font-export.h +++ /dev/null @@ -1,23 +0,0 @@ - -#pragma once - -#include -#include -#include "types.h" -#include "FontGeometry.h" - -namespace msdf_atlas { - -struct ArteryFontExportProperties { - double fontSize; - double pxRange; - ImageType imageType; - ImageFormat imageFormat; - YDirection yDirection; -}; - -/// Encodes the atlas bitmap and its layout into an Artery Atlas Font file -template -bool exportArteryFont(const FontGeometry *fonts, int fontCount, const msdfgen::BitmapConstRef &atlas, const char *filename, const ArteryFontExportProperties &properties); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/bitmap-blit.cpp b/Nuake/src/Vendors/msdf-atlas-gen/bitmap-blit.cpp deleted file mode 100644 index c1e6afad..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/bitmap-blit.cpp +++ /dev/null @@ -1,58 +0,0 @@ - -#include "bitmap-blit.h" - -#include - -namespace msdf_atlas { - -template -void blitSameType(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h) { - for (int y = 0; y < h; ++y) - memcpy(dst(dx, dy+y), src(sx, sy+y), sizeof(T)*N*w); -} - -#define BLIT_SAME_TYPE_IMPL(T, N) void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h) { blitSameType(dst, src, dx, dy, sx, sy, w, h); } - -BLIT_SAME_TYPE_IMPL(byte, 1) -BLIT_SAME_TYPE_IMPL(byte, 3) -BLIT_SAME_TYPE_IMPL(byte, 4) -BLIT_SAME_TYPE_IMPL(float, 1) -BLIT_SAME_TYPE_IMPL(float, 3) -BLIT_SAME_TYPE_IMPL(float, 4) - -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h) { - for (int y = 0; y < h; ++y) { - byte *dstPixel = dst(dx, dy+y); - for (int x = 0; x < w; ++x) { - const float *srcPixel = src(sx+x, sy+y); - *dstPixel++ = msdfgen::pixelFloatToByte(*srcPixel); - } - } -} - -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h) { - for (int y = 0; y < h; ++y) { - byte *dstPixel = dst(dx, dy+y); - for (int x = 0; x < w; ++x) { - const float *srcPixel = src(sx+x, sy+y); - *dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[0]); - *dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[1]); - *dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[2]); - } - } -} - -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h) { - for (int y = 0; y < h; ++y) { - byte *dstPixel = dst(dx, dy+y); - for (int x = 0; x < w; ++x) { - const float *srcPixel = src(sx+x, sy+y); - *dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[0]); - *dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[1]); - *dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[2]); - *dstPixel++ = msdfgen::pixelFloatToByte(srcPixel[3]); - } - } -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/bitmap-blit.h b/Nuake/src/Vendors/msdf-atlas-gen/bitmap-blit.h deleted file mode 100644 index b186d120..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/bitmap-blit.h +++ /dev/null @@ -1,26 +0,0 @@ - -#pragma once - -#include -#include "types.h" - -namespace msdf_atlas { - -/* - * Copies a rectangular section from source bitmap to destination bitmap. - * Width and height are not checked and must not exceed bitmap bounds! - */ - -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); - -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); - -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); -void blit(const msdfgen::BitmapRef &dst, const msdfgen::BitmapConstRef &src, int dx, int dy, int sx, int sy, int w, int h); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/charset-parser.cpp b/Nuake/src/Vendors/msdf-atlas-gen/charset-parser.cpp deleted file mode 100644 index 23c68a3d..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/charset-parser.cpp +++ /dev/null @@ -1,250 +0,0 @@ - -#include "Charset.h" - -#include -#include -#include "utf8.h" - -namespace msdf_atlas { - -static char escapedChar(char c) { - switch (c) { - case '0': - return '\0'; - case 'n': case 'N': - return '\n'; - case 'r': case 'R': - return '\r'; - case 's': case 'S': - return ' '; - case 't': case 'T': - return '\t'; - case '\\': case '"': case '\'': - default: - return c; - } -} - -static int readWord(std::string &str, FILE *f) { - while (true) { - int c = fgetc(f); - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_') - str.push_back((char) c); - else - return c; - } -} - -static bool readString(std::string &str, FILE *f, char terminator) { - bool escape = false; - while (true) { - int c = fgetc(f); - if (c < 0) - return false; - if (escape) { - str.push_back(escapedChar((char) c)); - escape = false; - } else { - if (c == terminator) - return true; - else if (c == '\\') - escape = true; - else - str.push_back((char) c); - } - } -} - -static bool parseInt(int &i, const char *str) { - i = 0; - if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')) { // hex - str += 2; - for (; *str; ++str) { - if (*str >= '0' && *str <= '9') { - i <<= 4; - i += *str-'0'; - } else if (*str >= 'A' && *str <= 'F') { - i <<= 4; - i += *str-'A'+10; - } else if (*str >= 'a' && *str <= 'f') { - i <<= 4; - i += *str-'a'+10; - } else - return false; - } - } else { // dec - for (; *str; ++str) { - if (*str >= '0' && *str <= '9') { - i *= 10; - i += *str-'0'; - } else - return false; - } - } - return true; -} - -static std::string combinePath(const char *basePath, const char *relPath) { - if (relPath[0] == '/' || (relPath[0] && relPath[1] == ':')) // absolute path? - return relPath; - int lastSlash = -1; - for (int i = 0; basePath[i]; ++i) - if (basePath[i] == '/' || basePath[i] == '\\') - lastSlash = i; - if (lastSlash < 0) - return relPath; - return std::string(basePath, lastSlash+1)+relPath; -} - -bool Charset::load(const char *filename, bool disableCharLiterals) { - - if (FILE *f = fopen(filename, "rb")) { - - enum { - CLEAR, - TIGHT, - RANGE_BRACKET, - RANGE_START, - RANGE_SEPARATOR, - RANGE_END - } state = CLEAR; - - std::string buffer; - std::vector unicodeBuffer; - unicode_t rangeStart = 0; - for (int c = fgetc(f), start = true; c >= 0; start = false) { - switch (c) { - case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': // number - if (!(state == CLEAR || state == RANGE_BRACKET || state == RANGE_SEPARATOR)) - goto FAIL; - buffer.push_back((char) c); - c = readWord(buffer, f); - { - int cp; - if (!parseInt(cp, buffer.c_str())) - goto FAIL; - switch (state) { - case CLEAR: - if (cp >= 0) - add((unicode_t) cp); - state = TIGHT; - break; - case RANGE_BRACKET: - rangeStart = (unicode_t) cp; - state = RANGE_START; - break; - case RANGE_SEPARATOR: - for (unicode_t u = rangeStart; (int) u <= cp; ++u) - add(u); - state = RANGE_END; - break; - default:; - } - } - buffer.clear(); - continue; // next character already read - case '\'': // single UTF-8 character - if (!(state == CLEAR || state == RANGE_BRACKET || state == RANGE_SEPARATOR) || disableCharLiterals) - goto FAIL; - if (!readString(buffer, f, '\'')) - goto FAIL; - utf8Decode(unicodeBuffer, buffer.c_str()); - if (unicodeBuffer.size() == 1) { - switch (state) { - case CLEAR: - if (unicodeBuffer[0] > 0) - add(unicodeBuffer[0]); - state = TIGHT; - break; - case RANGE_BRACKET: - rangeStart = unicodeBuffer[0]; - state = RANGE_START; - break; - case RANGE_SEPARATOR: - for (unicode_t u = rangeStart; u <= unicodeBuffer[0]; ++u) - add(u); - state = RANGE_END; - break; - default:; - } - } else - goto FAIL; - unicodeBuffer.clear(); - buffer.clear(); - break; - case '"': // string of UTF-8 characters - if (state != CLEAR || disableCharLiterals) - goto FAIL; - if (!readString(buffer, f, '"')) - goto FAIL; - utf8Decode(unicodeBuffer, buffer.c_str()); - for (unicode_t cp : unicodeBuffer) - add(cp); - unicodeBuffer.clear(); - buffer.clear(); - state = TIGHT; - break; - case '[': // character range start - if (state != CLEAR) - goto FAIL; - state = RANGE_BRACKET; - break; - case ']': // character range end - if (state == RANGE_END) - state = TIGHT; - else - goto FAIL; - break; - case '@': // annotation - if (state != CLEAR) - goto FAIL; - c = readWord(buffer, f); - if (buffer == "include") { - while (c == ' ' || c == '\t' || c == '\n' || c == '\r') - c = fgetc(f); - if (c != '"') - goto FAIL; - buffer.clear(); - if (!readString(buffer, f, '"')) - goto FAIL; - load(combinePath(filename, buffer.c_str()).c_str()); - state = TIGHT; - } else - goto FAIL; - buffer.clear(); - break; - case ',': case ';': // separator - if (!(state == CLEAR || state == TIGHT)) { - if (state == RANGE_START) - state = RANGE_SEPARATOR; - else - goto FAIL; - } // else treat as whitespace - case ' ': case '\n': case '\r': case '\t': // whitespace - if (state == TIGHT) - state = CLEAR; - break; - case 0xef: // UTF-8 byte order mark - if (start) { - if (!(fgetc(f) == 0xbb && fgetc(f) == 0xbf)) - goto FAIL; - break; - } - default: // unexpected character - goto FAIL; - } - c = fgetc(f); - } - - fclose(f); - return state == CLEAR || state == TIGHT; - - FAIL: - fclose(f); - return false; - } - - return false; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/csv-export.cpp b/Nuake/src/Vendors/msdf-atlas-gen/csv-export.cpp deleted file mode 100644 index a85f9bc3..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/csv-export.cpp +++ /dev/null @@ -1,45 +0,0 @@ - -#include "csv-export.h" - -#include -#include "GlyphGeometry.h" - -namespace msdf_atlas { - -bool exportCSV(const FontGeometry *fonts, int fontCount, int atlasWidth, int atlasHeight, YDirection yDirection, const char *filename) { - FILE *f = fopen(filename, "w"); - if (!f) - return false; - - for (int i = 0; i < fontCount; ++i) { - for (const GlyphGeometry &glyph : fonts[i].getGlyphs()) { - double l, b, r, t; - if (fontCount > 1) - fprintf(f, "%d,", i); - fprintf(f, "%d,%.17g,", glyph.getIdentifier(fonts[i].getPreferredIdentifierType()), glyph.getAdvance()); - glyph.getQuadPlaneBounds(l, b, r, t); - switch (yDirection) { - case YDirection::BOTTOM_UP: - fprintf(f, "%.17g,%.17g,%.17g,%.17g,", l, b, r, t); - break; - case YDirection::TOP_DOWN: - fprintf(f, "%.17g,%.17g,%.17g,%.17g,", l, -t, r, -b); - break; - } - glyph.getQuadAtlasBounds(l, b, r, t); - switch (yDirection) { - case YDirection::BOTTOM_UP: - fprintf(f, "%.17g,%.17g,%.17g,%.17g\n", l, b, r, t); - break; - case YDirection::TOP_DOWN: - fprintf(f, "%.17g,%.17g,%.17g,%.17g\n", l, atlasHeight-t, r, atlasHeight-b); - break; - } - } - } - - fclose(f); - return true; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/csv-export.h b/Nuake/src/Vendors/msdf-atlas-gen/csv-export.h deleted file mode 100644 index 56d5c4c9..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/csv-export.h +++ /dev/null @@ -1,14 +0,0 @@ - -#pragma once - -#include "FontGeometry.h" - -namespace msdf_atlas { - -/** - * Writes the positioning data and atlas layout of the glyphs into a CSV file - * The columns are: font variant index (if fontCount > 1), glyph identifier (index or Unicode), horizontal advance, plane bounds (l, b, r, t), atlas bounds (l, b, r, t) - */ -bool exportCSV(const FontGeometry *fonts, int fontCount, int atlasWidth, int atlasHeight, YDirection yDirection, const char *filename); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/glyph-generators.cpp b/Nuake/src/Vendors/msdf-atlas-gen/glyph-generators.cpp deleted file mode 100644 index af4a325e..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/glyph-generators.cpp +++ /dev/null @@ -1,52 +0,0 @@ - -#include "glyph-generators.h" - -namespace msdf_atlas { - -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.getBoxProjection(), glyph.getBoxRange(), attribs.config); - if (attribs.scanlinePass) - msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxProjection(), MSDF_ATLAS_GLYPH_FILL_RULE); -} - -void psdfGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) { - msdfgen::generatePseudoSDF(output, glyph.getShape(), glyph.getBoxProjection(), glyph.getBoxRange(), attribs.config); - if (attribs.scanlinePass) - msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxProjection(), MSDF_ATLAS_GLYPH_FILL_RULE); -} - -void msdfGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) { - msdfgen::MSDFGeneratorConfig config = attribs.config; - if (attribs.scanlinePass) - config.errorCorrection.mode = msdfgen::ErrorCorrectionConfig::DISABLED; - msdfgen::generateMSDF(output, glyph.getShape(), glyph.getBoxProjection(), glyph.getBoxRange(), config); - if (attribs.scanlinePass) { - msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxProjection(), MSDF_ATLAS_GLYPH_FILL_RULE); - if (attribs.config.errorCorrection.mode != msdfgen::ErrorCorrectionConfig::DISABLED) { - config.errorCorrection.mode = attribs.config.errorCorrection.mode; - config.errorCorrection.distanceCheckMode = msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE; - msdfgen::msdfErrorCorrection(output, glyph.getShape(), glyph.getBoxProjection(), glyph.getBoxRange(), config); - } - } -} - -void mtsdfGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs) { - msdfgen::MSDFGeneratorConfig config = attribs.config; - if (attribs.scanlinePass) - config.errorCorrection.mode = msdfgen::ErrorCorrectionConfig::DISABLED; - msdfgen::generateMTSDF(output, glyph.getShape(), glyph.getBoxProjection(), glyph.getBoxRange(), config); - if (attribs.scanlinePass) { - msdfgen::distanceSignCorrection(output, glyph.getShape(), glyph.getBoxProjection(), MSDF_ATLAS_GLYPH_FILL_RULE); - if (attribs.config.errorCorrection.mode != msdfgen::ErrorCorrectionConfig::DISABLED) { - config.errorCorrection.mode = attribs.config.errorCorrection.mode; - config.errorCorrection.distanceCheckMode = msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE; - msdfgen::msdfErrorCorrection(output, glyph.getShape(), glyph.getBoxProjection(), glyph.getBoxRange(), config); - } - } -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/glyph-generators.h b/Nuake/src/Vendors/msdf-atlas-gen/glyph-generators.h deleted file mode 100644 index 1df7c24d..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/glyph-generators.h +++ /dev/null @@ -1,25 +0,0 @@ - -#pragma once - -#include -#include "GlyphGeometry.h" -#include "AtlasGenerator.h" - -#define MSDF_ATLAS_GLYPH_FILL_RULE msdfgen::FILL_NONZERO - -namespace msdf_atlas { - -// Glyph bitmap generator functions - -/// Generates non-anti-aliased binary image of the glyph using scanline rasterization -void scanlineGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs); -/// Generates a true signed distance field of the glyph -void sdfGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs); -/// Generates a signed pseudo-distance field of the glyph -void psdfGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs); -/// Generates a multi-channel signed distance field of the glyph -void msdfGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs); -/// Generates a multi-channel and alpha-encoded true signed distance field of the glyph -void mtsdfGenerator(const msdfgen::BitmapRef &output, const GlyphGeometry &glyph, const GeneratorAttributes &attribs); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/icon.ico b/Nuake/src/Vendors/msdf-atlas-gen/icon.ico deleted file mode 100644 index 09e1a936..00000000 Binary files a/Nuake/src/Vendors/msdf-atlas-gen/icon.ico and /dev/null differ diff --git a/Nuake/src/Vendors/msdf-atlas-gen/image-encode.cpp b/Nuake/src/Vendors/msdf-atlas-gen/image-encode.cpp deleted file mode 100644 index b34fc5a0..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/image-encode.cpp +++ /dev/null @@ -1,63 +0,0 @@ - -#include "image-encode.h" - -#include - -namespace msdf_atlas { - -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap) { - std::vector pixels(bitmap.width*bitmap.height); - for (int y = 0; y < bitmap.height; ++y) - memcpy(&pixels[bitmap.width*y], bitmap(0, bitmap.height-y-1), bitmap.width); - return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_GREY); -} - -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap) { - std::vector pixels(3*bitmap.width*bitmap.height); - for (int y = 0; y < bitmap.height; ++y) - memcpy(&pixels[3*bitmap.width*y], bitmap(0, bitmap.height-y-1), 3*bitmap.width); - return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGB); -} - -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap) { - std::vector pixels(4*bitmap.width*bitmap.height); - for (int y = 0; y < bitmap.height; ++y) - memcpy(&pixels[4*bitmap.width*y], bitmap(0, bitmap.height-y-1), 4*bitmap.width); - return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGBA); -} - -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap) { - std::vector pixels(bitmap.width*bitmap.height); - std::vector::iterator it = pixels.begin(); - for (int y = bitmap.height-1; y >= 0; --y) - for (int x = 0; x < bitmap.width; ++x) - *it++ = msdfgen::pixelFloatToByte(*bitmap(x, y)); - return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_GREY); -} - -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap) { - std::vector pixels(3*bitmap.width*bitmap.height); - std::vector::iterator it = pixels.begin(); - for (int y = bitmap.height-1; y >= 0; --y) - for (int x = 0; x < bitmap.width; ++x) { - *it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[0]); - *it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[1]); - *it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[2]); - } - return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGB); -} - -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap) { - std::vector pixels(4*bitmap.width*bitmap.height); - std::vector::iterator it = pixels.begin(); - for (int y = bitmap.height-1; y >= 0; --y) - for (int x = 0; x < bitmap.width; ++x) { - *it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[0]); - *it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[1]); - *it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[2]); - *it++ = msdfgen::pixelFloatToByte(bitmap(x, y)[3]); - } - return !lodepng::encode(output, pixels, bitmap.width, bitmap.height, LCT_RGBA); -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/image-encode.h b/Nuake/src/Vendors/msdf-atlas-gen/image-encode.h deleted file mode 100644 index 59a8fc59..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/image-encode.h +++ /dev/null @@ -1,20 +0,0 @@ - -#pragma once - -#include -#include -#include "types.h" - -namespace msdf_atlas { - -// Functions to encode an image as a sequence of bytes in memory -// Only PNG format available currently - -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap); -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap); -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap); -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap); -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap); -bool encodePng(std::vector &output, const msdfgen::BitmapConstRef &bitmap); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/image-save.h b/Nuake/src/Vendors/msdf-atlas-gen/image-save.h deleted file mode 100644 index 0a0b37e8..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/image-save.h +++ /dev/null @@ -1,15 +0,0 @@ - -#pragma once - -#include -#include "types.h" - -namespace msdf_atlas { - -/// Saves the bitmap as an image file with the specified format -template -bool saveImage(const msdfgen::BitmapConstRef &bitmap, ImageFormat format, const char *filename, YDirection outputYDirection = YDirection::BOTTOM_UP); - -} - -#include "image-save.hpp" diff --git a/Nuake/src/Vendors/msdf-atlas-gen/image-save.hpp b/Nuake/src/Vendors/msdf-atlas-gen/image-save.hpp deleted file mode 100644 index 861f9830..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/image-save.hpp +++ /dev/null @@ -1,172 +0,0 @@ - -#include "image-save.h" - -#include -#include - -namespace msdf_atlas { - -template -bool saveImageBinary(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection); -template -bool saveImageBinaryLE(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection); -template -bool saveImageBinaryBE(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection); - -template -bool saveImageText(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection); -template -bool saveImageText(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection); - -template -bool saveImage(const msdfgen::BitmapConstRef &bitmap, ImageFormat format, const char *filename, YDirection outputYDirection) { - switch (format) { - //case ImageFormat::PNG: - // return msdfgen::savePng(bitmap, filename); - case ImageFormat::BMP: - return msdfgen::saveBmp(bitmap, filename); - case ImageFormat::TIFF: - return false; - case ImageFormat::TEXT: - return saveImageText(bitmap, filename, outputYDirection); - case ImageFormat::TEXT_FLOAT: - return false; - case ImageFormat::BINARY: - return saveImageBinary(bitmap, filename, outputYDirection); - case ImageFormat::BINARY_FLOAT: - case ImageFormat::BINARY_FLOAT_BE: - return false; - default:; - } - return false; -} - -template -bool saveImage(const msdfgen::BitmapConstRef &bitmap, ImageFormat format, const char *filename, YDirection outputYDirection) { - switch (format) { - case ImageFormat::PNG: - return msdfgen::savePng(bitmap, filename); - case ImageFormat::BMP: - return msdfgen::saveBmp(bitmap, filename); - case ImageFormat::TIFF: - return msdfgen::saveTiff(bitmap, filename); - case ImageFormat::TEXT: - return false; - case ImageFormat::TEXT_FLOAT: - return saveImageText(bitmap, filename, outputYDirection); - case ImageFormat::BINARY: - return false; - case ImageFormat::BINARY_FLOAT: - return saveImageBinaryLE(bitmap, filename, outputYDirection); - case ImageFormat::BINARY_FLOAT_BE: - return saveImageBinaryBE(bitmap, filename, outputYDirection); - default:; - } - return false; -} - -template -bool saveImageBinary(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection) { - bool success = false; - if (FILE *f = fopen(filename, "wb")) { - int written = 0; - switch (outputYDirection) { - case YDirection::BOTTOM_UP: - written = fwrite(bitmap.pixels, 1, N*bitmap.width*bitmap.height, f); - break; - case YDirection::TOP_DOWN: - for (int y = bitmap.height-1; y >= 0; --y) - written += fwrite(bitmap.pixels+N*bitmap.width*y, 1, N*bitmap.width, f); - break; - } - success = written == N*bitmap.width*bitmap.height; - fclose(f); - } - return success; -} - -template -bool - #ifdef __BIG_ENDIAN__ - saveImageBinaryBE - #else - saveImageBinaryLE - #endif - (const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection) { - bool success = false; - if (FILE *f = fopen(filename, "wb")) { - int written = 0; - switch (outputYDirection) { - case YDirection::BOTTOM_UP: - written = fwrite(bitmap.pixels, sizeof(float), N*bitmap.width*bitmap.height, f); - break; - case YDirection::TOP_DOWN: - for (int y = bitmap.height-1; y >= 0; --y) - written += fwrite(bitmap.pixels+N*bitmap.width*y, sizeof(float), N*bitmap.width, f); - break; - } - success = written == N*bitmap.width*bitmap.height; - fclose(f); - } - return success; -} - -template -bool - #ifdef __BIG_ENDIAN__ - saveImageBinaryLE - #else - saveImageBinaryBE - #endif - (const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection) { - bool success = false; - if (FILE *f = fopen(filename, "wb")) { - int written = 0; - for (int y = 0; y < bitmap.height; ++y) { - const float *p = bitmap.pixels+N*bitmap.width*(outputYDirection == YDirection::TOP_DOWN ? bitmap.height-y-1 : y); - for (int x = 0; x < bitmap.width; ++x) { - const unsigned char *b = reinterpret_cast(p++); - for (int i = sizeof(float)-1; i >= 0; --i) - written += fwrite(b+i, 1, 1, f); - } - } - success = written == sizeof(float)*N*bitmap.width*bitmap.height; - fclose(f); - } - return success; -} - - -template -bool saveImageText(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection) { - bool success = false; - if (FILE *f = fopen(filename, "wb")) { - for (int y = 0; y < bitmap.height; ++y) { - const byte *p = bitmap.pixels+N*bitmap.width*(outputYDirection == YDirection::TOP_DOWN ? bitmap.height-y-1 : y); - for (int x = 0; x < N*bitmap.width; ++x) { - fprintf(f, x ? " %02X" : "%02X", (unsigned) *p++); - } - fprintf(f, "\n"); - } - fclose(f); - } - return success; -} - -template -bool saveImageText(const msdfgen::BitmapConstRef &bitmap, const char *filename, YDirection outputYDirection) { - bool success = false; - if (FILE *f = fopen(filename, "wb")) { - for (int y = 0; y < bitmap.height; ++y) { - const float *p = bitmap.pixels+N*bitmap.width*(outputYDirection == YDirection::TOP_DOWN ? bitmap.height-y-1 : y); - for (int x = 0; x < N*bitmap.width; ++x) { - fprintf(f, x ? " %g" : "%g", *p++); - } - fprintf(f, "\n"); - } - fclose(f); - } - return success; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/json-export.cpp b/Nuake/src/Vendors/msdf-atlas-gen/json-export.cpp deleted file mode 100644 index 2bf24dc3..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/json-export.cpp +++ /dev/null @@ -1,186 +0,0 @@ - -#include "json-export.h" - -#include -#include "GlyphGeometry.h" - -namespace msdf_atlas { - -static std::string escapeJsonString(const char *str) { - char uval[7] = "\\u0000"; - std::string outStr; - while (*str) { - switch (*str) { - case '\\': - outStr += "\\\\"; - break; - case '"': - outStr += "\\\""; - break; - case '\n': - outStr += "\\n"; - break; - case '\r': - outStr += "\\r"; - break; - case '\t': - outStr += "\\t"; - break; - case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: /* \\t */ /* \\n */ case 0x0b: case 0x0c: /* \\r */ case 0x0e: case 0x0f: - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: - uval[4] = '0'+(*str >= 0x10); - uval[5] = "0123456789abcdef"[*str&0x0f]; - outStr += uval; - break; - default: - outStr.push_back(*str); - } - ++str; - } - return outStr; -} - -static const char * imageTypeString(ImageType type) { - switch (type) { - case ImageType::HARD_MASK: - return "hardmask"; - case ImageType::SOFT_MASK: - return "softmask"; - case ImageType::SDF: - return "sdf"; - case ImageType::PSDF: - return "psdf"; - case ImageType::MSDF: - return "msdf"; - case ImageType::MTSDF: - return "mtsdf"; - } - return nullptr; -} - -bool exportJSON(const FontGeometry *fonts, int fontCount, double fontSize, double pxRange, int atlasWidth, int atlasHeight, ImageType imageType, YDirection yDirection, const char *filename, bool kerning) { - FILE *f = fopen(filename, "w"); - if (!f) - return false; - fputs("{", f); - - // Atlas properties - fputs("\"atlas\":{", f); { - fprintf(f, "\"type\":\"%s\",", imageTypeString(imageType)); - if (imageType == ImageType::SDF || imageType == ImageType::PSDF || imageType == ImageType::MSDF || imageType == ImageType::MTSDF) - fprintf(f, "\"distanceRange\":%.17g,", pxRange); - fprintf(f, "\"size\":%.17g,", fontSize); - fprintf(f, "\"width\":%d,", atlasWidth); - fprintf(f, "\"height\":%d,", atlasHeight); - fprintf(f, "\"yOrigin\":\"%s\"", yDirection == YDirection::TOP_DOWN ? "top" : "bottom"); - } fputs("},", f); - - if (fontCount > 1) - fputs("\"variants\":[", f); - for (int i = 0; i < fontCount; ++i) { - const FontGeometry &font = fonts[i]; - if (fontCount > 1) - fputs(i == 0 ? "{" : ",{", f); - - // Font name - const char *name = font.getName(); - if (name) - fprintf(f, "\"name\":\"%s\",", escapeJsonString(name).c_str()); - - // Font metrics - fputs("\"metrics\":{", f); { - double yFactor = yDirection == YDirection::TOP_DOWN ? -1 : 1; - const msdfgen::FontMetrics &metrics = font.getMetrics(); - fprintf(f, "\"emSize\":%.17g,", metrics.emSize); - fprintf(f, "\"lineHeight\":%.17g,", metrics.lineHeight); - fprintf(f, "\"ascender\":%.17g,", yFactor*metrics.ascenderY); - fprintf(f, "\"descender\":%.17g,", yFactor*metrics.descenderY); - fprintf(f, "\"underlineY\":%.17g,", yFactor*metrics.underlineY); - fprintf(f, "\"underlineThickness\":%.17g", metrics.underlineThickness); - } fputs("},", f); - - // Glyph mapping - fputs("\"glyphs\":[", f); - bool firstGlyph = true; - for (const GlyphGeometry &glyph : font.getGlyphs()) { - fputs(firstGlyph ? "{" : ",{", f); - switch (font.getPreferredIdentifierType()) { - case GlyphIdentifierType::GLYPH_INDEX: - fprintf(f, "\"index\":%d,", glyph.getIndex()); - break; - case GlyphIdentifierType::UNICODE_CODEPOINT: - fprintf(f, "\"unicode\":%u,", glyph.getCodepoint()); - break; - } - fprintf(f, "\"advance\":%.17g", glyph.getAdvance()); - double l, b, r, t; - glyph.getQuadPlaneBounds(l, b, r, t); - if (l || b || r || t) { - switch (yDirection) { - case YDirection::BOTTOM_UP: - fprintf(f, ",\"planeBounds\":{\"left\":%.17g,\"bottom\":%.17g,\"right\":%.17g,\"top\":%.17g}", l, b, r, t); - break; - case YDirection::TOP_DOWN: - fprintf(f, ",\"planeBounds\":{\"left\":%.17g,\"top\":%.17g,\"right\":%.17g,\"bottom\":%.17g}", l, -t, r, -b); - break; - } - } - glyph.getQuadAtlasBounds(l, b, r, t); - if (l || b || r || t) { - switch (yDirection) { - case YDirection::BOTTOM_UP: - fprintf(f, ",\"atlasBounds\":{\"left\":%.17g,\"bottom\":%.17g,\"right\":%.17g,\"top\":%.17g}", l, b, r, t); - break; - case YDirection::TOP_DOWN: - fprintf(f, ",\"atlasBounds\":{\"left\":%.17g,\"top\":%.17g,\"right\":%.17g,\"bottom\":%.17g}", l, atlasHeight-t, r, atlasHeight-b); - break; - } - } - fputs("}", f); - firstGlyph = false; - } fputs("]", f); - - // Kerning pairs - if (kerning) { - fputs(",\"kerning\":[", f); - bool firstPair = true; - switch (font.getPreferredIdentifierType()) { - case GlyphIdentifierType::GLYPH_INDEX: - for (const std::pair, double> &kernPair : font.getKerning()) { - fputs(firstPair ? "{" : ",{", f); - fprintf(f, "\"index1\":%d,", kernPair.first.first); - fprintf(f, "\"index2\":%d,", kernPair.first.second); - fprintf(f, "\"advance\":%.17g", kernPair.second); - fputs("}", f); - firstPair = false; - } - break; - case GlyphIdentifierType::UNICODE_CODEPOINT: - for (const std::pair, double> &kernPair : font.getKerning()) { - const GlyphGeometry *glyph1 = font.getGlyph(msdfgen::GlyphIndex(kernPair.first.first)); - const GlyphGeometry *glyph2 = font.getGlyph(msdfgen::GlyphIndex(kernPair.first.second)); - if (glyph1 && glyph2 && glyph1->getCodepoint() && glyph2->getCodepoint()) { - fputs(firstPair ? "{" : ",{", f); - fprintf(f, "\"unicode1\":%u,", glyph1->getCodepoint()); - fprintf(f, "\"unicode2\":%u,", glyph2->getCodepoint()); - fprintf(f, "\"advance\":%.17g", kernPair.second); - fputs("}", f); - firstPair = false; - } - } - break; - } fputs("]", f); - } - - if (fontCount > 1) - fputs("}", f); - } - if (fontCount > 1) - fputs("]", f); - - fputs("}\n", f); - fclose(f); - return true; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/json-export.h b/Nuake/src/Vendors/msdf-atlas-gen/json-export.h deleted file mode 100644 index fe7bc042..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/json-export.h +++ /dev/null @@ -1,14 +0,0 @@ - -#pragma once - -#include -#include -#include "types.h" -#include "FontGeometry.h" - -namespace msdf_atlas { - -/// Writes the font and glyph metrics and atlas layout data into a comprehensive JSON file -bool exportJSON(const FontGeometry *fonts, int fontCount, double fontSize, double pxRange, int atlasWidth, int atlasHeight, ImageType imageType, YDirection yDirection, const char *filename, bool kerning); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/main.cpp b/Nuake/src/Vendors/msdf-atlas-gen/main.cpp deleted file mode 100644 index 5c13f0ee..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/main.cpp +++ /dev/null @@ -1,999 +0,0 @@ - -/* -* MULTI-CHANNEL SIGNED DISTANCE FIELD ATLAS GENERATOR v1.2 (2021-05-29) - standalone console program -* -------------------------------------------------------------------------------------------------- -* A utility by Viktor Chlumsky, (c) 2020 - 2021 -* -*/ - -#ifdef MSDF_ATLAS_STANDALONE - -#define _USE_MATH_DEFINES -#include -#include -#include -#include -#include -#include -#include - -#include "msdf-atlas-gen.h" - -using namespace msdf_atlas; - -#define DEFAULT_ANGLE_THRESHOLD 3.0 -#define DEFAULT_MITER_LIMIT 1.0 -#define DEFAULT_PIXEL_RANGE 2.0 -#define SDF_ERROR_ESTIMATE_PRECISION 19 -#define GLYPH_FILL_RULE msdfgen::FILL_NONZERO -#define LCG_MULTIPLIER 6364136223846793005ull -#define LCG_INCREMENT 1442695040888963407ull - -#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 TITLE_SUFFIX R"() -----------------------------------------------------------------)" EXTRA_UNDERLINE R"( - -INPUT SPECIFICATION - -font - Specifies the input TrueType / OpenType font file. This is required. - -charset - Specifies the input character set. Refer to the documentation for format of charset specification. Defaults to ASCII. - -glyphset - Specifies the set of input glyphs as glyph indices within the font file. - -fontscale - Specifies the scale to be applied to the glyph geometry of the font. - -fontname - Specifies a name for the font that will be propagated into the output files as metadata. - -and - Separates multiple inputs to be combined into a single atlas. - -ATLAS CONFIGURATION - -type - Selects the type of atlas to be generated. - -format - Selects the format for the atlas image output. Some image formats may be incompatible with embedded output formats. - -dimensions - Sets the atlas to have fixed dimensions (width x height). - -pots / -potr / -square / -square2 / -square4 - Picks the minimum atlas dimensions that fit all glyphs and satisfy the selected constraint: - power of two square / ... rectangle / any square / square with side divisible by 2 / ... 4 - -yorigin - Determines whether the Y-axis is oriented upwards (bottom origin, default) or downwards (top origin). - -OUTPUT SPECIFICATION - one or more can be specified - -imageout - Saves the atlas as an image file with the specified format. Layout data must be stored separately. - -json - Writes the atlas's layout data, as well as other metrics into a structured JSON file. - -csv - Writes the layout data of the glyphs into a simple CSV file. - -arfont - Stores the atlas and its layout data as an Artery Font file. Supported formats: png, bin, binfloat. - -shadronpreview - Generates a Shadron script that uses the generated atlas to draw a sample text as a preview. - -GLYPH CONFIGURATION - -size - Specifies the size of the glyphs in the atlas bitmap in pixels per EM. - -minsize - Specifies the minimum size. The largest possible size that fits the same atlas dimensions will be used. - -emrange - Specifies the SDF distance range in EM's. - -pxrange - Specifies the SDF distance range in output pixels. The default value is 2. - -nokerning - Disables inclusion of kerning pair table in output files. - -DISTANCE FIELD GENERATOR SETTINGS - -angle - Specifies the minimum angle between adjacent edges to be considered a corner. Append D for degrees. (msdf / mtsdf only) - -coloringstrategy - Selects the strategy of the edge coloring heuristic. - -errorcorrection - Changes the MSDF/MTSDF error correction mode. Use -errorcorrection help for a list of valid modes. - -errordeviationratio - Sets the minimum ratio between the actual and maximum expected distance delta to be considered an error. - -errorimproveratio - Sets the minimum ratio between the pre-correction distance error and the post-correction distance error. - -miterlimit - 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.)" -#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 const char *errorCorrectionHelpText = R"( -ERROR CORRECTION MODES - auto-fast - Detects inversion artifacts and distance errors that do not affect edges by range testing. - auto-full - Detects inversion artifacts and distance errors that do not affect edges by exact distance evaluation. - auto-mixed (default) - Detects inversions by distance evaluation and distance errors that do not affect edges by range testing. - disabled - Disables error correction. - distance-fast - Detects distance errors by range testing. Does not care if edges and corners are affected. - distance-full - Detects distance errors by exact distance evaluation. Does not care if edges and corners are affected, slow. - edge-fast - Detects inversion artifacts only by range testing. - edge-full - Detects inversion artifacts only by exact distance evaluation. - help - Displays this help. -)"; - -static char toupper(char c) { - return c >= 'a' && c <= 'z' ? c-'a'+'A' : c; -} - -static bool parseUnsigned(unsigned &value, const char *arg) { - static char c; - return sscanf(arg, "%u%c", &value, &c) == 1; -} - -static bool parseUnsignedLL(unsigned long long &value, const char *arg) { - static char c; - return sscanf(arg, "%llu%c", &value, &c) == 1; -} - -static bool parseDouble(double &value, const char *arg) { - static char c; - return sscanf(arg, "%lf%c", &value, &c) == 1; -} - -static bool parseAngle(double &value, const char *arg) { - char c1, c2; - int result = sscanf(arg, "%lf%c%c", &value, &c1, &c2); - if (result == 1) - return true; - if (result == 2 && (c1 == 'd' || c1 == 'D')) { - value *= M_PI/180; - return true; - } - return false; -} - -static bool cmpExtension(const char *path, const char *ext) { - for (const char *a = path+strlen(path)-1, *b = ext+strlen(ext)-1; b >= ext; --a, --b) - if (a < path || toupper(*a) != toupper(*b)) - return false; - return true; -} - -struct FontInput { - const char *fontFilename; - GlyphIdentifierType glyphIdentifierType; - const char *charsetFilename; - double fontScale; - const char *fontName; -}; - -struct Configuration { - ImageType imageType; - ImageFormat imageFormat; - YDirection yDirection; - int width, height; - double emSize; - double pxRange; - double angleThreshold; - double miterLimit; - void (*edgeColoring)(msdfgen::Shape &, double, unsigned long long); - bool expensiveColoring; - unsigned long long coloringSeed; - GeneratorAttributes generatorAttributes; - bool preprocessGeometry; - bool kerning; - int threadCount; - const char *arteryFontFilename; - const char *imageFilename; - const char *jsonFilename; - const char *csvFilename; - const char *shadronPreviewFilename; - const char *shadronPreviewText; -}; - -template GEN_FN> -static bool makeAtlas(const std::vector &glyphs, const std::vector &fonts, const Configuration &config) { - ImmediateAtlasGenerator > generator(config.width, config.height); - generator.setAttributes(config.generatorAttributes); - generator.setThreadCount(config.threadCount); - generator.generate(glyphs.data(), glyphs.size()); - msdfgen::BitmapConstRef bitmap = (msdfgen::BitmapConstRef) generator.atlasStorage(); - - bool success = true; - - if (config.imageFilename) { - if (saveImage(bitmap, config.imageFormat, config.imageFilename, config.yDirection)) - puts("Atlas image file saved."); - else { - success = false; - puts("Failed to save the atlas as an image file."); - } - } - - if (config.arteryFontFilename) { - ArteryFontExportProperties arfontProps; - arfontProps.fontSize = config.emSize; - arfontProps.pxRange = config.pxRange; - arfontProps.imageType = config.imageType; - arfontProps.imageFormat = config.imageFormat; - arfontProps.yDirection = config.yDirection; - if (exportArteryFont(fonts.data(), fonts.size(), bitmap, config.arteryFontFilename, arfontProps)) - puts("Artery Font file generated."); - else { - success = false; - puts("Failed to generate Artery Font file."); - } - } - - return success; -} - -int main(int argc, const char * const *argv) { - #define ABORT(msg) { puts(msg); return 1; } - - int result = 0; - std::vector fontInputs; - FontInput fontInput = { }; - Configuration config = { }; - fontInput.glyphIdentifierType = GlyphIdentifierType::UNICODE_CODEPOINT; - fontInput.fontScale = -1; - config.imageType = ImageType::MSDF; - config.imageFormat = ImageFormat::UNSPECIFIED; - config.yDirection = YDirection::BOTTOM_UP; - config.edgeColoring = msdfgen::edgeColoringInkTrap; - config.kerning = true; - const char *imageFormatName = nullptr; - int fixedWidth = -1, fixedHeight = -1; - config.preprocessGeometry = ( - #ifdef MSDFGEN_USE_SKIA - true - #else - false - #endif - ); - config.generatorAttributes.config.overlapSupport = !config.preprocessGeometry; - config.generatorAttributes.scanlinePass = !config.preprocessGeometry; - double minEmSize = 0; - enum { - /// Range specified in EMs - RANGE_EM, - /// Range specified in output pixels - RANGE_PIXEL, - } rangeMode = RANGE_PIXEL; - double rangeValue = 0; - TightAtlasPacker::DimensionsConstraint atlasSizeConstraint = TightAtlasPacker::DimensionsConstraint::MULTIPLE_OF_FOUR_SQUARE; - config.angleThreshold = DEFAULT_ANGLE_THRESHOLD; - config.miterLimit = DEFAULT_MITER_LIMIT; - config.threadCount = 0; - - // Parse command line - int argPos = 1; - bool suggestHelp = false; - bool explicitErrorCorrectionMode = false; - while (argPos < argc) { - const char *arg = argv[argPos]; - #define ARG_CASE(s, p) if (!strcmp(arg, s) && argPos+(p) < argc) - - ARG_CASE("-type", 1) { - arg = argv[++argPos]; - if (!strcmp(arg, "hardmask")) - config.imageType = ImageType::HARD_MASK; - else if (!strcmp(arg, "softmask")) - config.imageType = ImageType::SOFT_MASK; - else if (!strcmp(arg, "sdf")) - config.imageType = ImageType::SDF; - else if (!strcmp(arg, "psdf")) - config.imageType = ImageType::PSDF; - else if (!strcmp(arg, "msdf")) - config.imageType = ImageType::MSDF; - else if (!strcmp(arg, "mtsdf")) - config.imageType = ImageType::MTSDF; - else - ABORT("Invalid atlas type. Valid types are: hardmask, softmask, sdf, psdf, msdf, mtsdf"); - ++argPos; - continue; - } - ARG_CASE("-format", 1) { - arg = argv[++argPos]; - if (!strcmp(arg, "png")) - config.imageFormat = ImageFormat::PNG; - else if (!strcmp(arg, "bmp")) - config.imageFormat = ImageFormat::BMP; - else if (!strcmp(arg, "tiff")) - config.imageFormat = ImageFormat::TIFF; - else if (!strcmp(arg, "text")) - config.imageFormat = ImageFormat::TEXT; - else if (!strcmp(arg, "textfloat")) - config.imageFormat = ImageFormat::TEXT_FLOAT; - else if (!strcmp(arg, "bin")) - config.imageFormat = ImageFormat::BINARY; - else if (!strcmp(arg, "binfloat")) - config.imageFormat = ImageFormat::BINARY_FLOAT; - else if (!strcmp(arg, "binfloatbe")) - config.imageFormat = ImageFormat::BINARY_FLOAT_BE; - else - ABORT("Invalid image format. Valid formats are: png, bmp, tiff, text, textfloat, bin, binfloat"); - imageFormatName = arg; - ++argPos; - continue; - } - ARG_CASE("-font", 1) { - fontInput.fontFilename = argv[++argPos]; - ++argPos; - continue; - } - ARG_CASE("-charset", 1) { - fontInput.charsetFilename = argv[++argPos]; - fontInput.glyphIdentifierType = GlyphIdentifierType::UNICODE_CODEPOINT; - ++argPos; - continue; - } - ARG_CASE("-glyphset", 1) { - fontInput.charsetFilename = argv[++argPos]; - fontInput.glyphIdentifierType = GlyphIdentifierType::GLYPH_INDEX; - ++argPos; - continue; - } - ARG_CASE("-fontscale", 1) { - double fs; - if (!(parseDouble(fs, argv[++argPos]) && fs > 0)) - ABORT("Invalid font scale argument. Use -fontscale with a positive real number."); - fontInput.fontScale = fs; - ++argPos; - continue; - } - ARG_CASE("-fontname", 1) { - fontInput.fontName = argv[++argPos]; - ++argPos; - continue; - } - ARG_CASE("-and", 0) { - if (!fontInput.fontFilename && !fontInput.charsetFilename && fontInput.fontScale < 0) - ABORT("No font, character set, or font scale specified before -and separator."); - if (!fontInputs.empty() && !memcmp(&fontInputs.back(), &fontInput, sizeof(FontInput))) - ABORT("No changes between subsequent inputs. A different font, character set, or font scale must be set inbetween -and separators."); - fontInputs.push_back(fontInput); - fontInput.fontName = nullptr; - ++argPos; - continue; - } - ARG_CASE("-arfont", 1) { - config.arteryFontFilename = argv[++argPos]; - ++argPos; - continue; - } - ARG_CASE("-imageout", 1) { - config.imageFilename = argv[++argPos]; - ++argPos; - continue; - } - ARG_CASE("-json", 1) { - config.jsonFilename = argv[++argPos]; - ++argPos; - continue; - } - ARG_CASE("-csv", 1) { - config.csvFilename = argv[++argPos]; - ++argPos; - continue; - } - ARG_CASE("-shadronpreview", 2) { - config.shadronPreviewFilename = argv[++argPos]; - config.shadronPreviewText = argv[++argPos]; - ++argPos; - continue; - } - ARG_CASE("-dimensions", 2) { - unsigned w, h; - if (!(parseUnsigned(w, argv[argPos+1]) && parseUnsigned(h, argv[argPos+2]) && w && h)) - ABORT("Invalid atlas dimensions. Use -dimensions with two positive integers."); - fixedWidth = w, fixedHeight = h; - argPos += 3; - continue; - } - ARG_CASE("-pots", 0) { - atlasSizeConstraint = TightAtlasPacker::DimensionsConstraint::POWER_OF_TWO_SQUARE; - fixedWidth = -1, fixedHeight = -1; - ++argPos; - continue; - } - ARG_CASE("-potr", 0) { - atlasSizeConstraint = TightAtlasPacker::DimensionsConstraint::POWER_OF_TWO_RECTANGLE; - fixedWidth = -1, fixedHeight = -1; - ++argPos; - continue; - } - ARG_CASE("-square", 0) { - atlasSizeConstraint = TightAtlasPacker::DimensionsConstraint::SQUARE; - fixedWidth = -1, fixedHeight = -1; - ++argPos; - continue; - } - ARG_CASE("-square2", 0) { - atlasSizeConstraint = TightAtlasPacker::DimensionsConstraint::EVEN_SQUARE; - fixedWidth = -1, fixedHeight = -1; - ++argPos; - continue; - } - ARG_CASE("-square4", 0) { - atlasSizeConstraint = TightAtlasPacker::DimensionsConstraint::MULTIPLE_OF_FOUR_SQUARE; - fixedWidth = -1, fixedHeight = -1; - ++argPos; - continue; - } - ARG_CASE("-yorigin", 1) { - arg = argv[++argPos]; - if (!strcmp(arg, "bottom")) - config.yDirection = YDirection::BOTTOM_UP; - else if (!strcmp(arg, "top")) - config.yDirection = YDirection::TOP_DOWN; - else - ABORT("Invalid Y-axis origin. Use bottom or top."); - ++argPos; - continue; - } - ARG_CASE("-size", 1) { - double s; - if (!(parseDouble(s, argv[++argPos]) && s > 0)) - ABORT("Invalid EM size argument. Use -size with a positive real number."); - config.emSize = s; - ++argPos; - continue; - } - ARG_CASE("-minsize", 1) { - double s; - if (!(parseDouble(s, argv[++argPos]) && s > 0)) - ABORT("Invalid minimum EM size argument. Use -minsize with a positive real number."); - minEmSize = s; - ++argPos; - continue; - } - ARG_CASE("-emrange", 1) { - double r; - if (!(parseDouble(r, argv[++argPos]) && r >= 0)) - ABORT("Invalid range argument. Use -emrange with a positive real number."); - rangeMode = RANGE_EM; - rangeValue = r; - ++argPos; - continue; - } - ARG_CASE("-pxrange", 1) { - double r; - if (!(parseDouble(r, argv[++argPos]) && r >= 0)) - ABORT("Invalid range argument. Use -pxrange with a positive real number."); - rangeMode = RANGE_PIXEL; - rangeValue = r; - ++argPos; - continue; - } - ARG_CASE("-angle", 1) { - double at; - if (!parseAngle(at, argv[argPos+1])) - ABORT("Invalid angle threshold. Use -angle with a positive real number less than PI or a value in degrees followed by 'd' below 180d."); - config.angleThreshold = at; - argPos += 2; - continue; - } - ARG_CASE("-errorcorrection", 1) { - msdfgen::ErrorCorrectionConfig &ec = config.generatorAttributes.config.errorCorrection; - if (!strcmp(argv[argPos+1], "disabled") || !strcmp(argv[argPos+1], "0") || !strcmp(argv[argPos+1], "none")) { - ec.mode = msdfgen::ErrorCorrectionConfig::DISABLED; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE; - } else if (!strcmp(argv[argPos+1], "default") || !strcmp(argv[argPos+1], "auto") || !strcmp(argv[argPos+1], "auto-mixed") || !strcmp(argv[argPos+1], "mixed")) { - ec.mode = msdfgen::ErrorCorrectionConfig::EDGE_PRIORITY; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::CHECK_DISTANCE_AT_EDGE; - } else if (!strcmp(argv[argPos+1], "auto-fast") || !strcmp(argv[argPos+1], "fast")) { - ec.mode = msdfgen::ErrorCorrectionConfig::EDGE_PRIORITY; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE; - } else if (!strcmp(argv[argPos+1], "auto-full") || !strcmp(argv[argPos+1], "full")) { - ec.mode = msdfgen::ErrorCorrectionConfig::EDGE_PRIORITY; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::ALWAYS_CHECK_DISTANCE; - } else if (!strcmp(argv[argPos+1], "distance") || !strcmp(argv[argPos+1], "distance-fast") || !strcmp(argv[argPos+1], "indiscriminate") || !strcmp(argv[argPos+1], "indiscriminate-fast")) { - ec.mode = msdfgen::ErrorCorrectionConfig::INDISCRIMINATE; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE; - } else if (!strcmp(argv[argPos+1], "distance-full") || !strcmp(argv[argPos+1], "indiscriminate-full")) { - ec.mode = msdfgen::ErrorCorrectionConfig::INDISCRIMINATE; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::ALWAYS_CHECK_DISTANCE; - } else if (!strcmp(argv[argPos+1], "edge-fast")) { - ec.mode = msdfgen::ErrorCorrectionConfig::EDGE_ONLY; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE; - } else if (!strcmp(argv[argPos+1], "edge") || !strcmp(argv[argPos+1], "edge-full")) { - ec.mode = msdfgen::ErrorCorrectionConfig::EDGE_ONLY; - ec.distanceCheckMode = msdfgen::ErrorCorrectionConfig::ALWAYS_CHECK_DISTANCE; - } else if (!strcmp(argv[argPos+1], "help")) { - puts(errorCorrectionHelpText); - return 0; - } else - ABORT("Unknown error correction mode. Use -errorcorrection help for more information."); - explicitErrorCorrectionMode = true; - argPos += 2; - continue; - } - ARG_CASE("-errordeviationratio", 1) { - double edr; - if (!(parseDouble(edr, argv[argPos+1]) && edr > 0)) - ABORT("Invalid error deviation ratio. Use -errordeviationratio with a positive real number."); - config.generatorAttributes.config.errorCorrection.minDeviationRatio = edr; - argPos += 2; - continue; - } - ARG_CASE("-errorimproveratio", 1) { - double eir; - if (!(parseDouble(eir, argv[argPos+1]) && eir > 0)) - ABORT("Invalid error improvement ratio. Use -errorimproveratio with a positive real number."); - config.generatorAttributes.config.errorCorrection.minImproveRatio = eir; - argPos += 2; - continue; - } - ARG_CASE("-coloringstrategy", 1) { - if (!strcmp(argv[argPos+1], "simple")) config.edgeColoring = msdfgen::edgeColoringSimple, config.expensiveColoring = false; - else if (!strcmp(argv[argPos+1], "inktrap")) config.edgeColoring = msdfgen::edgeColoringInkTrap, config.expensiveColoring = false; - else if (!strcmp(argv[argPos+1], "distance")) config.edgeColoring = msdfgen::edgeColoringByDistance, config.expensiveColoring = true; - else - puts("Unknown coloring strategy specified."); - argPos += 2; - continue; - } - ARG_CASE("-miterlimit", 1) { - double m; - if (!(parseDouble(m, argv[++argPos]) && m >= 0)) - ABORT("Invalid miter limit argument. Use -miterlimit with a positive real number."); - config.miterLimit = m; - ++argPos; - continue; - } - ARG_CASE("-nokerning", 0) { - config.kerning = false; - ++argPos; - continue; - } - ARG_CASE("-kerning", 0) { - config.kerning = true; - ++argPos; - continue; - } - ARG_CASE("-nopreprocess", 0) { - config.preprocessGeometry = false; - ++argPos; - continue; - } - ARG_CASE("-preprocess", 0) { - config.preprocessGeometry = true; - ++argPos; - continue; - } - ARG_CASE("-nooverlap", 0) { - config.generatorAttributes.config.overlapSupport = false; - ++argPos; - continue; - } - ARG_CASE("-overlap", 0) { - config.generatorAttributes.config.overlapSupport = true; - ++argPos; - continue; - } - ARG_CASE("-noscanline", 0) { - config.generatorAttributes.scanlinePass = false; - ++argPos; - continue; - } - ARG_CASE("-scanline", 0) { - config.generatorAttributes.scanlinePass = true; - ++argPos; - continue; - } - ARG_CASE("-seed", 1) { - if (!parseUnsignedLL(config.coloringSeed, argv[argPos+1])) - ABORT("Invalid seed. Use -seed with N being a non-negative integer."); - 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; - } - printf("Unknown setting or insufficient parameters: %s\n", arg); - suggestHelp = true; - ++argPos; - } - if (suggestHelp) - printf("Use -help for more information.\n"); - - // Nothing to do? - if (argc == 1) { - printf( - "Usage: msdf-atlas-gen" - #ifdef _WIN32 - ".exe" - #endif - " -font -charset \n" - "Use -help for more information.\n" - ); - return 0; - } - if (!fontInput.fontFilename) - ABORT("No font specified."); - if (!(config.arteryFontFilename || config.imageFilename || config.jsonFilename || config.csvFilename || config.shadronPreviewFilename)) { - puts("No output specified."); - return 0; - } - bool layoutOnly = !(config.arteryFontFilename || config.imageFilename); - - // Finalize font inputs - const FontInput *nextFontInput = &fontInput; - for (std::vector::reverse_iterator it = fontInputs.rbegin(); it != fontInputs.rend(); ++it) { - if (!it->fontFilename && nextFontInput->fontFilename) - it->fontFilename = nextFontInput->fontFilename; - if (!it->charsetFilename && nextFontInput->charsetFilename) { - it->charsetFilename = nextFontInput->charsetFilename; - it->glyphIdentifierType = nextFontInput->glyphIdentifierType; - } - if (it->fontScale < 0 && nextFontInput->fontScale >= 0) - it->fontScale = nextFontInput->fontScale; - nextFontInput = &*it; - } - if (fontInputs.empty() || memcmp(&fontInputs.back(), &fontInput, sizeof(FontInput))) - fontInputs.push_back(fontInput); - - // Fix up configuration based on related values - if (!(config.imageType == ImageType::PSDF || config.imageType == ImageType::MSDF || config.imageType == ImageType::MTSDF)) - config.miterLimit = 0; - if (config.emSize > minEmSize) - minEmSize = config.emSize; - if (!(fixedWidth > 0 && fixedHeight > 0) && !(minEmSize > 0)) { - puts("Neither atlas size nor glyph size selected, using default..."); - minEmSize = MSDF_ATLAS_DEFAULT_EM_SIZE; - } - if (!(config.imageType == ImageType::SDF || config.imageType == ImageType::PSDF || config.imageType == ImageType::MSDF || config.imageType == ImageType::MTSDF)) { - rangeMode = RANGE_PIXEL; - rangeValue = (double) (config.imageType == ImageType::SOFT_MASK); - } else if (rangeValue <= 0) { - rangeMode = RANGE_PIXEL; - rangeValue = DEFAULT_PIXEL_RANGE; - } - if (config.kerning && !(config.arteryFontFilename || config.jsonFilename || config.shadronPreviewFilename)) - config.kerning = false; - if (config.threadCount <= 0) - config.threadCount = std::max((int) std::thread::hardware_concurrency(), 1); - if (config.generatorAttributes.scanlinePass) { - if (explicitErrorCorrectionMode && config.generatorAttributes.config.errorCorrection.distanceCheckMode != msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE) { - const char *fallbackModeName = "unknown"; - switch (config.generatorAttributes.config.errorCorrection.mode) { - case msdfgen::ErrorCorrectionConfig::DISABLED: fallbackModeName = "disabled"; break; - case msdfgen::ErrorCorrectionConfig::INDISCRIMINATE: fallbackModeName = "distance-fast"; break; - case msdfgen::ErrorCorrectionConfig::EDGE_PRIORITY: fallbackModeName = "auto-fast"; break; - case msdfgen::ErrorCorrectionConfig::EDGE_ONLY: fallbackModeName = "edge-fast"; break; - } - printf("Selected error correction mode not compatible with scanline mode, falling back to %s.\n", fallbackModeName); - } - config.generatorAttributes.config.errorCorrection.distanceCheckMode = msdfgen::ErrorCorrectionConfig::DO_NOT_CHECK_DISTANCE; - } - - // Finalize image format - ImageFormat imageExtension = ImageFormat::UNSPECIFIED; - if (config.imageFilename) { - if (cmpExtension(config.imageFilename, ".png")) imageExtension = ImageFormat::PNG; - else if (cmpExtension(config.imageFilename, ".bmp")) imageExtension = ImageFormat::BMP; - else if (cmpExtension(config.imageFilename, ".tif") || cmpExtension(config.imageFilename, ".tiff")) imageExtension = ImageFormat::TIFF; - else if (cmpExtension(config.imageFilename, ".txt")) imageExtension = ImageFormat::TEXT; - else if (cmpExtension(config.imageFilename, ".bin")) imageExtension = ImageFormat::BINARY; - } - if (config.imageFormat == ImageFormat::UNSPECIFIED) { - config.imageFormat = ImageFormat::PNG; - imageFormatName = "png"; - // If image format is not specified and -imageout is the only image output, infer format from its extension - if (imageExtension != ImageFormat::UNSPECIFIED && !config.arteryFontFilename) - config.imageFormat = imageExtension; - } - if (config.imageType == ImageType::MTSDF && config.imageFormat == ImageFormat::BMP) - ABORT("Atlas type not compatible with image format. MTSDF requires a format with alpha channel."); - if (config.arteryFontFilename && !(config.imageFormat == ImageFormat::PNG || config.imageFormat == ImageFormat::BINARY || config.imageFormat == ImageFormat::BINARY_FLOAT)) { - config.arteryFontFilename = nullptr; - result = 1; - puts("Error: Unable to create an Artery Font file with the specified image format!"); - // Recheck whether there is anything else to do - if (!(config.arteryFontFilename || config.imageFilename || config.jsonFilename || config.csvFilename || config.shadronPreviewFilename)) - return result; - layoutOnly = !(config.arteryFontFilename || config.imageFilename); - } - if (imageExtension != ImageFormat::UNSPECIFIED) { - // Warn if image format mismatches -imageout extension - bool mismatch = false; - switch (config.imageFormat) { - case ImageFormat::TEXT: case ImageFormat::TEXT_FLOAT: - mismatch = imageExtension != ImageFormat::TEXT; - break; - case ImageFormat::BINARY: case ImageFormat::BINARY_FLOAT: case ImageFormat::BINARY_FLOAT_BE: - mismatch = imageExtension != ImageFormat::BINARY; - break; - default: - mismatch = imageExtension != config.imageFormat; - } - if (mismatch) - printf("Warning: Output image file extension does not match the image's actual format (%s)!\n", imageFormatName); - } - imageFormatName = nullptr; // No longer consistent with imageFormat - bool floatingPointFormat = ( - config.imageFormat == ImageFormat::TIFF || - config.imageFormat == ImageFormat::TEXT_FLOAT || - config.imageFormat == ImageFormat::BINARY_FLOAT || - config.imageFormat == ImageFormat::BINARY_FLOAT_BE - ); - - // Load fonts - std::vector glyphs; - std::vector fonts; - bool anyCodepointsAvailable = false; - { - class FontHolder { - msdfgen::FreetypeHandle *ft; - msdfgen::FontHandle *font; - const char *fontFilename; - public: - FontHolder() : ft(msdfgen::initializeFreetype()), font(nullptr), fontFilename(nullptr) { } - ~FontHolder() { - if (ft) { - if (font) - msdfgen::destroyFont(font); - msdfgen::deinitializeFreetype(ft); - } - } - bool load(const char *fontFilename) { - if (ft && fontFilename) { - if (this->fontFilename && !strcmp(this->fontFilename, fontFilename)) - return true; - if (font) - msdfgen::destroyFont(font); - if ((font = msdfgen::loadFont(ft, fontFilename))) { - this->fontFilename = fontFilename; - return true; - } - this->fontFilename = nullptr; - } - return false; - } - operator msdfgen::FontHandle *() const { - return font; - } - } font; - - for (FontInput &fontInput : fontInputs) { - if (!font.load(fontInput.fontFilename)) - ABORT("Failed to load specified font file."); - if (fontInput.fontScale <= 0) - fontInput.fontScale = 1; - - // Load character set - Charset charset; - if (fontInput.charsetFilename) { - if (!charset.load(fontInput.charsetFilename, fontInput.glyphIdentifierType != GlyphIdentifierType::UNICODE_CODEPOINT)) - ABORT(fontInput.glyphIdentifierType == GlyphIdentifierType::GLYPH_INDEX ? "Failed to load glyph set specification." : "Failed to load character set specification."); - } else { - charset = Charset::ASCII; - fontInput.glyphIdentifierType = GlyphIdentifierType::UNICODE_CODEPOINT; - } - - // Load glyphs - FontGeometry fontGeometry(&glyphs); - int glyphsLoaded = -1; - switch (fontInput.glyphIdentifierType) { - case GlyphIdentifierType::GLYPH_INDEX: - glyphsLoaded = fontGeometry.loadGlyphset(font, fontInput.fontScale, charset, config.preprocessGeometry, config.kerning); - break; - case GlyphIdentifierType::UNICODE_CODEPOINT: - glyphsLoaded = fontGeometry.loadCharset(font, fontInput.fontScale, charset, config.preprocessGeometry, config.kerning); - anyCodepointsAvailable |= glyphsLoaded > 0; - break; - } - if (glyphsLoaded < 0) - ABORT("Failed to load glyphs from font."); - printf("Loaded geometry of %d out of %d glyphs", glyphsLoaded, (int) charset.size()); - if (fontInputs.size() > 1) - printf(" from font \"%s\"", fontInput.fontFilename); - printf(".\n"); - // List missing glyphs - if (glyphsLoaded < (int) charset.size()) { - printf("Missing %d %s", (int) charset.size()-glyphsLoaded, fontInput.glyphIdentifierType == GlyphIdentifierType::UNICODE_CODEPOINT ? "codepoints" : "glyphs"); - bool first = true; - switch (fontInput.glyphIdentifierType) { - case GlyphIdentifierType::GLYPH_INDEX: - for (unicode_t cp : charset) - if (!fontGeometry.getGlyph(msdfgen::GlyphIndex(cp))) - printf("%c 0x%02X", first ? ((first = false), ':') : ',', cp); - break; - case GlyphIdentifierType::UNICODE_CODEPOINT: - for (unicode_t cp : charset) - if (!fontGeometry.getGlyph(cp)) - printf("%c 0x%02X", first ? ((first = false), ':') : ',', cp); - break; - } - printf("\n"); - } - - if (fontInput.fontName) - fontGeometry.setName(fontInput.fontName); - - fonts.push_back((FontGeometry &&) fontGeometry); - } - } - if (glyphs.empty()) - ABORT("No glyphs loaded."); - - // Determine final atlas dimensions, scale and range, pack glyphs - { - double unitRange = 0, pxRange = 0; - switch (rangeMode) { - case RANGE_EM: - unitRange = rangeValue; - break; - case RANGE_PIXEL: - pxRange = rangeValue; - break; - } - bool fixedDimensions = fixedWidth >= 0 && fixedHeight >= 0; - bool fixedScale = config.emSize > 0; - TightAtlasPacker atlasPacker; - if (fixedDimensions) - atlasPacker.setDimensions(fixedWidth, fixedHeight); - else - atlasPacker.setDimensionsConstraint(atlasSizeConstraint); - atlasPacker.setPadding(config.imageType == ImageType::MSDF || config.imageType == ImageType::MTSDF ? 0 : -1); - // TODO: In this case (if padding is -1), the border pixels of each glyph are black, but still computed. For floating-point output, this may play a role. - if (fixedScale) - atlasPacker.setScale(config.emSize); - else - atlasPacker.setMinimumScale(minEmSize); - atlasPacker.setPixelRange(pxRange); - atlasPacker.setUnitRange(unitRange); - atlasPacker.setMiterLimit(config.miterLimit); - if (int remaining = atlasPacker.pack(glyphs.data(), glyphs.size())) { - if (remaining < 0) { - ABORT("Failed to pack glyphs into atlas."); - } else { - printf("Error: Could not fit %d out of %d glyphs into the atlas.\n", remaining, (int) glyphs.size()); - return 1; - } - } - atlasPacker.getDimensions(config.width, config.height); - if (!(config.width > 0 && config.height > 0)) - ABORT("Unable to determine atlas size."); - config.emSize = atlasPacker.getScale(); - config.pxRange = atlasPacker.getPixelRange(); - if (!fixedScale) - printf("Glyph size: %.9g pixels/EM\n", config.emSize); - if (!fixedDimensions) - printf("Atlas dimensions: %d x %d\n", config.width, config.height); - } - - // Generate atlas bitmap - if (!layoutOnly) { - - // Edge coloring - if (config.imageType == ImageType::MSDF || config.imageType == ImageType::MTSDF) { - if (config.expensiveColoring) { - Workload([&glyphs, &config](int i, int threadNo) -> bool { - unsigned long long glyphSeed = (LCG_MULTIPLIER*(config.coloringSeed^i)+LCG_INCREMENT)*!!config.coloringSeed; - glyphs[i].edgeColoring(config.edgeColoring, config.angleThreshold, glyphSeed); - return true; - }, glyphs.size()).finish(config.threadCount); - } else { - unsigned long long glyphSeed = config.coloringSeed; - for (GlyphGeometry &glyph : glyphs) { - glyphSeed *= LCG_MULTIPLIER; - glyph.edgeColoring(config.edgeColoring, config.angleThreshold, glyphSeed); - } - } - } - - bool success = false; - switch (config.imageType) { - case ImageType::HARD_MASK: - if (floatingPointFormat) - success = makeAtlas(glyphs, fonts, config); - else - success = makeAtlas(glyphs, fonts, config); - break; - case ImageType::SOFT_MASK: - case ImageType::SDF: - if (floatingPointFormat) - success = makeAtlas(glyphs, fonts, config); - else - success = makeAtlas(glyphs, fonts, config); - break; - case ImageType::PSDF: - if (floatingPointFormat) - success = makeAtlas(glyphs, fonts, config); - else - success = makeAtlas(glyphs, fonts, config); - break; - case ImageType::MSDF: - if (floatingPointFormat) - success = makeAtlas(glyphs, fonts, config); - else - success = makeAtlas(glyphs, fonts, config); - break; - case ImageType::MTSDF: - if (floatingPointFormat) - success = makeAtlas(glyphs, fonts, config); - else - success = makeAtlas(glyphs, fonts, config); - break; - } - if (!success) - result = 1; - } - - if (config.csvFilename) { - if (exportCSV(fonts.data(), fonts.size(), config.width, config.height, config.yDirection, config.csvFilename)) - puts("Glyph layout written into CSV file."); - else { - result = 1; - puts("Failed to write CSV output file."); - } - } - if (config.jsonFilename) { - if (exportJSON(fonts.data(), fonts.size(), config.emSize, config.pxRange, config.width, config.height, config.imageType, config.yDirection, config.jsonFilename, config.kerning)) - puts("Glyph layout and metadata written into JSON file."); - else { - result = 1; - puts("Failed to write JSON output file."); - } - } - - if (config.shadronPreviewFilename && config.shadronPreviewText) { - if (anyCodepointsAvailable) { - std::vector previewText; - utf8Decode(previewText, config.shadronPreviewText); - previewText.push_back(0); - if (generateShadronPreview(fonts.data(), fonts.size(), config.imageType, config.width, config.height, config.pxRange, previewText.data(), config.imageFilename, floatingPointFormat, config.shadronPreviewFilename)) - puts("Shadron preview script generated."); - else { - result = 1; - puts("Failed to generate Shadron preview file."); - } - } else { - result = 1; - puts("Shadron preview not supported in -glyphset mode."); - } - } - - return result; -} - -#endif diff --git a/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.h b/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.h deleted file mode 100644 index cf24d542..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.h +++ /dev/null @@ -1,42 +0,0 @@ - -#pragma once - -/* - * MULTI-CHANNEL SIGNED DISTANCE FIELD ATLAS GENERATOR v1.2 (2021-05-29) - * --------------------------------------------------------------------- - * A utility by Viktor Chlumsky, (c) 2020 - 2021 - * - * Generates compact bitmap font atlases using MSDFGEN. - * - */ - -#include -#include - -#include "types.h" -#include "utf8.h" -#include "Rectangle.h" -#include "Charset.h" -#include "GlyphBox.h" -#include "GlyphGeometry.h" -#include "FontGeometry.h" -#include "RectanglePacker.h" -#include "rectangle-packing.h" -#include "Workload.h" -#include "size-selectors.h" -#include "bitmap-blit.h" -#include "AtlasStorage.h" -#include "BitmapAtlasStorage.h" -#include "TightAtlasPacker.h" -#include "AtlasGenerator.h" -#include "ImmediateAtlasGenerator.h" -#include "DynamicAtlas.h" -#include "glyph-generators.h" -#include "image-encode.h" -#include "image-save.h" -#include "artery-font-export.h" -#include "csv-export.h" -#include "json-export.h" -#include "shadron-preview-generator.h" - -#define MSDF_ATLAS_VERSION "1.2" diff --git a/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.rc b/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.rc deleted file mode 100644 index 49499c63..00000000 Binary files a/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.rc and /dev/null differ diff --git a/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.sln b/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.sln deleted file mode 100644 index 4dcff669..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/msdf-atlas-gen.sln +++ /dev/null @@ -1,61 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Msdfgen", "msdfgen\Msdfgen.vcxproj", "{84BE2D91-F071-4151-BE12-61460464C494}" -EndProject -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "msdf-atlas-gen", "msdf-atlas-gen.vcxproj", "{223EDB94-5B35-45F2-A584-273DE6E45F6F}" - ProjectSection(ProjectDependencies) = postProject - {84BE2D91-F071-4151-BE12-61460464C494} = {84BE2D91-F071-4151-BE12-61460464C494} - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug Library|x64 = Debug Library|x64 - Debug Library|x86 = Debug Library|x86 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release Library|x64 = Release Library|x64 - Release Library|x86 = Release Library|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x64.ActiveCfg = Debug Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x64.Build.0 = Debug Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x86.ActiveCfg = Debug Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x86.Build.0 = Debug Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x64.ActiveCfg = Debug Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x64.Build.0 = Debug Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x86.ActiveCfg = Debug Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x86.Build.0 = Debug Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x64.ActiveCfg = Release Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x64.Build.0 = Release Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x86.ActiveCfg = Release Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x86.Build.0 = Release Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x64.ActiveCfg = Release Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x64.Build.0 = Release Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x86.ActiveCfg = Release Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x86.Build.0 = Release Library|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug Library|x64.ActiveCfg = Debug Library|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug Library|x64.Build.0 = Debug Library|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug Library|x86.ActiveCfg = Debug Library|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug Library|x86.Build.0 = Debug Library|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug|x64.ActiveCfg = Debug|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug|x64.Build.0 = Debug|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug|x86.ActiveCfg = Debug|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Debug|x86.Build.0 = Debug|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release Library|x64.ActiveCfg = Release Library|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release Library|x64.Build.0 = Release Library|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release Library|x86.ActiveCfg = Release Library|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release Library|x86.Build.0 = Release Library|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release|x64.ActiveCfg = Release|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release|x64.Build.0 = Release|x64 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release|x86.ActiveCfg = Release|Win32 - {223EDB94-5B35-45F2-A584-273DE6E45F6F}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Nuake/src/Vendors/msdf-atlas-gen/rectangle-packing.h b/Nuake/src/Vendors/msdf-atlas-gen/rectangle-packing.h deleted file mode 100644 index 4bcc6a83..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/rectangle-packing.h +++ /dev/null @@ -1,19 +0,0 @@ - -#pragma once - -#include -#include "Rectangle.h" - -namespace msdf_atlas { - -/// Packs the rectangle array into an atlas with fixed dimensions, returns how many didn't fit (0 on success) -template -int packRectangles(RectangleType *rectangles, int count, int width, int height, int padding = 0); - -/// Packs the rectangle array into an atlas of unknown size, returns the minimum required dimensions constrained by SizeSelector -template -std::pair packRectangles(RectangleType *rectangles, int count, int padding = 0); - -} - -#include "rectangle-packing.hpp" diff --git a/Nuake/src/Vendors/msdf-atlas-gen/rectangle-packing.hpp b/Nuake/src/Vendors/msdf-atlas-gen/rectangle-packing.hpp deleted file mode 100644 index 56c7a847..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/rectangle-packing.hpp +++ /dev/null @@ -1,61 +0,0 @@ - -#include "rectangle-packing.h" - -#include -#include "RectanglePacker.h" - -namespace msdf_atlas { - -static void copyRectanglePlacement(Rectangle &dst, const Rectangle &src) { - dst.x = src.x; - dst.y = src.y; -} - -static void copyRectanglePlacement(OrientedRectangle &dst, const OrientedRectangle &src) { - dst.x = src.x; - dst.y = src.y; - dst.rotated = src.rotated; -} - -template -int packRectangles(RectangleType *rectangles, int count, int width, int height, int padding) { - if (padding) - for (int i = 0; i < count; ++i) { - rectangles[i].w += padding; - rectangles[i].h += padding; - } - int result = RectanglePacker(width+padding, height+padding).pack(rectangles, count); - if (padding) - for (int i = 0; i < count; ++i) { - rectangles[i].w -= padding; - rectangles[i].h -= padding; - } - return result; -} - -template -std::pair packRectangles(RectangleType *rectangles, int count, int padding) { - std::vector rectanglesCopy(count); - int totalArea = 0; - for (int i = 0; i < count; ++i) { - rectanglesCopy[i].w = rectangles[i].w+padding; - rectanglesCopy[i].h = rectangles[i].h+padding; - totalArea += rectangles[i].w*rectangles[i].h; - } - std::pair dimensions; - SizeSelector sizeSelector(totalArea); - int width, height; - while (sizeSelector(width, height)) { - if (!RectanglePacker(width+padding, height+padding).pack(rectanglesCopy.data(), count)) { - dimensions.first = width; - dimensions.second = height; - for (int i = 0; i < count; ++i) - copyRectanglePlacement(rectangles[i], rectanglesCopy[i]); - --sizeSelector; - } else - ++sizeSelector; - } - return dimensions; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/resource.h b/Nuake/src/Vendors/msdf-atlas-gen/resource.h deleted file mode 100644 index d0ca059f..00000000 Binary files a/Nuake/src/Vendors/msdf-atlas-gen/resource.h and /dev/null differ diff --git a/Nuake/src/Vendors/msdf-atlas-gen/shadron-preview-generator.cpp b/Nuake/src/Vendors/msdf-atlas-gen/shadron-preview-generator.cpp deleted file mode 100644 index 479e7738..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/shadron-preview-generator.cpp +++ /dev/null @@ -1,155 +0,0 @@ - -#include "shadron-preview-generator.h" - -#include -#include - -namespace msdf_atlas { - -static const char * const shadronFillGlyphMask = R"( -template -glsl vec4 fillGlyph(vec2 texCoord) { - float fill = texture((ATLAS), texCoord).r; - return vec4(vec3(COLOR), fill); -} -)"; - -static const char * const shadronFillGlyphSdf = R"( -template -glsl vec4 fillGlyph(vec2 texCoord) { - vec3 s = texture((ATLAS), texCoord).rgb; - float sd = dot(vec2(RANGE), 0.5/fwidth(texCoord))*(median(s.r, s.g, s.b)-0.5); - float fill = clamp(sd+0.5, 0.0, 1.0); - return vec4(vec3(COLOR), fill); -} -)"; - -static const char * const shadronPreviewPreamble = R"( -#include - -glsl struct GlyphVertex { - vec2 coord; - vec2 texCoord; -}; - -template -glsl vec4 projectVertex(out vec2 texCoord, in GlyphVertex vertex) { - vec2 coord = vertex.coord; - float scale = 2.0/max((TEXT_SIZE).x, shadron_Aspect*(TEXT_SIZE).y); - scale *= exp(0.0625*shadron_Mouse.z); - coord += vec2(-0.5, 0.5)*vec2(TEXT_SIZE); - coord *= scale*vec2(1.0, shadron_Aspect); - texCoord = vertex.texCoord; - return vec4(coord, 0.0, 1.0); -} -%s -#define PREVIEW_IMAGE(NAME, ATLAS, RANGE, COLOR, VERTEX_LIST, TEXT_SIZE, DIMENSIONS) model image NAME : \ - vertex_data(GlyphVertex), \ - fragment_data(vec2), \ - vertex(projectVertex, triangles, VERTEX_LIST), \ - fragment(fillGlyph), \ - depth(false), \ - blend(transparency), \ - background(vec4(vec3(COLOR), 0.0)), \ - dimensions(DIMENSIONS), \ - resizable(true) - -)"; - -static std::string relativizePath(const char *base, const char *target) { - if (target[0] == '/' || (target[0] && target[1] == ':')) // absolute path? - return target; - int commonPrefix = 0; - for (int i = 0; base[i] && target[i] && base[i] == target[i]; ++i) { - if (base[i] == '/' || base[i] == '\\') - commonPrefix = i+1; - } - base += commonPrefix; - target += commonPrefix; - int baseNesting = 0; - for (int i = 0; base[i]; ++i) - if (base[i] == '/' || base[i] == '\\') - ++baseNesting; - std::string output; - for (int i = 0; i < baseNesting; ++i) - output += "../"; - output += target; - return output; -} - -bool generateShadronPreview(const FontGeometry *fonts, int fontCount, ImageType atlasType, int atlasWidth, int atlasHeight, double pxRange, const unicode_t *text, const char *imageFilename, bool fullRange, const char *outputFilename) { - if (fontCount <= 0) - return false; - double texelWidth = 1./atlasWidth; - double texelHeight = 1./atlasHeight; - bool anyGlyphs = false; - FILE *file = fopen(outputFilename, "w"); - if (!file) - return false; - fprintf(file, shadronPreviewPreamble, atlasType == ImageType::HARD_MASK || atlasType == ImageType::SOFT_MASK ? shadronFillGlyphMask : shadronFillGlyphSdf); - if (imageFilename) - fprintf(file, "image Atlas = file(\"%s\")", relativizePath(outputFilename, imageFilename).c_str()); - else - fprintf(file, "image Atlas = file()"); - fprintf(file, " : %sfilter(%s), map(repeat);\n", fullRange ? "full_range(true), " : "", atlasType == ImageType::HARD_MASK ? "nearest" : "linear"); - fprintf(file, "const vec2 txRange = vec2(%.9g, %.9g);\n\n", pxRange*texelWidth, pxRange*texelHeight); - { - msdfgen::FontMetrics fontMetrics = fonts->getMetrics(); - for (int i = 1; i < fontCount; ++i) { - fontMetrics.lineHeight = std::max(fontMetrics.lineHeight, fonts[i].getMetrics().lineHeight); - fontMetrics.ascenderY = std::max(fontMetrics.ascenderY, fonts[i].getMetrics().ascenderY); - fontMetrics.descenderY = std::min(fontMetrics.descenderY, fonts[i].getMetrics().descenderY); - } - double fsScale = 1/(fontMetrics.ascenderY-fontMetrics.descenderY); - fputs("vertex_list GlyphVertex textQuadVertices = {\n", file); - double x = 0, y = -fsScale*fontMetrics.ascenderY; - double textWidth = 0; - for (const unicode_t *cp = text; *cp; ++cp) { - if (*cp == '\r') - continue; - if (*cp == '\n') { - textWidth = std::max(textWidth, x); - x = 0; - y -= fsScale*fontMetrics.lineHeight; - continue; - } - for (int i = 0; i < fontCount; ++i) { - const GlyphGeometry *glyph = fonts[i].getGlyph(*cp); - if (glyph) { - if (!glyph->isWhitespace()) { - double pl, pb, pr, pt; - double il, ib, ir, it; - glyph->getQuadPlaneBounds(pl, pb, pr, pt); - glyph->getQuadAtlasBounds(il, ib, ir, it); - pl *= fsScale, pb *= fsScale, pr *= fsScale, pt *= fsScale; - pl += x, pb += y, pr += x, pt += y; - il *= texelWidth, ib *= texelHeight, ir *= texelWidth, it *= texelHeight; - fprintf(file, " %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g, %.9g,\n", - pl, pb, il, ib, - pr, pb, ir, ib, - pl, pt, il, it, - pr, pt, ir, it, - pl, pt, il, it, - pr, pb, ir, ib - ); - } - double advance = glyph->getAdvance(); - fonts[i].getAdvance(advance, cp[0], cp[1]); - x += fsScale*advance; - anyGlyphs = true; - break; - } - } - } - textWidth = std::max(textWidth, x); - y += fsScale*fontMetrics.descenderY; - fputs("};\n", file); - fprintf(file, "const vec2 textSize = vec2(%.9g, %.9g);\n\n", textWidth, -y); - } - fputs("PREVIEW_IMAGE(Preview, Atlas, txRange, vec3(1.0), textQuadVertices, textSize, ivec2(1200, 400));\n", file); - fputs("export png(Preview, \"preview.png\");\n", file); - fclose(file); - return anyGlyphs; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/shadron-preview-generator.h b/Nuake/src/Vendors/msdf-atlas-gen/shadron-preview-generator.h deleted file mode 100644 index 75da3ebc..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/shadron-preview-generator.h +++ /dev/null @@ -1,14 +0,0 @@ - -#pragma once - -#include -#include -#include "types.h" -#include "FontGeometry.h" - -namespace msdf_atlas { - -/// Generates a Shadron script that displays a string using the generated atlas -bool generateShadronPreview(const FontGeometry *fonts, int fontCount, ImageType atlasType, int atlasWidth, int atlasHeight, double pxRange, const unicode_t *text, const char *imageFilename, bool fullRange, const char *outputFilename); - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/size-selectors.cpp b/Nuake/src/Vendors/msdf-atlas-gen/size-selectors.cpp deleted file mode 100644 index ef2f21b8..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/size-selectors.cpp +++ /dev/null @@ -1,90 +0,0 @@ - -#include "size-selectors.h" - -#include - -namespace msdf_atlas { - -template -SquareSizeSelector::SquareSizeSelector(int minArea) : lowerBound(0), upperBound(-1) { - if (minArea > 0) - lowerBound = int(sqrt(minArea-1))/MULTIPLE+1; - updateCurrent(); -} - -template -void SquareSizeSelector::updateCurrent() { - if (upperBound < 0) - current = 5*lowerBound/4+16/MULTIPLE; - else - current = lowerBound+(upperBound-lowerBound)/2; -} - -template -bool SquareSizeSelector::operator()(int &width, int &height) const { - width = MULTIPLE*current, height = MULTIPLE*current; - return lowerBound < upperBound || upperBound < 0; -} - -template -SquareSizeSelector & SquareSizeSelector::operator++() { - lowerBound = current+1; - updateCurrent(); - return *this; -} - -template -SquareSizeSelector & SquareSizeSelector::operator--() { - upperBound = current; - updateCurrent(); - return *this; -} - -template class SquareSizeSelector<1>; -template class SquareSizeSelector<2>; -template class SquareSizeSelector<4>; - -SquarePowerOfTwoSizeSelector::SquarePowerOfTwoSizeSelector(int minArea) : side(1) { - while (side*side < minArea) - side <<= 1; -} - -bool SquarePowerOfTwoSizeSelector::operator()(int &width, int &height) const { - width = side, height = side; - return side > 0; -} - -SquarePowerOfTwoSizeSelector & SquarePowerOfTwoSizeSelector::operator++() { - side <<= 1; - return *this; -} - -SquarePowerOfTwoSizeSelector & SquarePowerOfTwoSizeSelector::operator--() { - side = 0; - return *this; -} - -PowerOfTwoSizeSelector::PowerOfTwoSizeSelector(int minArea) : w(1), h(1) { - while (w*h < minArea) - ++*this; -} - -bool PowerOfTwoSizeSelector::operator()(int &width, int &height) const { - width = w, height = h; - return w > 0 && h > 0; -} - -PowerOfTwoSizeSelector & PowerOfTwoSizeSelector::operator++() { - if (w == h) - w <<= 1; - else - h = w; - return *this; -} - -PowerOfTwoSizeSelector & PowerOfTwoSizeSelector::operator--() { - w = 0, h = 0; - return *this; -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/size-selectors.h b/Nuake/src/Vendors/msdf-atlas-gen/size-selectors.h deleted file mode 100644 index b75fc3a2..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/size-selectors.h +++ /dev/null @@ -1,54 +0,0 @@ - -#pragma once - -namespace msdf_atlas { - -// The size selector classes are used to select the minimum dimensions of the atlas fitting a given constraint. - -/// Selects square dimensions which are also a multiple of MULTIPLE -template -class SquareSizeSelector { - -public: - explicit SquareSizeSelector(int minArea = 0); - bool operator()(int &width, int &height) const; - SquareSizeSelector & operator++(); - SquareSizeSelector & operator--(); - -private: - int lowerBound, upperBound; - int current; - - void updateCurrent(); - -}; - -/// Selects square power-of-two dimensions -class SquarePowerOfTwoSizeSelector { - -public: - explicit SquarePowerOfTwoSizeSelector(int minArea = 0); - bool operator()(int &width, int &height) const; - SquarePowerOfTwoSizeSelector & operator++(); - SquarePowerOfTwoSizeSelector & operator--(); - -private: - int side; - -}; - -/// Selects square or rectangular (2:1) power-of-two dimensions -class PowerOfTwoSizeSelector { - -public: - explicit PowerOfTwoSizeSelector(int minArea = 0); - bool operator()(int &width, int &height) const; - PowerOfTwoSizeSelector & operator++(); - PowerOfTwoSizeSelector & operator--(); - -private: - int w, h; - -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/types.h b/Nuake/src/Vendors/msdf-atlas-gen/types.h deleted file mode 100644 index 27311e79..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/types.h +++ /dev/null @@ -1,52 +0,0 @@ - -#pragma once - -#include - -namespace msdf_atlas { - -typedef unsigned char byte; -typedef uint32_t unicode_t; - -/// Type of atlas image contents -enum class ImageType { - /// Rendered glyphs without anti-aliasing (two colors only) - HARD_MASK, - /// Rendered glyphs with anti-aliasing - SOFT_MASK, - /// Signed (true) distance field - SDF, - /// Signed pseudo-distance field - PSDF, - /// Multi-channel signed distance field - MSDF, - /// Multi-channel & true signed distance field - MTSDF -}; - -/// Atlas image encoding -enum class ImageFormat { - UNSPECIFIED, - PNG, - BMP, - TIFF, - TEXT, - TEXT_FLOAT, - BINARY, - BINARY_FLOAT, - BINARY_FLOAT_BE -}; - -/// Glyph identification -enum class GlyphIdentifierType { - GLYPH_INDEX, - UNICODE_CODEPOINT -}; - -/// Direction of the Y-axis -enum class YDirection { - BOTTOM_UP, - TOP_DOWN -}; - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/utf8.cpp b/Nuake/src/Vendors/msdf-atlas-gen/utf8.cpp deleted file mode 100644 index 393c5f2b..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/utf8.cpp +++ /dev/null @@ -1,38 +0,0 @@ - -#include "utf8.h" - -namespace msdf_atlas { - -void utf8Decode(std::vector &codepoints, const char *utf8String) { - bool start = true; - int rBytes = 0; - unicode_t cp = 0; - - for (const char *c = utf8String; *c; ++c) { - if (rBytes > 0) { - --rBytes; - if ((*c&0xc0) == 0x80) - cp |= (*c&0x3f)<<(6*rBytes); - // else error - } else if (!(*c&0x80)) { - cp = *c; - rBytes = 0; - } else if (*c&0x40) { - int block; - for (block = 0; ((unsigned char) *c<>block))<<(6*block); - rBytes = block; - } else - continue; // error - } else - continue; // error - if (!rBytes) { - if (!(start && cp == 0xfeff)) // BOM - codepoints.push_back(cp); - start = false; - } - } -} - -} diff --git a/Nuake/src/Vendors/msdf-atlas-gen/utf8.h b/Nuake/src/Vendors/msdf-atlas-gen/utf8.h deleted file mode 100644 index 740c2fb0..00000000 --- a/Nuake/src/Vendors/msdf-atlas-gen/utf8.h +++ /dev/null @@ -1,12 +0,0 @@ - -#pragma once - -#include -#include "types.h" - -namespace msdf_atlas { - -/// Decodes the UTF-8 string into an array of Unicode codepoints -void utf8Decode(std::vector &codepoints, const char *utf8String); - -} diff --git a/Nuake/src/Vendors/msdfgen/.gitattributes b/Nuake/src/Vendors/msdfgen/.gitattributes deleted file mode 100644 index 3fc77eb7..00000000 --- a/Nuake/src/Vendors/msdfgen/.gitattributes +++ /dev/null @@ -1,5 +0,0 @@ -* text=auto -include/** linguist-vendored -lib/** linguist-vendored -freetype/** linguist-vendored -skia/** linguist-vendored diff --git a/Nuake/src/Vendors/msdfgen/.gitignore b/Nuake/src/Vendors/msdfgen/.gitignore deleted file mode 100644 index 033ff852..00000000 --- a/Nuake/src/Vendors/msdfgen/.gitignore +++ /dev/null @@ -1,28 +0,0 @@ -/Debug/ -/Release/ -/Release OpenMP/ -/Debug Library/ -/Release Library/ -/Release Library OpenMP/ -/x86/ -/x64/ -.vs/ -*.exe -*.zip -*.user -*.sdf -*.pdb -*.ipdb -*.iobj -*.suo -*.VC.opendb -*.VC.db -/bin/*.lib -/bin/msdfgen -output.png -render.png -out/ -build/ -build_xcode/ -skia/win32/ -skia/win64/ diff --git a/Nuake/src/Vendors/msdfgen/CHANGELOG.md b/Nuake/src/Vendors/msdfgen/CHANGELOG.md deleted file mode 100644 index 4b9a7526..00000000 --- a/Nuake/src/Vendors/msdfgen/CHANGELOG.md +++ /dev/null @@ -1,82 +0,0 @@ - -## Version 1.9 (2021-05-28) - -- Error correction of multi-channel distance fields has been completely reworked -- Added new edge coloring strategy that optimizes colors based on distances between edges -- Added some minor functions for the library API -- Minor code refactor and optimizations - -## Version 1.8 (2020-10-17) - -- Integrated the Skia library into the project, which is used to preprocess the shape geometry and eliminate any self-intersections and other irregularities previously unsupported by the software - - The scanline pass and overlapping contour mode is made obsolete by this step and has been disabled by default. The preprocess step can be disabled by the new `-nopreprocess` switch and the former enabled by `-scanline` and `-overlap` respectively. - - The project can be built without the Skia library, forgoing the geometry preprocessing feature. This is controlled by the macro definition `MSDFGEN_USE_SKIA` -- Significantly improved performance of the core algorithm by reusing results from previously computed pixels -- Introduced an additional error correction routine which eliminates MSDF artifacts by analytically predicting results of bilinear interpolation -- Added the possibility to load font glyphs by their index rather than a Unicode value (use the prefix `g` before the character code in `-font` argument) -- Added `-distanceshift` argument that can be used to adjust the center of the distance range in the output distance field -- Fixed several errors in the evaluation of curve distances -- Fixed an issue with paths containing convergent corners (those whose inner angle is zero) -- The algorithm for pseudo-distance computation slightly changed, fixing certain rare edge cases and improving consistency -- Added the ability to supply own `FT_Face` handle to the msdfgen library -- Minor refactor of the core algorithm - -### Version 1.7.1 (2020-03-09) - -- Fixed an edge case bug in scanline rasterization - -## Version 1.7 (2020-03-07) - -- Added `mtsdf` mode - a combination of `msdf` with `sdf` in the alpha channel -- Distance fields can now be stored as uncompressed TIFF image files with floating point precision -- Bitmap class refactor - template argument split into data type and number of channels, bitmap reference classes introduced -- Added a secondary "ink trap" edge coloring heuristic, can be selected using `-coloringstrategy inktrap` -- Added computation of estimated rendering error for a given SDF -- Added computation of bounding box that includes sharp mitered corners -- The API for bounds computation of the `Shape` class changed for clarity -- Fixed several edge case bugs - -## Version 1.6 (2019-04-08) - -- Core algorithm rewritten to split up advanced edge selection logic into modular template arguments. -- Pseudo-distance evaluation reworked to eliminate discontinuities at the midpoint between edges. -- MSDF error correction reworked to also fix distances away from edges and consider diagonal pairs. Code simplified. -- Added scanline rasterization support for `Shape`. -- Added a scanline pass in the standalone version, which corrects the signs in the distance field according to the selected fill rule (`-fillrule`). Can be disabled using `-noscanline`. -- Fixed autoframe scaling, which previously caused the output to have unnecessary empty border. -- `-guessorder` switch no longer enabled by default, as the functionality is now provided by the scanline pass. -- Updated FreeType and other libraries, changed to static linkage -- Added 64-bit and static library builds to the Visual Studio solution - -## Version 1.5 (2017-07-23) - -- Fixed rounding error in cubic curve splitting. -- SVG parser fixes and support for additional path commands. -- Added CMake build script. - -## Version 1.4 (2017-02-09) - -- Reworked contour combining logic to support overlapping contours. Original algorithm preserved in functions with `_legacy` suffix, which are invoked by the new `-legacy` switch. -- Fixed a severe bug in cubic curve distance computation, where a control point lies at the endpoint. -- Standalone version now automatically detects if the input has the wrong orientation and adjusts the distance field accordingly. Can be disabled by `-keeporder` or `-reverseorder` switch. -- SVG parser fixes and improvements. - -## Version 1.3 (2016-12-07) - -- Fixed `-reverseorder` switch. -- Fixed glyph loading to use the proper method of acquiring outlines from FreeType. - -## Version 1.2 (2016-07-20) - -- Added option to specify that shape vertices are listed in reverse order (`-reverseorder`). -- Added option to set a seed for the edge coloring heuristic (-seed \), which can be used to adjust the output. -- Fixed parsing of glyph contours that start with a curve control point. - -## Version 1.1 (2016-05-08) - -- Switched to MIT license due to popular demand. -- Fixed SDF rendering anti-aliasing when the output is smaller than the distance field. - -## Version 1.0 (2016-04-28) - -- Project published. diff --git a/Nuake/src/Vendors/msdfgen/CMakeLists.txt b/Nuake/src/Vendors/msdfgen/CMakeLists.txt deleted file mode 100644 index 01b048d5..00000000 --- a/Nuake/src/Vendors/msdfgen/CMakeLists.txt +++ /dev/null @@ -1,194 +0,0 @@ -cmake_minimum_required(VERSION 3.10) - -project(msdfgen VERSION 1.8 LANGUAGES CXX) -option(MSDFGEN_BUILD_MSDFGEN_STANDALONE "Build the msdfgen standalone executable" ON) -option(MSDFGEN_USE_OPENMP "Build with OpenMP support for multithreaded code" OFF) -option(MSDFGEN_USE_CPP11 "Build with C++11 enabled" ON) -option(MSDFGEN_USE_SKIA "Build with the Skia library" OFF) -option(MSDFGEN_INSTALL "Generate installation target" ON) -option(FREETYPE_WITH_PNG "Link libpng and zlib because FreeType is configured to require it" OFF) -option(FREETYPE_WITH_HARFBUZZ "Link HarfBuzz because FreeType is configured to require it" OFF) - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") - -if(NOT TARGET Freetype::Freetype) - find_package(Freetype REQUIRED) -endif() - -#---------------------------------------------------------------- -# Gathering File -#---------------------------------------------------------------- - -file(GLOB_RECURSE msdfgen_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - "core/*.h" - "core/*.hpp" -) - -file(GLOB_RECURSE msdfgen_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - "core/*.cpp" -) - -file(GLOB_RECURSE msdfgen-ext_PUBLIC_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - "ext/*.h" - "ext/*.hpp" -) - -file(GLOB_RECURSE msdfgen-ext_PRIVATE_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - "include/*.h" -) - -file(GLOB_RECURSE msdfgen-ext_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} - "ext/*.cpp" - "lib/*.cpp" - "lib/*.cpp" -) - -# Build the library (aliased name because it's the same target name the exe) -include(folderize) -folderize_sources(msdfgen_HEADERS ${CMAKE_SOURCE_DIR}) -folderize_sources(msdfgen_SOURCES ${CMAKE_SOURCE_DIR}) -folderize_sources(msdfgen-ext_PUBLIC_HEADERS ${CMAKE_SOURCE_DIR}) -folderize_sources(msdfgen-ext_PRIVATE_HEADERS ${CMAKE_SOURCE_DIR}) -folderize_sources(msdfgen-ext_SOURCES ${CMAKE_SOURCE_DIR}) - -#---------------------------------------------------------------- -# Target configuration -#---------------------------------------------------------------- - -add_library(msdfgen ${msdfgen_SOURCES} ${msdfgen_HEADERS} "./msdfgen.h") -add_library(msdfgen::msdfgen ALIAS msdfgen) -set_target_properties(msdfgen PROPERTIES PUBLIC_HEADER "${msdfgen_HEADERS}") -target_include_directories(msdfgen INTERFACE - $ - $ -) - -if(MSDFGEN_USE_CPP11) - target_compile_features(msdfgen PUBLIC cxx_std_11) - target_compile_definitions(msdfgen PUBLIC MSDFGEN_USE_CPP11) -endif() - -if(MSDFGEN_USE_OPENMP) - # Note: Clang doesn't support OpenMP by default... - find_package(OpenMP REQUIRED COMPONENTS CXX) - target_link_libraries(msdfgen PRIVATE OpenMP::OpenMP_CXX) - target_compile_definitions(msdfgen PRIVATE MSDFGEN_USE_OPENMP) -endif() - -if(MSDFGEN_USE_SKIA) - find_package(Skia REQUIRED) - target_link_libraries(msdfgen-ext PRIVATE Skia::Skia) - target_compile_definitions(msdfgen-ext PUBLIC MSDFGEN_USE_SKIA) -endif() - -add_library(msdfgen-ext ${msdfgen-ext_SOURCES} ${msdfgen-ext_PUBLIC_HEADERS} ${msdfgen-ext_PRIVATE_HEADERS} "./msdfgen-ext.h") -add_library(msdfgen::msdfgen-ext ALIAS msdfgen-ext) -set_target_properties(msdfgen-ext PROPERTIES - PUBLIC_HEADER "${msdfgen-ext_PUBLIC_HEADERS}" -) -target_link_libraries(msdfgen-ext PUBLIC msdfgen::msdfgen Freetype::Freetype) -target_include_directories(msdfgen-ext -PUBLIC - $ - $ - -PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/include -) - -target_compile_definitions(msdfgen-ext PUBLIC MSDFGEN_CMAKE_BUILD) - -if(MSDFGEN_USE_CPP11) - target_compile_features(msdfgen-ext PUBLIC cxx_std_11) - target_compile_definitions(msdfgen-ext PUBLIC MSDFGEN_USE_CPP11) -endif() - -# Build the executable if requested -if(MSDFGEN_BUILD_MSDFGEN_STANDALONE) - add_executable(msdfgen-standalone main.cpp) - set_target_properties(msdfgen-standalone PROPERTIES ARCHIVE_OUTPUT_DIRECTORY archive OUTPUT_NAME msdfgen) - target_compile_definitions(msdfgen-standalone PRIVATE MSDFGEN_STANDALONE) - target_link_libraries(msdfgen-standalone PRIVATE msdfgen::msdfgen msdfgen::msdfgen-ext) - - if(FREETYPE_WITH_PNG) - find_package(ZLIB REQUIRED) - find_package(PNG REQUIRED) - target_link_libraries(msdfgen-standalone PRIVATE ZLIB::ZLIB PNG::PNG) - endif() - if(FREETYPE_WITH_HARFBUZZ) - # No FindHarfBuzz.cmake available so falling back to CMAKE_LIBRARY_PATH - find_library(FREETYPE_HARFBUZZ_LIB "harfbuzz") - target_link_libraries(msdfgen-standalone PRIVATE "${FREETYPE_HARFBUZZ_LIB}") - endif() -endif() - -#---------------------------------------------------------------- -# Installation and exportation of the libraries -#---------------------------------------------------------------- - -if(MSDFGEN_INSTALL) - include(CMakePackageConfigHelpers) - set(MSDFGEN_CONFIG_PATH "lib/cmake/msdfgen") - - # install tree package config - write_basic_package_version_file( - "${CMAKE_CURRENT_BINARY_DIR}/msdfgenConfigVersion.cmake" - VERSION ${PROJECT_VERSION} - COMPATIBILITY SameMajorVersion - ) - - configure_package_config_file( - cmake/msdfgenConfig.cmake.in - ${MSDFGEN_CONFIG_PATH}/msdfgenConfig.cmake - INSTALL_DESTINATION ${MSDFGEN_CONFIG_PATH} - NO_CHECK_REQUIRED_COMPONENTS_MACRO - ) - - # build tree package config - configure_file( - cmake/msdfgenConfig.cmake.in - msdfgenConfig.cmake - @ONLY - ) - - install(TARGETS msdfgen EXPORT msdfgenTargets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - FRAMEWORK DESTINATION lib - PUBLIC_HEADER DESTINATION include/msdfgen/core - ) - - install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/msdfgen.h" "${CMAKE_CURRENT_SOURCE_DIR}/msdfgen-ext.h" DESTINATION include/msdfgen) - - install(TARGETS msdfgen-ext EXPORT msdfgenTargets - RUNTIME DESTINATION bin - LIBRARY DESTINATION lib - ARCHIVE DESTINATION lib - FRAMEWORK DESTINATION lib - PUBLIC_HEADER DESTINATION include/msdfgen/ext - ) - - if(MSDFGEN_BUILD_MSDFGEN_STANDALONE) - install(TARGETS msdfgen-standalone EXPORT msdfgenTargets RUNTIME DESTINATION bin) - endif() - - install( - FILES - "${CMAKE_CURRENT_BINARY_DIR}/${MSDFGEN_CONFIG_PATH}/msdfgenConfig.cmake" - "${CMAKE_CURRENT_BINARY_DIR}/msdfgenConfigVersion.cmake" - DESTINATION ${MSDFGEN_CONFIG_PATH} - ) - - export( - EXPORT msdfgenTargets - NAMESPACE msdfgen:: - FILE "${CMAKE_CURRENT_BINARY_DIR}/msdfgenTargets.cmake" - ) - - install( - EXPORT msdfgenTargets FILE msdfgenTargets.cmake - NAMESPACE msdfgen:: - DESTINATION ${MSDFGEN_CONFIG_PATH} - ) -endif() diff --git a/Nuake/src/Vendors/msdfgen/LICENSE.txt b/Nuake/src/Vendors/msdfgen/LICENSE.txt deleted file mode 100644 index 5fb05446..00000000 --- a/Nuake/src/Vendors/msdfgen/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2016 Viktor Chlumsky - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/Nuake/src/Vendors/msdfgen/Msdfgen.rc b/Nuake/src/Vendors/msdfgen/Msdfgen.rc deleted file mode 100644 index 38b344f8..00000000 Binary files a/Nuake/src/Vendors/msdfgen/Msdfgen.rc and /dev/null differ diff --git a/Nuake/src/Vendors/msdfgen/Msdfgen.sln b/Nuake/src/Vendors/msdfgen/Msdfgen.sln deleted file mode 100644 index 19d35c0d..00000000 --- a/Nuake/src/Vendors/msdfgen/Msdfgen.sln +++ /dev/null @@ -1,52 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Msdfgen", "Msdfgen.vcxproj", "{84BE2D91-F071-4151-BE12-61460464C494}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug Library|x64 = Debug Library|x64 - Debug Library|x86 = Debug Library|x86 - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release Library OpenMP|x64 = Release Library OpenMP|x64 - Release Library OpenMP|x86 = Release Library OpenMP|x86 - Release Library|x64 = Release Library|x64 - Release Library|x86 = Release Library|x86 - Release OpenMP|x64 = Release OpenMP|x64 - Release OpenMP|x86 = Release OpenMP|x86 - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x64.ActiveCfg = Debug Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x64.Build.0 = Debug Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x86.ActiveCfg = Debug Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug Library|x86.Build.0 = Debug Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x64.ActiveCfg = Debug|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x64.Build.0 = Debug|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x86.ActiveCfg = Debug|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Debug|x86.Build.0 = Debug|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library OpenMP|x64.ActiveCfg = Release Library OpenMP|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library OpenMP|x64.Build.0 = Release Library OpenMP|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library OpenMP|x86.ActiveCfg = Release Library OpenMP|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library OpenMP|x86.Build.0 = Release Library OpenMP|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x64.ActiveCfg = Release Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x64.Build.0 = Release Library|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x86.ActiveCfg = Release Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release Library|x86.Build.0 = Release Library|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release OpenMP|x64.ActiveCfg = Release OpenMP|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release OpenMP|x64.Build.0 = Release OpenMP|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release OpenMP|x86.ActiveCfg = Release OpenMP|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release OpenMP|x86.Build.0 = Release OpenMP|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x64.ActiveCfg = Release|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x64.Build.0 = Release|x64 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x86.ActiveCfg = Release|Win32 - {84BE2D91-F071-4151-BE12-61460464C494}.Release|x86.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/Nuake/src/Vendors/msdfgen/README.md b/Nuake/src/Vendors/msdfgen/README.md deleted file mode 100644 index c624256a..00000000 --- a/Nuake/src/Vendors/msdfgen/README.md +++ /dev/null @@ -1,209 +0,0 @@ -# Multi-channel signed distance field generator - -This is a utility for generating signed distance fields from vector shapes and font glyphs, -which serve as a texture representation that can be used in real-time graphics to efficiently reproduce said shapes. -Although it can also be used to generate conventional signed distance fields best known from -[this Valve paper](https://steamcdn-a.akamaihd.net/apps/valve/2007/SIGGRAPH2007_AlphaTestedMagnification.pdf) -and pseudo-distance fields, its primary purpose is to generate multi-channel distance fields, -using a method I have developed. Unlike monochrome distance fields, they have the ability -to reproduce sharp corners almost perfectly by utilizing all three color channels. - -The following comparison demonstrates the improvement in image quality. - -![demo-msdf16](https://user-images.githubusercontent.com/18639794/106391899-e37ebe80-63ef-11eb-988b-4764004bb196.png) -![demo-sdf16](https://user-images.githubusercontent.com/18639794/106391905-e679af00-63ef-11eb-96c3-993176330911.png) -![demo-sdf32](https://user-images.githubusercontent.com/18639794/106391906-e7aadc00-63ef-11eb-8f84-d402d0dd9174.png) - -- To learn more about this method, you can read my [Master's thesis](https://github.com/Chlumsky/msdfgen/files/3050967/thesis.pdf). -- Check out my [MSDF-Atlas-Gen](https://github.com/Chlumsky/msdf-atlas-gen) if you want to generate entire glyph atlases for text rendering. -- See what's new in the [changelog](CHANGELOG.md). - -## Getting started - -The project can be used either as a library or as a console program. It is divided into two parts, **[core](core)** -and **[extensions](ext)**. The core module has no dependencies and only uses bare C++. It contains all -key data structures and algorithms, which can be accessed through the [msdfgen.h](msdfgen.h) header. -Extensions contain utilities for loading fonts and SVG files, as well as saving PNG images. -Those are exposed by the [msdfgen-ext.h](msdfgen-ext.h) header. This module uses -[FreeType](http://www.freetype.org/), -[TinyXML2](http://www.grinninglizard.com/tinyxml2/), -[LodePNG](http://lodev.org/lodepng/), -and (optionally) [Skia](https://skia.org/). - -Additionally, there is the [main.cpp](main.cpp), which wraps the functionality into -a comprehensive standalone console program. To start using the program immediately, -there is a Windows binary available for download in the ["Releases" section](https://github.com/Chlumsky/msdfgen/releases). -To build the project, you may use the included [Visual Studio solution](Msdfgen.sln) -or [CMake script](CMakeLists.txt). - -## Console commands - -The standalone program is executed as -``` -msdfgen.exe -``` -where only the input specification is required. - -Mode can be one of: - - **sdf** – generates a conventional monochrome (true) signed distance field. - - **psdf** – generates a monochrome signed pseudo-distance field. - - **msdf** (default) – generates a multi-channel signed distance field using my new method. - - **mtsdf** – generates a combined multi-channel and true signed distance field in the alpha channel. - -The input can be specified as one of: - - **-font \ \** – to load a glyph from a font file. - Character code can be expressed as either a decimal (63) or hexadecimal (0x3F) Unicode value, or an ASCII character - in single quotes ('?'). - - **-svg \** – to load an SVG file. Note that only the last vector path in the file will be used. - - **-shapedesc \**, -defineshape \, -stdin – to load a text description of the shape - from either a file, the next argument, or the standard input, respectively. Its syntax is documented further down. - -The complete list of available options can be printed with **-help**. -Some of the important ones are: - - **-o \** – specifies the output file name. The desired format will be deduced from the extension - (png, bmp, tif, txt, bin). Otherwise, use -format. - - **-size \ \** – specifies the dimensions of the output distance field (in pixels). - - **-range \**, **-pxrange \** – specifies the width of the range around the shape - between the minimum and maximum representable signed distance in shape units or distance field pixels, respectivelly. - - **-scale \** – sets the scale used to convert shape units to distance field pixels. - - **-translate \ \** – sets the translation of the shape in shape units. Otherwise the origin (0, 0) - lies in the bottom left corner. - - **-autoframe** – automatically frames the shape to fit the distance field. If the output must be precisely aligned, - you should manually position it using -translate and -scale instead. - - **-angle \** – specifies the maximum angle to be considered a corner. - Can be expressed in radians (3.0) or degrees with D at the end (171.9D). - - **-testrender \ \ \** - tests the generated distance field by using it to render an image - of the original shape into a PNG file with the specified dimensions. Alternatively, -testrendermulti renders - an image without combining the color channels, and may give you an insight in how the multi-channel distance field works. - - **-exportshape \** - saves the text description of the shape with edge coloring to the specified file. - This can be later edited and used as input through -shapedesc. - - **-printmetrics** – prints some useful information about the shape's layout. - -For example, -``` -msdfgen.exe msdf -font C:\Windows\Fonts\arialbd.ttf 'M' -o msdf.png -size 32 32 -pxrange 4 -autoframe -testrender render.png 1024 1024 -``` - -will take the glyph capital M from the Arial Bold typeface, generate a 32×32 multi-channel distance field -with a 4 pixels wide distance range, store it into msdf.png, and create a test render of the glyph as render.png. - -**Note:** Do not use `-autoframe` to generate character maps! It is intended as a quick preview only. - -## Library API - -If you choose to use this utility inside your own program, there are a few simple steps you need to perform -in order to generate a distance field. Please note that all classes and functions are in the `msdfgen` namespace. - - - Acquire a `Shape` object. You can either load it via `loadGlyph` or `loadSvgShape`, or construct it manually. - It consists of closed contours, which in turn consist of edges. An edge is represented by a `LinearEdge`, `QuadraticEdge`, - or `CubicEdge`. You can construct them from two endpoints and 0 to 2 Bézier control points. - - Normalize the shape using its `normalize` method and assign colors to edges if you need a multi-channel SDF. - This can be performed automatically using the `edgeColoringSimple` heuristic, or manually by setting each edge's - `color` member. Keep in mind that at least two color channels must be turned on in each edge, and iff two edges meet - at a sharp corner, they must only have one channel in common. - - Call `generateSDF`, `generatePseudoSDF`, or `generateMSDF` to generate a distance field into a floating point - `Bitmap` object. This can then be worked with further or saved to a file using `saveBmp`, `savePng`, or `saveTiff`. - - You may also render an image from the distance field using `renderSDF`. Consider calling `simulate8bit` - on the distance field beforehand to simulate the standard 8 bits/channel image format. - -Example: -```c++ -#include "msdfgen.h" -#include "msdfgen-ext.h" - -using namespace msdfgen; - -int main() { - FreetypeHandle *ft = initializeFreetype(); - if (ft) { - FontHandle *font = loadFont(ft, "C:\\Windows\\Fonts\\arialbd.ttf"); - if (font) { - Shape shape; - if (loadGlyph(shape, font, 'A')) { - shape.normalize(); - // max. angle - edgeColoringSimple(shape, 3.0); - // image width, height - Bitmap msdf(32, 32); - // range, scale, translation - generateMSDF(msdf, shape, 4.0, 1.0, Vector2(4.0, 4.0)); - savePng(msdf, "output.png"); - } - destroyFont(font); - } - deinitializeFreetype(ft); - } - return 0; -} - -``` - -## Using a multi-channel distance field - -Using a multi-channel distance field generated by this program is similarly simple to how a monochrome distance field is used. -The only additional operation is computing the **median** of the three channels inside the fragment shader, -right after sampling the distance field. This signed distance value can then be used the same way as usual. - -The following is an example GLSL fragment shader with anti-aliasing: - -```glsl -in vec2 texCoord; -out vec4 color; -uniform sampler2D msdf; -uniform vec4 bgColor; -uniform vec4 fgColor; - -float median(float r, float g, float b) { - return max(min(r, g), min(max(r, g), b)); -} - -void main() { - vec3 msd = texture(msdf, texCoord).rgb; - float sd = median(msd.r, msd.g, msd.b); - float screenPxDistance = screenPxRange()*(sd - 0.5); - float opacity = clamp(screenPxDistance + 0.5, 0.0, 1.0); - color = mix(bgColor, fgColor, opacity); -} -``` - -Here, `screenPxRange()` represents the distance field range in output screen pixels. For example, if the pixel range was set to 2 -when generating a 32x32 distance field, and it is used to draw a quad that is 72x72 pixels on the screen, -it should return 4.5 (because 72/32 * 2 = 4.5). -**For 2D rendering, this can generally be replaced by a precomputed uniform value.** - -For rendering in a **3D perspective only**, where the texture scale varies across the screen, -you may want to implement this function with fragment derivatives in the following way. -I would suggest precomputing `unitRange` as a uniform variable instead of `pxRange` for better performance. - -```glsl -uniform float pxRange; // set to distance field's pixel range - -float screenPxRange() { - vec2 unitRange = vec2(pxRange)/vec2(textureSize(msdf, 0)); - vec2 screenTexSize = vec2(1.0)/fwidth(texCoord); - return max(0.5*dot(unitRange, screenTexSize), 1.0); -} -``` - -`screenPxRange()` must never be lower than 1. If it is lower than 2, there is a high probability that the anti-aliasing will fail -and you may want to re-generate your distance field with a wider range. - -## Shape description syntax - -The text shape description has the following syntax. - - Each closed contour is enclosed by braces: `{ } { }` - - Each point (and control point) is written as two real numbers separated by a comma. - - Points in a contour are separated with semicolons. - - The last point of each contour must be equal to the first, or the symbol `#` can be used, which represents the first point. - - There can be an edge segment specification between any two points, also separated by semicolons. - This can include the edge's color (`c`, `m`, `y` or `w`) and/or one or two Bézier curve control points inside parentheses. - -For example, -``` -{ -1, -1; m; -1, +1; y; +1, +1; m; +1, -1; y; # } -``` -would represent a square with magenta and yellow edges, -``` -{ 0, 1; (+1.6, -0.8; -1.6, -0.8); # } -``` -is a teardrop shape formed by a single cubic Bézier curve. diff --git a/Nuake/src/Vendors/msdfgen/cmake/folderize.cmake b/Nuake/src/Vendors/msdfgen/cmake/folderize.cmake deleted file mode 100644 index 93e08adf..00000000 --- a/Nuake/src/Vendors/msdfgen/cmake/folderize.cmake +++ /dev/null @@ -1,17 +0,0 @@ -# Mirror the folder structure for sources inside the IDE... -function(folderize_sources sources prefix) - foreach(FILE ${${sources}}) - get_filename_component(PARENT_DIR "${FILE}" PATH) - - # skip src or include and changes /'s to \\'s - string(REPLACE "${prefix}" "" GROUP "${PARENT_DIR}") - string(REPLACE "/" "\\" GROUP "${GROUP}") - - # If it's got a path, then append a "\\" separator (otherwise leave it blank) - if ("${GROUP}" MATCHES ".+") - set(GROUP "\\${GROUP}") - endif() - - source_group("${GROUP}" FILES "${FILE}") - endforeach() -endfunction(folderize_sources) diff --git a/Nuake/src/Vendors/msdfgen/cmake/msdfgenConfig.cmake.in b/Nuake/src/Vendors/msdfgen/cmake/msdfgenConfig.cmake.in deleted file mode 100644 index 15a571f9..00000000 --- a/Nuake/src/Vendors/msdfgen/cmake/msdfgenConfig.cmake.in +++ /dev/null @@ -1,12 +0,0 @@ -include(CMakeFindDependencyMacro) - -find_dependency(Freetype REQUIRED) - -set(MSDFGEN_USE_OPENMP "@MSDFGEN_USE_OPENMP@") -if(MSDFGEN_USE_OPENMP) - find_dependency(OpenMP REQUIRED COMPONENTS CXX) -endif() - -include("${CMAKE_CURRENT_LIST_DIR}/msdfgenTargets.cmake") - -unset(MSDFGEN_USE_OPENMP) diff --git a/Nuake/src/Vendors/msdfgen/core/Bitmap.h b/Nuake/src/Vendors/msdfgen/core/Bitmap.h deleted file mode 100644 index 14407d6c..00000000 --- a/Nuake/src/Vendors/msdfgen/core/Bitmap.h +++ /dev/null @@ -1,50 +0,0 @@ - -#pragma once - -#include "BitmapRef.hpp" - -namespace msdfgen { - -/// A 2D image bitmap with N channels of type T. Pixel memory is managed by the class. -template -class Bitmap { - -public: - Bitmap(); - Bitmap(int width, int height); - Bitmap(const BitmapConstRef &orig); - Bitmap(const Bitmap &orig); -#ifdef MSDFGEN_USE_CPP11 - Bitmap(Bitmap &&orig); -#endif - ~Bitmap(); - Bitmap & operator=(const BitmapConstRef &orig); - Bitmap & operator=(const Bitmap &orig); -#ifdef MSDFGEN_USE_CPP11 - Bitmap & operator=(Bitmap &&orig); -#endif - /// Bitmap width in pixels. - int width() const; - /// Bitmap height in pixels. - int height() const; - T * operator()(int x, int y); - const T * operator()(int x, int y) const; -#ifdef MSDFGEN_USE_CPP11 - explicit operator T *(); - explicit operator const T *() const; -#else - operator T *(); - operator const T *() const; -#endif - operator BitmapRef(); - operator BitmapConstRef() const; - -private: - T *pixels; - int w, h; - -}; - -} - -#include "Bitmap.hpp" diff --git a/Nuake/src/Vendors/msdfgen/core/Bitmap.hpp b/Nuake/src/Vendors/msdfgen/core/Bitmap.hpp deleted file mode 100644 index cb16cac8..00000000 --- a/Nuake/src/Vendors/msdfgen/core/Bitmap.hpp +++ /dev/null @@ -1,117 +0,0 @@ - -#include "Bitmap.h" - -#include -#include - -namespace msdfgen { - -template -Bitmap::Bitmap() : pixels(NULL), w(0), h(0) { } - -template -Bitmap::Bitmap(int width, int height) : w(width), h(height) { - pixels = new T[N*w*h]; -} - -template -Bitmap::Bitmap(const BitmapConstRef &orig) : w(orig.width), h(orig.height) { - pixels = new T[N*w*h]; - memcpy(pixels, orig.pixels, sizeof(T)*N*w*h); -} - -template -Bitmap::Bitmap(const Bitmap &orig) : w(orig.w), h(orig.h) { - pixels = new T[N*w*h]; - memcpy(pixels, orig.pixels, sizeof(T)*N*w*h); -} - -#ifdef MSDFGEN_USE_CPP11 -template -Bitmap::Bitmap(Bitmap &&orig) : pixels(orig.pixels), w(orig.w), h(orig.h) { - orig.pixels = NULL; - orig.w = 0, orig.h = 0; -} -#endif - -template -Bitmap::~Bitmap() { - delete [] pixels; -} - -template -Bitmap & Bitmap::operator=(const BitmapConstRef &orig) { - if (pixels != orig.pixels) { - delete [] pixels; - w = orig.width, h = orig.height; - pixels = new T[N*w*h]; - memcpy(pixels, orig.pixels, sizeof(T)*N*w*h); - } - return *this; -} - -template -Bitmap & Bitmap::operator=(const Bitmap &orig) { - if (this != &orig) { - delete [] pixels; - w = orig.w, h = orig.h; - pixels = new T[N*w*h]; - memcpy(pixels, orig.pixels, sizeof(T)*N*w*h); - } - return *this; -} - -#ifdef MSDFGEN_USE_CPP11 -template -Bitmap & Bitmap::operator=(Bitmap &&orig) { - if (this != &orig) { - delete [] pixels; - pixels = orig.pixels; - w = orig.w, h = orig.h; - orig.pixels = NULL; - } - return *this; -} -#endif - -template -int Bitmap::width() const { - return w; -} - -template -int Bitmap::height() const { - return h; -} - -template -T * Bitmap::operator()(int x, int y) { - return pixels+N*(w*y+x); -} - -template -const T * Bitmap::operator()(int x, int y) const { - return pixels+N*(w*y+x); -} - -template -Bitmap::operator T *() { - return pixels; -} - -template -Bitmap::operator const T *() const { - return pixels; -} - -template -Bitmap::operator BitmapRef() { - return BitmapRef(pixels, w, h); -} - -template -Bitmap::operator BitmapConstRef() const { - return BitmapConstRef(pixels, w, h); -} - -} diff --git a/Nuake/src/Vendors/msdfgen/core/BitmapRef.hpp b/Nuake/src/Vendors/msdfgen/core/BitmapRef.hpp deleted file mode 100644 index 6f9620dc..00000000 --- a/Nuake/src/Vendors/msdfgen/core/BitmapRef.hpp +++ /dev/null @@ -1,43 +0,0 @@ - -#pragma once - -#include - -namespace msdfgen { - -typedef unsigned char byte; - -/// Reference to a 2D image bitmap or a buffer acting as one. Pixel storage not owned or managed by the object. -template -struct BitmapRef { - - T *pixels; - int width, height; - - inline BitmapRef() : pixels(NULL), width(0), height(0) { } - inline BitmapRef(T *pixels, int width, int height) : pixels(pixels), width(width), height(height) { } - - inline T * operator()(int x, int y) const { - return pixels+N*(width*y+x); - } - -}; - -/// Constant reference to a 2D image bitmap or a buffer acting as one. Pixel storage not owned or managed by the object. -template -struct BitmapConstRef { - - const T *pixels; - int width, height; - - inline BitmapConstRef() : pixels(NULL), width(0), height(0) { } - inline BitmapConstRef(const T *pixels, int width, int height) : pixels(pixels), width(width), height(height) { } - inline BitmapConstRef(const BitmapRef &orig) : pixels(orig.pixels), width(orig.width), height(orig.height) { } - - inline const T * operator()(int x, int y) const { - return pixels+N*(width*y+x); - } - -}; - -} diff --git a/Nuake/src/Vendors/msdfgen/core/Contour.cpp b/Nuake/src/Vendors/msdfgen/core/Contour.cpp deleted file mode 100644 index ca80d3c5..00000000 --- a/Nuake/src/Vendors/msdfgen/core/Contour.cpp +++ /dev/null @@ -1,90 +0,0 @@ - -#include "Contour.h" - -#include "arithmetics.hpp" - -namespace msdfgen { - -static double shoelace(const Point2 &a, const Point2 &b) { - return (b.x-a.x)*(a.y+b.y); -} - -void Contour::addEdge(const EdgeHolder &edge) { - edges.push_back(edge); -} - -#ifdef MSDFGEN_USE_CPP11 -void Contour::addEdge(EdgeHolder &&edge) { - edges.push_back((EdgeHolder &&) edge); -} -#endif - -EdgeHolder & Contour::addEdge() { - edges.resize(edges.size()+1); - return edges.back(); -} - -static void boundPoint(double &l, double &b, double &r, double &t, Point2 p) { - if (p.x < l) l = p.x; - if (p.y < b) b = p.y; - if (p.x > r) r = p.x; - if (p.y > t) t = p.y; -} - -void Contour::bound(double &l, double &b, double &r, double &t) const { - for (std::vector::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) - (*edge)->bound(l, b, r, t); -} - -void Contour::boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const { - if (edges.empty()) - return; - Vector2 prevDir = edges.back()->direction(1).normalize(true); - for (std::vector::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) { - Vector2 dir = -(*edge)->direction(0).normalize(true); - if (polarity*crossProduct(prevDir, dir) >= 0) { - double miterLength = miterLimit; - double q = .5*(1-dotProduct(prevDir, dir)); - if (q > 0) - miterLength = min(1/sqrt(q), miterLimit); - Point2 miter = (*edge)->point(0)+border*miterLength*(prevDir+dir).normalize(true); - boundPoint(l, b, r, t, miter); - } - prevDir = (*edge)->direction(1).normalize(true); - } -} - -int Contour::winding() const { - if (edges.empty()) - return 0; - double total = 0; - if (edges.size() == 1) { - Point2 a = edges[0]->point(0), b = edges[0]->point(1/3.), c = edges[0]->point(2/3.); - total += shoelace(a, b); - total += shoelace(b, c); - total += shoelace(c, a); - } else if (edges.size() == 2) { - Point2 a = edges[0]->point(0), b = edges[0]->point(.5), c = edges[1]->point(0), d = edges[1]->point(.5); - total += shoelace(a, b); - total += shoelace(b, c); - total += shoelace(c, d); - total += shoelace(d, a); - } else { - Point2 prev = edges.back()->point(0); - for (std::vector::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) { - Point2 cur = (*edge)->point(0); - total += shoelace(prev, cur); - prev = cur; - } - } - return sign(total); -} - -void Contour::reverse() { - for (int i = (int) edges.size()/2; i > 0; --i) - EdgeHolder::swap(edges[i-1], edges[edges.size()-i]); - for (std::vector::iterator edge = edges.begin(); edge != edges.end(); ++edge) - (*edge)->reverse(); -} - -} diff --git a/Nuake/src/Vendors/msdfgen/core/Contour.h b/Nuake/src/Vendors/msdfgen/core/Contour.h deleted file mode 100644 index f79b2695..00000000 --- a/Nuake/src/Vendors/msdfgen/core/Contour.h +++ /dev/null @@ -1,34 +0,0 @@ - -#pragma once - -#include -#include "EdgeHolder.h" - -namespace msdfgen { - -/// A single closed contour of a shape. -class Contour { - -public: - /// The sequence of edges that make up the contour. - std::vector edges; - - /// Adds an edge to the contour. - void addEdge(const EdgeHolder &edge); -#ifdef MSDFGEN_USE_CPP11 - void addEdge(EdgeHolder &&edge); -#endif - /// Creates a new edge in the contour and returns its reference. - EdgeHolder & addEdge(); - /// Adjusts the bounding box to fit the contour. - void bound(double &l, double &b, double &r, double &t) const; - /// Adjusts the bounding box to fit the contour border's mitered corners. - void boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const; - /// Computes the winding of the contour. Returns 1 if positive, -1 if negative. - int winding() const; - /// Reverses the sequence of edges on the contour. - void reverse(); - -}; - -} diff --git a/Nuake/src/Vendors/msdfgen/core/EdgeColor.h b/Nuake/src/Vendors/msdfgen/core/EdgeColor.h deleted file mode 100644 index 9d49a5a8..00000000 --- a/Nuake/src/Vendors/msdfgen/core/EdgeColor.h +++ /dev/null @@ -1,18 +0,0 @@ - -#pragma once - -namespace msdfgen { - -/// Edge color specifies which color channels an edge belongs to. -enum EdgeColor { - BLACK = 0, - RED = 1, - GREEN = 2, - YELLOW = 3, - BLUE = 4, - MAGENTA = 5, - CYAN = 6, - WHITE = 7 -}; - -} diff --git a/Nuake/src/Vendors/msdfgen/core/EdgeHolder.cpp b/Nuake/src/Vendors/msdfgen/core/EdgeHolder.cpp deleted file mode 100644 index 1a8c5f66..00000000 --- a/Nuake/src/Vendors/msdfgen/core/EdgeHolder.cpp +++ /dev/null @@ -1,77 +0,0 @@ - -#include "EdgeHolder.h" - -namespace msdfgen { - -void EdgeHolder::swap(EdgeHolder &a, EdgeHolder &b) { - EdgeSegment *tmp = a.edgeSegment; - a.edgeSegment = b.edgeSegment; - b.edgeSegment = tmp; -} - -EdgeHolder::EdgeHolder() : edgeSegment(NULL) { } - -EdgeHolder::EdgeHolder(EdgeSegment *segment) : edgeSegment(segment) { } - -EdgeHolder::EdgeHolder(Point2 p0, Point2 p1, EdgeColor edgeColor) : edgeSegment(new LinearSegment(p0, p1, edgeColor)) { } - -EdgeHolder::EdgeHolder(Point2 p0, Point2 p1, Point2 p2, EdgeColor edgeColor) : edgeSegment(new QuadraticSegment(p0, p1, p2, edgeColor)) { } - -EdgeHolder::EdgeHolder(Point2 p0, Point2 p1, Point2 p2, Point2 p3, EdgeColor edgeColor) : edgeSegment(new CubicSegment(p0, p1, p2, p3, edgeColor)) { } - -EdgeHolder::EdgeHolder(const EdgeHolder &orig) : edgeSegment(orig.edgeSegment ? orig.edgeSegment->clone() : NULL) { } - -#ifdef MSDFGEN_USE_CPP11 -EdgeHolder::EdgeHolder(EdgeHolder &&orig) : edgeSegment(orig.edgeSegment) { - orig.edgeSegment = NULL; -} -#endif - -EdgeHolder::~EdgeHolder() { - delete edgeSegment; -} - -EdgeHolder & EdgeHolder::operator=(const EdgeHolder &orig) { - if (this != &orig) { - delete edgeSegment; - edgeSegment = orig.edgeSegment ? orig.edgeSegment->clone() : NULL; - } - return *this; -} - -#ifdef MSDFGEN_USE_CPP11 -EdgeHolder & EdgeHolder::operator=(EdgeHolder &&orig) { - if (this != &orig) { - delete edgeSegment; - edgeSegment = orig.edgeSegment; - orig.edgeSegment = NULL; - } - return *this; -} -#endif - -EdgeSegment & EdgeHolder::operator*() { - return *edgeSegment; -} - -const EdgeSegment & EdgeHolder::operator*() const { - return *edgeSegment; -} - -EdgeSegment * EdgeHolder::operator->() { - return edgeSegment; -} - -const EdgeSegment * EdgeHolder::operator->() const { - return edgeSegment; -} - -EdgeHolder::operator EdgeSegment *() { - return edgeSegment; -} - -EdgeHolder::operator const EdgeSegment *() const { - return edgeSegment; -} - -} diff --git a/Nuake/src/Vendors/msdfgen/core/EdgeHolder.h b/Nuake/src/Vendors/msdfgen/core/EdgeHolder.h deleted file mode 100644 index c4c5be76..00000000 --- a/Nuake/src/Vendors/msdfgen/core/EdgeHolder.h +++ /dev/null @@ -1,41 +0,0 @@ - -#pragma once - -#include "edge-segments.h" - -namespace msdfgen { - -/// Container for a single edge of dynamic type. -class EdgeHolder { - -public: - /// Swaps the edges held by a and b. - static void swap(EdgeHolder &a, EdgeHolder &b); - - EdgeHolder(); - EdgeHolder(EdgeSegment *segment); - EdgeHolder(Point2 p0, Point2 p1, EdgeColor edgeColor = WHITE); - EdgeHolder(Point2 p0, Point2 p1, Point2 p2, EdgeColor edgeColor = WHITE); - EdgeHolder(Point2 p0, Point2 p1, Point2 p2, Point2 p3, EdgeColor edgeColor = WHITE); - EdgeHolder(const EdgeHolder &orig); -#ifdef MSDFGEN_USE_CPP11 - EdgeHolder(EdgeHolder &&orig); -#endif - ~EdgeHolder(); - EdgeHolder & operator=(const EdgeHolder &orig); -#ifdef MSDFGEN_USE_CPP11 - EdgeHolder & operator=(EdgeHolder &&orig); -#endif - EdgeSegment & operator*(); - const EdgeSegment & operator*() const; - EdgeSegment * operator->(); - const EdgeSegment * operator->() const; - operator EdgeSegment *(); - operator const EdgeSegment *() const; - -private: - EdgeSegment *edgeSegment; - -}; - -} diff --git a/Nuake/src/Vendors/msdfgen/core/MSDFErrorCorrection.cpp b/Nuake/src/Vendors/msdfgen/core/MSDFErrorCorrection.cpp deleted file mode 100644 index aaa6a866..00000000 --- a/Nuake/src/Vendors/msdfgen/core/MSDFErrorCorrection.cpp +++ /dev/null @@ -1,495 +0,0 @@ - -#include "MSDFErrorCorrection.h" - -#include -#include "arithmetics.hpp" -#include "equation-solver.h" -#include "EdgeColor.h" -#include "bitmap-interpolation.hpp" -#include "edge-selectors.h" -#include "contour-combiners.h" -#include "ShapeDistanceFinder.h" -#include "generator-config.h" - -namespace msdfgen { - -#define ARTIFACT_T_EPSILON .01 -#define PROTECTION_RADIUS_TOLERANCE 1.001 - -#define CLASSIFIER_FLAG_CANDIDATE 0x01 -#define CLASSIFIER_FLAG_ARTIFACT 0x02 - -const double ErrorCorrectionConfig::defaultMinDeviationRatio = 1.11111111111111111; -const double ErrorCorrectionConfig::defaultMinImproveRatio = 1.11111111111111111; - -/// The base artifact classifier recognizes artifacts based on the contents of the SDF alone. -class BaseArtifactClassifier { -public: - inline BaseArtifactClassifier(double span, bool protectedFlag) : span(span), protectedFlag(protectedFlag) { } - /// Evaluates if the median value xm interpolated at xt in the range between am at at and bm at bt indicates an artifact. - inline int rangeTest(double at, double bt, double xt, float am, float bm, float xm) const { - // For protected texels, only consider inversion artifacts (interpolated median has different sign than boundaries). For the rest, it is sufficient that the interpolated median is outside its boundaries. - if ((am > .5f && bm > .5f && xm < .5f) || (am < .5f && bm < .5f && xm > .5f) || (!protectedFlag && median(am, bm, xm) != xm)) { - double axSpan = (xt-at)*span, bxSpan = (bt-xt)*span; - // Check if the interpolated median's value is in the expected range based on its distance (span) from boundaries a, b. - if (!(xm >= am-axSpan && xm <= am+axSpan && xm >= bm-bxSpan && xm <= bm+bxSpan)) - return CLASSIFIER_FLAG_CANDIDATE|CLASSIFIER_FLAG_ARTIFACT; - return CLASSIFIER_FLAG_CANDIDATE; - } - return 0; - } - /// Returns true if the combined results of the tests performed on the median value m interpolated at t indicate an artifact. - inline bool evaluate(double t, float m, int flags) const { - return (flags&2) != 0; - } -private: - double span; - bool protectedFlag; -}; - -/// The shape distance checker evaluates the exact shape distance to find additional artifacts at a significant performance cost. -template