OSDN Git Service

am 7776408c: Merge "Adding crop UI. Fixes a number of other UI bugs." into gb-ub...
authorRuben Brunk <rubenbrunk@google.com>
Fri, 12 Oct 2012 21:04:11 +0000 (14:04 -0700)
committerAndroid Git Automerger <android-git-automerger@android.com>
Fri, 12 Oct 2012 21:04:11 +0000 (14:04 -0700)
* commit '7776408c5bbd4bb2669b7a577d157dc1967e434e':
  Adding crop UI.  Fixes a number of other UI bugs.

res/layout/filtershow_activity.xml
src/com/android/gallery3d/filtershow/FilterShowActivity.java
src/com/android/gallery3d/filtershow/PanelController.java
src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java
src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java
src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java
src/com/android/gallery3d/filtershow/imageshow/ImageGeometry.java
src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java

index fb14919..e8a988f 100644 (file)
                 android:layout_height="wrap_content"
                 android:visibility="gone" />
 
-            <!--
             <com.android.gallery3d.filtershow.imageshow.ImageCrop
                 android:id="@+id/imageCrop"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 android:visibility="gone" />
-             -->
 
             <com.android.gallery3d.filtershow.imageshow.ImageRotate
                 android:id="@+id/imageRotate"
index e877054..d308059 100644 (file)
@@ -77,7 +77,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
     private ImageBorder mImageBorders = null;
     private ImageStraighten mImageStraighten = null;
     private ImageZoom mImageZoom = null;
-    private final ImageCrop mImageCrop = null;
+    private ImageCrop mImageCrop = null;
     private ImageRotate mImageRotate = null;
     private ImageFlip mImageFlip = null;
 
@@ -140,8 +140,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
         mImageBorders = (ImageBorder) findViewById(R.id.imageBorder);
         mImageStraighten = (ImageStraighten) findViewById(R.id.imageStraighten);
         mImageZoom = (ImageZoom) findViewById(R.id.imageZoom);
-        // TODO: implement crop
-        // mImageCrop = (ImageCrop) findViewById(R.id.imageCrop);
+        mImageCrop = (ImageCrop) findViewById(R.id.imageCrop);
         mImageRotate = (ImageRotate) findViewById(R.id.imageRotate);
         mImageFlip = (ImageFlip) findViewById(R.id.imageFlip);
 
@@ -150,8 +149,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
         mImageViews.add(mImageBorders);
         mImageViews.add(mImageStraighten);
         mImageViews.add(mImageZoom);
-        // TODO: implement crop
-        // mImageViews.add(mImageCrop);
+        mImageViews.add(mImageCrop);
         mImageViews.add(mImageRotate);
         mImageViews.add(mImageFlip);
 
@@ -180,9 +178,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
         mImageStraighten.setMaster(mImageShow);
         mImageZoom.setImageLoader(mImageLoader);
         mImageZoom.setMaster(mImageShow);
-        // TODO: implement crop
-        // mImageCrop.setImageLoader(mImageLoader);
-        // mImageCrop.setMaster(mImageShow);
+        mImageCrop.setImageLoader(mImageLoader);
+        mImageCrop.setMaster(mImageShow);
         mImageRotate.setImageLoader(mImageLoader);
         mImageRotate.setMaster(mImageShow);
         mImageFlip.setImageLoader(mImageLoader);
@@ -192,8 +189,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
         mPanelController.addImageView(findViewById(R.id.imageCurves));
         mPanelController.addImageView(findViewById(R.id.imageBorder));
         mPanelController.addImageView(findViewById(R.id.imageStraighten));
-        // TODO: implement crop
-        // mPanelController.addImageView(findViewById(R.id.imageCrop));
+        mPanelController.addImageView(findViewById(R.id.imageCrop));
         mPanelController.addImageView(findViewById(R.id.imageRotate));
         mPanelController.addImageView(findViewById(R.id.imageFlip));
         mPanelController.addImageView(findViewById(R.id.imageZoom));
@@ -203,8 +199,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener,
 
         mPanelController.addPanel(mGeometryButton, mListGeometry, 2);
         mPanelController.addComponent(mGeometryButton, findViewById(R.id.straightenButton));
-        // TODO: implement crop
-//        mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton));
+        mPanelController.addComponent(mGeometryButton, findViewById(R.id.cropButton));
         mPanelController.addComponent(mGeometryButton, findViewById(R.id.rotateButton));
         mPanelController.addComponent(mGeometryButton, findViewById(R.id.flipButton));
 
index a937452..963d17a 100644 (file)
@@ -400,16 +400,13 @@ public class PanelController implements OnClickListener {
                 mUtilityPanel.setEffectName(ename);
                 break;
             }
-            /*
-            // TODO: implement crop
             case R.id.cropButton: {
                 mCurrentImage = showImageView(R.id.imageCrop);
                 String ename = mCurrentImage.getContext().getString(R.string.crop);
                 mUtilityPanel.setEffectName(ename);
-                mUtilityPanel.showParameter(false);
+                mUtilityPanel.setShowParameter(false);
                 break;
             }
-            */
             case R.id.rotateButton: {
                 mCurrentImage = showImageView(R.id.imageRotate);
                 String ename = mCurrentImage.getContext().getString(R.string.rotate);
index 527800e..9bdffee 100644 (file)
@@ -20,6 +20,8 @@ import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
 
 import com.android.gallery3d.filtershow.imageshow.GeometryMetadata;
 
@@ -61,15 +63,18 @@ public class ImageFilterGeometry extends ImageFilter {
     native protected void nativeApplyFilterStraighten(Bitmap src, int srcWidth, int srcHeight,
             Bitmap dst, int dstWidth, int dstHeight, float straightenAngle);
 
-    public Matrix buildMatrix(Bitmap bitmap, boolean rotated) {
-        float dx = bitmap.getWidth()/2;
-        float dy = bitmap.getHeight()/2;
+    public Matrix buildMatrix(RectF r) {
+        float dx = r.width()/2;
+        float dy = r.height()/2;
         if(mGeometry.hasSwitchedWidthHeight()){
             float temp = dx;
             dx = dy;
             dy = temp;
         }
-        Matrix m = mGeometry.buildGeometryMatrix(bitmap.getWidth(), bitmap.getHeight(), 1f/mGeometry.getScaleFactor(), dx, dy);
+        float w = r.left * 2 + r.width();
+        float h = r.top * 2 + r.height();
+        Matrix m = mGeometry.buildGeometryMatrix(w, h, 1f, dx, dy, false);
+
         return m;
     }
 
@@ -78,18 +83,18 @@ public class ImageFilterGeometry extends ImageFilter {
         // TODO: implement bilinear or bicubic here... for now, just use
         // canvas to do a simple implementation...
         // TODO: and be more memory efficient! (do it in native?)
-
+        Rect cropBounds = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
+        RectF c = mGeometry.getCropBounds();
+        if(c != null && c.width() > 0 && c.height() > 0)
+            c.roundOut(cropBounds);
         Bitmap temp = null;
-        float rotation = mGeometry.getRotation();
-        boolean rotated = false;
-        if (rotation == 0 || rotation % 180 == 0) {
-            temp = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), mConfig);
+        if (mGeometry.hasSwitchedWidthHeight()) {
+            temp = Bitmap.createBitmap(cropBounds.height(), cropBounds.width(), mConfig);
         } else {
-            temp = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getWidth(), mConfig);
-            rotated = true;
+            temp = Bitmap.createBitmap(cropBounds.width(), cropBounds.height(), mConfig);
         }
 
-        Matrix drawMatrix = buildMatrix(bitmap, rotated);
+        Matrix drawMatrix = buildMatrix(c);
         Canvas canvas = new Canvas(temp);
         canvas.drawBitmap(bitmap, drawMatrix, new Paint());
         return temp;
index a14e065..d412f58 100644 (file)
@@ -33,7 +33,6 @@ public class GeometryMetadata {
     private final RectF mPhotoBounds = new RectF();
     private FLIP mFlip = FLIP.NONE;
 
-
     private RectF mBounds = new RectF();
 
     public enum FLIP {
@@ -47,7 +46,7 @@ public class GeometryMetadata {
         set(g);
     }
 
-    public Bitmap apply(Bitmap original, float scaleFactor, boolean highQuality){
+    public Bitmap apply(Bitmap original, float scaleFactor, boolean highQuality) {
         mImageFilter.setGeometryMetadata(this);
         Bitmap m = mImageFilter.apply(original, scaleFactor, highQuality);
         return m;
@@ -87,7 +86,6 @@ public class GeometryMetadata {
         return new RectF(mPhotoBounds);
     }
 
-
     public void setScaleFactor(float scale) {
         mScaleFactor = scale;
     }
@@ -182,27 +180,34 @@ public class GeometryMetadata {
         }
     }
 
-    public boolean hasSwitchedWidthHeight(){
+    public boolean hasSwitchedWidthHeight() {
         return (((int) (mRotation / 90)) % 2) != 0;
     }
 
-    public Matrix buildGeometryMatrix(float width, float height, float scaling, float dx, float dy){
-        float dx0 = width/2;
-        float dy0 = height/2;
+    public Matrix buildGeometryMatrix(float width, float height, float scaling, float dx, float dy,
+            float rotation) {
+        float dx0 = width / 2;
+        float dy0 = height / 2;
         Matrix m = getFlipMatrix(width, height);
         m.postTranslate(-dx0, -dy0);
-        float rot = mRotation % 360;
-        if (rot < 0)
-            rot += 360;
-        m.postRotate(rot + mStraightenRotation);
+        m.postRotate(rotation);
         m.postScale(scaling, scaling);
         m.postTranslate(dx, dy);
         return m;
     }
 
-    public Matrix buildGeometryUIMatrix(float scaling, float dx, float dy){
+    public Matrix buildGeometryMatrix(float width, float height, float scaling, float dx, float dy,
+            boolean onlyRotate) {
+        float rot = mRotation;
+        if (!onlyRotate) {
+            rot += mStraightenRotation;
+        }
+        return buildGeometryMatrix(width, height, scaling, dx, dy, rot);
+    }
+
+    public Matrix buildGeometryUIMatrix(float scaling, float dx, float dy) {
         float w = mPhotoBounds.width();
         float h = mPhotoBounds.height();
-        return buildGeometryMatrix(w, h, scaling, dx, dy);
+        return buildGeometryMatrix(w, h, scaling, dx, dy, false);
     }
 }
index 90d36e9..4d171bf 100644 (file)
@@ -22,12 +22,10 @@ import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 import android.graphics.Paint;
-import android.graphics.Path;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
-
 import com.android.gallery3d.R;
 
 public class ImageCrop extends ImageGeometry {
@@ -40,19 +38,14 @@ public class ImageCrop extends ImageGeometry {
 
     private static final float MIN_CROP_WIDTH_HEIGHT = 0.1f;
     private static final int TOUCH_TOLERANCE = 30;
-    private static final int SHADOW_ALPHA = 160;
 
-    private final float mAspectWidth = 4;
-    private final float mAspectHeight = 3;
-    private final boolean mFixAspectRatio = false; // not working yet
+    private boolean mFirstDraw = true;
+    private float mAspectWidth = 1;
+    private float mAspectHeight = 1;
+    private boolean mFixAspectRatio = false;
 
     private final Paint borderPaint;
 
-    private float mCropOffsetX = 0;
-    private float mCropOffsetY = 0;
-    private float mPrevOffsetX = 0;
-    private float mPrevOffsetY = 0;
-
     private int movingEdges;
     private final Drawable cropIndicator;
     private final int indicatorSize;
@@ -86,22 +79,21 @@ public class ImageCrop extends ImageGeometry {
     }
 
     private float getScaledMinWidthHeight() {
-        RectF disp = getLocalDisplayBounds();
+        RectF disp = new RectF(0, 0, getWidth(), getHeight());
         float scaled = Math.min(disp.width(), disp.height()) * MIN_CROP_WIDTH_HEIGHT
-                / getLocalScale();
+                / computeScale(getWidth(), getHeight());
         return scaled;
     }
 
-    protected static Matrix getCropRotationMatrix(float rotation, RectF localImage) {
-        Matrix m = new Matrix();
-        m.setRotate(rotation, localImage.centerX(), localImage.centerY());
+    protected Matrix getCropRotationMatrix(float rotation, RectF localImage) {
+        Matrix m = getLocalGeoFlipMatrix(localImage.width(), localImage.height());
+        m.postRotate(rotation, localImage.centerX(), localImage.centerY());
         if (!m.rectStaysRect()) {
             return null;
         }
         return m;
     }
 
-    @Override
     protected RectF getCropBoundsDisplayed() {
         RectF bounds = getLocalCropBounds();
         RectF crop = new RectF(bounds);
@@ -115,7 +107,7 @@ public class ImageCrop extends ImageGeometry {
             m.mapRect(crop);
         }
         m = new Matrix();
-        float zoom = getLocalScale();
+        float zoom = computeScale(getWidth(), getHeight());
         m.setScale(zoom, zoom, mCenterX, mCenterY);
         m.preTranslate(mXOffset, mYOffset);
         m.mapRect(crop);
@@ -137,6 +129,44 @@ public class ImageCrop extends ImageGeometry {
         return crop;
     }
 
+    private RectF getUnrotatedCropBounds(RectF cropBounds) {
+        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());
+
+        if (m == null) {
+            if (LOGV)
+                Log.v(LOGTAG, "FAILED TO GET ROTATION MATRIX");
+            return null;
+        }
+        Matrix m0 = new Matrix();
+        if (!m.invert(m0)) {
+            if (LOGV)
+                Log.v(LOGTAG, "FAILED TO INVERT ROTATION MATRIX");
+            return null;
+        }
+        RectF crop = new RectF(cropBounds);
+        if (!m0.mapRect(crop)) {
+            if (LOGV)
+                Log.v(LOGTAG, "FAILED TO UNROTATE CROPPING BOUNDS");
+            return null;
+        }
+        return crop;
+    }
+
+    private RectF getRotatedStraightenBounds() {
+        RectF straightenBounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
+                getLocalStraighten());
+        Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());
+
+        if (m == null) {
+            if (LOGV)
+                Log.v(LOGTAG, "FAILED TO MAP STRAIGHTEN BOUNDS TO RECTANGLE");
+            return null;
+        } else {
+            m.mapRect(straightenBounds);
+        }
+        return straightenBounds;
+    }
+
     /**
      * Sets cropped bounds; modifies the bounds if it's smaller than the allowed
      * dimensions.
@@ -145,16 +175,33 @@ public class ImageCrop extends ImageGeometry {
         // Avoid cropping smaller than minimum width or height.
         RectF cbounds = new RectF(bounds);
         float minWidthHeight = getScaledMinWidthHeight();
+        float aw = mAspectWidth;
+        float ah = mAspectHeight;
+        if (mFixAspectRatio) {
+            minWidthHeight /= aw * ah;
+            int r = (int) (getLocalRotation() / 90);
+            if (r % 2 != 0) {
+                float temp = aw;
+                aw = ah;
+                ah = temp;
+            }
+        }
 
         float newWidth = cbounds.width();
         float newHeight = cbounds.height();
-        if (newWidth < minWidthHeight) {
-            newWidth = minWidthHeight;
-        }
-        if (newHeight < minWidthHeight) {
-            newHeight = minWidthHeight;
+        if (mFixAspectRatio) {
+            if (newWidth < (minWidthHeight * aw) || newHeight < (minWidthHeight * ah)) {
+                newWidth = minWidthHeight * aw;
+                newHeight = minWidthHeight * ah;
+            }
+        } else {
+            if (newWidth < minWidthHeight) {
+                newWidth = minWidthHeight;
+            }
+            if (newHeight < minWidthHeight) {
+                newHeight = minWidthHeight;
+            }
         }
-
         RectF pbounds = getLocalPhotoBounds();
         if (pbounds.width() < minWidthHeight) {
             newWidth = pbounds.width();
@@ -164,18 +211,14 @@ public class ImageCrop extends ImageGeometry {
         }
 
         cbounds.set(cbounds.left, cbounds.top, cbounds.left + newWidth, cbounds.top + newHeight);
-        RectF snappedCrop = findCropBoundForRotatedImg(cbounds, pbounds, getLocalStraighten(),
-                mCenterX - mXOffset, mCenterY - mYOffset);
-
-        RectF straightenBounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(), getLocalStraighten());
-        snappedCrop.intersect(straightenBounds);
-
+        RectF straightenBounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
+                getLocalStraighten());
+        cbounds.intersect(straightenBounds);
 
         if (mFixAspectRatio) {
-            // TODO: add aspect ratio stuff
-            fixAspectRatio(snappedCrop, mAspectWidth, mAspectHeight);
+            fixAspectRatio(cbounds, aw, ah);
         }
-        setLocalCropBounds(snappedCrop);
+        setLocalCropBounds(cbounds);
         invalidate();
     }
 
@@ -202,33 +245,88 @@ public class ImageCrop extends ImageGeometry {
         else if (bottom <= TOUCH_TOLERANCE) {
             movingEdges |= MOVE_BOTTOM;
         }
+        // Check inside block.
+        if (cropped.contains(x, y) && (movingEdges == 0)) {
+            movingEdges = MOVE_BLOCK;
+        }
         invalidate();
     }
 
     private void moveEdges(float dX, float dY) {
         RectF cropped = getRotatedCropBounds();
         float minWidthHeight = getScaledMinWidthHeight();
-        float scale = getLocalScale();
+        float scale = computeScale(getWidth(), getHeight());
         float deltaX = dX / scale;
         float deltaY = dY / scale;
-        if (movingEdges == MOVE_BLOCK) {
-            // TODO
+        int select = movingEdges;
+        if (mFixAspectRatio && (select != MOVE_BLOCK)) {
+            if ((select & MOVE_LEFT) != 0) {
+                select &= ~MOVE_BOTTOM;
+                select |= MOVE_TOP;
+                deltaY = getNewHeightForWidthAspect(deltaX, mAspectWidth, mAspectHeight);
+            }
+            if ((select & MOVE_TOP) != 0) {
+                select &= ~MOVE_RIGHT;
+                select |= MOVE_LEFT;
+                deltaX = getNewWidthForHeightAspect(deltaY, mAspectWidth, mAspectHeight);
+            }
+            if ((select & MOVE_RIGHT) != 0) {
+                select &= ~MOVE_TOP;
+                select |= MOVE_BOTTOM;
+                deltaY = getNewHeightForWidthAspect(deltaX, mAspectWidth, mAspectHeight);
+            }
+            if ((select & MOVE_BOTTOM) != 0) {
+                select &= ~MOVE_LEFT;
+                select |= MOVE_RIGHT;
+                deltaX = getNewWidthForHeightAspect(deltaY, mAspectWidth, mAspectHeight);
+            }
+        }
+
+        if (select == MOVE_BLOCK) {
+            RectF straight = getRotatedStraightenBounds();
+            // Move the whole cropped bounds within the photo display bounds.
+            deltaX = (deltaX > 0) ? Math.min(straight.right - cropped.right, deltaX)
+                    : Math.max(straight.left - cropped.left, deltaX);
+            deltaY = (deltaY > 0) ? Math.min(straight.bottom - cropped.bottom, deltaY)
+                    : Math.max(straight.top - cropped.top, deltaY);
+            cropped.offset(deltaX, deltaY);
         } else {
-            if ((movingEdges & MOVE_LEFT) != 0) {
-                cropped.left = Math.min(cropped.left + deltaX, cropped.right - minWidthHeight);
-                fixRectAspectW(cropped);
+            float dx = 0;
+            float dy = 0;
+            if ((select & MOVE_LEFT) != 0) {
+                dx = Math.min(cropped.left + deltaX, cropped.right - minWidthHeight) - cropped.left;
+            }
+            if ((select & MOVE_TOP) != 0) {
+                dy = Math.min(cropped.top + deltaY, cropped.bottom - minWidthHeight) - cropped.top;
+            }
+            if ((select & MOVE_RIGHT) != 0) {
+                dx = Math.max(cropped.right + deltaX, cropped.left + minWidthHeight)
+                        - cropped.right;
             }
-            if ((movingEdges & MOVE_TOP) != 0) {
-                cropped.top = Math.min(cropped.top + deltaY, cropped.bottom - minWidthHeight);
-                fixRectAspectH(cropped);
+            if ((select & MOVE_BOTTOM) != 0) {
+                dy = Math.max(cropped.bottom + deltaY, cropped.top + minWidthHeight)
+                        - cropped.bottom;
             }
-            if ((movingEdges & MOVE_RIGHT) != 0) {
-                cropped.right = Math.max(cropped.right + deltaX, cropped.left + minWidthHeight);
-                fixRectAspectW(cropped);
+
+            if (mFixAspectRatio) {
+                if (dx < dy) {
+                    dy = getNewHeightForWidthAspect(dx, mAspectWidth, mAspectHeight);
+                } else {
+                    dx = getNewWidthForHeightAspect(dy, mAspectWidth, mAspectHeight);
+                }
+            }
+
+            if ((select & MOVE_LEFT) != 0) {
+                cropped.left += dx;
             }
-            if ((movingEdges & MOVE_BOTTOM) != 0) {
-                cropped.bottom = Math.max(cropped.bottom + deltaY, cropped.top + minWidthHeight);
-                fixRectAspectH(cropped);
+            if ((select & MOVE_TOP) != 0) {
+                cropped.top += dy;
+            }
+            if ((select & MOVE_RIGHT) != 0) {
+                cropped.right += dx;
+            }
+            if ((select & MOVE_BOTTOM) != 0) {
+                cropped.bottom += dy;
             }
         }
         Matrix m = getCropRotationMatrix(getLocalRotation(), getLocalPhotoBounds());
@@ -244,24 +342,6 @@ public class ImageCrop extends ImageGeometry {
         setCropBounds(cropped);
     }
 
-    private void fixRectAspectH(RectF cropped) {
-        if (mFixAspectRatio) {
-            float half = getNewWidthForHeightAspect(cropped.height(), mAspectWidth, mAspectHeight) / 2;
-            float mid = (cropped.right - cropped.left) / 2;
-            cropped.left = mid - half;
-            cropped.right = mid + half;
-        }
-    }
-
-    private void fixRectAspectW(RectF cropped) {
-        if (mFixAspectRatio) {
-            float half = getNewHeightForWidthAspect(cropped.width(), mAspectWidth, mAspectHeight) / 2;
-            float mid = (cropped.bottom - cropped.top) / 2;
-            cropped.top = mid - half;
-            cropped.bottom = mid + half;
-        }
-    }
-
     private void drawIndicator(Canvas canvas, Drawable indicator, float centerX, float centerY) {
         int left = (int) centerX - indicatorSize / 2;
         int top = (int) centerY - indicatorSize / 2;
@@ -273,81 +353,111 @@ public class ImageCrop extends ImageGeometry {
     protected void setActionDown(float x, float y) {
         super.setActionDown(x, y);
         detectMovingEdges(x, y);
-        if (movingEdges == 0) {
-            mPrevOffsetX = mCropOffsetX;
-            mPrevOffsetY = mCropOffsetY;
-        }
+    }
+
+    @Override
+    protected void setActionUp() {
+        super.setActionUp();
+        movingEdges = 0;
     }
 
     @Override
     protected void setActionMove(float x, float y) {
-        if (movingEdges != 0) {
+        if (movingEdges != 0)
             moveEdges(x - mCurrentX, y - mCurrentY);
+
+        super.setActionMove(x, y);
+    }
+
+    private void cropSetup() {
+        if (mFixAspectRatio) {
+            RectF cb = getRotatedCropBounds();
+            fixAspectRatio(cb, mAspectWidth, mAspectHeight);
+            RectF cb0 = getUnrotatedCropBounds(cb);
+            setCropBounds(cb0);
         } else {
-            float dx = x - mTouchCenterX;
-            float dy = y - mTouchCenterY;
-            mCropOffsetX = dx + mPrevOffsetX;
-            mCropOffsetY = dy + mPrevOffsetY;
+            setCropBounds(getLocalCropBounds());
         }
-        super.setActionMove(x, y);
     }
 
     @Override
     protected void gainedVisibility() {
-        setCropBounds(getLocalCropBounds());
-        super.gainedVisibility();
+        cropSetup();
+        mFirstDraw = true;
     }
 
-    protected RectF drawCrop(Canvas canvas, Paint p, RectF cropBounds, float scale,
-            float rotation, float centerX, float centerY, float offsetX, float offsetY) {
-        RectF crop = new RectF(cropBounds);
-        Matrix m = new Matrix();
-        m.preTranslate(offsetX, offsetY);
-        m.mapRect(crop);
+    @Override
+    public void resetParameter() {
+        super.resetParameter();
+        cropSetup();
+    }
 
-        m.setRotate(rotation, centerX, centerY);
-        if (!m.rectStaysRect()) {
-            float[] corners = getCornersFromRect(crop);
-            m.mapPoints(corners);
-            drawClosedPath(canvas, p, corners);
-        } else {
-            RectF crop2 = new RectF(crop);
-            m.mapRect(crop2);
-            Path path = new Path();
-            path.addRect(crop2, Path.Direction.CCW);
-            canvas.drawPath(path, p);
-        }
-        return crop;
+    @Override
+    protected void lostVisibility() {
     }
 
     @Override
     protected void drawShape(Canvas canvas, Bitmap image) {
+        // TODO: move style to xml
         gPaint.setAntiAlias(true);
         gPaint.setFilterBitmap(true);
         gPaint.setDither(true);
         gPaint.setARGB(255, 255, 255, 255);
-        drawTransformedBitmap(canvas, image, gPaint, false);
 
-        float scale = getLocalScale();
+        if (mFirstDraw) {
+            cropSetup();
+            mFirstDraw = false;
+        }
         float rotation = getLocalRotation();
-
-        RectF scaledCrop = drawCrop(canvas, gPaint, getLocalCropBounds(), scale,
-                rotation, mCenterX, mCenterY, mXOffset,
-                mYOffset);
-
-        boolean notMoving = movingEdges == 0;
-        if (((movingEdges & MOVE_TOP) != 0) || notMoving) {
+        drawTransformedBitmap(canvas, image, gPaint, true);
+
+        gPaint.setARGB(255, 125, 255, 128);
+        gPaint.setStrokeWidth(3);
+        gPaint.setStyle(Paint.Style.STROKE);
+        drawStraighten(canvas, gPaint);
+        RectF scaledCrop = unrotatedCropBounds();
+        int decoded_moving = decoder(movingEdges, rotation);
+        canvas.save();
+        canvas.rotate(rotation, mCenterX, mCenterY);
+        boolean notMoving = decoded_moving == 0;
+        if (((decoded_moving & MOVE_TOP) != 0) || notMoving) {
             drawIndicator(canvas, cropIndicator, scaledCrop.centerX(), scaledCrop.top);
         }
-        if (((movingEdges & MOVE_BOTTOM) != 0) || notMoving) {
+        if (((decoded_moving & MOVE_BOTTOM) != 0) || notMoving) {
             drawIndicator(canvas, cropIndicator, scaledCrop.centerX(), scaledCrop.bottom);
         }
-        if (((movingEdges & MOVE_LEFT) != 0) || notMoving) {
+        if (((decoded_moving & MOVE_LEFT) != 0) || notMoving) {
             drawIndicator(canvas, cropIndicator, scaledCrop.left, scaledCrop.centerY());
         }
-        if (((movingEdges & MOVE_RIGHT) != 0) || notMoving) {
+        if (((decoded_moving & MOVE_RIGHT) != 0) || notMoving) {
             drawIndicator(canvas, cropIndicator, scaledCrop.right, scaledCrop.centerY());
         }
+        canvas.restore();
+    }
+
+    private int bitCycleLeft(int x, int times, int d){
+        int mask = (1 << d) - 1;
+        int mout = x & mask;
+        times %= d;
+        int hi = mout >> (d - times);
+        int low = (mout << times) & mask;
+        int ret = x & ~mask;
+        ret |= low;
+        ret |= hi;
+        return ret;
     }
 
-}
+    protected int decoder(int movingEdges, float rotation) {
+        int rot = constrainedRotation(rotation);
+        switch(rot){
+            case 90:
+                return bitCycleLeft(movingEdges, 3, 4);
+            case 180:
+                return bitCycleLeft(movingEdges, 2, 4);
+            case 270:
+                return bitCycleLeft(movingEdges, 1, 4);
+            default:
+                return movingEdges;
+        }
+    }
+}
\ No newline at end of file
index 8da673b..d8d03dc 100644 (file)
@@ -26,7 +26,6 @@ import android.graphics.Paint.Style;
 import android.graphics.Path;
 import android.graphics.RectF;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 
@@ -49,7 +48,7 @@ public abstract class ImageGeometry extends ImageSlave {
     protected float mTouchCenterY;
 
     // Local geometry data
-    private GeometryMetadata mLocalGeoMetadata = null;
+    private GeometryMetadata mLocalGeometry = null;
     private RectF mLocalDisplayBounds = null;
     protected float mXOffset = 0;
     protected float mYOffset = 0;
@@ -75,9 +74,9 @@ public abstract class ImageGeometry extends ImageSlave {
         calculateLocalScalingFactorAndOffset();
     }
 
-    private float computeScale(float width, float height) {
-        float imageWidth = mLocalGeoMetadata.getPhotoBounds().width();
-        float imageHeight = mLocalGeoMetadata.getPhotoBounds().height();
+    protected float computeScale(float width, float height) {
+        float imageWidth = mLocalGeometry.getPhotoBounds().width();
+        float imageHeight = mLocalGeometry.getPhotoBounds().height();
         float zoom = width / imageWidth;
         if (imageHeight > imageWidth) {
             zoom = height / imageHeight;
@@ -86,9 +85,9 @@ public abstract class ImageGeometry extends ImageSlave {
     }
 
     private void calculateLocalScalingFactorAndOffset() {
-        if (mLocalGeoMetadata == null || mLocalDisplayBounds == null)
+        if (mLocalGeometry == null || mLocalDisplayBounds == null)
             return;
-        RectF imageBounds = mLocalGeoMetadata.getPhotoBounds();
+        RectF imageBounds = mLocalGeometry.getPhotoBounds();
         float imageWidth = imageBounds.width();
         float imageHeight = imageBounds.height();
         float displayWidth = mLocalDisplayBounds.width();
@@ -98,6 +97,7 @@ public abstract class ImageGeometry extends ImageSlave {
         mCenterY = displayHeight / 2;
         mYOffset = (displayHeight - imageHeight) / 2.0f;
         mXOffset = (displayWidth - imageWidth) / 2.0f;
+        updateScale();
     }
 
     @Override
@@ -113,16 +113,16 @@ public abstract class ImageGeometry extends ImageSlave {
 
     // Overwrites local with master
     protected void syncLocalToMasterGeometry() {
-        mLocalGeoMetadata = getMaster().getGeometry();
+        mLocalGeometry = getMaster().getGeometry();
         calculateLocalScalingFactorAndOffset();
     }
 
     protected RectF getLocalPhotoBounds() {
-        return mLocalGeoMetadata.getPhotoBounds();
+        return mLocalGeometry.getPhotoBounds();
     }
 
     protected RectF getLocalCropBounds() {
-        return mLocalGeoMetadata.getCropBounds();
+        return mLocalGeometry.getCropBounds();
     }
 
     protected RectF getLocalDisplayBounds() {
@@ -130,52 +130,62 @@ public abstract class ImageGeometry extends ImageSlave {
     }
 
     protected float getLocalScale() {
-        return mLocalGeoMetadata.getScaleFactor();
+        return mLocalGeometry.getScaleFactor();
     }
 
     protected float getLocalRotation() {
-        return mLocalGeoMetadata.getRotation();
+        return mLocalGeometry.getRotation();
     }
 
     protected float getLocalStraighten() {
-        return mLocalGeoMetadata.getStraightenRotation();
+        return mLocalGeometry.getStraightenRotation();
     }
 
     protected void setLocalScale(float s) {
-        mLocalGeoMetadata.setScaleFactor(s);
+        mLocalGeometry.setScaleFactor(s);
     }
 
-    protected void updateScale(){
-        RectF bounds = getUntranslatedStraightenCropBounds(mLocalGeoMetadata.getPhotoBounds(),
+    protected void updateScale() {
+        RectF bounds = getUntranslatedStraightenCropBounds(mLocalGeometry.getPhotoBounds(),
                 getLocalStraighten());
         float zoom = computeScale(bounds.width(), bounds.height());
         setLocalScale(zoom);
     }
 
     protected void setLocalRotation(float r) {
-        mLocalGeoMetadata.setRotation(r);
+        mLocalGeometry.setRotation(r);
         updateScale();
     }
 
-    private Matrix getLocalGeoMatrix(float scaling, float dx, float dy) {
-        return mLocalGeoMetadata.buildGeometryUIMatrix(scaling, dx, dy);
+    /**
+     * Constrains rotation to be in [0, 90, 180, 270].
+     */
+    protected int constrainedRotation(float rotation) {
+        int r = (int) ((rotation % 360) / 90);
+        r = (r < 0) ? (r + 4) : r;
+        return r * 90;
+    }
+
+    protected Matrix getLocalGeoFlipMatrix(float width, float height) {
+        return mLocalGeometry.getFlipMatrix(width, height);
     }
 
     protected void setLocalStraighten(float r) {
-        mLocalGeoMetadata.setStraightenRotation(r);
+        mLocalGeometry.setStraightenRotation(r);
         updateScale();
     }
 
     protected void setLocalCropBounds(RectF c) {
-        mLocalGeoMetadata.setCropBounds(c);
+        mLocalGeometry.setCropBounds(c);
+        updateScale();
     }
 
     protected FLIP getLocalFlip() {
-        return mLocalGeoMetadata.getFlipType();
+        return mLocalGeometry.getFlipType();
     }
 
     protected void setLocalFlip(FLIP flip) {
-        mLocalGeoMetadata.setFlipType(flip);
+        mLocalGeometry.setFlipType(flip);
     }
 
     protected float getTotalLocalRotation() {
@@ -191,35 +201,18 @@ public abstract class ImageGeometry extends ImageSlave {
     protected static float[] getCornersFromRect(RectF r) {
         // Order is:
         // 0------->1
-        // ^ |
-        // | v
+        // ^        |
+        // |        v
         // 3<-------2
         float[] corners = {
                 r.left, r.top, // 0
                 r.right, r.top, // 1
                 r.right, r.bottom,// 2
-                r.left, r.bottom
-                // 3
+                r.left, r.bottom // 3
         };
         return corners;
     }
 
-    // Returns maximal rectangular crop bound that still fits within
-    // the image bound after the image has been rotated.
-    protected static RectF findCropBoundForRotatedImg(RectF cropBound, RectF imageBound,
-            float rotation, float centerX, float centerY) {
-        Matrix m = new Matrix();
-        float[] cropEdges = getCornersFromRect(cropBound);
-        m.setRotate(rotation, centerX, centerY);
-        Matrix m0 = new Matrix();
-        if (!m.invert(m0))
-            return null;
-        m0.mapPoints(cropEdges);
-        getEdgePoints(imageBound, cropEdges);
-        m.mapPoints(cropEdges);
-        return trapToRect(cropEdges);
-    }
-
     // If edge point [x, y] in array [x0, y0, x1, y1, ...] is outside of the
     // image bound rectangle, clamps it to the edge of the rectangle.
     protected static void getEdgePoints(RectF imageBound, float[] array) {
@@ -231,24 +224,6 @@ public abstract class ImageGeometry extends ImageSlave {
         }
     }
 
-    protected static RectF trapToRect(float[] array) {
-        float dx0 = array[4] - array[0];
-        float dy0 = array[5] - array[1];
-        float dx1 = array[6] - array[2];
-        float dy1 = array[7] - array[3];
-        float l0 = dx0 * dx0 + dy0 * dy0;
-        float l1 = dx1 * dx1 + dy1 * dy1;
-        if (l0 > l1) {
-            RectF n = new RectF(array[2], array[3], array[6], array[7]);
-            n.sort();
-            return n;
-        } else {
-            RectF n = new RectF(array[0], array[1], array[4], array[5]);
-            n.sort();
-            return n;
-        }
-    }
-
     protected static Path drawClosedPath(Canvas canvas, Paint paint, float[] points) {
         Path crop = new Path();
         crop.moveTo(points[0], points[1]);
@@ -260,26 +235,14 @@ public abstract class ImageGeometry extends ImageSlave {
         return crop;
     }
 
-    protected static float[] shortestVectorFromPointToLine(float[] point, float[] l1, float[] l2) {
-        float x1 = l1[0];
-        float x2 = l2[0];
-        float y1 = l1[1];
-        float y2 = l2[1];
-        float xdelt = x2 - x1;
-        float ydelt = y2 - y1;
-        if (xdelt == 0 && ydelt == 0)
-            return null;
-        float u = ((point[0] - x1) * xdelt + (point[1] - y1) * ydelt)
-                / (xdelt * xdelt + ydelt * ydelt);
-        float[] ret = {
-                (x1 + u * (x2 - x1)), (y1 + u * (y2 - y1))
-        };
-        return ret;
-    }
-
     protected static void fixAspectRatio(RectF r, float w, float h) {
         float scale = Math.min(r.width() / w, r.height() / h);
-        r.set(r.left, r.top, scale * w, scale * h);
+        float centX = r.centerX();
+        float centY = r.centerY();
+        float hw = scale * w / 2;
+        float hh = scale * h / 2;
+        r.set(centX - hw, centY - hh, centX + hw, centY + hh);
+
     }
 
     protected static float getNewHeightForWidthAspect(float width, float w, float h) {
@@ -296,6 +259,7 @@ public abstract class ImageGeometry extends ImageSlave {
         if (visibility == View.VISIBLE) {
             mVisibilityGained = true;
             syncLocalToMasterGeometry();
+            updateScale();
             gainedVisibility();
         } else {
             if (mVisibilityGained == true && mHasDrawn == true) {
@@ -308,7 +272,6 @@ public abstract class ImageGeometry extends ImageSlave {
 
     protected void gainedVisibility() {
         // TODO: Override this stub.
-        updateScale();
     }
 
     protected void lostVisibility() {
@@ -330,7 +293,6 @@ public abstract class ImageGeometry extends ImageSlave {
             case (MotionEvent.ACTION_UP):
                 setActionUp();
                 saveAndSetPreset();
-                Log.v(LOGTAG, "up action");
                 break;
             case (MotionEvent.ACTION_MOVE):
                 setActionMove(event.getX(), event.getY());
@@ -378,13 +340,12 @@ public abstract class ImageGeometry extends ImageSlave {
 
     protected void saveAndSetPreset() {
         ImagePreset copy = new ImagePreset(getImagePreset());
-        copy.setGeometry(mLocalGeoMetadata);
+        copy.setGeometry(mLocalGeometry);
         copy.setHistoryName("Geometry");
         copy.setIsFx(false);
         setImagePreset(copy);
     }
 
-    //
     protected static float clamp(float i, float low, float high) {
         return Math.max(Math.min(i, high), low);
     }
@@ -413,105 +374,123 @@ public abstract class ImageGeometry extends ImageSlave {
         return new RectF(left, top, right, bottom);
     }
 
-    protected static void drawShadows(Canvas canvas, Paint p, RectF innerBounds, RectF outerBounds,
-            float rotation, float centerX, float centerY) {
+    protected Matrix getGeoMatrix(RectF r, boolean onlyRotate) {
+        float scale = computeScale(getWidth(), getHeight());
+        float yoff = getHeight() / 2;
+        float xoff = getWidth() / 2;
+        float w = r.left * 2 + r.width();
+        float h = r.top * 2 + r.height();
+        return mLocalGeometry.buildGeometryMatrix(w, h, scale, xoff, yoff, onlyRotate);
+    }
+
+    protected void drawImageBitmap(Canvas canvas, Bitmap bitmap, Paint paint, Matrix m) {
         canvas.save();
-        canvas.rotate(rotation, centerX, centerY);
-        float dWidth = outerBounds.width();
-        float dHeight = outerBounds.height();
-        canvas.drawRect(0, 0, dWidth, innerBounds.top, p);
-        canvas.drawRect(0, innerBounds.bottom, dWidth, dHeight, p);
-        canvas.drawRect(0, innerBounds.top, innerBounds.left, innerBounds.bottom,
-                p);
-        canvas.drawRect(innerBounds.right, innerBounds.top, dWidth,
-                innerBounds.bottom, p);
-        canvas.rotate(-rotation, centerX, centerY);
+        canvas.drawBitmap(bitmap, m, paint);
         canvas.restore();
     }
 
-    public Matrix computeBoundsMatrix(Bitmap bitmap) {
-        float w = getWidth();
-        float h = getHeight();
-        Matrix boundsMatrix = new Matrix();
-        boundsMatrix.setTranslate((getWidth() - bitmap.getWidth()) / 2.0f,
-                (getHeight() - bitmap.getHeight()) / 2.0f);
-        boundsMatrix.postRotate(getLocalRotation(), getWidth() / 2.0f, getHeight() / 2.0f);
-        float scale = computeScale(w, h);
-        boundsMatrix.postScale(scale, scale, getWidth()/2, getHeight()/2);
-        return boundsMatrix;
+    protected void drawImageBitmap(Canvas canvas, Bitmap bitmap, Paint paint) {
+        float scale = computeScale(getWidth(), getHeight());
+        float yoff = getHeight() / 2;
+        float xoff = getWidth() / 2;
+        Matrix m = mLocalGeometry.buildGeometryUIMatrix(scale, xoff, yoff);
+        drawImageBitmap(canvas, bitmap, paint, m);
     }
 
-    public RectF cropBounds(Bitmap bitmap) {
-        Matrix boundsMatrix = computeBoundsMatrix(bitmap);
+    protected RectF straightenBounds() {
         RectF bounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
                 getLocalStraighten());
-        RectF transformedBounds = new RectF(bounds);
-        boundsMatrix.mapRect(transformedBounds);
-        return transformedBounds;
+        Matrix m = getGeoMatrix(bounds, true);
+        m.mapRect(bounds);
+        return bounds;
     }
 
-    protected void drawImage(Canvas canvas, Bitmap bitmap, Paint paint) {
-        float scale = computeScale(getWidth(), getHeight());
-        float yoff = getHeight()/2;
-        float xoff = getWidth()/2;
-        Matrix m = getLocalGeoMatrix(scale, xoff, yoff);
+    protected void drawStraighten(Canvas canvas, Paint paint) {
+        RectF bounds = straightenBounds();
         canvas.save();
-        canvas.drawBitmap(bitmap, m, paint);
+        canvas.drawRect(bounds, paint);
+        canvas.restore();
     }
 
-    protected void drawTransformedBitmap(Canvas canvas, Bitmap bitmap, Paint paint, boolean clip) {
-        float w = getWidth();
-        float h = getHeight();
-        Matrix boundsMatrix = computeBoundsMatrix(bitmap);
-        RectF bounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
-                getLocalStraighten());
-        RectF transformedBounds = new RectF(bounds);
-        boundsMatrix.mapRect(transformedBounds);
-        canvas.save();
-        paint.setARGB(255, 0, 0, 0);
-        drawImage(canvas, bitmap, paint);
-        canvas.restore();
+    protected RectF unrotatedCropBounds() {
+        RectF bounds = getLocalCropBounds();
+        RectF pbounds = getLocalPhotoBounds();
+        float scale = computeScale(getWidth(), getHeight());
+        float yoff = getHeight() / 2;
+        float xoff = getWidth() / 2;
+        Matrix m = mLocalGeometry.buildGeometryMatrix(pbounds.width(), pbounds.height(), scale, xoff, yoff, 0);
+        m.mapRect(bounds);
+        return bounds;
+    }
+
+    protected RectF cropBounds() {
+        RectF bounds = getLocalCropBounds();
+        Matrix m = getGeoMatrix(getLocalPhotoBounds(), true);
+        m.mapRect(bounds);
+        return bounds;
+    }
+
+    // Fails for non-90 degree
+    protected void drawCrop(Canvas canvas, Paint paint) {
+        RectF bounds = cropBounds();
         canvas.save();
-        canvas.setMatrix(boundsMatrix);
-        paint.setColor(Color.WHITE);
-        paint.setStyle(Style.STROKE);
-        paint.setStrokeWidth(2);
         canvas.drawRect(bounds, paint);
         canvas.restore();
+    }
 
-        if (!clip) { // we display the rest of the bitmap grayed-out
-            drawShadows(canvas, transformedBounds, new RectF(0, 0, w, h), paint);
+    protected void drawCropSafe(Canvas canvas, Paint paint) {
+        Matrix m = getGeoMatrix(getLocalPhotoBounds(), true);
+        RectF crop = getLocalCropBounds();
+        if (!m.rectStaysRect()) {
+            float[] corners = getCornersFromRect(crop);
+            m.mapPoints(corners);
+            drawClosedPath(canvas, paint, corners);
+        } else {
+            m.mapRect(crop);
+            Path path = new Path();
+            path.addRect(crop, Path.Direction.CCW);
+            canvas.drawPath(path, paint);
         }
     }
 
-    protected RectF getCropBoundsDisplayed() {
-        return getCropBoundsDisplayed(getLocalCropBounds());
+    protected void drawTransformedBitmap(Canvas canvas, Bitmap bitmap, Paint paint, boolean clip) {
+        paint.setARGB(255, 0, 0, 0);
+        drawImageBitmap(canvas, bitmap, paint);
+        paint.setColor(Color.WHITE);
+        paint.setStyle(Style.STROKE);
+        paint.setStrokeWidth(2);
+        drawCropSafe(canvas, paint);
+        paint.setARGB(128, 0, 0, 0);
+        paint.setStyle(Paint.Style.FILL);
+        drawShadows(canvas, paint, unrotatedCropBounds());
     }
 
-    protected RectF getCropBoundsDisplayed(RectF bounds) {
-        RectF crop = new RectF(bounds);
-        Matrix m = new Matrix();
-        float zoom = getLocalScale();
-        m.setScale(zoom, zoom, mCenterX, mCenterY);
-        m.preTranslate(mXOffset, mYOffset);
-        m.mapRect(crop);
-        return crop;
+    protected void drawShadows(Canvas canvas, Paint p, RectF innerBounds) {
+        RectF display = new RectF(0, 0, getWidth(), getHeight());
+        drawShadows(canvas, p, innerBounds, display, getLocalRotation(), getWidth() / 2,
+                getHeight() / 2);
     }
 
-    protected void drawShadows(Canvas canvas, RectF innerBounds, RectF outerBounds, Paint p) {
-        float dWidth = outerBounds.width();
-        float dHeight = outerBounds.height();
-
-        // TODO: move style to xml
-        p.setARGB(128, 0, 0, 0);
-        p.setStyle(Paint.Style.FILL);
+    protected static void drawShadows(Canvas canvas, Paint p, RectF innerBounds, RectF outerBounds,
+            float rotation, float centerX, float centerY) {
+        canvas.save();
+        canvas.rotate(rotation, centerX, centerY);
 
-        canvas.drawRect(0, 0, dWidth, innerBounds.top, p);
-        canvas.drawRect(0, innerBounds.bottom, dWidth, dHeight, p);
-        canvas.drawRect(0, innerBounds.top, innerBounds.left, innerBounds.bottom,
+        float x = (outerBounds.left - outerBounds.right);
+        float y = (outerBounds.top - outerBounds.bottom);
+        float longest = (float) Math.sqrt(x * x + y * y) / 2;
+        float minX = centerX - longest;
+        float maxX = centerX + longest;
+        float minY = centerY - longest;
+        float maxY = centerY + longest;
+        canvas.drawRect(minX, minY, innerBounds.right, innerBounds.top, p);
+        canvas.drawRect(minX, innerBounds.top, innerBounds.left, maxY, p);
+        canvas.drawRect(innerBounds.left, innerBounds.bottom, maxX, maxY,
                 p);
-        canvas.drawRect(innerBounds.right, innerBounds.top, dWidth,
+        canvas.drawRect(innerBounds.right, minY, maxX,
                 innerBounds.bottom, p);
+        canvas.rotate(-rotation, centerX, centerY);
+        canvas.restore();
     }
 
     @Override
index a94d629..2fd6b9b 100644 (file)
@@ -24,6 +24,8 @@ import android.graphics.Path;
 import android.graphics.RectF;
 import android.util.AttributeSet;
 
+import com.android.gallery3d.filtershow.imageshow.ImageGeometry.MODES;
+
 public class ImageStraighten extends ImageGeometry {
 
     private float mBaseAngle = 0;
@@ -46,11 +48,17 @@ public class ImageStraighten extends ImageGeometry {
         mBaseAngle = mAngle = getLocalStraighten();
     }
 
+    private void setCropToStraighten(){
+        setLocalCropBounds(getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
+                getLocalStraighten()));
+    }
+
     @Override
     protected void setActionMove(float x, float y) {
         super.setActionMove(x, y);
         computeValue();
         setLocalStraighten(mAngle);
+        setCropToStraighten();
     }
 
     private float angleFor(float dx, float dy) {
@@ -80,6 +88,17 @@ public class ImageStraighten extends ImageGeometry {
     }
 
     @Override
+    protected void gainedVisibility(){
+        setCropToStraighten();
+    }
+
+    @Override
+    protected void setActionUp() {
+        super.setActionUp();
+        setCropToStraighten();
+    }
+
+    @Override
     public void onNewValue(int value) {
         setLocalStraighten(clamp(value, MIN_STRAIGHTEN_ANGLE, MAX_STRAIGHTEN_ANGLE));
         if (getPanelController() != null) {
@@ -98,7 +117,7 @@ public class ImageStraighten extends ImageGeometry {
         drawTransformedBitmap(canvas, image, gPaint, false);
 
         // Draw the grid
-        RectF bounds = cropBounds(image);
+        RectF bounds = straightenBounds();
         Path path = new Path();
         path.addRect(bounds, Path.Direction.CCW);
         gPaint.setARGB(255, 255, 255, 255);