All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.labymedia.ultralight.math.IntRect Maven / Gradle / Ivy

/*
 * Ultralight Java - Java wrapper for the Ultralight web engine
 * Copyright (C) 2020 - 2021 LabyMedia and contributors
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

package com.labymedia.ultralight.math;

import com.labymedia.ultralight.annotation.NativeType;

import java.lang.annotation.Native;
import java.util.Objects;

/**
 * Integer Rectangle Helper.
 */
@NativeType("ultralight::IntRect")
public final class IntRect {
    @Native
    private int left;
    @Native
    private int top;
    @Native
    private int right;
    @Native
    private int bottom;

    /**
     * Creates a new {@link IntRect} with all coordinates set to 0.
     */
    public IntRect() {
        this.left = 0;
        this.top = 0;
        this.right = 0;
        this.bottom = 0;
    }

    /**
     * Creates a new {@link IntRect}.
     *
     * @param left   The left coordinate of the rectangle
     * @param top    The top coordinate of the rectangle
     * @param right  The right coordinate of the rectangle
     * @param bottom The bottom coordinate of the rectangle
     */
    public IntRect(int left, int top, int right, int bottom) {
        this.left = left;
        this.top = top;
        this.right = right;
        this.bottom = bottom;
    }

    /**
     * Retrieves the width of this {@link IntRect}.
     *
     * @return The width of this rectangle
     */
    public int width() {
        return right - left;
    }

    /**
     * Retrieves the height of this {@link IntRect}.
     *
     * @return The height of this rectangle
     */
    public int height() {
        return bottom - top;
    }

    /**
     * Retrieves the left coordinate of this {@link IntRect}.
     *
     * @return The x coordinate of this rectangle
     */
    public int x() {
        return left;
    }

    /**
     * Retrieves the upper coordinate of this {@link IntRect}.
     *
     * @return The y coordinate of this rectangle
     */
    public int y() {
        return top;
    }

    /**
     * Returns x coordinate in the center of this {@link IntRect}.
     *
     * @return The center x coordinate
     */
    public int centerX() {
        return (int) (Math.round(left + right) * 0.5f);
    }

    /**
     * Returns y coordinate in the center of this {@link IntRect}.
     *
     * @return The center y coordinate
     */
    public int centerY() {
        return (int) (Math.round(top + bottom) * 0.5f);
    }

    /**
     * Checks whether this {@link IntRect} is valid.
     *
     * @return Whether this rectangle is valid
     */
    public boolean isValid() {
        return width() > 0 && height() > 0;
    }

    /**
     * Insets this {@link IntRect} by the given insets.
     *
     * @param dx The x inset
     * @param dy The y inset
     */
    public void inset(int dx, int dy) {
        this.left += dx;
        this.top += dy;
        this.right -= dx;
        this.bottom -= dy;
    }

    /**
     * Outsets this {@link IntRect} by the given insets.
     *
     * @param dx The x outset
     * @param dy The y outset
     */
    public void outset(int dx, int dy) {
        inset(-dx, -dy);
    }

    /**
     * Moves this {@link IntRect} by the given offset.
     *
     * @param dx The x offset
     * @param dy The y offset
     */
    public void move(int dx, int dy) {
        this.left += dx;
        this.top += dy;
        this.right += dx;
        this.bottom += dy;
    }

    /**
     * Checks if this is an empty {@link IntRect} (all coordinates are 0).
     *
     * @return Whether this rectangle is empty
     */
    private boolean isEmpty() {
        return this.left == 0 && this.top == 0 && this.right == 0 && this.bottom == 0;
    }

    /**
     * Joins this {@link IntRect} with another {@link IntRect} by expanding this {@link IntRect}.
     *
     * @param other The {@link IntRect} to join with
     */
    public void join(IntRect other) {
        if (isEmpty()) {
            this.left = other.left;
            this.top = other.top;
            this.right = other.right;
            this.bottom = other.bottom;
        } else {
            if (other.left < this.left) {
                this.left = other.left;
            }

            if (other.top < this.top) {
                this.top = other.top;
            }

            if (other.right > this.right) {
                this.right = other.right;
            }

            if (other.bottom > this.bottom) {
                this.bottom = other.bottom;
            }
        }
    }

    /**
     * Checks if this {@link IntRect} contains another {@link IntRect}.
     *
     * @param other The rectangle to check for if it is contained in this rectangle
     * @return Whether this rectangle contains the other rectangle
     */
    public boolean contains(IntRect other) {
        return this.left <= other.left &&
                this.top <= other.top &&
                this.right >= other.right &&
                this.bottom >= other.bottom;
    }

    /**
     * Checks if this {@link IntRect} intersects with another {@link IntRect}.
     * This is used for pixel operations, so only intersections with a width and
     * height >= count as intersection!
     *
     * @param other The rectangle to check for intersection with this one
     * @return Whether this rectangle intersects with another rectangle
     */
    public boolean intersects(IntRect other) {
        return !(other.left >= this.right - 1 ||
                other.right < this.left ||
                other.top >= this.bottom - 1 ||
                other.bottom < this.top);
    }

    /**
     * Calculates the intersection of this {@link IntRect} with another {@link IntRect}.
     * This method only works correctly when {@link}
     *
     * @param other The rectangle this rectangle intersects with
     * @return The intersection of this rectangle with the other rectangle
     */
    public IntRect intersect(IntRect other) {
        return new IntRect(
                Math.max(this.left, other.left),
                Math.max(this.top, other.top),
                Math.min(other.right, this.right),
                Math.min(other.bottom, this.bottom)
        );
    }

    /**
     * Retrieves the left position of this rect.
     *
     * @return The left position
     */
    public int getLeft() {
        return left;
    }

    /**
     * Retrieves the top position of this rect.
     *
     * @return The top position
     */
    public int getTop() {
        return top;
    }

    /**
     * Retrieves the right position of this rect.
     *
     * @return The right position
     */
    public int getRight() {
        return right;
    }

    /**
     * Retrieves the bottom position of this rect.
     *
     * @return The bottom position
     */
    public int getBottom() {
        return bottom;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof IntRect)) return false;
        IntRect intRect = (IntRect) o;
        return left == intRect.left &&
                top == intRect.top &&
                right == intRect.right &&
                bottom == intRect.bottom;
    }

    @Override
    public int hashCode() {
        return Objects.hash(left, top, right, bottom);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy