summaryrefslogtreecommitdiff
path: root/thirdparty/msdfgen/core/contour-combiners.cpp
diff options
context:
space:
mode:
authorK. S. Ernest (iFire) Lee <fire@users.noreply.github.com>2021-08-27 08:51:37 -0700
committerGitHub <noreply@github.com>2021-08-27 08:51:37 -0700
commit90a35dac489bcbe39de35af661367519b411cb98 (patch)
tree8b6b4535556be521f9fbbadaebdea04e5316582c /thirdparty/msdfgen/core/contour-combiners.cpp
parentca4f20529c0b6588464f88fc0b0680a8df0fc77f (diff)
parent4c3f7d1290311456519ca2416590c7e62465b7f2 (diff)
Merge pull request #51908 from bruvzg/msdf_fonts2
Make FontData importable resource. Add multi-channel SDF font rendering.
Diffstat (limited to 'thirdparty/msdfgen/core/contour-combiners.cpp')
-rw-r--r--thirdparty/msdfgen/core/contour-combiners.cpp133
1 files changed, 133 insertions, 0 deletions
diff --git a/thirdparty/msdfgen/core/contour-combiners.cpp b/thirdparty/msdfgen/core/contour-combiners.cpp
new file mode 100644
index 0000000000..d0c5b46d74
--- /dev/null
+++ b/thirdparty/msdfgen/core/contour-combiners.cpp
@@ -0,0 +1,133 @@
+
+#include "contour-combiners.h"
+
+#include "arithmetics.hpp"
+
+namespace msdfgen {
+
+static void initDistance(double &distance) {
+ distance = SignedDistance::INFINITE.distance;
+}
+
+static void initDistance(MultiDistance &distance) {
+ distance.r = SignedDistance::INFINITE.distance;
+ distance.g = SignedDistance::INFINITE.distance;
+ distance.b = SignedDistance::INFINITE.distance;
+}
+
+static double resolveDistance(double distance) {
+ return distance;
+}
+
+static double resolveDistance(const MultiDistance &distance) {
+ return median(distance.r, distance.g, distance.b);
+}
+
+template <class EdgeSelector>
+SimpleContourCombiner<EdgeSelector>::SimpleContourCombiner(const Shape &shape) { }
+
+template <class EdgeSelector>
+void SimpleContourCombiner<EdgeSelector>::reset(const Point2 &p) {
+ shapeEdgeSelector.reset(p);
+}
+
+template <class EdgeSelector>
+EdgeSelector & SimpleContourCombiner<EdgeSelector>::edgeSelector(int) {
+ return shapeEdgeSelector;
+}
+
+template <class EdgeSelector>
+typename SimpleContourCombiner<EdgeSelector>::DistanceType SimpleContourCombiner<EdgeSelector>::distance() const {
+ return shapeEdgeSelector.distance();
+}
+
+template class SimpleContourCombiner<TrueDistanceSelector>;
+template class SimpleContourCombiner<PseudoDistanceSelector>;
+template class SimpleContourCombiner<MultiDistanceSelector>;
+template class SimpleContourCombiner<MultiAndTrueDistanceSelector>;
+
+template <class EdgeSelector>
+OverlappingContourCombiner<EdgeSelector>::OverlappingContourCombiner(const Shape &shape) {
+ windings.reserve(shape.contours.size());
+ for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
+ windings.push_back(contour->winding());
+ edgeSelectors.resize(shape.contours.size());
+}
+
+template <class EdgeSelector>
+void OverlappingContourCombiner<EdgeSelector>::reset(const Point2 &p) {
+ this->p = p;
+ for (typename std::vector<EdgeSelector>::iterator contourEdgeSelector = edgeSelectors.begin(); contourEdgeSelector != edgeSelectors.end(); ++contourEdgeSelector)
+ contourEdgeSelector->reset(p);
+}
+
+template <class EdgeSelector>
+EdgeSelector & OverlappingContourCombiner<EdgeSelector>::edgeSelector(int i) {
+ return edgeSelectors[i];
+}
+
+template <class EdgeSelector>
+typename OverlappingContourCombiner<EdgeSelector>::DistanceType OverlappingContourCombiner<EdgeSelector>::distance() const {
+ int contourCount = (int) edgeSelectors.size();
+ EdgeSelector shapeEdgeSelector;
+ EdgeSelector innerEdgeSelector;
+ EdgeSelector outerEdgeSelector;
+ shapeEdgeSelector.reset(p);
+ innerEdgeSelector.reset(p);
+ outerEdgeSelector.reset(p);
+ for (int i = 0; i < contourCount; ++i) {
+ DistanceType edgeDistance = edgeSelectors[i].distance();
+ shapeEdgeSelector.merge(edgeSelectors[i]);
+ if (windings[i] > 0 && resolveDistance(edgeDistance) >= 0)
+ innerEdgeSelector.merge(edgeSelectors[i]);
+ if (windings[i] < 0 && resolveDistance(edgeDistance) <= 0)
+ outerEdgeSelector.merge(edgeSelectors[i]);
+ }
+
+ DistanceType shapeDistance = shapeEdgeSelector.distance();
+ DistanceType innerDistance = innerEdgeSelector.distance();
+ DistanceType outerDistance = outerEdgeSelector.distance();
+ double innerScalarDistance = resolveDistance(innerDistance);
+ double outerScalarDistance = resolveDistance(outerDistance);
+ DistanceType distance;
+ initDistance(distance);
+
+ int winding = 0;
+ if (innerScalarDistance >= 0 && fabs(innerScalarDistance) <= fabs(outerScalarDistance)) {
+ distance = innerDistance;
+ winding = 1;
+ for (int i = 0; i < contourCount; ++i)
+ if (windings[i] > 0) {
+ DistanceType contourDistance = edgeSelectors[i].distance();
+ if (fabs(resolveDistance(contourDistance)) < fabs(outerScalarDistance) && resolveDistance(contourDistance) > resolveDistance(distance))
+ distance = contourDistance;
+ }
+ } else if (outerScalarDistance <= 0 && fabs(outerScalarDistance) < fabs(innerScalarDistance)) {
+ distance = outerDistance;
+ winding = -1;
+ for (int i = 0; i < contourCount; ++i)
+ if (windings[i] < 0) {
+ DistanceType contourDistance = edgeSelectors[i].distance();
+ if (fabs(resolveDistance(contourDistance)) < fabs(innerScalarDistance) && resolveDistance(contourDistance) < resolveDistance(distance))
+ distance = contourDistance;
+ }
+ } else
+ return shapeDistance;
+
+ for (int i = 0; i < contourCount; ++i)
+ if (windings[i] != winding) {
+ DistanceType contourDistance = edgeSelectors[i].distance();
+ if (resolveDistance(contourDistance)*resolveDistance(distance) >= 0 && fabs(resolveDistance(contourDistance)) < fabs(resolveDistance(distance)))
+ distance = contourDistance;
+ }
+ if (resolveDistance(distance) == resolveDistance(shapeDistance))
+ distance = shapeDistance;
+ return distance;
+}
+
+template class OverlappingContourCombiner<TrueDistanceSelector>;
+template class OverlappingContourCombiner<PseudoDistanceSelector>;
+template class OverlappingContourCombiner<MultiDistanceSelector>;
+template class OverlappingContourCombiner<MultiAndTrueDistanceSelector>;
+
+}