import android.view.MotionEvent;
import android.view.View;
+import com.android.gallery3d.filtershow.history.HistoryItem;
+import com.android.gallery3d.filtershow.filters.FilterRepresentation;
import com.android.gallery3d.filtershow.imageshow.GeometryMetadata.FLIP;
-import com.android.gallery3d.filtershow.presets.ImagePreset;
-import com.android.gallery3d.filtershow.imageshow.GeometryMath;
+import com.android.gallery3d.filtershow.pipeline.ImagePreset;
-public abstract class ImageGeometry extends ImageSlave {
- private boolean mVisibilityGained = false;
+public abstract class ImageGeometry extends ImageShow {
+ protected boolean mVisibilityGained = false;
private boolean mHasDrawn = false;
protected static final float MAX_STRAIGHTEN_ANGLE = 45;
return current * 90;
}
- protected float getCurrentTouchAngle(){
+ protected float getCurrentTouchAngle() {
if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) {
return 0;
}
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;
- }
- return zoom;
+ return GeometryMath.scale(imageWidth, imageHeight, width, height);
}
private void calculateLocalScalingFactorAndOffset() {
}
// Overwrites local with master
- protected void syncLocalToMasterGeometry() {
- mLocalGeometry = getMaster().getGeometry();
+ public void syncLocalToMasterGeometry() {
+ mLocalGeometry = getGeometry();
calculateLocalScalingFactorAndOffset();
}
return r * 90;
}
- protected Matrix getLocalGeoFlipMatrix(float width, float height) {
- return mLocalGeometry.getFlipMatrix(width, height);
+ protected boolean isHeightWidthSwapped() {
+ return ((int) (getLocalRotation() / 90)) % 2 != 0;
}
protected void setLocalStraighten(float r) {
return getLocalRotation() + getLocalStraighten();
}
- protected Bitmap getMasterImage() {
- if (getMaster() == null)
- return null;
- return getMaster().mForegroundImage;
- }
-
- protected static float[] getCornersFromRect(RectF r) {
- // Order is:
- // 0------->1
- // ^ |
- // | 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
- };
- return corners;
- }
-
- // 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) {
- if (array.length < 2)
- return;
- for (int x = 0; x < array.length; x += 2) {
- array[x] = GeometryMath.clamp(array[x], imageBound.left, imageBound.right);
- array[x + 1] = GeometryMath.clamp(array[x + 1], imageBound.top, imageBound.bottom);
- }
- }
-
protected static Path drawClosedPath(Canvas canvas, Paint paint, float[] points) {
Path crop = new Path();
crop.moveTo(points[0], points[1]);
return crop;
}
- protected static void fixAspectRatio(RectF r, float w, float h) {
- float scale = Math.min(r.width() / w, r.height() / 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) {
return width * h / w;
}
super.onVisibilityChanged(changedView, visibility);
if (visibility == View.VISIBLE) {
mVisibilityGained = true;
+ MasterImage.getImage().invalidateFiltersOnly();
syncLocalToMasterGeometry();
updateScale();
gainedVisibility();
}
protected void gainedVisibility() {
- // TODO: Override this stub.
+ // Override this stub.
}
protected void lostVisibility() {
- // TODO: Override this stub.
+ // Override this stub.
}
@Override
default:
setNoAction();
}
- if (getPanelController() != null) {
- getPanelController().onNewValue(getLocalValue());
- }
invalidate();
return true;
}
protected int getLocalValue() {
- return 0; // TODO: Override this
+ return 0; // Override this
}
protected void setActionDown(float x, float y) {
mMode = MODES.NONE;
}
- @Override
- public boolean showTitle() {
- return false;
- }
+ public void saveAndSetPreset() {
+ FilterRepresentation lastAction = null;
+ HistoryItem historyItem = MasterImage.getImage().getHistory().getLast();
+ if (historyItem != null) {
+ lastAction = historyItem.getFilterRepresentation();
+ }
- protected void saveAndSetPreset() {
- ImagePreset copy = new ImagePreset(getImagePreset());
- copy.setGeometry(mLocalGeometry);
- copy.setHistoryName("Geometry");
- copy.setIsFx(false);
- setImagePreset(copy);
+ if (lastAction != null
+ && lastAction.getSerializationName().equalsIgnoreCase(
+ GeometryMetadata.SERIALIZATION_NAME)) {
+ getImagePreset().setGeometry(mLocalGeometry);
+ resetImageCaches(this);
+ } else {
+ if (mLocalGeometry.hasModifications()) {
+ ImagePreset copy = new ImagePreset(getImagePreset());
+ copy.setGeometry(mLocalGeometry);
+ // TODO: we should have multiple filter representations for each
+ // of the different geometry operations we have, otherwise we cannot
+ // differentiate them in the history/state
+ MasterImage.getImage().setPreset(copy, copy.getGeometry(), true);
+ }
+ }
+ MasterImage.getImage().notifyGeometryChange();
+ invalidate();
}
public static RectF getUntranslatedStraightenCropBounds(RectF imageRect, float straightenAngle) {
return new RectF(left, top, right, bottom);
}
- 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.drawBitmap(bitmap, m, paint);
- canvas.restore();
- }
-
- 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);
- }
-
protected RectF straightenBounds() {
RectF bounds = getUntranslatedStraightenCropBounds(getLocalPhotoBounds(),
getLocalStraighten());
- Matrix m = getGeoMatrix(bounds, true);
- m.mapRect(bounds);
- return bounds;
- }
-
- protected void drawStraighten(Canvas canvas, Paint paint) {
- RectF bounds = straightenBounds();
- canvas.save();
- canvas.drawRect(bounds, 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);
+ bounds = GeometryMath.scaleRect(bounds, scale);
+ float dx = (getWidth() / 2) - bounds.centerX();
+ float dy = (getHeight() / 2) - bounds.centerY();
+ bounds.offset(dx, dy);
return bounds;
}
- // Fails for non-90 degree
- protected void drawCrop(Canvas canvas, Paint paint) {
- RectF bounds = cropBounds();
- canvas.save();
- canvas.drawRect(bounds, paint);
- canvas.restore();
- }
-
- 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 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 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 static void drawShadows(Canvas canvas, Paint p, RectF innerBounds, RectF outerBounds,
+ protected static void drawRotatedShadows(Canvas canvas, Paint p, RectF innerBounds,
+ RectF outerBounds,
float rotation, float centerX, float centerY) {
canvas.save();
canvas.rotate(rotation, centerX, centerY);
canvas.restore();
}
+ protected void drawShadows(Canvas canvas, Paint p, RectF innerBounds) {
+ float w = getWidth();
+ float h = getHeight();
+ canvas.drawRect(0f, 0f, w, innerBounds.top, p);
+ canvas.drawRect(0f, innerBounds.top, innerBounds.left, innerBounds.bottom, p);
+ canvas.drawRect(innerBounds.right, innerBounds.top, w, innerBounds.bottom, p);
+ canvas.drawRect(0f, innerBounds.bottom, w, h, p);
+ }
+
@Override
public void onDraw(Canvas canvas) {
- if (getDirtyGeometryFlag()) {
- syncLocalToMasterGeometry();
- clearDirtyGeometryFlag();
- }
- Bitmap image = getMasterImage();
+ Bitmap image = getFiltersOnlyImage();
if (image == null) {
+ invalidate();
return;
}
mHasDrawn = true;
+
drawShape(canvas, image);
}
protected void drawShape(Canvas canvas, Bitmap image) {
// TODO: Override this stub.
}
+
+ /**
+ * Sets up inputs for buildCenteredPhotoMatrix and buildWanderingCropMatrix
+ * and returns the scale factor.
+ */
+ protected float getTransformState(RectF photo, RectF crop, float[] displayCenter) {
+ RectF photoBounds = getLocalPhotoBounds();
+ RectF cropBounds = getLocalCropBounds();
+ float scale = computeScale(getWidth(), getHeight());
+ // checks if local rotation is an odd multiple of 90.
+ if (isHeightWidthSwapped()) {
+ scale = computeScale(getHeight(), getWidth());
+ }
+ // put in screen coordinates
+ if (crop != null) {
+ crop.set(GeometryMath.scaleRect(cropBounds, scale));
+ }
+ if (photo != null) {
+ photo.set(GeometryMath.scaleRect(photoBounds, scale));
+ }
+ if (displayCenter != null && displayCenter.length >= 2) {
+ displayCenter[0] = getWidth() / 2f;
+ displayCenter[1] = getHeight() / 2f;
+ }
+ return scale;
+ }
+
+ protected RectF drawTransformed(Canvas canvas, Bitmap photo, Paint p, float[] offset) {
+ p.setARGB(255, 0, 0, 0);
+ float[] displayCenter = new float[2];
+ RectF scaledCrop = new RectF();
+ RectF scaledPhoto = new RectF();
+ float scale = getTransformState(scaledPhoto, scaledCrop, displayCenter);
+ Matrix m = GeometryMetadata.buildCenteredPhotoMatrix(scaledPhoto, scaledCrop,
+ getLocalRotation(), getLocalStraighten(), getLocalFlip(), displayCenter);
+
+ Matrix m1 = GeometryMetadata.buildWanderingCropMatrix(scaledPhoto, scaledCrop,
+ getLocalRotation(), getLocalStraighten(), getLocalFlip(), displayCenter);
+ m1.mapRect(scaledCrop);
+ Path path = new Path();
+ scaledCrop.offset(-offset[0], -offset[1]);
+ path.addRect(scaledCrop, Path.Direction.CCW);
+
+ m.preScale(scale, scale);
+ m.postTranslate(-offset[0], -offset[1]);
+ canvas.save();
+ canvas.drawBitmap(photo, m, p);
+ canvas.restore();
+
+ p.setColor(Color.WHITE);
+ p.setStyle(Style.STROKE);
+ p.setStrokeWidth(2);
+ canvas.drawPath(path, p);
+
+ p.setColor(mBackgroundColor);
+ p.setAlpha(128);
+ p.setStyle(Paint.Style.FILL);
+ drawShadows(canvas, p, scaledCrop);
+ return scaledCrop;
+ }
+
+ protected void drawTransformedCropped(Canvas canvas, Bitmap photo, Paint p) {
+ RectF photoBounds = getLocalPhotoBounds();
+ RectF cropBounds = getLocalCropBounds();
+ float imageWidth = cropBounds.width();
+ float imageHeight = cropBounds.height();
+ float scale = GeometryMath.scale(imageWidth, imageHeight, getWidth(), getHeight());
+ // checks if local rotation is an odd multiple of 90.
+ if (isHeightWidthSwapped()) {
+ scale = GeometryMath.scale(imageWidth, imageHeight, getHeight(), getWidth());
+ }
+ // put in screen coordinates
+ RectF scaledCrop = GeometryMath.scaleRect(cropBounds, scale);
+ RectF scaledPhoto = GeometryMath.scaleRect(photoBounds, scale);
+ float[] displayCenter = {
+ getWidth() / 2f, getHeight() / 2f
+ };
+ Matrix m1 = GeometryMetadata.buildWanderingCropMatrix(scaledPhoto, scaledCrop,
+ getLocalRotation(), getLocalStraighten(), getLocalFlip(), displayCenter);
+ float[] cropCenter = {
+ scaledCrop.centerX(), scaledCrop.centerY()
+ };
+ m1.mapPoints(cropCenter);
+ GeometryMetadata.concatRecenterMatrix(m1, cropCenter, displayCenter);
+ m1.preRotate(getLocalStraighten(), scaledPhoto.centerX(), scaledPhoto.centerY());
+ m1.preScale(scale, scale);
+
+ p.setARGB(255, 0, 0, 0);
+ canvas.save();
+ canvas.drawBitmap(photo, m1, p);
+ canvas.restore();
+
+ p.setColor(mBackgroundColor);
+ p.setStyle(Paint.Style.FILL);
+ scaledCrop.offset(displayCenter[0] - scaledCrop.centerX(), displayCenter[1]
+ - scaledCrop.centerY());
+ RectF display = new RectF(0, 0, getWidth(), getHeight());
+ drawRotatedShadows(canvas, p, scaledCrop, display, getLocalRotation(), getWidth() / 2,
+ getHeight() / 2);
+ }
}