diff --git a/src/org/thoughtcrime/securesms/imageeditor/Bounds.java b/src/org/thoughtcrime/securesms/imageeditor/Bounds.java index 0b8faf663b..f5d4e0ca5a 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/Bounds.java +++ b/src/org/thoughtcrime/securesms/imageeditor/Bounds.java @@ -1,6 +1,9 @@ package org.thoughtcrime.securesms.imageeditor; +import android.graphics.Matrix; import android.graphics.RectF; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; /** * The local extent of a {@link org.thoughtcrime.securesms.imageeditor.model.EditorElement}. @@ -21,9 +24,51 @@ public final class Bounds { public static final float[] CENTRE = new float[]{ CENTRE_X, CENTRE_Y }; + private static final float[] POINTS = { Bounds.LEFT, Bounds.TOP, + Bounds.RIGHT, Bounds.TOP, + Bounds.RIGHT, Bounds.BOTTOM, + Bounds.LEFT, Bounds.BOTTOM }; + static RectF newFullBounds() { return new RectF(LEFT, TOP, RIGHT, BOTTOM); } public static RectF FULL_BOUNDS = newFullBounds(); + + public static boolean contains(float x, float y) { + return x >= FULL_BOUNDS.left && x <= FULL_BOUNDS.right && + y >= FULL_BOUNDS.top && y <= FULL_BOUNDS.bottom; + } + + /** + * Maps all the points of bounds with the supplied matrix and determines whether they are still in bounds. + * + * @param matrix matrix to transform points by, null is treated as identity. + * @return true iff all points remain in bounds after transformation. + */ + public static boolean boundsRemainInBounds(@Nullable Matrix matrix) { + if (matrix == null) return true; + + float[] dst = new float[POINTS.length]; + + matrix.mapPoints(dst, POINTS); + + return allWithinBounds(dst); + } + + private static boolean allWithinBounds(@NonNull float[] points) { + boolean allHit = true; + + for (int i = 0; i < points.length / 2; i++) { + float x = points[2 * i]; + float y = points[2 * i + 1]; + + if (!Bounds.contains(x, y)) { + allHit = false; + break; + } + } + + return allHit; + } } diff --git a/src/org/thoughtcrime/securesms/imageeditor/EditSession.java b/src/org/thoughtcrime/securesms/imageeditor/EditSession.java index 3c79c07b45..cd883cf562 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/EditSession.java +++ b/src/org/thoughtcrime/securesms/imageeditor/EditSession.java @@ -2,6 +2,7 @@ package org.thoughtcrime.securesms.imageeditor; import android.graphics.Matrix; import android.graphics.PointF; +import android.support.annotation.NonNull; import org.thoughtcrime.securesms.imageeditor.model.EditorElement; @@ -18,13 +19,13 @@ import org.thoughtcrime.securesms.imageeditor.model.EditorElement; */ interface EditSession { - void movePoint(int p, PointF point); + void movePoint(int p, @NonNull PointF point); EditorElement getSelected(); - EditSession newPoint(Matrix newInverse, PointF point, int p); + EditSession newPoint(@NonNull Matrix newInverse, @NonNull PointF point, int p); - EditSession removePoint(Matrix newInverse, int p); + EditSession removePoint(@NonNull Matrix newInverse, int p); void commit(); } diff --git a/src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java index 732175104c..6f8e053563 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java +++ b/src/org/thoughtcrime/securesms/imageeditor/ElementDragEditSession.java @@ -31,12 +31,12 @@ final class ElementDragEditSession extends ElementEditSession { } @Override - public EditSession newPoint(Matrix newInverse, PointF point, int p) { + public EditSession newPoint(@NonNull Matrix newInverse, PointF point, int p) { return ElementScaleEditSession.startScale(this, newInverse, point, p); } @Override - public EditSession removePoint(Matrix newInverse, int p) { + public EditSession removePoint(@NonNull Matrix newInverse, int p) { return this; } } diff --git a/src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java index cc37ddb587..4dd7221121 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java +++ b/src/org/thoughtcrime/securesms/imageeditor/ElementEditSession.java @@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.imageeditor.model.EditorElement; abstract class ElementEditSession implements EditSession { - private final Matrix inverseMatrix; + private final Matrix inverseMatrix; final EditorElement selected; @@ -60,7 +60,7 @@ abstract class ElementEditSession implements EditSession { * @param matrix Matrix to transform point with. * @param src Input point. */ - static void mapPoint(@NonNull PointF dst, @NonNull Matrix matrix, @NonNull PointF src) { + private static void mapPoint(@NonNull PointF dst, @NonNull Matrix matrix, @NonNull PointF src) { float[] in = { src.x, src.y }; float[] out = new float[2]; matrix.mapPoints(out, in); diff --git a/src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java index 95197c1fb6..4594c964a7 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java +++ b/src/org/thoughtcrime/securesms/imageeditor/ElementScaleEditSession.java @@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.imageeditor.model.EditorElement; final class ElementScaleEditSession extends ElementEditSession { - private ElementScaleEditSession(EditorElement selected, Matrix inverseMatrix) { + private ElementScaleEditSession(@NonNull EditorElement selected, @NonNull Matrix inverseMatrix) { super(selected, inverseMatrix); } @@ -56,20 +56,20 @@ final class ElementScaleEditSession extends ElementEditSession { } @Override - public EditSession newPoint(Matrix newInverse, PointF point, int p) { + public EditSession newPoint(@NonNull Matrix newInverse, @NonNull PointF point, int p) { return this; } @Override - public EditSession removePoint(Matrix newInverse, int p) { + public EditSession removePoint(@NonNull Matrix newInverse, int p) { return convertToDrag(p, newInverse); } - private static double angle(PointF a, PointF b) { + private static double angle(@NonNull PointF a, @NonNull PointF b) { return Math.atan2(a.y - b.y, a.x - b.x); } - private ElementDragEditSession convertToDrag(int p, Matrix inverse) { + private ElementDragEditSession convertToDrag(int p, @NonNull Matrix inverse) { return ElementDragEditSession.startDrag(selected, inverse, endPointScreen[1 - p]); } diff --git a/src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java b/src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java index 7b746667fc..ed98f296e2 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java +++ b/src/org/thoughtcrime/securesms/imageeditor/ImageEditorView.java @@ -70,6 +70,7 @@ public final class ImageEditorView extends FrameLayout { @Nullable private EditSession editSession; + private boolean moreThanOnePointerUsedInSession; public ImageEditorView(Context context) { super(context); @@ -215,6 +216,7 @@ public final class ImageEditorView extends FrameLayout { PointF point = getPoint(event); EditorElement selected = model.findElementAtPoint(point, viewMatrix, inverse); + moreThanOnePointerUsedInSession = false; model.pushUndoPoint(); editSession = startEdit(inverse, point, selected); @@ -230,9 +232,19 @@ public final class ImageEditorView extends FrameLayout { } case MotionEvent.ACTION_MOVE: { if (editSession != null) { - for (int p = 0; p < Math.min(2, event.getPointerCount()); p++) { + int historySize = event.getHistorySize(); + int pointerCount = Math.min(2, event.getPointerCount()); + + for (int h = 0; h < historySize; h++) { + for (int p = 0; p < pointerCount; p++) { + editSession.movePoint(p, getHistoricalPoint(event, p, h)); + } + } + + for (int p = 0; p < pointerCount; p++) { editSession.movePoint(p, getPoint(event, p)); } + model.moving(editSession.getSelected()); invalidate(); return true; } @@ -240,11 +252,16 @@ public final class ImageEditorView extends FrameLayout { } case MotionEvent.ACTION_POINTER_DOWN: { if (editSession != null && event.getPointerCount() == 2) { + moreThanOnePointerUsedInSession = true; editSession.commit(); model.pushUndoPoint(); Matrix newInverse = model.findElementInverseMatrix(editSession.getSelected(), viewMatrix); - editSession = editSession.newPoint(newInverse, getPoint(event, event.getActionIndex()), event.getActionIndex()); + if (newInverse != null) { + editSession = editSession.newPoint(newInverse, getPoint(event, event.getActionIndex()), event.getActionIndex()); + } else { + editSession = null; + } if (editSession == null) { dragDropRelease(); } @@ -259,7 +276,11 @@ public final class ImageEditorView extends FrameLayout { dragDropRelease(); Matrix newInverse = model.findElementInverseMatrix(editSession.getSelected(), viewMatrix); - editSession = editSession.removePoint(newInverse, event.getActionIndex()); + if (newInverse != null) { + editSession = editSession.removePoint(newInverse, event.getActionIndex()); + } else { + editSession = null; + } return true; } break; @@ -270,8 +291,11 @@ public final class ImageEditorView extends FrameLayout { dragDropRelease(); editSession = null; + model.postEdit(moreThanOnePointerUsedInSession); invalidate(); return true; + } else { + model.postEdit(moreThanOnePointerUsedInSession); } break; } @@ -349,6 +373,11 @@ public final class ImageEditorView extends FrameLayout { return new PointF(event.getX(p), event.getY(p)); } + private static PointF getHistoricalPoint(MotionEvent event, int p, int historicalIndex) { + return new PointF(event.getHistoricalX(p, historicalIndex), + event.getHistoricalY(p, historicalIndex)); + } + public EditorModel getModel() { return model; } diff --git a/src/org/thoughtcrime/securesms/imageeditor/RendererContext.java b/src/org/thoughtcrime/securesms/imageeditor/RendererContext.java index 9ca600f39f..d133e8f6c1 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/RendererContext.java +++ b/src/org/thoughtcrime/securesms/imageeditor/RendererContext.java @@ -96,6 +96,10 @@ public final class RendererContext { canvasMatrix.restore(); } + public void getCurrent(@NonNull Matrix into) { + canvasMatrix.getCurrent(into); + } + public interface Ready { Ready NULL = (renderer, cropMatrix, size) -> { diff --git a/src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java b/src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java index 591e16afe8..197921c1fa 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java +++ b/src/org/thoughtcrime/securesms/imageeditor/ThumbDragEditSession.java @@ -39,7 +39,7 @@ class ThumbDragEditSession extends ElementEditSession { editorMatrix.postTranslate(-x, -y); - boolean aspectLocked = selected.getFlags().isAspectLocked(); + boolean aspectLocked = selected.getFlags().isAspectLocked() && !controlPoint.isCenter(); float defaultScale = aspectLocked ? 2 : 1; @@ -57,12 +57,12 @@ class ThumbDragEditSession extends ElementEditSession { } @Override - public EditSession newPoint(Matrix newInverse, PointF point, int p) { + public EditSession newPoint(@NonNull Matrix newInverse, @NonNull PointF point, int p) { return null; } @Override - public EditSession removePoint(Matrix newInverse, int p) { + public EditSession removePoint(@NonNull Matrix newInverse, int p) { return null; } } diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java b/src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java index d16c677bfa..a8c72588fd 100644 --- a/src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java +++ b/src/org/thoughtcrime/securesms/imageeditor/model/EditorElementHierarchy.java @@ -66,7 +66,7 @@ final class EditorElementHierarchy { private EditorElementHierarchy(@NonNull EditorElement root) { this.root = root; - this.view = this.root.getChild(0); + this.view = this.root.getChild(0); this.flipRotate = this.view.getChild(0); this.imageRoot = this.flipRotate.getChild(0); this.overlay = this.flipRotate.getChild(1); @@ -237,6 +237,30 @@ final class EditorElementHierarchy { return matrix; } + /** + * Returns a matrix that maps points from the crop on to the visible image. + *
+ * i.e. if a mapped point is in bounds, then the point is on the visible image.
+ */
+ @Nullable Matrix imageMatrixRelativeToCrop() {
+ EditorElement mainImage = getMainImage();
+ if (mainImage == null) return null;
+
+ Matrix matrix1 = new Matrix(imageCrop.getLocalMatrix());
+ matrix1.preConcat(cropEditorElement.getLocalMatrix());
+ matrix1.preConcat(cropEditorElement.getEditorMatrix());
+
+ Matrix matrix2 = new Matrix(mainImage.getLocalMatrix());
+ matrix2.preConcat(mainImage.getEditorMatrix());
+ matrix2.preConcat(imageCrop.getLocalMatrix());
+
+ Matrix inverse = new Matrix();
+ matrix2.invert(inverse);
+ inverse.preConcat(matrix1);
+
+ return inverse;
+ }
+
void dragDropRelease(@NonNull RectF visibleViewPort, @NonNull Runnable invalidate) {
if (cropEditorElement.getFlags().isVisible()) {
updateViewToCrop(visibleViewPort, invalidate);
@@ -299,9 +323,10 @@ final class EditorElementHierarchy {
matrix.preConcat(flipRotate.getLocalMatrix());
matrix.preConcat(cropEditorElement.getLocalMatrix());
+ matrix.preConcat(cropEditorElement.getEditorMatrix());
EditorElement mainImage = getMainImage();
if (mainImage != null) {
- float xScale = 1f / xScale(mainImage.getLocalMatrix());
+ float xScale = 1f / (xScale(mainImage.getLocalMatrix()) * xScale(mainImage.getEditorMatrix()));
matrix.preScale(xScale, xScale);
}
diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java b/src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java
index 9f178c1a3b..fde68048c1 100644
--- a/src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java
+++ b/src/org/thoughtcrime/securesms/imageeditor/model/EditorModel.java
@@ -37,11 +37,14 @@ public final class EditorModel implements Parcelable, RendererContext.Ready {
private static final int MINIMUM_OUTPUT_WIDTH = 0;
+ private static final float MAXIMUM_CROP = 0.20f;
+
@NonNull
private Runnable invalidate = NULL_RUNNABLE;
private final UndoRedoStacks undoRedoStacks;
private final UndoRedoStacks cropUndoRedoStacks;
+ private final InBoundsMemory inBoundsMemory = new InBoundsMemory();
private EditorElementHierarchy editorElementHierarchy;
@@ -88,7 +91,7 @@ public final class EditorModel implements Parcelable, RendererContext.Ready {
return null;
}
- private @Nullable Matrix findElementMatrix(@NonNull EditorElement element, @NonNull Matrix viewMatrix) {
+ public @Nullable Matrix findElementMatrix(@NonNull EditorElement element, @NonNull Matrix viewMatrix) {
Matrix inverse = findElementInverseMatrix(element, viewMatrix);
if (inverse != null) {
Matrix regular = new Matrix();
@@ -107,7 +110,12 @@ public final class EditorModel implements Parcelable, RendererContext.Ready {
}
public void pushUndoPoint() {
- UndoRedoStacks stacks = isCropping() ? cropUndoRedoStacks : undoRedoStacks;
+ boolean cropping = isCropping();
+ if (cropping && !currentCropIsAcceptable()) {
+ return;
+ }
+
+ UndoRedoStacks stacks = cropping ? cropUndoRedoStacks : undoRedoStacks;
if (stacks.getUndoStack().tryPush(editorElementHierarchy.getRoot())) {
stacks.getRedoStack().clear();
@@ -140,12 +148,14 @@ public final class EditorModel implements Parcelable, RendererContext.Ready {
// re-zoom image root as the view port might be different now
editorElementHierarchy.updateViewToCrop(visibleViewPort, invalidate);
+
+ inBoundsMemory.push(editorElementHierarchy.getMainImage(), editorElementHierarchy.getCropEditorElement());
}
}
private static void restoreStateWithAnimations(@NonNull EditorElement fromRootElement, @NonNull EditorElement toRootElement, @NonNull Runnable onInvalidate, boolean keepEditorState) {
Map
+ * Does not respect minimum scale, so does need a further check to {@link #currentCropIsAcceptable} afterwards.
+ *
+ * @param element The element to be scaled. If successful, it will be animated to the correct position.
+ * @param scaleAtMost The amount of scale to apply at most. Use < 1 for the crop, and > 1 for the image.
+ * @return true if successfully scaled the element. false if the element was left unchanged.
+ */
+ private boolean tryToScaleToFit(@NonNull EditorElement element, float scaleAtMost) {
+ Matrix elementMatrix = element.getLocalMatrix();
+ Matrix original = new Matrix(elementMatrix);
+ Matrix lastSuccessful = new Matrix();
+ boolean success = false;
+ float unsuccessfulScale = 1;
+ int attempt = 0;
+
+ do {
+ float tryScale = (scaleAtMost + unsuccessfulScale) / 2f;
+ elementMatrix.set(original);
+ elementMatrix.preScale(tryScale, tryScale);
+
+ if (cropIsWithinMainImageBounds(editorElementHierarchy)) {
+ scaleAtMost = tryScale;
+ success = true;
+ lastSuccessful.set(elementMatrix);
+ } else {
+ unsuccessfulScale = tryScale;
+ }
+ attempt++;
+ } while (attempt < 16 && Math.abs(scaleAtMost - unsuccessfulScale) > 0.001f);
+
+ elementMatrix.set(original);
+ if (success) {
+ element.animateLocalTo(lastSuccessful, invalidate);
+ }
+ return success;
+ }
+
public void dragDropRelease() {
editorElementHierarchy.dragDropRelease(visibleViewPort, invalidate);
}
+ /**
+ * Pixel count must be no smaller than the MAXIMUM_CROP of its original size and all points must be within the bounds.
+ */
+ private boolean currentCropIsAcceptable() {
+ Point outputSize = getOutputSize();
+ int outputPixelCount = outputSize.x * outputSize.y;
+ int minimumPixelCount = (int) (size.x * size.y * MAXIMUM_CROP * MAXIMUM_CROP);
+
+ return outputPixelCount >= minimumPixelCount &&
+ cropIsWithinMainImageBounds(editorElementHierarchy);
+ }
+
+ /**
+ * @return true if and only if the current crop rect is fully in the bounds.
+ */
+ private static boolean cropIsWithinMainImageBounds(@NonNull EditorElementHierarchy hierarchy) {
+ return Bounds.boundsRemainInBounds(hierarchy.imageMatrixRelativeToCrop());
+ }
+
+ /**
+ * Called as edits are underway.
+ */
+ public void moving(@NonNull EditorElement editorElement) {
+ if (!isCropping()) return;
+
+ EditorElement mainImage = editorElementHierarchy.getMainImage();
+ EditorElement cropEditorElement = editorElementHierarchy.getCropEditorElement();
+
+ if (editorElement == mainImage || editorElement == cropEditorElement) {
+ if (currentCropIsAcceptable()) {
+ inBoundsMemory.push(mainImage, cropEditorElement);
+ }
+ }
+ }
+
public void setVisibleViewPort(@NonNull RectF visibleViewPort) {
this.visibleViewPort.set(visibleViewPort);
this.editorElementHierarchy.updateViewToCrop(visibleViewPort, invalidate);
@@ -364,23 +480,38 @@ public final class EditorModel implements Parcelable, RendererContext.Ready {
return findCropRelativeTo(editorElementHierarchy.getRoot());
}
- private RectF findCropRelativeTo(EditorElement element) {
+ RectF findCropRelativeTo(EditorElement element) {
return findRelativeBounds(editorElementHierarchy.getCropEditorElement(), element);
}
- private RectF findRelativeBounds(EditorElement from, EditorElement to) {
- Matrix matrix1 = findElementMatrix(from, new Matrix());
- Matrix matrix2 = findElementInverseMatrix(to, new Matrix());
+ RectF findRelativeBounds(EditorElement from, EditorElement to) {
+ Matrix relative = findRelativeMatrix(from, to);
RectF dst = new RectF(Bounds.FULL_BOUNDS);
- if (matrix1 != null) {
- matrix1.preConcat(matrix2);
-
- matrix1.mapRect(dst, Bounds.FULL_BOUNDS);
+ if (relative != null) {
+ relative.mapRect(dst, Bounds.FULL_BOUNDS);
}
return dst;
}
+ /**
+ * Returns a matrix that maps points in the {@param from} element in to points in the {@param to} element.
+ *
+ * @param from
+ * @param to
+ * @return
+ */
+ @Nullable Matrix findRelativeMatrix(@NonNull EditorElement from, @NonNull EditorElement to) {
+ Matrix matrix = findElementInverseMatrix(to, new Matrix());
+ Matrix outOf = findElementMatrix(from, new Matrix());
+
+ if (outOf != null && matrix != null) {
+ matrix.preConcat(outOf);
+ return matrix;
+ }
+ return null;
+ }
+
public void rotate90clockwise() {
pushUndoPoint();
editorElementHierarchy.flipRotate(90, 1, 1, visibleViewPort, invalidate);
diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/InBoundsMemory.java b/src/org/thoughtcrime/securesms/imageeditor/model/InBoundsMemory.java
new file mode 100644
index 0000000000..fcc3533806
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/imageeditor/model/InBoundsMemory.java
@@ -0,0 +1,30 @@
+package org.thoughtcrime.securesms.imageeditor.model;
+
+import android.graphics.Matrix;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+
+final class InBoundsMemory {
+
+ private final Matrix lastGoodUserCrop = new Matrix();
+ private final Matrix lastGoodMainImage = new Matrix();
+
+ void push(@Nullable EditorElement mainImage, @NonNull EditorElement userCrop) {
+ if (mainImage == null) {
+ lastGoodMainImage.reset();
+ } else {
+ lastGoodMainImage.set(mainImage.getLocalMatrix());
+ lastGoodMainImage.preConcat(mainImage.getEditorMatrix());
+ }
+
+ lastGoodUserCrop.set(userCrop.getLocalMatrix());
+ lastGoodUserCrop.preConcat(userCrop.getEditorMatrix());
+ }
+
+ void restore(@Nullable EditorElement mainImage, @NonNull EditorElement cropEditorElement, @Nullable Runnable invalidate) {
+ if (mainImage != null) {
+ mainImage.animateLocalTo(lastGoodMainImage, invalidate);
+ }
+ cropEditorElement.animateLocalTo(lastGoodUserCrop, invalidate);
+ }
+}
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java
index 21020b5253..1447664490 100644
--- a/src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java
+++ b/src/org/thoughtcrime/securesms/imageeditor/model/ThumbRenderer.java
@@ -65,6 +65,10 @@ public interface ThumbRenderer extends Renderer {
public boolean isVerticalCenter() {
return this == ControlPoint.TOP_CENTER || this == ControlPoint.BOTTOM_CENTER;
}
+
+ public boolean isCenter() {
+ return isHorizontalCenter() || isVerticalCenter();
+ }
}
ControlPoint getControlPoint();
diff --git a/src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java b/src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java
index 67f26354fc..6c15f2b2e6 100644
--- a/src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java
+++ b/src/org/thoughtcrime/securesms/imageeditor/renderers/CropAreaRenderer.java
@@ -106,7 +106,7 @@ public final class CropAreaRenderer implements Renderer {
@Override
public boolean hitTest(float x, float y) {
- return !Bounds.FULL_BOUNDS.contains(x, y);
+ return !Bounds.contains(x, y);
}
public static final Creator