16fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk/* 26fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * Copyright (C) 2013 The Android Open Source Project 36fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * 46fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * Licensed under the Apache License, Version 2.0 (the "License"); 56fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * you may not use this file except in compliance with the License. 66fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * You may obtain a copy of the License at 76fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * 86fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * http://www.apache.org/licenses/LICENSE-2.0 96fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * 106fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * Unless required by applicable law or agreed to in writing, software 116fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * distributed under the License is distributed on an "AS IS" BASIS, 126fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * See the License for the specific language governing permissions and 146fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk * limitations under the License. 156fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk */ 166fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 176fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunkpackage com.android.gallery3d.filtershow.crop; 186fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 196fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunkimport android.graphics.Rect; 206fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunkimport android.graphics.RectF; 216fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 22b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunkimport com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; 236fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 246fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunkpublic class CropObject { 256fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private BoundedRect mBoundedRect; 266fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private float mAspectWidth = 1; 276fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private float mAspectHeight = 1; 286fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private boolean mFixAspectRatio = false; 296fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private float mRotation = 0; 306fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private float mTouchTolerance = 45; 316fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private float mMinSideSize = 20; 326fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 336fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int MOVE_NONE = 0; 346fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // Sides 356fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int MOVE_LEFT = 1; 366fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int MOVE_TOP = 2; 376fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int MOVE_RIGHT = 4; 386fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int MOVE_BOTTOM = 8; 396fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int MOVE_BLOCK = 16; 406fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 416fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // Corners 426fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int TOP_LEFT = MOVE_TOP | MOVE_LEFT; 436fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int TOP_RIGHT = MOVE_TOP | MOVE_RIGHT; 446fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int BOTTOM_RIGHT = MOVE_BOTTOM | MOVE_RIGHT; 456fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static final int BOTTOM_LEFT = MOVE_BOTTOM | MOVE_LEFT; 466fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 476fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private int mMovingEdges = MOVE_NONE; 486fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 496fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public CropObject(Rect outerBound, Rect innerBound, int outerAngle) { 506fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound); 516fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 526fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 536fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public CropObject(RectF outerBound, RectF innerBound, int outerAngle) { 546fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound); 556fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 566fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 57ea2fa83c2dd2b59b8a67ec363e4ac431748f997bRuben Brunk public void resetBoundsTo(RectF inner, RectF outer) { 58ea2fa83c2dd2b59b8a67ec363e4ac431748f997bRuben Brunk mBoundedRect.resetTo(0, outer, inner); 59ea2fa83c2dd2b59b8a67ec363e4ac431748f997bRuben Brunk } 60ea2fa83c2dd2b59b8a67ec363e4ac431748f997bRuben Brunk 61ea2fa83c2dd2b59b8a67ec363e4ac431748f997bRuben Brunk public void getInnerBounds(RectF r) { 626fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect.setToInner(r); 636fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 646fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 65ea2fa83c2dd2b59b8a67ec363e4ac431748f997bRuben Brunk public void getOuterBounds(RectF r) { 666fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect.setToOuter(r); 676fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 686fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 696fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public RectF getInnerBounds() { 706fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return mBoundedRect.getInner(); 716fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 726fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 736fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public RectF getOuterBounds() { 746fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return mBoundedRect.getOuter(); 756fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 766fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 776fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public int getSelectState() { 786fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return mMovingEdges; 796fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 806fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 816fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public boolean isFixedAspect() { 826fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return mFixAspectRatio; 836fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 846fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 856fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public void rotateOuter(int angle) { 866fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mRotation = angle % 360; 876fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect.setRotation(mRotation); 886fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk clearSelectState(); 896fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 906fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 9188cd551c2f42061ca7482b884c0c5bb686ec7eb2Ruben Brunk public boolean setInnerAspectRatio(float width, float height) { 926fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (width <= 0 || height <= 0) { 936fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk throw new IllegalArgumentException("Width and Height must be greater than zero"); 946fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 956fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk RectF inner = mBoundedRect.getInner(); 966fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk CropMath.fixAspectRatioContained(inner, width, height); 976fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (inner.width() < mMinSideSize || inner.height() < mMinSideSize) { 986fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return false; 996fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1006fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mAspectWidth = width; 1016fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mAspectHeight = height; 1026fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mFixAspectRatio = true; 1036fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect.setInner(inner); 1046fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk clearSelectState(); 1056fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return true; 1066fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1076fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1086fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public void setTouchTolerance(float tolerance) { 1096fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (tolerance <= 0) { 1106fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk throw new IllegalArgumentException("Tolerance must be greater than zero"); 1116fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1126fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mTouchTolerance = tolerance; 1136fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1146fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1156fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public void setMinInnerSideSize(float minSide) { 1166fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (minSide <= 0) { 1176fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk throw new IllegalArgumentException("Min dide must be greater than zero"); 1186fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1196fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mMinSideSize = minSide; 1206fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1216fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1226fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public void unsetAspectRatio() { 1236fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mFixAspectRatio = false; 1246fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk clearSelectState(); 1256fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1266fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1276fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public boolean hasSelectedEdge() { 1286fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return mMovingEdges != MOVE_NONE; 1296fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1306fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1316fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static boolean checkCorner(int selected) { 1326fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return selected == TOP_LEFT || selected == TOP_RIGHT || selected == BOTTOM_RIGHT 1336fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk || selected == BOTTOM_LEFT; 1346fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1356fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1366fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static boolean checkEdge(int selected) { 1376fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return selected == MOVE_LEFT || selected == MOVE_TOP || selected == MOVE_RIGHT 1386fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk || selected == MOVE_BOTTOM; 1396fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1406fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1416fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static boolean checkBlock(int selected) { 1426fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return selected == MOVE_BLOCK; 1436fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1446fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1456fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public static boolean checkValid(int selected) { 1466fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return selected == MOVE_NONE || checkBlock(selected) || checkEdge(selected) 1476fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk || checkCorner(selected); 1486fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1496fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1506fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public void clearSelectState() { 1516fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mMovingEdges = MOVE_NONE; 1526fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1536fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1546fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public int wouldSelectEdge(float x, float y) { 1556fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk int edgeSelected = calculateSelectedEdge(x, y); 1566fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (edgeSelected != MOVE_NONE && edgeSelected != MOVE_BLOCK) { 1576fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return edgeSelected; 1586fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1596fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return MOVE_NONE; 1606fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1616fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1626fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public boolean selectEdge(int edge) { 1636fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (!checkValid(edge)) { 1646fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // temporary 1656fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk throw new IllegalArgumentException("bad edge selected"); 1666fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // return false; 1676fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1686cfb081cdf5acf454ecb05c50c575bcb3ce74cf0Ruben Brunk if ((mFixAspectRatio && !checkCorner(edge)) && !checkBlock(edge) && edge != MOVE_NONE) { 1696fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // temporary 1706fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk throw new IllegalArgumentException("bad corner selected"); 1716fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // return false; 1726fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1736fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mMovingEdges = edge; 1746fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return true; 1756fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1766fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1776fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public boolean selectEdge(float x, float y) { 1786fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk int edgeSelected = calculateSelectedEdge(x, y); 1796fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (mFixAspectRatio) { 1806fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk edgeSelected = fixEdgeToCorner(edgeSelected); 1816fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1826fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (edgeSelected == MOVE_NONE) { 1836fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return false; 1846fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1856fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return selectEdge(edgeSelected); 1866fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1876fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1886fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk public boolean moveCurrentSelection(float dX, float dY) { 1896fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (mMovingEdges == MOVE_NONE) { 1906fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return false; 1916fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 1926fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk RectF crop = mBoundedRect.getInner(); 1936fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1946fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float minWidthHeight = mMinSideSize; 1956fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 1966fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk int movingEdges = mMovingEdges; 1976fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (movingEdges == MOVE_BLOCK) { 1986fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect.moveInner(dX, dY); 1996fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return true; 2006fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } else { 2016fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float dx = 0; 2026fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float dy = 0; 2036fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2046fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_LEFT) != 0) { 2056fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk dx = Math.min(crop.left + dX, crop.right - minWidthHeight) - crop.left; 2066fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2076fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_TOP) != 0) { 2086fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk dy = Math.min(crop.top + dY, crop.bottom - minWidthHeight) - crop.top; 2096fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2106fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_RIGHT) != 0) { 2116fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk dx = Math.max(crop.right + dX, crop.left + minWidthHeight) 2126fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk - crop.right; 2136fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2146fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_BOTTOM) != 0) { 2156fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk dy = Math.max(crop.bottom + dY, crop.top + minWidthHeight) 2166fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk - crop.bottom; 2176fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2186fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2196fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (mFixAspectRatio) { 2206fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float[] l1 = { 2216fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk crop.left, crop.bottom 2226fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk }; 2236fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float[] l2 = { 2246fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk crop.right, crop.top 2256fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk }; 2266fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (movingEdges == TOP_LEFT || movingEdges == BOTTOM_RIGHT) { 2276fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk l1[1] = crop.top; 2286fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk l2[1] = crop.bottom; 2296fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2306fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float[] b = { 2316fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk l1[0] - l2[0], l1[1] - l2[1] 2326fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk }; 2336fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float[] disp = { 2346fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk dx, dy 2356fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk }; 236b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float[] bUnit = GeometryMathUtils.normalize(b); 237b0f7a8f7f7d95ae12e92f529fd9a8a37f75b105cRuben Brunk float sp = GeometryMathUtils.scalarProjection(disp, bUnit); 2386fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk dx = sp * bUnit[0]; 2396fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk dy = sp * bUnit[1]; 2406fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk RectF newCrop = fixedCornerResize(crop, movingEdges, dx, dy); 2416fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2426fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect.fixedAspectResizeInner(newCrop); 2436fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } else { 2446fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_LEFT) != 0) { 2456fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk crop.left += dx; 2466fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2476fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_TOP) != 0) { 2486fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk crop.top += dy; 2496fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2506fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_RIGHT) != 0) { 2516fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk crop.right += dx; 2526fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2536fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((movingEdges & MOVE_BOTTOM) != 0) { 2546fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk crop.bottom += dy; 2556fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2566fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk mBoundedRect.resizeInner(crop); 2576fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2586fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2596fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return true; 2606fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2616fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2626fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // Helper methods 2636fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2646fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private int calculateSelectedEdge(float x, float y) { 2656fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk RectF cropped = mBoundedRect.getInner(); 2666fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2676fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float left = Math.abs(x - cropped.left); 2686fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float right = Math.abs(x - cropped.right); 2696fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float top = Math.abs(y - cropped.top); 2706fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk float bottom = Math.abs(y - cropped.bottom); 2716fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2726fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk int edgeSelected = MOVE_NONE; 2736fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // Check left or right. 2746fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((left <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top) 2756fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk && ((y - mTouchTolerance) <= cropped.bottom) && (left < right)) { 2766fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk edgeSelected |= MOVE_LEFT; 2776fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2786fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk else if ((right <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top) 2796fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk && ((y - mTouchTolerance) <= cropped.bottom)) { 2806fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk edgeSelected |= MOVE_RIGHT; 2816fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2826fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2836fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // Check top or bottom. 2846fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if ((top <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left) 2856fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk && ((x - mTouchTolerance) <= cropped.right) && (top < bottom)) { 2866fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk edgeSelected |= MOVE_TOP; 2876fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2886fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk else if ((bottom <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left) 2896fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk && ((x - mTouchTolerance) <= cropped.right)) { 2906fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk edgeSelected |= MOVE_BOTTOM; 2916fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2926fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return edgeSelected; 2936fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 2946fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 2956fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private static RectF fixedCornerResize(RectF r, int moving_corner, float dx, float dy) { 2966fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk RectF newCrop = null; 2976fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk // Fix opposite corner in place and move sides 2986fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (moving_corner == BOTTOM_RIGHT) { 2996fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk newCrop = new RectF(r.left, r.top, r.left + r.width() + dx, r.top + r.height() 3006fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk + dy); 3016fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } else if (moving_corner == BOTTOM_LEFT) { 3026fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk newCrop = new RectF(r.right - r.width() + dx, r.top, r.right, r.top + r.height() 3036fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk + dy); 3046fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } else if (moving_corner == TOP_LEFT) { 3056fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk newCrop = new RectF(r.right - r.width() + dx, r.bottom - r.height() + dy, 3066fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk r.right, r.bottom); 3076fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } else if (moving_corner == TOP_RIGHT) { 3086fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk newCrop = new RectF(r.left, r.bottom - r.height() + dy, r.left 3096fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk + r.width() + dx, r.bottom); 3106fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 3116fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return newCrop; 3126fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 3136fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 3146fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk private static int fixEdgeToCorner(int moving_edges) { 3156fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (moving_edges == MOVE_LEFT) { 3166fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk moving_edges |= MOVE_TOP; 3176fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 3186fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (moving_edges == MOVE_TOP) { 3196fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk moving_edges |= MOVE_LEFT; 3206fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 3216fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (moving_edges == MOVE_RIGHT) { 3226fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk moving_edges |= MOVE_BOTTOM; 3236fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 3246fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk if (moving_edges == MOVE_BOTTOM) { 3256fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk moving_edges |= MOVE_RIGHT; 3266fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 3276fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk return moving_edges; 3286fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk } 3296fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk 3306fe165b7d28299d5b2f97deb135b233d84eb300fRuben Brunk} 331