1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.photoeditor;
18
19import android.graphics.Matrix;
20import android.graphics.RectF;
21import android.view.View;
22
23/**
24 * Utils for rectangles/bounds related calculations.
25 */
26public class RectUtils {
27
28    private static final float MATH_PI = (float) Math.PI;
29    private static final float DEGREES_TO_RADIAN = MATH_PI / 180.0f;
30
31    /**
32     * Gets straighten matrix for the given bounds and degrees.
33     */
34    public static void getStraightenMatrix(RectF bounds, float degrees, Matrix matrix) {
35        matrix.reset();
36        if ((degrees != 0) && !bounds.isEmpty()) {
37            float w = bounds.width() / 2;
38            float h = bounds.height() / 2;
39            float adjustAngle;
40            if ((degrees < 0 && w > h) || (degrees > 0 && w <= h)) {
41                // The top left point is the boundary.
42                adjustAngle = (float) Math.atan(h / -w) + MATH_PI + degrees * DEGREES_TO_RADIAN;
43            } else {
44                // The top right point is the boundary.
45                adjustAngle = (float) Math.atan(h / w) - MATH_PI + degrees * DEGREES_TO_RADIAN;
46            }
47            float radius = (float) Math.hypot(w, h);
48            float scaleX = (float) Math.abs(radius * Math.cos(adjustAngle)) / w;
49            float scaleY = (float) Math.abs(radius * Math.sin(adjustAngle)) / h;
50            float scale = Math.max(scaleX, scaleY);
51
52            postRotateMatrix(degrees, new RectF(bounds), matrix);
53            matrix.postScale(scale, scale);
54        }
55    }
56
57    /**
58     * Post rotates the matrix and bounds for the given bounds and degrees.
59     */
60    public static void postRotateMatrix(float degrees, RectF bounds, Matrix matrix) {
61        matrix.postRotate(degrees);
62        matrix.mapRect(bounds);
63        matrix.postTranslate(-bounds.left, -bounds.top);
64    }
65
66    /**
67     * Post translates the matrix to center the given bounds inside the view.
68     */
69    public static void postCenterMatrix(RectF contentBounds, View view, Matrix matrix) {
70        matrix.postTranslate((view.getWidth() - contentBounds.width()) / 2,
71                (view.getHeight() - contentBounds.height()) / 2);
72    }
73
74    /**
75     * Gets the proper scale value that scales down the content and keeps its aspect ratio to
76     * display inside the view.
77     */
78    public static float getDisplayScale(RectF contentBounds, View view) {
79        if (contentBounds.isEmpty()) {
80            return 1;
81        }
82
83        float scale = Math.min(view.getWidth() / contentBounds.width(),
84                view.getHeight() / contentBounds.height());
85        // Avoid scaling up the content.
86        return Math.min(scale, 1);
87    }
88}
89