#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 SimpleContourCombiner::SimpleContourCombiner(const Shape &shape) { } template void SimpleContourCombiner::reset(const Point2 &p) { shapeEdgeSelector.reset(p); } template EdgeSelector & SimpleContourCombiner::edgeSelector(int) { return shapeEdgeSelector; } template typename SimpleContourCombiner::DistanceType SimpleContourCombiner::distance() const { return shapeEdgeSelector.distance(); } template class SimpleContourCombiner; template class SimpleContourCombiner; template class SimpleContourCombiner; template class SimpleContourCombiner; template OverlappingContourCombiner::OverlappingContourCombiner(const Shape &shape) { windings.reserve(shape.contours.size()); for (std::vector::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour) windings.push_back(contour->winding()); edgeSelectors.resize(shape.contours.size()); } template void OverlappingContourCombiner::reset(const Point2 &p) { this->p = p; for (typename std::vector::iterator contourEdgeSelector = edgeSelectors.begin(); contourEdgeSelector != edgeSelectors.end(); ++contourEdgeSelector) contourEdgeSelector->reset(p); } template EdgeSelector & OverlappingContourCombiner::edgeSelector(int i) { return edgeSelectors[i]; } template typename OverlappingContourCombiner::DistanceType OverlappingContourCombiner::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; template class OverlappingContourCombiner; template class OverlappingContourCombiner; template class OverlappingContourCombiner; }