diff --git a/modules/juce_graphics/geometry/juce_Point.h b/modules/juce_graphics/geometry/juce_Point.h index 00ace96e33..1a21454d17 100644 --- a/modules/juce_graphics/geometry/juce_Point.h +++ b/modules/juce_graphics/geometry/juce_Point.h @@ -196,8 +196,8 @@ public: /** Returns the position of this point, if it is transformed by a given AffineTransform. */ Point transformedBy (const AffineTransform& transform) const noexcept { - return Point (transform.mat00 * x + transform.mat01 * y + transform.mat02, - transform.mat10 * x + transform.mat11 * y + transform.mat12); + return Point (static_cast (transform.mat00 * x + transform.mat01 * y + transform.mat02), + static_cast (transform.mat10 * x + transform.mat11 * y + transform.mat12)); } //============================================================================== diff --git a/modules/juce_graphics/geometry/juce_Rectangle.h b/modules/juce_graphics/geometry/juce_Rectangle.h index 6cc1a71bdf..facba9f45a 100644 --- a/modules/juce_graphics/geometry/juce_Rectangle.h +++ b/modules/juce_graphics/geometry/juce_Rectangle.h @@ -587,8 +587,9 @@ public: pos.y = newY; return true; } - else if (pos.y == other.pos.y && getBottom() == other.getBottom() - && (other.getRight() >= pos.x && other.pos.x <= getRight())) + + if (pos.y == other.pos.y && getBottom() == other.getBottom() + && (other.getRight() >= pos.x && other.pos.x <= getRight())) { const ValueType newX = jmin (pos.x, other.pos.x); w = jmax (getRight(), other.getRight()) - newX; @@ -652,20 +653,24 @@ public: */ Rectangle transformed (const AffineTransform& transform) const noexcept { - float x1 = pos.x, y1 = pos.y; - float x2 = pos.x + w, y2 = pos.y; - float x3 = pos.x, y3 = pos.y + h; - float x4 = x2, y4 = y3; + typedef typename TypeHelpers::SmallestFloatType::type FloatType; + + FloatType x1 = static_cast (pos.x), y1 = static_cast (pos.y); + FloatType x2 = static_cast (pos.x + w), y2 = static_cast (pos.y); + FloatType x3 = static_cast (pos.x), y3 = static_cast (pos.y + h); + FloatType x4 = static_cast (x2), y4 = static_cast (y3); transform.transformPoints (x1, y1, x2, y2); transform.transformPoints (x3, y3, x4, y4); - const float rx = jmin (x1, x2, x3, x4); - const float ry = jmin (y1, y2, y3, y4); + const FloatType rx1 = jmin (x1, x2, x3, x4); + const FloatType rx2 = jmax (x1, x2, x3, x4); + const FloatType ry1 = jmin (y1, y2, y3, y4); + const FloatType ry2 = jmax (y1, y2, y3, y4); - return Rectangle (rx, ry, - jmax (x1, x2, x3, x4) - rx, - jmax (y1, y2, y3, y4) - ry); + Rectangle r; + Rectangle (rx1, ry1, rx2 - rx1, ry2 - ry1).copyWithRounding (r); + return r; } /** Returns the smallest integer-aligned rectangle that completely contains this one. @@ -674,34 +679,22 @@ public: */ Rectangle getSmallestIntegerContainer() const noexcept { - const int x1 = static_cast (std::floor (static_cast (pos.x))); - const int y1 = static_cast (std::floor (static_cast (pos.y))); - const int x2 = static_cast (std::ceil (static_cast (pos.x + w))); - const int y2 = static_cast (std::ceil (static_cast (pos.y + h))); - - return Rectangle (x1, y1, x2 - x1, y2 - y1); + return getSmallestIntegerContainerWithType(); } - /** Returns the smallest Rectangle that can contain a set of points. */ - static Rectangle findAreaContainingPoints (const Point* const points, const int numPoints) noexcept + /** Returns the smallest integer-aligned rectangle that completely contains this one. + This is only relevent for floating-point rectangles, of course. + @see toFloat() + */ + template + Rectangle getSmallestIntegerContainerWithType() const noexcept { - if (numPoints == 0) - return Rectangle(); - - ValueType minX (points[0].x); - ValueType maxX (minX); - ValueType minY (points[0].y); - ValueType maxY (minY); + const IntType x1 = static_cast (std::floor (static_cast (pos.x))); + const IntType y1 = static_cast (std::floor (static_cast (pos.y))); + const IntType x2 = static_cast (std::ceil (static_cast (pos.x + w))); + const IntType y2 = static_cast (std::ceil (static_cast (pos.y + h))); - for (int i = 1; i < numPoints; ++i) - { - minX = jmin (minX, points[i].x); - maxX = jmax (maxX, points[i].x); - minY = jmin (minY, points[i].y); - maxY = jmax (maxY, points[i].y); - } - - return Rectangle (minX, minY, maxX - minX, maxY - minY); + return Rectangle (x1, y1, x2 - x1, y2 - y1); } /** Casts this rectangle to a Rectangle. @@ -724,6 +717,28 @@ public: static_cast (w), static_cast (h)); } + /** Returns the smallest Rectangle that can contain a set of points. */ + static Rectangle findAreaContainingPoints (const Point* const points, const int numPoints) noexcept + { + if (numPoints == 0) + return Rectangle(); + + ValueType minX (points[0].x); + ValueType maxX (minX); + ValueType minY (points[0].y); + ValueType maxY (minY); + + for (int i = 1; i < numPoints; ++i) + { + minX = jmin (minX, points[i].x); + maxX = jmax (maxX, points[i].x); + minY = jmin (minY, points[i].y); + maxY = jmax (maxY, points[i].y); + } + + return Rectangle (minX, minY, maxX - minX, maxY - minY); + } + //============================================================================== /** Static utility to intersect two sets of rectangular coordinates. Returns false if the two regions didn't overlap. @@ -789,6 +804,8 @@ public: parseIntAfterSpace (toks[3])); } + typedef ValueType Type; + private: friend class RectangleList; Point pos; @@ -796,6 +813,12 @@ private: static int parseIntAfterSpace (const String& s) noexcept { return s.getCharPointer().findEndOfWhitespace().getIntValue32(); } + + template friend class Rectangle; + + void copyWithRounding (Rectangle& result) const noexcept { result = getSmallestIntegerContainer(); } + void copyWithRounding (Rectangle& result) const noexcept { result = toFloat(); } + void copyWithRounding (Rectangle& result) const noexcept { result = toDouble(); } }; diff --git a/modules/juce_graphics/native/juce_RenderingHelpers.h b/modules/juce_graphics/native/juce_RenderingHelpers.h index 777ae79137..819958aed7 100644 --- a/modules/juce_graphics/native/juce_RenderingHelpers.h +++ b/modules/juce_graphics/native/juce_RenderingHelpers.h @@ -121,15 +121,15 @@ public: } template - Rectangle transformed (const Rectangle& r) const noexcept + Rectangle transformed (const Rectangle& r) const noexcept { - return r.toFloat().transformed (complexTransform); + return r.transformed (complexTransform); } Rectangle deviceSpaceToUserSpace (const Rectangle& r) const noexcept { return isOnlyTranslated ? r.translated (-xOffset, -yOffset) - : r.toFloat().transformed (complexTransform.inverted()).getSmallestIntegerContainer(); + : r.transformed (complexTransform.inverted()); } AffineTransform complexTransform; @@ -2065,7 +2065,7 @@ public: else if (transform.isIntegerScaling) { cloneClipIfMultiplyReferenced(); - clip = clip->clipToRectangle (transform.transformed (r).getSmallestIntegerContainer()); + clip = clip->clipToRectangle (transform.transformed (r)); } else { @@ -2095,7 +2095,7 @@ public: RectangleList scaledList; for (const Rectangle* i = r.begin(), * const e = r.end(); i != e; ++i) - scaledList.add (transform.transformed (*i).getSmallestIntegerContainer()); + scaledList.add (transform.transformed (*i)); clip = clip->clipToRectangleList (scaledList); } @@ -2120,7 +2120,7 @@ public: } else if (transform.isIntegerScaling) { - clip = clip->excludeClipRectangle (transform.transformed (r).getSmallestIntegerContainer()); + clip = clip->excludeClipRectangle (transform.transformed (r)); } else { @@ -2262,7 +2262,7 @@ public: if (transform.isOnlyTranslated) fillTargetRect (transform.translated (r), replaceContents); else if (transform.isIntegerScaling) - fillTargetRect (transform.transformed (r).getSmallestIntegerContainer(), replaceContents); + fillTargetRect (transform.transformed (r), replaceContents); else fillRectAsPath (r); }