1b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin/*
2b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Copyright (C) 2014 The Android Open Source Project
3b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin *
4b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Licensed under the Apache License, Version 2.0 (the "License");
5b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * you may not use this file except in compliance with the License.
6b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * You may obtain a copy of the License at
7b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin *
8b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin *      http://www.apache.org/licenses/LICENSE-2.0
9b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin *
10b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * Unless required by applicable law or agreed to in writing, software
11b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * distributed under the License is distributed on an "AS IS" BASIS,
12b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * See the License for the specific language governing permissions and
14b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * limitations under the License.
15b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */
1697f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh
1772f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinpackage android.hardware.camera2.params;
18b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
19b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinimport android.util.Size;
20b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinimport static com.android.internal.util.Preconditions.*;
21b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
22b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinimport android.graphics.Point;
23b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinimport android.graphics.Rect;
2472f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.CameraCharacteristics;
2572f9f0a96e4476ef231d5001cb30521ad4ce5b1eIgor Murashkinimport android.hardware.camera2.CaptureRequest;
263c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkinimport android.hardware.camera2.utils.HashCodeHelpers;
27b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
28b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin/**
2997f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * An immutable class to represent a rectangle {@code (x, y, width, height)} with an additional
3097f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * weight component.
3197f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * <p>
3297f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * The rectangle is defined to be inclusive of the specified coordinates.
3397f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * </p>
3497f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * <p>
3597f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * When used with a {@link CaptureRequest}, the coordinate system is based on the active pixel
36b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * array, with {@code (0,0)} being the top-left pixel in the
37b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE active pixel array}, and
38b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * {@code (android.sensor.info.activeArraySize.width - 1,
3997f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * android.sensor.info.activeArraySize.height - 1)} being the bottom-right pixel in the active pixel
4097f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * array.
4197f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * </p>
4297f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * <p>
4397f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * The weight must range from {@value #METERING_WEIGHT_MIN} to {@value #METERING_WEIGHT_MAX}
4497f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * inclusively, and represents a weight for every pixel in the area. This means that a large
4597f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * metering area with the same weight as a smaller area will have more effect in the metering
4697f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * result. Metering areas can partially overlap and the camera device will add the weights in the
4797f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * overlap rectangle.
4897f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * </p>
4997f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * <p>
5097f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * If all rectangles have 0 weight, then no specific metering area needs to be used by the camera
5197f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * device. If the metering rectangle is outside the used android.scaler.cropRegion returned in
5297f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * capture result metadata, the camera device will ignore the sections outside the rectangle and
5397f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh * output the used sections in the result metadata.
54b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin * </p>
55b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin */
56b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkinpublic final class MeteringRectangle {
5797f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh    /**
5897f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     * The minimum value of valid metering weight.
5997f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     */
6097f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh    public static final int METERING_WEIGHT_MIN = 0;
6197f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh
6297f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh    /**
6397f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     * The maximum value of valid metering weight.
6497f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     */
6597f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh    public static final int METERING_WEIGHT_MAX = 1000;
6697f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh
6797f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh    /**
6897f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     * Weights set to this value will cause the camera device to ignore this rectangle.
6997f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     * If all metering rectangles are weighed with 0, the camera device will choose its own metering
7097f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     * rectangles.
7197f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     */
7297f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh    public static final int METERING_WEIGHT_DONT_CARE = 0;
73b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
74b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    private final int mX;
75b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    private final int mY;
76b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    private final int mWidth;
77b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    private final int mHeight;
78b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    private final int mWeight;
79b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
80b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
81b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Create a new metering rectangle.
82b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
83b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param x coordinate >= 0
84b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param y coordinate >= 0
85b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param width width >= 0
86b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param height height >= 0
8797f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     * @param meteringWeight weight between {@value #METERING_WEIGHT_MIN} and
8897f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh     *        {@value #METERING_WEIGHT_MAX} inclusively
89817f8933ee1c11130ad2ca45b5ac8ce8b729f125Yin-Chia Yeh     * @throws IllegalArgumentException if any of the parameters were negative
90b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
91b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public MeteringRectangle(int x, int y, int width, int height, int meteringWeight) {
92b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mX = checkArgumentNonnegative(x, "x must be nonnegative");
93b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mY = checkArgumentNonnegative(y, "y must be nonnegative");
94b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mWidth = checkArgumentNonnegative(width, "width must be nonnegative");
95b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mHeight = checkArgumentNonnegative(height, "height must be nonnegative");
9697f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh        mWeight = checkArgumentInRange(
9797f1c854993a65b2c700426a1e3a83b23ea65337Yin-Chia Yeh                meteringWeight, METERING_WEIGHT_MIN, METERING_WEIGHT_MAX, "meteringWeight");
98b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
99b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
100b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
101b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Create a new metering rectangle.
102b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
1037ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * <p>The point {@code xy}'s data is copied; the reference is not retained.</p>
1047ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     *
105b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param xy a non-{@code null} {@link Point} with both x,y >= 0
106b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param dimensions a non-{@code null} {@link android.util.Size Size} with width, height >= 0
107b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param meteringWeight weight >= 0
108b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
109817f8933ee1c11130ad2ca45b5ac8ce8b729f125Yin-Chia Yeh     * @throws IllegalArgumentException if any of the parameters were negative
110b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @throws NullPointerException if any of the arguments were null
111b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
112b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public MeteringRectangle(Point xy, Size dimensions, int meteringWeight) {
113b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        checkNotNull(xy, "xy must not be null");
114b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        checkNotNull(dimensions, "dimensions must not be null");
115b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
116b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mX = checkArgumentNonnegative(xy.x, "x must be nonnegative");
117b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mY = checkArgumentNonnegative(xy.y, "y must be nonnegative");
118b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mWidth = checkArgumentNonnegative(dimensions.getWidth(), "width must be nonnegative");
119b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mHeight = checkArgumentNonnegative(dimensions.getHeight(), "height must be nonnegative");
120b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
121b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
122b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
123b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
124b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Create a new metering rectangle.
125b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
1267ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * <p>The rectangle data is copied; the reference is not retained.</p>
1277ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     *
128b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param rect a non-{@code null} rectangle with all x,y,w,h dimensions >= 0
129b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param meteringWeight weight >= 0
130b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
131817f8933ee1c11130ad2ca45b5ac8ce8b729f125Yin-Chia Yeh     * @throws IllegalArgumentException if any of the parameters were negative
132b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @throws NullPointerException if any of the arguments were null
133b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
134b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public MeteringRectangle(Rect rect, int meteringWeight) {
135b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        checkNotNull(rect, "rect must not be null");
136b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
137b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mX = checkArgumentNonnegative(rect.left, "rect.left must be nonnegative");
138b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mY = checkArgumentNonnegative(rect.top, "rect.top must be nonnegative");
139b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mWidth = checkArgumentNonnegative(rect.width(), "rect.width must be nonnegative");
140b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mHeight = checkArgumentNonnegative(rect.height(), "rect.height must be nonnegative");
141b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        mWeight = checkArgumentNonnegative(meteringWeight, "meteringWeight must be nonnegative");
142b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
143b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
144b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
145b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Return the X coordinate of the left side of the rectangle.
146b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
147b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @return x coordinate >= 0
148b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
149b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public int getX() {
150b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return mX;
151b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
152b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
153b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
154b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Return the Y coordinate of the upper side of the rectangle.
155b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
156b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @return y coordinate >= 0
157b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
158b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public int getY() {
159b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return mY;
160b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
161b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
162b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
163b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Return the width of the rectangle.
164b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
165b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @return width >= 0
166b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
167b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public int getWidth() {
168b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return mWidth;
169b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
170b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
171b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
172b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Return the height of the rectangle.
173b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
174b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @return height >= 0
175b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
176b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public int getHeight() {
177b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return mHeight;
178b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
179b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
180b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
181b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Return the metering weight of the rectangle.
182b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
183b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @return weight >= 0
184b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
185b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public int getMeteringWeight() {
186b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return mWeight;
187b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
188b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
189b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
190b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Convenience method to create the upper-left (X,Y) coordinate as a {@link Point}.
191b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
1927ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * @return a new {@code (x,y)} {@link Point} with both x,y >= 0
193b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
194b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public Point getUpperLeftPoint() {
195b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return new Point(mX, mY);
196b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
197b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
198b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
199b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Convenience method to create the size from this metering rectangle.
200b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
201b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * <p>This strips away the X,Y,weight from the rectangle.</p>
202b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
2037ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * @return a new {@link Size} with non-negative width and height
204b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
205b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public Size getSize() {
206b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return new Size(mWidth, mHeight);
207b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
208b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
209b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
210b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Convenience method to create a {@link Rect} from this metering rectangle.
211b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
212b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * <p>This strips away the weight from the rectangle.</p>
213b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
2147ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * @return a new {@link Rect} with non-negative x1, y1, x2, y2
215b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
216b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public Rect getRect() {
217b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return new Rect(mX, mY, mX + mWidth, mY + mHeight);
218b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
219b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
220b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
221b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * {@inheritDoc}
222b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
223b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    @Override
224b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public boolean equals(final Object other) {
2253c40a046cf0ea7b6af01ec93e5276eccb3234bfeIgor Murashkin        return other instanceof MeteringRectangle && equals((MeteringRectangle)other);
226b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
227b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
228b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
229b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Compare two metering rectangles to see if they are equal.
230b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
231b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * Two weighted rectangles are only considered equal if each of their components
232b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * (x, y, width, height, weight) is respectively equal.
233b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
234b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @param other Another MeteringRectangle
235b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     *
236b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * @return {@code true} if the metering rectangles are equal, {@code false} otherwise
237b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
238b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public boolean equals(final MeteringRectangle other) {
239b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        if (other == null) {
240b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin            return false;
241b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        }
242b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
243b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return (mX == other.mX
244b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin                && mY == other.mY
245b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin                && mWidth == other.mWidth
246b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin                && mHeight == other.mHeight
247817f8933ee1c11130ad2ca45b5ac8ce8b729f125Yin-Chia Yeh                && mWeight == other.mWeight);
248b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
249b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin
250b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    /**
251b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     * {@inheritDoc}
252b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin     */
253b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    @Override
254b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    public int hashCode() {
255b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin        return HashCodeHelpers.hashCode(mX, mY, mWidth, mHeight, mWeight);
256b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin    }
2577ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin
2587ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin    /**
2597ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * Return the metering rectangle as a string representation
2607ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * {@code "(x:%d, y:%d, w:%d, h:%d, wt:%d)"} where each {@code %d} respectively represents
2617ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * the x, y, width, height, and weight points.
2627ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     *
2637ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     * @return string representation of the metering rectangle
2647ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin     */
2657ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin    @Override
2667ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin    public String toString() {
2677ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin        return String.format("(x:%d, y:%d, w:%d, h:%d, wt:%d)", mX, mY, mWidth, mHeight, mWeight);
2687ee78d1ee3ee068897b9313af2ed6446675c1be0Igor Murashkin    }
269b3a78b2ca9655396e2d73950221d187b7e5bb3baIgor Murashkin}
270