diff options
Diffstat (limited to 'src/com/android/gallery3d/filtershow/crop/BoundedRect.java')
-rw-r--r-- | src/com/android/gallery3d/filtershow/crop/BoundedRect.java | 368 |
1 files changed, 0 insertions, 368 deletions
diff --git a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java b/src/com/android/gallery3d/filtershow/crop/BoundedRect.java deleted file mode 100644 index 13b8d6de1..000000000 --- a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.crop; - -import android.graphics.Matrix; -import android.graphics.Rect; -import android.graphics.RectF; - -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; - -import java.util.Arrays; - -/** - * Maintains invariant that inner rectangle is constrained to be within the - * outer, rotated rectangle. - */ -public class BoundedRect { - private float rot; - private RectF outer; - private RectF inner; - private float[] innerRotated; - - public BoundedRect(float rotation, Rect outerRect, Rect innerRect) { - rot = rotation; - outer = new RectF(outerRect); - inner = new RectF(innerRect); - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - public BoundedRect(float rotation, RectF outerRect, RectF innerRect) { - rot = rotation; - outer = new RectF(outerRect); - inner = new RectF(innerRect); - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - public void resetTo(float rotation, RectF outerRect, RectF innerRect) { - rot = rotation; - outer.set(outerRect); - inner.set(innerRect); - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - /** - * Sets inner, and re-constrains it to fit within the rotated bounding rect. - */ - public void setInner(RectF newInner) { - if (inner.equals(newInner)) - return; - inner = newInner; - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - /** - * Sets rotation, and re-constrains inner to fit within the rotated bounding rect. - */ - public void setRotation(float rotation) { - if (rotation == rot) - return; - rot = rotation; - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - public void setToInner(RectF r) { - r.set(inner); - } - - public void setToOuter(RectF r) { - r.set(outer); - } - - public RectF getInner() { - return new RectF(inner); - } - - public RectF getOuter() { - return new RectF(outer); - } - - /** - * Tries to move the inner rectangle by (dx, dy). If this would cause it to leave - * the bounding rectangle, snaps the inner rectangle to the edge of the bounding - * rectangle. - */ - public void moveInner(float dx, float dy) { - Matrix m0 = getInverseRotMatrix(); - - RectF translatedInner = new RectF(inner); - translatedInner.offset(dx, dy); - - float[] translatedInnerCorners = CropMath.getCornersFromRect(translatedInner); - float[] outerCorners = CropMath.getCornersFromRect(outer); - - m0.mapPoints(translatedInnerCorners); - float[] correction = { - 0, 0 - }; - - // find correction vectors for corners that have moved out of bounds - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) { - float[] badCorner = { - correctedInnerX, correctedInnerY - }; - float[] nearestSide = CropMath.closestSide(badCorner, outerCorners); - float[] correctionVec = - GeometryMathUtils.shortestVectorFromPointToLine(badCorner, nearestSide); - correction[0] += correctionVec[0]; - correction[1] += correctionVec[1]; - } - } - - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) { - float[] correctionVec = { - correctedInnerX, correctedInnerY - }; - CropMath.getEdgePoints(outer, correctionVec); - correctionVec[0] -= correctedInnerX; - correctionVec[1] -= correctedInnerY; - correction[0] += correctionVec[0]; - correction[1] += correctionVec[1]; - } - } - - // Set correction - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - // update translated corners with correction vectors - translatedInnerCorners[i] = correctedInnerX; - translatedInnerCorners[i + 1] = correctedInnerY; - } - - innerRotated = translatedInnerCorners; - // reconstrain to update inner - reconstrain(); - } - - /** - * Attempts to resize the inner rectangle. If this would cause it to leave - * the bounding rect, clips the inner rectangle to fit. - */ - public void resizeInner(RectF newInner) { - Matrix m = getRotMatrix(); - Matrix m0 = getInverseRotMatrix(); - - float[] outerCorners = CropMath.getCornersFromRect(outer); - m.mapPoints(outerCorners); - float[] oldInnerCorners = CropMath.getCornersFromRect(inner); - float[] newInnerCorners = CropMath.getCornersFromRect(newInner); - RectF ret = new RectF(newInner); - - for (int i = 0; i < newInnerCorners.length; i += 2) { - float[] c = { - newInnerCorners[i], newInnerCorners[i + 1] - }; - float[] c0 = Arrays.copyOf(c, 2); - m0.mapPoints(c0); - if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) { - float[] outerSide = CropMath.closestSide(c, outerCorners); - float[] pathOfCorner = { - newInnerCorners[i], newInnerCorners[i + 1], - oldInnerCorners[i], oldInnerCorners[i + 1] - }; - float[] p = GeometryMathUtils.lineIntersect(pathOfCorner, outerSide); - if (p == null) { - // lines are parallel or not well defined, so don't resize - p = new float[2]; - p[0] = oldInnerCorners[i]; - p[1] = oldInnerCorners[i + 1]; - } - // relies on corners being in same order as method - // getCornersFromRect - switch (i) { - case 0: - case 1: - ret.left = (p[0] > ret.left) ? p[0] : ret.left; - ret.top = (p[1] > ret.top) ? p[1] : ret.top; - break; - case 2: - case 3: - ret.right = (p[0] < ret.right) ? p[0] : ret.right; - ret.top = (p[1] > ret.top) ? p[1] : ret.top; - break; - case 4: - case 5: - ret.right = (p[0] < ret.right) ? p[0] : ret.right; - ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom; - break; - case 6: - case 7: - ret.left = (p[0] > ret.left) ? p[0] : ret.left; - ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom; - break; - default: - break; - } - } - } - float[] retCorners = CropMath.getCornersFromRect(ret); - m0.mapPoints(retCorners); - innerRotated = retCorners; - // reconstrain to update inner - reconstrain(); - } - - /** - * Attempts to resize the inner rectangle. If this would cause it to leave - * the bounding rect, clips the inner rectangle to fit while maintaining - * aspect ratio. - */ - public void fixedAspectResizeInner(RectF newInner) { - Matrix m = getRotMatrix(); - Matrix m0 = getInverseRotMatrix(); - - float aspectW = inner.width(); - float aspectH = inner.height(); - float aspRatio = aspectW / aspectH; - float[] corners = CropMath.getCornersFromRect(outer); - - m.mapPoints(corners); - float[] oldInnerCorners = CropMath.getCornersFromRect(inner); - float[] newInnerCorners = CropMath.getCornersFromRect(newInner); - - // find fixed corner - int fixed = -1; - if (inner.top == newInner.top) { - if (inner.left == newInner.left) - fixed = 0; // top left - else if (inner.right == newInner.right) - fixed = 2; // top right - } else if (inner.bottom == newInner.bottom) { - if (inner.right == newInner.right) - fixed = 4; // bottom right - else if (inner.left == newInner.left) - fixed = 6; // bottom left - } - // no fixed corner, return without update - if (fixed == -1) - return; - float widthSoFar = newInner.width(); - int moved = -1; - for (int i = 0; i < newInnerCorners.length; i += 2) { - float[] c = { - newInnerCorners[i], newInnerCorners[i + 1] - }; - float[] c0 = Arrays.copyOf(c, 2); - m0.mapPoints(c0); - if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) { - moved = i; - if (moved == fixed) - continue; - float[] l2 = CropMath.closestSide(c, corners); - float[] l1 = { - newInnerCorners[i], newInnerCorners[i + 1], - oldInnerCorners[i], oldInnerCorners[i + 1] - }; - float[] p = GeometryMathUtils.lineIntersect(l1, l2); - if (p == null) { - // lines are parallel or not well defined, so set to old - // corner - p = new float[2]; - p[0] = oldInnerCorners[i]; - p[1] = oldInnerCorners[i + 1]; - } - // relies on corners being in same order as method - // getCornersFromRect - float fixed_x = oldInnerCorners[fixed]; - float fixed_y = oldInnerCorners[fixed + 1]; - float newWidth = Math.abs(fixed_x - p[0]); - float newHeight = Math.abs(fixed_y - p[1]); - newWidth = Math.max(newWidth, aspRatio * newHeight); - if (newWidth < widthSoFar) - widthSoFar = newWidth; - } - } - - float heightSoFar = widthSoFar / aspRatio; - RectF ret = new RectF(inner); - if (fixed == 0) { - ret.right = ret.left + widthSoFar; - ret.bottom = ret.top + heightSoFar; - } else if (fixed == 2) { - ret.left = ret.right - widthSoFar; - ret.bottom = ret.top + heightSoFar; - } else if (fixed == 4) { - ret.left = ret.right - widthSoFar; - ret.top = ret.bottom - heightSoFar; - } else if (fixed == 6) { - ret.right = ret.left + widthSoFar; - ret.top = ret.bottom - heightSoFar; - } - float[] retCorners = CropMath.getCornersFromRect(ret); - m0.mapPoints(retCorners); - innerRotated = retCorners; - // reconstrain to update inner - reconstrain(); - } - - // internal methods - - private boolean isConstrained() { - for (int i = 0; i < 8; i += 2) { - if (!CropMath.inclusiveContains(outer, innerRotated[i], innerRotated[i + 1])) - return false; - } - return true; - } - - private void reconstrain() { - // innerRotated has been changed to have incorrect values - CropMath.getEdgePoints(outer, innerRotated); - Matrix m = getRotMatrix(); - float[] unrotated = Arrays.copyOf(innerRotated, 8); - m.mapPoints(unrotated); - inner = CropMath.trapToRect(unrotated); - } - - private void rotateInner() { - Matrix m = getInverseRotMatrix(); - m.mapPoints(innerRotated); - } - - private Matrix getRotMatrix() { - Matrix m = new Matrix(); - m.setRotate(rot, outer.centerX(), outer.centerY()); - return m; - } - - private Matrix getInverseRotMatrix() { - Matrix m = new Matrix(); - m.setRotate(-rot, outer.centerX(), outer.centerY()); - return m; - } -} |