123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- #include "contour-combiners.h"
- #include <cfloat>
- #include "arithmetics.hpp"
- namespace msdfgen {
- static void initDistance(real &distance) {
- distance = -FLT_MAX;
- }
- static void initDistance(MultiDistance &distance) {
- distance.r = -FLT_MAX;
- distance.g = -FLT_MAX;
- distance.b = -FLT_MAX;
- }
- static real resolveDistance(real distance) {
- return distance;
- }
- static real 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) >= real(0))
- innerEdgeSelector.merge(edgeSelectors[i]);
- if (windings[i] < 0 && resolveDistance(edgeDistance) <= real(0))
- outerEdgeSelector.merge(edgeSelectors[i]);
- }
- DistanceType shapeDistance = shapeEdgeSelector.distance();
- DistanceType innerDistance = innerEdgeSelector.distance();
- DistanceType outerDistance = outerEdgeSelector.distance();
- real innerScalarDistance = resolveDistance(innerDistance);
- real outerScalarDistance = resolveDistance(outerDistance);
- DistanceType distance;
- initDistance(distance);
- int winding = 0;
- if (innerScalarDistance >= real(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 <= real(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) >= real(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>;
- }
|