/* * Copyright (c) 2018-2020, Andreas Kling * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include namespace Gfx { void Rect::intersect(const Rect& other) { int l = max(left(), other.left()); int r = min(right(), other.right()); int t = max(top(), other.top()); int b = min(bottom(), other.bottom()); if (l > r || t > b) { m_location = {}; m_size = {}; return; } m_location.set_x(l); m_location.set_y(t); m_size.set_width((r - l) + 1); m_size.set_height((b - t) + 1); } Rect Rect::united(const Rect& other) const { if (is_null()) return other; if (other.is_null()) return *this; Rect rect; rect.set_left(min(left(), other.left())); rect.set_top(min(top(), other.top())); rect.set_right(max(right(), other.right())); rect.set_bottom(max(bottom(), other.bottom())); return rect; } Vector Rect::shatter(const Rect& hammer) const { Vector pieces; if (!intersects(hammer)) { pieces.unchecked_append(*this); return pieces; } Rect top_shard { x(), y(), width(), hammer.y() - y() }; Rect bottom_shard { x(), hammer.y() + hammer.height(), width(), (y() + height()) - (hammer.y() + hammer.height()) }; Rect left_shard { x(), max(hammer.y(), y()), hammer.x() - x(), min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y()) }; Rect right_shard { hammer.x() + hammer.width(), max(hammer.y(), y()), right() - hammer.right(), min((hammer.y() + hammer.height()), (y() + height())) - max(hammer.y(), y()) }; if (intersects(top_shard)) pieces.unchecked_append(top_shard); if (intersects(bottom_shard)) pieces.unchecked_append(bottom_shard); if (intersects(left_shard)) pieces.unchecked_append(left_shard); if (intersects(right_shard)) pieces.unchecked_append(right_shard); return pieces; } void Rect::align_within(const Rect& other, TextAlignment alignment) { switch (alignment) { case TextAlignment::Center: center_within(other); return; case TextAlignment::TopLeft: set_location(other.location()); return; case TextAlignment::TopRight: set_x(other.x() + other.width() - width()); set_y(other.y()); return; case TextAlignment::CenterLeft: set_x(other.x()); center_vertically_within(other); return; case TextAlignment::CenterRight: set_x(other.x() + other.width() - width()); center_vertically_within(other); return; } } String Rect::to_string() const { return String::format("[%d,%d %dx%d]", x(), y(), width(), height()); } const LogStream& operator<<(const LogStream& stream, const Rect& value) { return stream << value.to_string(); } } namespace IPC { bool decode(Decoder& decoder, Gfx::Rect& rect) { Gfx::Point point; Gfx::Size size; if (!decoder.decode(point)) return false; if (!decoder.decode(size)) return false; rect = { point, size }; return true; } }