mirror of https://github.com/Chlumsky/msdfgen.git
Shape bounds refactor
This commit is contained in:
parent
e88da21071
commit
fd50406d67
|
|
@ -24,30 +24,32 @@ EdgeHolder & Contour::addEdge() {
|
|||
return edges.back();
|
||||
}
|
||||
|
||||
static void pointBounds(Point2 p, double &l, double &b, double &r, double &t) {
|
||||
static void boundPoint(double &l, double &b, double &r, double &t, Point2 p) {
|
||||
if (p.x < l) l = p.x;
|
||||
if (p.y < b) b = p.y;
|
||||
if (p.x > r) r = p.x;
|
||||
if (p.y > t) t = p.y;
|
||||
}
|
||||
|
||||
void Contour::bounds(double &l, double &b, double &r, double &t) const {
|
||||
void Contour::bound(double &l, double &b, double &r, double &t) const {
|
||||
for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge)
|
||||
(*edge)->bounds(l, b, r, t);
|
||||
(*edge)->bound(l, b, r, t);
|
||||
}
|
||||
|
||||
void Contour::miterBounds(double &l, double &b, double &r, double &t, double border, double miterLimit) const {
|
||||
void Contour::boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const {
|
||||
if (edges.empty())
|
||||
return;
|
||||
Vector2 prevDir = edges.back()->direction(1).normalize(true);
|
||||
for (std::vector<EdgeHolder>::const_iterator edge = edges.begin(); edge != edges.end(); ++edge) {
|
||||
Vector2 dir = -(*edge)->direction(0).normalize(true);
|
||||
if (polarity*crossProduct(prevDir, dir) >= 0) {
|
||||
double miterLength = miterLimit;
|
||||
double q = .5*(1-dotProduct(prevDir, dir));
|
||||
if (q > 0)
|
||||
miterLength = min(1/sqrt(q), miterLimit);
|
||||
Point2 miter = (*edge)->point(0)+border*miterLength*(prevDir+dir).normalize(true);
|
||||
pointBounds(miter, l, b, r, t);
|
||||
boundPoint(l, b, r, t, miter);
|
||||
}
|
||||
prevDir = (*edge)->direction(1).normalize(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ public:
|
|||
/// Creates a new edge in the contour and returns its reference.
|
||||
EdgeHolder & addEdge();
|
||||
/// Adjusts the bounding box to fit the contour.
|
||||
void bounds(double &l, double &b, double &r, double &t) const;
|
||||
void bound(double &l, double &b, double &r, double &t) const;
|
||||
/// Adjusts the bounding box to fit the contour border's mitered corners.
|
||||
void miterBounds(double &l, double &b, double &r, double &t, double border, double miterLimit) const;
|
||||
void boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const;
|
||||
/// Computes the winding of the contour. Returns 1 if positive, -1 if negative.
|
||||
int winding() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -48,14 +48,27 @@ void Shape::normalize() {
|
|||
}
|
||||
}
|
||||
|
||||
void Shape::bounds(double &l, double &b, double &r, double &t) const {
|
||||
void Shape::bound(double &l, double &b, double &r, double &t) const {
|
||||
for (std::vector<Contour>::const_iterator contour = contours.begin(); contour != contours.end(); ++contour)
|
||||
contour->bounds(l, b, r, t);
|
||||
contour->bound(l, b, r, t);
|
||||
}
|
||||
|
||||
void Shape::miterBounds(double &l, double &b, double &r, double &t, double border, double miterLimit) const {
|
||||
void Shape::boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const {
|
||||
for (std::vector<Contour>::const_iterator contour = contours.begin(); contour != contours.end(); ++contour)
|
||||
contour->miterBounds(l, b, r, t, border, miterLimit);
|
||||
contour->boundMiters(l, b, r, t, border, miterLimit, polarity);
|
||||
}
|
||||
|
||||
Shape::Bounds Shape::getBounds(double border, double miterLimit, int polarity) const {
|
||||
static const double LARGE_VALUE = 1e240;
|
||||
Shape::Bounds bounds = { +LARGE_VALUE, +LARGE_VALUE, -LARGE_VALUE, -LARGE_VALUE };
|
||||
bound(bounds.l, bounds.b, bounds.r, bounds.t);
|
||||
if (border > 0) {
|
||||
bounds.l -= border, bounds.b -= border;
|
||||
bounds.r += border, bounds.t += border;
|
||||
if (miterLimit > 0)
|
||||
boundMiters(bounds.l, bounds.b, bounds.r, bounds.t, border, miterLimit, polarity);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void Shape::scanline(Scanline &line, double y) const {
|
||||
|
|
|
|||
10
core/Shape.h
10
core/Shape.h
|
|
@ -11,6 +11,10 @@ namespace msdfgen {
|
|||
class Shape {
|
||||
|
||||
public:
|
||||
struct Bounds {
|
||||
double l, b, r, t;
|
||||
};
|
||||
|
||||
/// The list of contours the shape consists of.
|
||||
std::vector<Contour> contours;
|
||||
/// Specifies whether the shape uses bottom-to-top (false) or top-to-bottom (true) Y coordinates.
|
||||
|
|
@ -29,9 +33,11 @@ public:
|
|||
/// Performs basic checks to determine if the object represents a valid shape.
|
||||
bool validate() const;
|
||||
/// Adjusts the bounding box to fit the shape.
|
||||
void bounds(double &l, double &b, double &r, double &t) const;
|
||||
void bound(double &l, double &b, double &r, double &t) const;
|
||||
/// Adjusts the bounding box to fit the shape border's mitered corners.
|
||||
void miterBounds(double &l, double &b, double &r, double &t, double border, double miterLimit) const;
|
||||
void boundMiters(double &l, double &b, double &r, double &t, double border, double miterLimit, int polarity) const;
|
||||
/// Computes the minimum bounding box that fits the shape, optionally with a (mitered) border.
|
||||
Bounds getBounds(double border = 0, double miterLimit = 0, int polarity = 0) const;
|
||||
/// Outputs the scanline that intersects the shape at y.
|
||||
void scanline(Scanline &line, double y) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -325,12 +325,12 @@ static void pointBounds(Point2 p, double &l, double &b, double &r, double &t) {
|
|||
if (p.y > t) t = p.y;
|
||||
}
|
||||
|
||||
void LinearSegment::bounds(double &l, double &b, double &r, double &t) const {
|
||||
void LinearSegment::bound(double &l, double &b, double &r, double &t) const {
|
||||
pointBounds(p[0], l, b, r, t);
|
||||
pointBounds(p[1], l, b, r, t);
|
||||
}
|
||||
|
||||
void QuadraticSegment::bounds(double &l, double &b, double &r, double &t) const {
|
||||
void QuadraticSegment::bound(double &l, double &b, double &r, double &t) const {
|
||||
pointBounds(p[0], l, b, r, t);
|
||||
pointBounds(p[2], l, b, r, t);
|
||||
Vector2 bot = (p[1]-p[0])-(p[2]-p[1]);
|
||||
|
|
@ -346,7 +346,7 @@ void QuadraticSegment::bounds(double &l, double &b, double &r, double &t) const
|
|||
}
|
||||
}
|
||||
|
||||
void CubicSegment::bounds(double &l, double &b, double &r, double &t) const {
|
||||
void CubicSegment::bound(double &l, double &b, double &r, double &t) const {
|
||||
pointBounds(p[0], l, b, r, t);
|
||||
pointBounds(p[3], l, b, r, t);
|
||||
Vector2 a0 = p[1]-p[0];
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public:
|
|||
/// Outputs a list of (at most three) intersections (their X coordinates) with an infinite horizontal scanline at y and returns how many there are.
|
||||
virtual int scanlineIntersections(double x[3], int dy[3], double y) const = 0;
|
||||
/// Adjusts the bounding box to fit the edge segment.
|
||||
virtual void bounds(double &l, double &b, double &r, double &t) const = 0;
|
||||
virtual void bound(double &l, double &b, double &r, double &t) const = 0;
|
||||
|
||||
/// Moves the start point of the edge segment.
|
||||
virtual void moveStartPoint(Point2 to) = 0;
|
||||
|
|
@ -55,7 +55,7 @@ public:
|
|||
Vector2 direction(double param) const;
|
||||
SignedDistance signedDistance(Point2 origin, double ¶m) const;
|
||||
int scanlineIntersections(double x[3], int dy[3], double y) const;
|
||||
void bounds(double &l, double &b, double &r, double &t) const;
|
||||
void bound(double &l, double &b, double &r, double &t) const;
|
||||
|
||||
void moveStartPoint(Point2 to);
|
||||
void moveEndPoint(Point2 to);
|
||||
|
|
@ -75,7 +75,7 @@ public:
|
|||
Vector2 direction(double param) const;
|
||||
SignedDistance signedDistance(Point2 origin, double ¶m) const;
|
||||
int scanlineIntersections(double x[3], int dy[3], double y) const;
|
||||
void bounds(double &l, double &b, double &r, double &t) const;
|
||||
void bound(double &l, double &b, double &r, double &t) const;
|
||||
|
||||
void moveStartPoint(Point2 to);
|
||||
void moveEndPoint(Point2 to);
|
||||
|
|
@ -95,7 +95,7 @@ public:
|
|||
Vector2 direction(double param) const;
|
||||
SignedDistance signedDistance(Point2 origin, double ¶m) const;
|
||||
int scanlineIntersections(double x[3], int dy[3], double y) const;
|
||||
void bounds(double &l, double &b, double &r, double &t) const;
|
||||
void bound(double &l, double &b, double &r, double &t) const;
|
||||
|
||||
void moveStartPoint(Point2 to);
|
||||
void moveEndPoint(Point2 to);
|
||||
|
|
|
|||
9
main.cpp
9
main.cpp
|
|
@ -20,7 +20,6 @@
|
|||
#pragma warning(disable:4996)
|
||||
#endif
|
||||
|
||||
#define LARGE_VALUE 1e240
|
||||
#define SDF_ERROR_ESTIMATE_PRECISION 19
|
||||
|
||||
using namespace msdfgen;
|
||||
|
|
@ -730,13 +729,9 @@ int main(int argc, const char * const *argv) {
|
|||
shape.inverseYAxis = !shape.inverseYAxis;
|
||||
|
||||
double avgScale = .5*(scale.x+scale.y);
|
||||
struct {
|
||||
double l, b, r, t;
|
||||
} bounds = {
|
||||
LARGE_VALUE, LARGE_VALUE, -LARGE_VALUE, -LARGE_VALUE
|
||||
};
|
||||
Shape::Bounds bounds = { };
|
||||
if (autoFrame || mode == METRICS || printMetrics || orientation == GUESS)
|
||||
shape.bounds(bounds.l, bounds.b, bounds.r, bounds.t);
|
||||
bounds = shape.getBounds();
|
||||
|
||||
// Auto-frame
|
||||
if (autoFrame) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue