contour-combiners.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. #include "contour-combiners.h"
  2. #include <cfloat>
  3. #include "arithmetics.hpp"
  4. namespace msdfgen {
  5. static void initDistance(double &distance) {
  6. distance = -DBL_MAX;
  7. }
  8. static void initDistance(MultiDistance &distance) {
  9. distance.r = -DBL_MAX;
  10. distance.g = -DBL_MAX;
  11. distance.b = -DBL_MAX;
  12. }
  13. static void initDistance(M7AndTrueDistanceSelector::DistanceType &distance) {
  14. distance.p[0] = -DBL_MAX;
  15. distance.p[1] = -DBL_MAX;
  16. distance.p[2] = -DBL_MAX;
  17. distance.p[3] = -DBL_MAX;
  18. distance.p[4] = -DBL_MAX;
  19. distance.p[5] = -DBL_MAX;
  20. distance.p[6] = -DBL_MAX;
  21. distance.t = -DBL_MAX;
  22. }
  23. static double resolveDistance(double distance) {
  24. return distance;
  25. }
  26. static double resolveDistance(const MultiDistance &distance) {
  27. return median(distance.r, distance.g, distance.b);
  28. }
  29. static int cmpDbl(const void *a, const void *b) {
  30. return *reinterpret_cast<const double *>(a) < *reinterpret_cast<const double *>(b);
  31. }
  32. static double resolveDistance(M7AndTrueDistanceSelector::DistanceType distance) {
  33. qsort(distance.p, 7, sizeof(*distance.p), &cmpDbl);
  34. return distance.p[3];
  35. }
  36. template <class EdgeSelector>
  37. SimpleContourCombiner<EdgeSelector>::SimpleContourCombiner(const Shape &shape) { }
  38. template <class EdgeSelector>
  39. void SimpleContourCombiner<EdgeSelector>::reset(const Point2 &p) {
  40. shapeEdgeSelector.reset(p);
  41. }
  42. template <class EdgeSelector>
  43. EdgeSelector &SimpleContourCombiner<EdgeSelector>::edgeSelector(int) {
  44. return shapeEdgeSelector;
  45. }
  46. template <class EdgeSelector>
  47. typename SimpleContourCombiner<EdgeSelector>::DistanceType SimpleContourCombiner<EdgeSelector>::distance() const {
  48. return shapeEdgeSelector.distance();
  49. }
  50. template class SimpleContourCombiner<TrueDistanceSelector>;
  51. template class SimpleContourCombiner<PseudoDistanceSelector>;
  52. template class SimpleContourCombiner<MultiDistanceSelector>;
  53. template class SimpleContourCombiner<MultiAndTrueDistanceSelector>;
  54. template class SimpleContourCombiner<M7AndTrueDistanceSelector>;
  55. template <class EdgeSelector>
  56. OverlappingContourCombiner<EdgeSelector>::OverlappingContourCombiner(const Shape &shape) {
  57. windings.reserve(shape.contours.size());
  58. for (std::vector<Contour>::const_iterator contour = shape.contours.begin(); contour != shape.contours.end(); ++contour)
  59. windings.push_back(contour->winding());
  60. edgeSelectors.resize(shape.contours.size());
  61. }
  62. template <class EdgeSelector>
  63. void OverlappingContourCombiner<EdgeSelector>::reset(const Point2 &p) {
  64. this->p = p;
  65. for (typename std::vector<EdgeSelector>::iterator contourEdgeSelector = edgeSelectors.begin(); contourEdgeSelector != edgeSelectors.end(); ++contourEdgeSelector)
  66. contourEdgeSelector->reset(p);
  67. }
  68. template <class EdgeSelector>
  69. EdgeSelector &OverlappingContourCombiner<EdgeSelector>::edgeSelector(int i) {
  70. return edgeSelectors[i];
  71. }
  72. template <class EdgeSelector>
  73. typename OverlappingContourCombiner<EdgeSelector>::DistanceType OverlappingContourCombiner<EdgeSelector>::distance() const {
  74. int contourCount = (int) edgeSelectors.size();
  75. EdgeSelector shapeEdgeSelector;
  76. EdgeSelector innerEdgeSelector;
  77. EdgeSelector outerEdgeSelector;
  78. shapeEdgeSelector.reset(p);
  79. innerEdgeSelector.reset(p);
  80. outerEdgeSelector.reset(p);
  81. for (int i = 0; i < contourCount; ++i) {
  82. DistanceType edgeDistance = edgeSelectors[i].distance();
  83. shapeEdgeSelector.merge(edgeSelectors[i]);
  84. if (windings[i] > 0 && resolveDistance(edgeDistance) >= 0)
  85. innerEdgeSelector.merge(edgeSelectors[i]);
  86. if (windings[i] < 0 && resolveDistance(edgeDistance) <= 0)
  87. outerEdgeSelector.merge(edgeSelectors[i]);
  88. }
  89. DistanceType shapeDistance = shapeEdgeSelector.distance();
  90. DistanceType innerDistance = innerEdgeSelector.distance();
  91. DistanceType outerDistance = outerEdgeSelector.distance();
  92. double innerScalarDistance = resolveDistance(innerDistance);
  93. double outerScalarDistance = resolveDistance(outerDistance);
  94. DistanceType distance;
  95. initDistance(distance);
  96. int winding = 0;
  97. if (innerScalarDistance >= 0 && fabs(innerScalarDistance) <= fabs(outerScalarDistance)) {
  98. distance = innerDistance;
  99. winding = 1;
  100. for (int i = 0; i < contourCount; ++i)
  101. if (windings[i] > 0) {
  102. DistanceType contourDistance = edgeSelectors[i].distance();
  103. if (fabs(resolveDistance(contourDistance)) < fabs(outerScalarDistance) && resolveDistance(contourDistance) > resolveDistance(distance))
  104. distance = contourDistance;
  105. }
  106. } else if (outerScalarDistance <= 0 && fabs(outerScalarDistance) < fabs(innerScalarDistance)) {
  107. distance = outerDistance;
  108. winding = -1;
  109. for (int i = 0; i < contourCount; ++i)
  110. if (windings[i] < 0) {
  111. DistanceType contourDistance = edgeSelectors[i].distance();
  112. if (fabs(resolveDistance(contourDistance)) < fabs(innerScalarDistance) && resolveDistance(contourDistance) < resolveDistance(distance))
  113. distance = contourDistance;
  114. }
  115. } else
  116. return shapeDistance;
  117. for (int i = 0; i < contourCount; ++i)
  118. if (windings[i] != winding) {
  119. DistanceType contourDistance = edgeSelectors[i].distance();
  120. if (resolveDistance(contourDistance)*resolveDistance(distance) >= 0 && fabs(resolveDistance(contourDistance)) < fabs(resolveDistance(distance)))
  121. distance = contourDistance;
  122. }
  123. if (resolveDistance(distance) == resolveDistance(shapeDistance))
  124. distance = shapeDistance;
  125. return distance;
  126. }
  127. template class OverlappingContourCombiner<TrueDistanceSelector>;
  128. template class OverlappingContourCombiner<PseudoDistanceSelector>;
  129. template class OverlappingContourCombiner<MultiDistanceSelector>;
  130. template class OverlappingContourCombiner<MultiAndTrueDistanceSelector>;
  131. template class OverlappingContourCombiner<M7AndTrueDistanceSelector>;
  132. }