Merge pull request #89414 from bruvzg/update_icu_msdfgen

Update ICU and msdfgen.
This commit is contained in:
Rémi Verschelde 2024-03-13 18:41:35 +01:00
commit 0478998148
No known key found for this signature in database
GPG key ID: C3336907360768E1
53 changed files with 421 additions and 396 deletions

View file

@ -20,8 +20,6 @@ if env["builtin_msdfgen"]:
"core/Projection.cpp",
"core/Scanline.cpp",
"core/Shape.cpp",
"core/SignedDistance.cpp",
"core/Vector2.cpp",
"core/contour-combiners.cpp",
"core/edge-coloring.cpp",
"core/edge-segments.cpp",
@ -36,6 +34,7 @@ if env["builtin_msdfgen"]:
]
thirdparty_sources = [thirdparty_dir + file for file in thirdparty_sources]
env_msdfgen.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
env_msdfgen.Prepend(CPPPATH=["#thirdparty/freetype/include", "#thirdparty/msdfgen", "#thirdparty/nanosvg"])
lib = env_msdfgen.add_library("msdfgen_builtin", thirdparty_sources)

View file

@ -531,6 +531,7 @@ module_obj = []
if env["builtin_msdfgen"] and msdfgen_enabled:
# Treat msdfgen headers as system headers to avoid raising warnings. Not supported on MSVC.
env_text_server_adv.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
if not env.msvc:
env_text_server_adv.Append(CPPFLAGS=["-isystem", Dir("#thirdparty/msdfgen").path])
else:

View file

@ -133,8 +133,6 @@ if env["msdfgen_enabled"] and env["freetype_enabled"]:
"core/Projection.cpp",
"core/Scanline.cpp",
"core/Shape.cpp",
"core/SignedDistance.cpp",
"core/Vector2.cpp",
"core/contour-combiners.cpp",
"core/edge-coloring.cpp",
"core/edge-segments.cpp",
@ -149,8 +147,10 @@ if env["msdfgen_enabled"] and env["freetype_enabled"]:
]
thirdparty_msdfgen_sources = [thirdparty_msdfgen_dir + file for file in thirdparty_msdfgen_sources]
env_msdfgen.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
env_msdfgen.Append(CPPPATH=["../../../thirdparty/freetype/include", "../../../thirdparty/msdfgen"])
env.Append(CPPPATH=["../../../thirdparty/msdfgen"])
env.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
env.Append(CPPDEFINES=["MODULE_MSDFGEN_ENABLED"])
lib = env_msdfgen.Library(

View file

@ -67,10 +67,16 @@ using namespace godot;
// Thirdparty headers.
#ifdef MODULE_MSDFGEN_ENABLED
#ifdef _MSC_VER
#pragma warning(disable : 4458)
#endif
#include <core/ShapeDistanceFinder.h>
#include <core/contour-combiners.h>
#include <core/edge-selectors.h>
#include <msdfgen.h>
#ifdef _MSC_VER
#pragma warning(default : 4458)
#endif
#endif
#ifdef MODULE_SVG_ENABLED

View file

@ -17,6 +17,7 @@ if "svg" in env.module_list:
if env["builtin_msdfgen"] and msdfgen_enabled:
# Treat msdfgen headers as system headers to avoid raising warnings. Not supported on MSVC.
env_text_server_fb.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
if not env.msvc:
env_text_server_fb.Append(CPPFLAGS=["-isystem", Dir("#thirdparty/msdfgen").path])
else:

View file

@ -144,8 +144,10 @@ if env["msdfgen_enabled"] and env["freetype_enabled"]:
]
thirdparty_msdfgen_sources = [thirdparty_msdfgen_dir + file for file in thirdparty_msdfgen_sources]
env_msdfgen.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
env_msdfgen.Append(CPPPATH=["../../../thirdparty/freetype/include", "../../../thirdparty/msdfgen"])
env.Append(CPPPATH=["../../../thirdparty/msdfgen"])
env.Append(CPPDEFINES=[("MSDFGEN_PUBLIC", "")])
env.Append(CPPDEFINES=["MODULE_MSDFGEN_ENABLED"])
lib = env_msdfgen.Library(

View file

@ -59,10 +59,16 @@ using namespace godot;
// Thirdparty headers.
#ifdef MODULE_MSDFGEN_ENABLED
#ifdef _MSC_VER
#pragma warning(disable : 4458)
#endif
#include <core/ShapeDistanceFinder.h>
#include <core/contour-combiners.h>
#include <core/edge-selectors.h>
#include <msdfgen.h>
#ifdef _MSC_VER
#pragma warning(default : 4458)
#endif
#endif
#ifdef MODULE_SVG_ENABLED

View file

@ -390,7 +390,7 @@ Files extracted from upstream source:
## icu4c
- Upstream: https://github.com/unicode-org/icu
- Version: 74.1 (9edac7b78327a1cb58db29e2714b15f9fa14e4d7, 2023)
- Version: 74.2 (2d029329c82c7792b985024b2bdab5fc7278fbc8, 2023)
- License: Unicode
Files extracted from upstream source:
@ -690,7 +690,7 @@ Collection of single-file libraries used in Godot components.
## msdfgen
- Upstream: https://github.com/Chlumsky/msdfgen
- Version: 1.10 (64a91eec3ca3787e6f78b4c99fcd3052ad3e37c0, 2021)
- Version: 1.11 (f12d7ca00091a632a289865b85c3f2e0bfc6542d, 2023)
- License: MIT
Files extracted from the upstream source:

View file

@ -59,7 +59,7 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.6
*/
#define U_ICU_VERSION_MINOR_NUM 1
#define U_ICU_VERSION_MINOR_NUM 2
/** The current ICU patchlevel version as an integer.
* This value will change in the subsequent releases of ICU
@ -132,7 +132,7 @@
* This value will change in the subsequent releases of ICU
* @stable ICU 2.4
*/
#define U_ICU_VERSION "74.1"
#define U_ICU_VERSION "74.2"
/**
* The current ICU library major version number as a string, for library name suffixes.
@ -151,7 +151,7 @@
/** Data version in ICU4C.
* @internal ICU 4.4 Internal Use Only
**/
#define U_ICU_DATA_VERSION "74.1"
#define U_ICU_DATA_VERSION "74.2"
#endif /* U_HIDE_INTERNAL_API */
/*===========================================================================

Binary file not shown.

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2016 - 2022 Viktor Chlumsky
Copyright (c) 2016 - 2023 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

View file

@ -18,17 +18,17 @@ public:
Bitmap(Bitmap<T, N> &&orig);
#endif
~Bitmap();
Bitmap<T, N> & operator=(const BitmapConstRef<T, N> &orig);
Bitmap<T, N> & operator=(const Bitmap<T, N> &orig);
Bitmap<T, N> &operator=(const BitmapConstRef<T, N> &orig);
Bitmap<T, N> &operator=(const Bitmap<T, N> &orig);
#ifdef MSDFGEN_USE_CPP11
Bitmap<T, N> & operator=(Bitmap<T, N> &&orig);
Bitmap<T, N> &operator=(Bitmap<T, N> &&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;
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;

View file

@ -40,7 +40,7 @@ Bitmap<T, N>::~Bitmap() {
}
template <typename T, int N>
Bitmap<T, N> & Bitmap<T, N>::operator=(const BitmapConstRef<T, N> &orig) {
Bitmap<T, N> &Bitmap<T, N>::operator=(const BitmapConstRef<T, N> &orig) {
if (pixels != orig.pixels) {
delete [] pixels;
w = orig.width, h = orig.height;
@ -51,7 +51,7 @@ Bitmap<T, N> & Bitmap<T, N>::operator=(const BitmapConstRef<T, N> &orig) {
}
template <typename T, int N>
Bitmap<T, N> & Bitmap<T, N>::operator=(const Bitmap<T, N> &orig) {
Bitmap<T, N> &Bitmap<T, N>::operator=(const Bitmap<T, N> &orig) {
if (this != &orig) {
delete [] pixels;
w = orig.w, h = orig.h;
@ -63,7 +63,7 @@ Bitmap<T, N> & Bitmap<T, N>::operator=(const Bitmap<T, N> &orig) {
#ifdef MSDFGEN_USE_CPP11
template <typename T, int N>
Bitmap<T, N> & Bitmap<T, N>::operator=(Bitmap<T, N> &&orig) {
Bitmap<T, N> &Bitmap<T, N>::operator=(Bitmap<T, N> &&orig) {
if (this != &orig) {
delete [] pixels;
pixels = orig.pixels;
@ -85,12 +85,12 @@ int Bitmap<T, N>::height() const {
}
template <typename T, int N>
T * Bitmap<T, N>::operator()(int x, int y) {
T *Bitmap<T, N>::operator()(int x, int y) {
return pixels+N*(w*y+x);
}
template <typename T, int N>
const T * Bitmap<T, N>::operator()(int x, int y) const {
const T *Bitmap<T, N>::operator()(int x, int y) const {
return pixels+N*(w*y+x);
}

View file

@ -1,12 +1,10 @@
#pragma once
#include <cstdlib>
#include "base.h"
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 <typename T, int N = 1>
struct BitmapRef {
@ -17,7 +15,7 @@ struct BitmapRef {
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 {
inline T *operator()(int x, int y) const {
return pixels+N*(width*y+x);
}
@ -34,7 +32,7 @@ struct BitmapConstRef {
inline BitmapConstRef(const T *pixels, int width, int height) : pixels(pixels), width(width), height(height) { }
inline BitmapConstRef(const BitmapRef<T, N> &orig) : pixels(orig.pixels), width(orig.width), height(orig.height) { }
inline const T * operator()(int x, int y) const {
inline const T *operator()(int x, int y) const {
return pixels+N*(width*y+x);
}

View file

@ -19,7 +19,7 @@ void Contour::addEdge(EdgeHolder &&edge) {
}
#endif
EdgeHolder & Contour::addEdge() {
EdgeHolder &Contour::addEdge() {
edges.resize(edges.size()+1);
return edges.back();
}

View file

@ -19,7 +19,7 @@ public:
void addEdge(EdgeHolder &&edge);
#endif
/// Creates a new edge in the contour and returns its reference.
EdgeHolder & addEdge();
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.

View file

@ -1,6 +1,8 @@
#pragma once
#include "base.h"
namespace msdfgen {
/// Edge color specifies which color channels an edge belongs to.

View file

@ -31,7 +31,7 @@ EdgeHolder::~EdgeHolder() {
delete edgeSegment;
}
EdgeHolder & EdgeHolder::operator=(const EdgeHolder &orig) {
EdgeHolder &EdgeHolder::operator=(const EdgeHolder &orig) {
if (this != &orig) {
delete edgeSegment;
edgeSegment = orig.edgeSegment ? orig.edgeSegment->clone() : NULL;
@ -40,7 +40,7 @@ EdgeHolder & EdgeHolder::operator=(const EdgeHolder &orig) {
}
#ifdef MSDFGEN_USE_CPP11
EdgeHolder & EdgeHolder::operator=(EdgeHolder &&orig) {
EdgeHolder &EdgeHolder::operator=(EdgeHolder &&orig) {
if (this != &orig) {
delete edgeSegment;
edgeSegment = orig.edgeSegment;
@ -50,19 +50,19 @@ EdgeHolder & EdgeHolder::operator=(EdgeHolder &&orig) {
}
#endif
EdgeSegment & EdgeHolder::operator*() {
EdgeSegment &EdgeHolder::operator*() {
return *edgeSegment;
}
const EdgeSegment & EdgeHolder::operator*() const {
const EdgeSegment &EdgeHolder::operator*() const {
return *edgeSegment;
}
EdgeSegment * EdgeHolder::operator->() {
EdgeSegment *EdgeHolder::operator->() {
return edgeSegment;
}
const EdgeSegment * EdgeHolder::operator->() const {
const EdgeSegment *EdgeHolder::operator->() const {
return edgeSegment;
}

View file

@ -22,14 +22,14 @@ public:
EdgeHolder(EdgeHolder &&orig);
#endif
~EdgeHolder();
EdgeHolder & operator=(const EdgeHolder &orig);
EdgeHolder &operator=(const EdgeHolder &orig);
#ifdef MSDFGEN_USE_CPP11
EdgeHolder & operator=(EdgeHolder &&orig);
EdgeHolder &operator=(EdgeHolder &&orig);
#endif
EdgeSegment & operator*();
const EdgeSegment & operator*() const;
EdgeSegment * operator->();
const EdgeSegment * operator->() const;
EdgeSegment &operator*();
const EdgeSegment &operator*() const;
EdgeSegment *operator->();
const EdgeSegment *operator->() const;
operator EdgeSegment *();
operator const EdgeSegment *() const;

View file

@ -19,8 +19,8 @@ namespace msdfgen {
#define CLASSIFIER_FLAG_CANDIDATE 0x01
#define CLASSIFIER_FLAG_ARTIFACT 0x02
const double ErrorCorrectionConfig::defaultMinDeviationRatio = 1.11111111111111111;
const double ErrorCorrectionConfig::defaultMinImproveRatio = 1.11111111111111111;
MSDFGEN_PUBLIC const double ErrorCorrectionConfig::defaultMinDeviationRatio = 1.11111111111111111;
MSDFGEN_PUBLIC const double ErrorCorrectionConfig::defaultMinImproveRatio = 1.11111111111111111;
/// The base artifact classifier recognizes artifacts based on the contents of the SDF alone.
class BaseArtifactClassifier {
@ -317,7 +317,7 @@ static bool hasDiagonalArtifactInner(const ArtifactClassifier &artifactClassifie
em[0] = am, em[1] = dm;
tEnd[tEx0 > t[i]] = tEx0;
em[tEx0 > t[i]] = interpolatedMedian(a, l, q, tEx0);
rangeFlags |= artifactClassifier.rangeTest(tEnd[0], tEnd[1], t[i], am, dm, xm);
rangeFlags |= artifactClassifier.rangeTest(tEnd[0], tEnd[1], t[i], em[0], em[1], xm);
}
// tEx1
if (tEx1 > 0 && tEx1 < 1) {
@ -325,7 +325,7 @@ static bool hasDiagonalArtifactInner(const ArtifactClassifier &artifactClassifie
em[0] = am, em[1] = dm;
tEnd[tEx1 > t[i]] = tEx1;
em[tEx1 > t[i]] = interpolatedMedian(a, l, q, tEx1);
rangeFlags |= artifactClassifier.rangeTest(tEnd[0], tEnd[1], t[i], am, dm, xm);
rangeFlags |= artifactClassifier.rangeTest(tEnd[0], tEnd[1], t[i], em[0], em[1], xm);
}
if (artifactClassifier.evaluate(t[i], xm, rangeFlags))
return true;

View file

@ -1,7 +1,7 @@
#pragma once
#include "Vector2.h"
#include "Vector2.hpp"
namespace msdfgen {

View file

@ -1,7 +1,7 @@
#include "Scanline.h"
#include <algorithm>
#include <cstdlib>
#include "arithmetics.hpp"
namespace msdfgen {

View file

@ -2,6 +2,7 @@
#pragma once
#include <vector>
#include "base.h"
namespace msdfgen {

View file

@ -1,7 +1,7 @@
#include "Shape.h"
#include <algorithm>
#include <cstdlib>
#include "arithmetics.hpp"
namespace msdfgen {
@ -18,7 +18,7 @@ void Shape::addContour(Contour &&contour) {
}
#endif
Contour & Shape::addContour() {
Contour &Shape::addContour() {
contours.resize(contours.size()+1);
return contours.back();
}
@ -40,15 +40,12 @@ bool Shape::validate() const {
}
static void deconvergeEdge(EdgeHolder &edgeHolder, int param) {
{
const QuadraticSegment *quadraticSegment = dynamic_cast<const QuadraticSegment *>(&*edgeHolder);
if (quadraticSegment)
edgeHolder = quadraticSegment->convertToCubic();
}
{
CubicSegment *cubicSegment = dynamic_cast<CubicSegment *>(&*edgeHolder);
if (cubicSegment)
cubicSegment->deconverge(param, MSDFGEN_DECONVERGENCE_FACTOR);
switch (edgeHolder->type()) {
case (int) QuadraticSegment::EDGE_TYPE:
edgeHolder = static_cast<const QuadraticSegment *>(&*edgeHolder)->convertToCubic();
// fallthrough
case (int) CubicSegment::EDGE_TYPE:
static_cast<CubicSegment *>(&*edgeHolder)->deconverge(param, MSDFGEN_DECONVERGENCE_FACTOR);
}
}
@ -162,16 +159,18 @@ void Shape::orientContours() {
}
}
}
qsort(&intersections[0], intersections.size(), sizeof(Intersection), &Intersection::compare);
// Disqualify multiple intersections
for (int j = 1; j < (int) intersections.size(); ++j)
if (intersections[j].x == intersections[j-1].x)
intersections[j].direction = intersections[j-1].direction = 0;
// Inspect scanline and deduce orientations of intersected contours
for (int j = 0; j < (int) intersections.size(); ++j)
if (intersections[j].direction)
orientations[intersections[j].contourIndex] += 2*((j&1)^(intersections[j].direction > 0))-1;
intersections.clear();
if (!intersections.empty()) {
qsort(&intersections[0], intersections.size(), sizeof(Intersection), &Intersection::compare);
// Disqualify multiple intersections
for (int j = 1; j < (int) intersections.size(); ++j)
if (intersections[j].x == intersections[j-1].x)
intersections[j].direction = intersections[j-1].direction = 0;
// Inspect scanline and deduce orientations of intersected contours
for (int j = 0; j < (int) intersections.size(); ++j)
if (intersections[j].direction)
orientations[intersections[j].contourIndex] += 2*((j&1)^(intersections[j].direction > 0))-1;
intersections.clear();
}
}
}
// Reverse contours that have the opposite orientation

View file

@ -32,7 +32,7 @@ public:
void addContour(Contour &&contour);
#endif
/// Adds a blank contour and returns its reference.
Contour & addContour();
Contour &addContour();
/// Normalizes the shape geometry for distance field generation.
void normalize();
/// Performs basic checks to determine if the object represents a valid shape.

View file

@ -2,7 +2,7 @@
#pragma once
#include <vector>
#include "Vector2.h"
#include "Vector2.hpp"
#include "edge-selectors.h"
#include "contour-combiners.h"

View file

@ -9,7 +9,11 @@ ShapeDistanceFinder<ContourCombiner>::ShapeDistanceFinder(const Shape &shape) :
template <class ContourCombiner>
typename ShapeDistanceFinder<ContourCombiner>::DistanceType ShapeDistanceFinder<ContourCombiner>::distance(const Point2 &origin) {
contourCombiner.reset(origin);
typename ContourCombiner::EdgeSelectorType::EdgeCache *edgeCache = &shapeEdgeCache[0];
#ifdef MSDFGEN_USE_CPP11
typename ContourCombiner::EdgeSelectorType::EdgeCache *edgeCache = shapeEdgeCache.data();
#else
typename ContourCombiner::EdgeSelectorType::EdgeCache *edgeCache = shapeEdgeCache.empty() ? NULL : &shapeEdgeCache[0];
#endif
for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) {
if (!contour->edges.empty()) {

View file

@ -1,29 +0,0 @@
#include "SignedDistance.h"
#include <cmath>
#include <cfloat>
namespace msdfgen {
SignedDistance::SignedDistance() : distance(-DBL_MAX), dot(1) { }
SignedDistance::SignedDistance(double dist, double d) : distance(dist), dot(d) { }
bool operator<(SignedDistance a, SignedDistance b) {
return fabs(a.distance) < fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot < b.dot);
}
bool operator>(SignedDistance a, SignedDistance b) {
return fabs(a.distance) > fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot > b.dot);
}
bool operator<=(SignedDistance a, SignedDistance b) {
return fabs(a.distance) < fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot <= b.dot);
}
bool operator>=(SignedDistance a, SignedDistance b) {
return fabs(a.distance) > fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot >= b.dot);
}
}

View file

@ -1,23 +0,0 @@
#pragma once
namespace msdfgen {
/// Represents a signed distance and alignment, which together can be compared to uniquely determine the closest edge segment.
class SignedDistance {
public:
double distance;
double dot;
SignedDistance();
SignedDistance(double dist, double d);
friend bool operator<(SignedDistance a, SignedDistance b);
friend bool operator>(SignedDistance a, SignedDistance b);
friend bool operator<=(SignedDistance a, SignedDistance b);
friend bool operator>=(SignedDistance a, SignedDistance b);
};
}

View file

@ -0,0 +1,38 @@
#pragma once
#include <cmath>
#include <cfloat>
#include "base.h"
namespace msdfgen {
/// Represents a signed distance and alignment, which together can be compared to uniquely determine the closest edge segment.
class SignedDistance {
public:
double distance;
double dot;
inline SignedDistance() : distance(-DBL_MAX), dot(0) { }
inline SignedDistance(double dist, double d) : distance(dist), dot(d) { }
};
inline bool operator<(const SignedDistance a, const SignedDistance b) {
return fabs(a.distance) < fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot < b.dot);
}
inline bool operator>(const SignedDistance a, const SignedDistance b) {
return fabs(a.distance) > fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot > b.dot);
}
inline bool operator<=(const SignedDistance a, const SignedDistance b) {
return fabs(a.distance) < fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot <= b.dot);
}
inline bool operator>=(const SignedDistance a, const SignedDistance b) {
return fabs(a.distance) > fabs(b.distance) || (fabs(a.distance) == fabs(b.distance) && a.dot >= b.dot);
}
}

View file

@ -1,146 +0,0 @@
#include "Vector2.h"
namespace msdfgen {
Vector2::Vector2(double val) : x(val), y(val) { }
Vector2::Vector2(double x, double y) : x(x), y(y) { }
void Vector2::reset() {
x = 0, y = 0;
}
void Vector2::set(double x, double y) {
Vector2::x = x, Vector2::y = y;
}
double Vector2::length() const {
return sqrt(x*x+y*y);
}
double Vector2::direction() const {
return atan2(y, x);
}
Vector2 Vector2::normalize(bool allowZero) const {
double len = length();
if (len == 0)
return Vector2(0, !allowZero);
return Vector2(x/len, y/len);
}
Vector2 Vector2::getOrthogonal(bool polarity) const {
return polarity ? Vector2(-y, x) : Vector2(y, -x);
}
Vector2 Vector2::getOrthonormal(bool polarity, bool allowZero) const {
double len = length();
if (len == 0)
return polarity ? Vector2(0, !allowZero) : Vector2(0, -!allowZero);
return polarity ? Vector2(-y/len, x/len) : Vector2(y/len, -x/len);
}
Vector2 Vector2::project(const Vector2 &vector, bool positive) const {
Vector2 n = normalize(true);
double t = dotProduct(vector, n);
if (positive && t <= 0)
return Vector2();
return t*n;
}
Vector2::operator const void*() const {
return x || y ? this : NULL;
}
bool Vector2::operator!() const {
return !x && !y;
}
bool Vector2::operator==(const Vector2 &other) const {
return x == other.x && y == other.y;
}
bool Vector2::operator!=(const Vector2 &other) const {
return x != other.x || y != other.y;
}
Vector2 Vector2::operator+() const {
return *this;
}
Vector2 Vector2::operator-() const {
return Vector2(-x, -y);
}
Vector2 Vector2::operator+(const Vector2 &other) const {
return Vector2(x+other.x, y+other.y);
}
Vector2 Vector2::operator-(const Vector2 &other) const {
return Vector2(x-other.x, y-other.y);
}
Vector2 Vector2::operator*(const Vector2 &other) const {
return Vector2(x*other.x, y*other.y);
}
Vector2 Vector2::operator/(const Vector2 &other) const {
return Vector2(x/other.x, y/other.y);
}
Vector2 Vector2::operator*(double value) const {
return Vector2(x*value, y*value);
}
Vector2 Vector2::operator/(double value) const {
return Vector2(x/value, y/value);
}
Vector2 & Vector2::operator+=(const Vector2 &other) {
x += other.x, y += other.y;
return *this;
}
Vector2 & Vector2::operator-=(const Vector2 &other) {
x -= other.x, y -= other.y;
return *this;
}
Vector2 & Vector2::operator*=(const Vector2 &other) {
x *= other.x, y *= other.y;
return *this;
}
Vector2 & Vector2::operator/=(const Vector2 &other) {
x /= other.x, y /= other.y;
return *this;
}
Vector2 & Vector2::operator*=(double value) {
x *= value, y *= value;
return *this;
}
Vector2 & Vector2::operator/=(double value) {
x /= value, y /= value;
return *this;
}
double dotProduct(const Vector2 &a, const Vector2 &b) {
return a.x*b.x+a.y*b.y;
}
double crossProduct(const Vector2 &a, const Vector2 &b) {
return a.x*b.y-a.y*b.x;
}
Vector2 operator*(double value, const Vector2 &vector) {
return Vector2(value*vector.x, value*vector.y);
}
Vector2 operator/(double value, const Vector2 &vector) {
return Vector2(value/vector.x, value/vector.y);
}
}

View file

@ -1,66 +0,0 @@
#pragma once
#include <cstdlib>
#include <cmath>
namespace msdfgen {
/**
* A 2-dimensional euclidean vector with double precision.
* Implementation based on the Vector2 template from Artery Engine.
* @author Viktor Chlumsky
*/
struct Vector2 {
double x, y;
Vector2(double val = 0);
Vector2(double x, double y);
/// Sets the vector to zero.
void reset();
/// Sets individual elements of the vector.
void set(double x, double y);
/// Returns the vector's length.
double length() const;
/// Returns the angle of the vector in radians (atan2).
double direction() const;
/// Returns the normalized vector - one that has the same direction but unit length.
Vector2 normalize(bool allowZero = false) const;
/// Returns a vector with the same length that is orthogonal to this one.
Vector2 getOrthogonal(bool polarity = true) const;
/// Returns a vector with unit length that is orthogonal to this one.
Vector2 getOrthonormal(bool polarity = true, bool allowZero = false) const;
/// Returns a vector projected along this one.
Vector2 project(const Vector2 &vector, bool positive = false) const;
operator const void *() const;
bool operator!() const;
bool operator==(const Vector2 &other) const;
bool operator!=(const Vector2 &other) const;
Vector2 operator+() const;
Vector2 operator-() const;
Vector2 operator+(const Vector2 &other) const;
Vector2 operator-(const Vector2 &other) const;
Vector2 operator*(const Vector2 &other) const;
Vector2 operator/(const Vector2 &other) const;
Vector2 operator*(double value) const;
Vector2 operator/(double value) const;
Vector2 & operator+=(const Vector2 &other);
Vector2 & operator-=(const Vector2 &other);
Vector2 & operator*=(const Vector2 &other);
Vector2 & operator/=(const Vector2 &other);
Vector2 & operator*=(double value);
Vector2 & operator/=(double value);
/// Dot product of two vectors.
friend double dotProduct(const Vector2 &a, const Vector2 &b);
/// A special version of the cross product for 2D vectors (returns scalar value).
friend double crossProduct(const Vector2 &a, const Vector2 &b);
friend Vector2 operator*(double value, const Vector2 &vector);
friend Vector2 operator/(double value, const Vector2 &vector);
};
/// A vector may also represent a point, which shall be differentiated semantically using the alias Point2.
typedef Vector2 Point2;
}

167
thirdparty/msdfgen/core/Vector2.hpp vendored Normal file
View file

@ -0,0 +1,167 @@
#pragma once
#include <cmath>
#include "base.h"
namespace msdfgen {
/**
* A 2-dimensional euclidean floating-point vector.
* @author Viktor Chlumsky
*/
struct Vector2 {
double x, y;
inline Vector2(double val = 0) : x(val), y(val) { }
inline Vector2(double x, double y) : x(x), y(y) { }
/// Sets the vector to zero.
inline void reset() {
x = 0, y = 0;
}
/// Sets individual elements of the vector.
inline void set(double x, double y) {
this->x = x, this->y = y;
}
/// Returns the vector's squared length.
inline double squaredLength() const {
return x*x+y*y;
}
/// Returns the vector's length.
inline double length() const {
return sqrt(x*x+y*y);
}
/// Returns the normalized vector - one that has the same direction but unit length.
inline Vector2 normalize(bool allowZero = false) const {
if (double len = length())
return Vector2(x/len, y/len);
return Vector2(0, !allowZero);
}
/// Returns a vector with the same length that is orthogonal to this one.
inline Vector2 getOrthogonal(bool polarity = true) const {
return polarity ? Vector2(-y, x) : Vector2(y, -x);
}
/// Returns a vector with unit length that is orthogonal to this one.
inline Vector2 getOrthonormal(bool polarity = true, bool allowZero = false) const {
if (double len = length())
return polarity ? Vector2(-y/len, x/len) : Vector2(y/len, -x/len);
return polarity ? Vector2(0, !allowZero) : Vector2(0, -!allowZero);
}
#ifdef MSDFGEN_USE_CPP11
inline explicit operator bool() const {
return x || y;
}
#else
inline operator const void *() const {
return x || y ? this : NULL;
}
#endif
inline Vector2 &operator+=(const Vector2 other) {
x += other.x, y += other.y;
return *this;
}
inline Vector2 &operator-=(const Vector2 other) {
x -= other.x, y -= other.y;
return *this;
}
inline Vector2 &operator*=(const Vector2 other) {
x *= other.x, y *= other.y;
return *this;
}
inline Vector2 &operator/=(const Vector2 other) {
x /= other.x, y /= other.y;
return *this;
}
inline Vector2 &operator*=(double value) {
x *= value, y *= value;
return *this;
}
inline Vector2 &operator/=(double value) {
x /= value, y /= value;
return *this;
}
};
/// A vector may also represent a point, which shall be differentiated semantically using the alias Point2.
typedef Vector2 Point2;
/// Dot product of two vectors.
inline double dotProduct(const Vector2 a, const Vector2 b) {
return a.x*b.x+a.y*b.y;
}
/// A special version of the cross product for 2D vectors (returns scalar value).
inline double crossProduct(const Vector2 a, const Vector2 b) {
return a.x*b.y-a.y*b.x;
}
inline bool operator==(const Vector2 a, const Vector2 b) {
return a.x == b.x && a.y == b.y;
}
inline bool operator!=(const Vector2 a, const Vector2 b) {
return a.x != b.x || a.y != b.y;
}
inline Vector2 operator+(const Vector2 v) {
return v;
}
inline Vector2 operator-(const Vector2 v) {
return Vector2(-v.x, -v.y);
}
inline bool operator!(const Vector2 v) {
return !v.x && !v.y;
}
inline Vector2 operator+(const Vector2 a, const Vector2 b) {
return Vector2(a.x+b.x, a.y+b.y);
}
inline Vector2 operator-(const Vector2 a, const Vector2 b) {
return Vector2(a.x-b.x, a.y-b.y);
}
inline Vector2 operator*(const Vector2 a, const Vector2 b) {
return Vector2(a.x*b.x, a.y*b.y);
}
inline Vector2 operator/(const Vector2 a, const Vector2 b) {
return Vector2(a.x/b.x, a.y/b.y);
}
inline Vector2 operator*(double a, const Vector2 b) {
return Vector2(a*b.x, a*b.y);
}
inline Vector2 operator/(double a, const Vector2 b) {
return Vector2(a/b.x, a/b.y);
}
inline Vector2 operator*(const Vector2 a, double b) {
return Vector2(a.x*b, a.y*b);
}
inline Vector2 operator/(const Vector2 a, double b) {
return Vector2(a.x/b, a.y/b);
}
}

View file

@ -1,8 +1,8 @@
#pragma once
#include <cstdlib>
#include <cmath>
#include "base.h"
namespace msdfgen {

16
thirdparty/msdfgen/core/base.h vendored Normal file
View file

@ -0,0 +1,16 @@
#pragma once
// This file needs to be included first for all MSDFgen sources
#ifndef MSDFGEN_PUBLIC
#include <msdfgen/msdfgen-config.h>
#endif
#include <cstddef>
namespace msdfgen {
typedef unsigned char byte;
}

View file

@ -2,7 +2,7 @@
#pragma once
#include "arithmetics.hpp"
#include "Vector2.h"
#include "Vector2.hpp"
#include "BitmapRef.hpp"
namespace msdfgen {

View file

@ -33,7 +33,7 @@ void SimpleContourCombiner<EdgeSelector>::reset(const Point2 &p) {
}
template <class EdgeSelector>
EdgeSelector & SimpleContourCombiner<EdgeSelector>::edgeSelector(int) {
EdgeSelector &SimpleContourCombiner<EdgeSelector>::edgeSelector(int) {
return shapeEdgeSelector;
}
@ -63,7 +63,7 @@ void OverlappingContourCombiner<EdgeSelector>::reset(const Point2 &p) {
}
template <class EdgeSelector>
EdgeSelector & OverlappingContourCombiner<EdgeSelector>::edgeSelector(int i) {
EdgeSelector &OverlappingContourCombiner<EdgeSelector>::edgeSelector(int i) {
return edgeSelectors[i];
}

View file

@ -16,7 +16,7 @@ public:
explicit SimpleContourCombiner(const Shape &shape);
void reset(const Point2 &p);
EdgeSelector & edgeSelector(int i);
EdgeSelector &edgeSelector(int i);
DistanceType distance() const;
private:
@ -34,7 +34,7 @@ public:
explicit OverlappingContourCombiner(const Shape &shape);
void reset(const Point2 &p);
EdgeSelector & edgeSelector(int i);
EdgeSelector &edgeSelector(int i);
DistanceType distance() const;
private:

View file

@ -5,6 +5,7 @@
#include <cmath>
#include <cstring>
#include <cfloat>
#include <vector>
#include <queue>
#include "arithmetics.hpp"
@ -244,7 +245,7 @@ static double edgeToEdgeDistance(const EdgeSegment &a, const EdgeSegment &b, int
return minDistance;
}
static double splineToSplineDistance(EdgeSegment * const *edgeSegments, int aStart, int aEnd, int bStart, int bEnd, int precision) {
static double splineToSplineDistance(EdgeSegment *const *edgeSegments, int aStart, int aEnd, int bStart, int bEnd, int precision) {
double minDistance = DBL_MAX;
for (int ai = aStart; ai < aEnd; ++ai)
for (int bi = bStart; bi < bEnd && minDistance; ++bi) {
@ -254,7 +255,7 @@ static double splineToSplineDistance(EdgeSegment * const *edgeSegments, int aSta
return minDistance;
}
static void colorSecondDegreeGraph(int *coloring, const int * const *edgeMatrix, int vertexCount, unsigned long long seed) {
static void colorSecondDegreeGraph(int *coloring, const int *const *edgeMatrix, int vertexCount, unsigned long long seed) {
for (int i = 0; i < vertexCount; ++i) {
int possibleColors = 7;
for (int j = 0; j < i; ++j) {
@ -301,7 +302,7 @@ static int vertexPossibleColors(const int *coloring, const int *edgeVector, int
return 7&~usedColors;
}
static void uncolorSameNeighbors(std::queue<int> &uncolored, int *coloring, const int * const *edgeMatrix, int vertex, int vertexCount) {
static void uncolorSameNeighbors(std::queue<int> &uncolored, int *coloring, const int *const *edgeMatrix, int vertex, int vertexCount) {
for (int i = vertex+1; i < vertexCount; ++i) {
if (edgeMatrix[vertex][i] && coloring[i] == coloring[vertex]) {
coloring[i] = -1;
@ -316,7 +317,7 @@ static void uncolorSameNeighbors(std::queue<int> &uncolored, int *coloring, cons
}
}
static bool tryAddEdge(int *coloring, int * const *edgeMatrix, int vertexCount, int vertexA, int vertexB, int *coloringBuffer) {
static bool tryAddEdge(int *coloring, int *const *edgeMatrix, int vertexCount, int vertexA, int vertexB, int *coloringBuffer) {
static const int FIRST_POSSIBLE_COLOR[8] = { -1, 0, 1, 0, 2, 2, 1, 0 };
edgeMatrix[vertexA][vertexB] = 1;
edgeMatrix[vertexB][vertexA] = 1;
@ -358,7 +359,7 @@ static bool tryAddEdge(int *coloring, int * const *edgeMatrix, int vertexCount,
}
static int cmpDoublePtr(const void *a, const void *b) {
return sign(**reinterpret_cast<const double * const *>(a)-**reinterpret_cast<const double * const *>(b));
return sign(**reinterpret_cast<const double *const *>(a)-**reinterpret_cast<const double *const *>(b));
}
void edgeColoringByDistance(Shape &shape, double angleThreshold, unsigned long long seed) {

View file

@ -56,18 +56,42 @@ CubicSegment::CubicSegment(Point2 p0, Point2 p1, Point2 p2, Point2 p3, EdgeColor
p[3] = p3;
}
LinearSegment * LinearSegment::clone() const {
LinearSegment *LinearSegment::clone() const {
return new LinearSegment(p[0], p[1], color);
}
QuadraticSegment * QuadraticSegment::clone() const {
QuadraticSegment *QuadraticSegment::clone() const {
return new QuadraticSegment(p[0], p[1], p[2], color);
}
CubicSegment * CubicSegment::clone() const {
CubicSegment *CubicSegment::clone() const {
return new CubicSegment(p[0], p[1], p[2], p[3], color);
}
int LinearSegment::type() const {
return (int) EDGE_TYPE;
}
int QuadraticSegment::type() const {
return (int) EDGE_TYPE;
}
int CubicSegment::type() const {
return (int) EDGE_TYPE;
}
const Point2 *LinearSegment::controlPoints() const {
return p;
}
const Point2 *QuadraticSegment::controlPoints() const {
return p;
}
const Point2 *CubicSegment::controlPoints() const {
return p;
}
Point2 LinearSegment::point(double param) const {
return mix(p[0], p[1], param);
}
@ -483,7 +507,7 @@ void CubicSegment::splitInThirds(EdgeSegment *&part1, EdgeSegment *&part2, EdgeS
part3 = new CubicSegment(point(2/3.), mix(mix(p[1], p[2], 2/3.), mix(p[2], p[3], 2/3.), 2/3.), p[2] == p[3] ? p[3] : mix(p[2], p[3], 2/3.), p[3], color);
}
EdgeSegment * QuadraticSegment::convertToCubic() const {
EdgeSegment *QuadraticSegment::convertToCubic() const {
return new CubicSegment(p[0], mix(p[0], p[1], 2/3.), mix(p[1], p[2], 1/3.), p[2], color);
}

View file

@ -1,8 +1,8 @@
#pragma once
#include "Vector2.h"
#include "SignedDistance.h"
#include "Vector2.hpp"
#include "SignedDistance.hpp"
#include "EdgeColor.h"
namespace msdfgen {
@ -20,7 +20,11 @@ public:
EdgeSegment(EdgeColor edgeColor = WHITE) : color(edgeColor) { }
virtual ~EdgeSegment() { }
/// Creates a copy of the edge segment.
virtual EdgeSegment * clone() const = 0;
virtual EdgeSegment *clone() const = 0;
/// Returns the numeric code of the edge segment's type.
virtual int type() const = 0;
/// Returns the array of control points.
virtual const Point2 *controlPoints() const = 0;
/// Returns the point on the edge specified by the parameter (between 0 and 1).
virtual Point2 point(double param) const = 0;
/// Returns the direction the edge has at the point specified by the parameter.
@ -51,10 +55,16 @@ public:
class LinearSegment : public EdgeSegment {
public:
enum EdgeType {
EDGE_TYPE = 1
};
Point2 p[2];
LinearSegment(Point2 p0, Point2 p1, EdgeColor edgeColor = WHITE);
LinearSegment * clone() const;
LinearSegment *clone() const;
int type() const;
const Point2 *controlPoints() const;
Point2 point(double param) const;
Vector2 direction(double param) const;
Vector2 directionChange(double param) const;
@ -74,10 +84,16 @@ public:
class QuadraticSegment : public EdgeSegment {
public:
enum EdgeType {
EDGE_TYPE = 2
};
Point2 p[3];
QuadraticSegment(Point2 p0, Point2 p1, Point2 p2, EdgeColor edgeColor = WHITE);
QuadraticSegment * clone() const;
QuadraticSegment *clone() const;
int type() const;
const Point2 *controlPoints() const;
Point2 point(double param) const;
Vector2 direction(double param) const;
Vector2 directionChange(double param) const;
@ -91,7 +107,7 @@ public:
void moveEndPoint(Point2 to);
void splitInThirds(EdgeSegment *&part1, EdgeSegment *&part2, EdgeSegment *&part3) const;
EdgeSegment * convertToCubic() const;
EdgeSegment *convertToCubic() const;
};
@ -99,10 +115,16 @@ public:
class CubicSegment : public EdgeSegment {
public:
enum EdgeType {
EDGE_TYPE = 3
};
Point2 p[4];
CubicSegment(Point2 p0, Point2 p1, Point2 p2, Point2 p3, EdgeColor edgeColor = WHITE);
CubicSegment * clone() const;
CubicSegment *clone() const;
int type() const;
const Point2 *controlPoints() const;
Point2 point(double param) const;
Vector2 direction(double param) const;
Vector2 directionChange(double param) const;

View file

@ -1,8 +1,8 @@
#pragma once
#include "Vector2.h"
#include "SignedDistance.h"
#include "Vector2.hpp"
#include "SignedDistance.hpp"
#include "edge-segments.h"
namespace msdfgen {

View file

@ -49,7 +49,7 @@ static int solveCubicNormed(double x[3], double a, double b, double c) {
x[2] = q*cos(1/3.*(t-2*M_PI))-a;
return 3;
} else {
double u = (r < 0 ? 1 : -1)*pow(fabs(r)+sqrt(r2-q3), 1/3.);
double u = (r < 0 ? 1 : -1)*pow(fabs(r)+sqrt(r2-q3), 1/3.);
double v = u == 0 ? 0 : q/u;
x[0] = (u+v)-a;
if (u == v || fabs(u-v) < 1e-12*fabs(u+v)) {

View file

@ -1,6 +1,8 @@
#pragma once
#include "base.h"
namespace msdfgen {
// ax^2 + bx + c = 0

View file

@ -1,7 +1,6 @@
#pragma once
#include <cstdlib>
#include "BitmapRef.hpp"
#ifndef MSDFGEN_PUBLIC

View file

@ -1,7 +1,7 @@
#pragma once
#include "Vector2.h"
#include "Vector2.hpp"
#include "Projection.h"
#include "Shape.h"
#include "BitmapRef.hpp"

View file

@ -5,8 +5,6 @@
namespace msdfgen {
typedef unsigned char byte;
inline byte pixelFloatToByte(float x) {
return byte(clamp(256.f*x, 255.f));
}

View file

@ -1,7 +1,7 @@
#pragma once
#include "Vector2.h"
#include "Vector2.hpp"
#include "Shape.h"
#include "Projection.h"
#include "Scanline.h"

View file

@ -1,7 +1,7 @@
#pragma once
#include "Vector2.h"
#include "Vector2.hpp"
#include "BitmapRef.hpp"
namespace msdfgen {

View file

@ -1,7 +1,7 @@
#pragma once
#include "Vector2.h"
#include "Vector2.hpp"
#include "Shape.h"
#include "Projection.h"
#include "Scanline.h"

View file

@ -244,34 +244,37 @@ bool writeShapeDescription(FILE *output, const Shape &shape) {
default:;
}
}
if (const LinearSegment *e = dynamic_cast<const LinearSegment *>(&**edge)) {
fprintf(output, "\t");
writeCoord(output, e->p[0]);
fprintf(output, ";\n");
if (colorCode)
fprintf(output, "\t\t%c;\n", colorCode);
}
if (const QuadraticSegment *e = dynamic_cast<const QuadraticSegment *>(&**edge)) {
fprintf(output, "\t");
writeCoord(output, e->p[0]);
fprintf(output, ";\n\t\t");
if (colorCode)
fprintf(output, "%c", colorCode);
fprintf(output, "(");
writeCoord(output, e->p[1]);
fprintf(output, ");\n");
}
if (const CubicSegment *e = dynamic_cast<const CubicSegment *>(&**edge)) {
fprintf(output, "\t");
writeCoord(output, e->p[0]);
fprintf(output, ";\n\t\t");
if (colorCode)
fprintf(output, "%c", colorCode);
fprintf(output, "(");
writeCoord(output, e->p[1]);
fprintf(output, "; ");
writeCoord(output, e->p[2]);
fprintf(output, ");\n");
const Point2 *p = (*edge)->controlPoints();
switch ((*edge)->type()) {
case (int) LinearSegment::EDGE_TYPE:
fprintf(output, "\t");
writeCoord(output, p[0]);
fprintf(output, ";\n");
if (colorCode)
fprintf(output, "\t\t%c;\n", colorCode);
break;
case (int) QuadraticSegment::EDGE_TYPE:
fprintf(output, "\t");
writeCoord(output, p[0]);
fprintf(output, ";\n\t\t");
if (colorCode)
fprintf(output, "%c", colorCode);
fprintf(output, "(");
writeCoord(output, p[1]);
fprintf(output, ");\n");
break;
case (int) CubicSegment::EDGE_TYPE:
fprintf(output, "\t");
writeCoord(output, p[0]);
fprintf(output, ";\n\t\t");
if (colorCode)
fprintf(output, "%c", colorCode);
fprintf(output, "(");
writeCoord(output, p[1]);
fprintf(output, "; ");
writeCoord(output, p[2]);
fprintf(output, ");\n");
break;
}
}
fprintf(output, "\t#\n");

View file

@ -1,7 +1,6 @@
#pragma once
#include <cstdlib>
#include <cstdio>
#include "Shape.h"

View file

@ -4,7 +4,7 @@
/*
* MULTI-CHANNEL SIGNED DISTANCE FIELD GENERATOR
* ---------------------------------------------
* A utility by Viktor Chlumsky, (c) 2014 - 2022
* A utility by Viktor Chlumsky, (c) 2014 - 2023
*
* The technique used to generate multi-channel distance fields in this code
* has been developed by Viktor Chlumsky in 2014 for his master's thesis,
@ -15,8 +15,9 @@
*
*/
#include "core/base.h"
#include "core/arithmetics.hpp"
#include "core/Vector2.h"
#include "core/Vector2.hpp"
#include "core/Projection.h"
#include "core/Scanline.h"
#include "core/Shape.h"