diff --git a/kandinsky/include/kandinsky/rect.h b/kandinsky/include/kandinsky/rect.h index d5c93ae82..fc3fe47af 100644 --- a/kandinsky/include/kandinsky/rect.h +++ b/kandinsky/include/kandinsky/rect.h @@ -62,6 +62,7 @@ public: bool intersects(const KDRect & other) const; KDRect intersectedWith(const KDRect & other) const; KDRect unionedWith(const KDRect & other) const; // Returns the smallest rectangle containing r1 and r2 + KDRect differencedWith(const KDRect & other) const; // Returns the smallest rectangle containing r1\r2 bool contains(KDPoint p) const; bool isAbove(KDPoint p) const; bool isUnder(KDPoint p) const; diff --git a/kandinsky/src/rect.cpp b/kandinsky/src/rect.cpp index 9cf0df654..4373d4f93 100644 --- a/kandinsky/src/rect.cpp +++ b/kandinsky/src/rect.cpp @@ -101,6 +101,47 @@ KDRect KDRect::unionedWith(const KDRect & other) const { ); } +KDRect KDRect::differencedWith(const KDRect & other) const { + if (this->isEmpty() || other.isEmpty()) { + return *this; + } + + KDRect intersection = intersectedWith(other); + if (intersection.isEmpty()) { + return *this; + } + + if (intersection == *this) { + return KDRectZero; + } + + KDCoordinate resultLeft = left(); + KDCoordinate resultTop = top(); + KDCoordinate resultRight = right(); + KDCoordinate resultBottom = bottom(); + + if (intersection.height() == height()) { + if (intersection.left() == left()) { + resultLeft = intersection.right() + 1; + } else if (intersection.right() == right()) { + resultRight = intersection.left() - 1; + } + } else if (intersection.width() == width()) { + if (intersection.top() == top()) { + resultTop = intersection.bottom() + 1; + } else if (intersection.bottom() == bottom()) { + resultBottom = intersection.top() - 1; + } + } + + return KDRect( + resultLeft, + resultTop, + resultRight-resultLeft+1, + resultBottom-resultTop+1 + ); +} + bool KDRect::contains(KDPoint p) const { return (p.x() >= x() && p.x() <= right() && p.y() >= y() && p.y() <= bottom()); }