diff options
Diffstat (limited to 'src/com/android/gallery3d')
19 files changed, 293 insertions, 165 deletions
diff --git a/src/com/android/gallery3d/app/OrientationManager.java b/src/com/android/gallery3d/app/OrientationManager.java index 0e033ebe4..0a644ef66 100644 --- a/src/com/android/gallery3d/app/OrientationManager.java +++ b/src/com/android/gallery3d/app/OrientationManager.java @@ -27,30 +27,16 @@ import android.view.Surface; import com.android.gallery3d.ui.OrientationSource; -import java.util.ArrayList; - public class OrientationManager implements OrientationSource { private static final String TAG = "OrientationManager"; - public interface Listener { - public void onOrientationCompensationChanged(); - } - // Orientation hysteresis amount used in rounding, in degrees private static final int ORIENTATION_HYSTERESIS = 5; private Activity mActivity; - private ArrayList<Listener> mListeners; private MyOrientationEventListener mOrientationListener; - // The degrees of the device rotated clockwise from its natural orientation. - private int mOrientation = OrientationEventListener.ORIENTATION_UNKNOWN; // If the framework orientation is locked. private boolean mOrientationLocked = false; - // The orientation compensation: if the framwork orientation is locked, the - // device orientation and the framework orientation may be different, so we - // need to rotate the UI. For example, if this value is 90, the UI - // components should be rotated 90 degrees counter-clockwise. - private int mOrientationCompensation = 0; // This is true if "Settings -> Display -> Rotation Lock" is checked. We // don't allow the orientation to be unlocked if the value is true. @@ -58,7 +44,6 @@ public class OrientationManager implements OrientationSource { public OrientationManager(Activity activity) { mActivity = activity; - mListeners = new ArrayList<Listener>(); mOrientationListener = new MyOrientationEventListener(activity); } @@ -73,18 +58,6 @@ public class OrientationManager implements OrientationSource { mOrientationListener.disable(); } - public void addListener(Listener listener) { - synchronized (mListeners) { - mListeners.add(listener); - } - } - - public void removeListener(Listener listener) { - synchronized (mListeners) { - mListeners.remove(listener); - } - } - //////////////////////////////////////////////////////////////////////////// // Orientation handling // @@ -98,15 +71,27 @@ public class OrientationManager implements OrientationSource { public void lockOrientation() { if (mOrientationLocked) return; mOrientationLocked = true; + mActivity.setRequestedOrientation(calculateCurrentScreenOrientation()); + } + + // Unlock the framework orientation, so it can change when the device + // rotates. + public void unlockOrientation() { + if (!mOrientationLocked) return; + mOrientationLocked = false; + Log.d(TAG, "unlock orientation"); + mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); + } + + private int calculateCurrentScreenOrientation() { int displayRotation = getDisplayRotation(); // Display rotation >= 180 means we need to use the REVERSE landscape/portrait boolean standard = displayRotation < 180; if (mActivity.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { - Log.d(TAG, "lock orientation to landscape"); - mActivity.setRequestedOrientation(standard + return standard ? ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE - : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); + : ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; } else { if (displayRotation == 90 || displayRotation == 270) { // If displayRotation = 90 or 270 then we are on a landscape @@ -115,53 +100,9 @@ public class OrientationManager implements OrientationSource { // to flip which portrait we pick as display rotation is counter clockwise standard = !standard; } - Log.d(TAG, "lock orientation to portrait"); - mActivity.setRequestedOrientation(standard + return standard ? ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); - } - updateCompensation(); - } - - // Unlock the framework orientation, so it can change when the device - // rotates. - public void unlockOrientation() { - if (!mOrientationLocked) return; - if (mRotationLockedSetting) return; - mOrientationLocked = false; - Log.d(TAG, "unlock orientation"); - mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); - disableCompensation(); - } - - // Calculate the compensation value and send it to listeners. - private void updateCompensation() { - if (mOrientation == OrientationEventListener.ORIENTATION_UNKNOWN) { - return; - } - - int orientationCompensation = - (mOrientation + getDisplayRotation(mActivity)) % 360; - - if (mOrientationCompensation != orientationCompensation) { - mOrientationCompensation = orientationCompensation; - notifyListeners(); - } - } - - // Make the compensation value 0 and send it to listeners. - private void disableCompensation() { - if (mOrientationCompensation != 0) { - mOrientationCompensation = 0; - notifyListeners(); - } - } - - private void notifyListeners() { - synchronized (mListeners) { - for (int i = 0, n = mListeners.size(); i < n; i++) { - mListeners.get(i).onOrientationCompensationChanged(); - } + : ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; } } @@ -177,10 +118,7 @@ public class OrientationManager implements OrientationSource { // the camera then point the camera to floor or sky, we still have // the correct orientation. if (orientation == ORIENTATION_UNKNOWN) return; - mOrientation = roundOrientation(orientation, mOrientation); - // If the framework orientation is locked, we update the - // compensation value and notify the listeners. - if (mOrientationLocked) updateCompensation(); + orientation = roundOrientation(orientation, 0); } } @@ -191,7 +129,7 @@ public class OrientationManager implements OrientationSource { @Override public int getCompensation() { - return mOrientationCompensation; + return 0; } private static int roundOrientation(int orientation, int orientationHistory) { diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java index cda0f341c..506d1ca6f 100644 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ b/src/com/android/gallery3d/app/PhotoPage.java @@ -72,7 +72,7 @@ import com.android.gallery3d.ui.SynchronizedHandler; import com.android.gallery3d.util.GalleryUtils; public class PhotoPage extends ActivityState implements - PhotoView.Listener, OrientationManager.Listener, AppBridge.Server, + PhotoView.Listener, AppBridge.Server, PhotoPageBottomControls.Delegate, GalleryActionBar.OnAlbumModeSelectedListener { private static final String TAG = "PhotoPage"; @@ -285,7 +285,6 @@ public class PhotoPage extends ActivityState implements mRootPane.addComponent(mPhotoView); mApplication = (GalleryApp) ((Activity) mActivity).getApplication(); mOrientationManager = mActivity.getOrientationManager(); - mOrientationManager.addListener(this); mActivity.getGLRoot().setOrientationSource(mOrientationManager); mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { @@ -305,7 +304,9 @@ public class PhotoPage extends ActivityState implements break; } case MSG_ON_FULL_SCREEN_CHANGED: { - mAppBridge.onFullScreenChanged(message.arg1 == 1); + if (mAppBridge != null) { + mAppBridge.onFullScreenChanged(message.arg1 == 1); + } break; } case MSG_UPDATE_ACTION_BAR: { @@ -865,11 +866,6 @@ public class PhotoPage extends ActivityState implements } @Override - public void onOrientationCompensationChanged() { - mActivity.getGLRoot().requestLayoutContentPane(); - } - - @Override protected void onBackPressed() { if (mShowDetails) { hideDetails(); @@ -1424,7 +1420,6 @@ public class PhotoPage extends ActivityState implements mScreenNailSet = null; mScreenNailItem = null; } - mOrientationManager.removeListener(this); mActivity.getGLRoot().setOrientationSource(null); if (mBottomControls != null) mBottomControls.cleanup(); diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java index 8d3790e3b..fd6d9294d 100644 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ b/src/com/android/gallery3d/filtershow/FilterShowActivity.java @@ -159,6 +159,8 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, // TODO: get those values from XML. ImageZoom.setZoomedSize(getPixelsFromDip(256)); FramedTextButton.setTextSize((int) getPixelsFromDip(14)); + FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4)); + FramedTextButton.setTriangleSize((int) getPixelsFromDip(10)); ImageShow.setTextSize((int) getPixelsFromDip(12)); ImageShow.setTextPadding((int) getPixelsFromDip(10)); ImageShow.setOriginalTextMargin((int) getPixelsFromDip(4)); @@ -201,6 +203,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, mImageFlip = (ImageFlip) findViewById(R.id.imageFlip); mImageTinyPlanet = (ImageTinyPlanet) findViewById(R.id.imageTinyPlanet); + mImageCrop.setAspectTextSize((int) getPixelsFromDip(18)); ImageCrop.setTouchTolerance((int) getPixelsFromDip(25)); mImageViews.add(mImageShow); mImageViews.add(mImageCurves); @@ -228,6 +231,11 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, mGeometryButton = (ImageButton) findViewById(R.id.geometryButton); mColorsButton = (ImageButton) findViewById(R.id.colorsButton); + mBottomPanelButtons.add(mFxButton); + mBottomPanelButtons.add(mBorderButton); + mBottomPanelButtons.add(mGeometryButton); + mBottomPanelButtons.add(mColorsButton); + mImageShow.setImageLoader(mImageLoader); mImageCurves.setImageLoader(mImageLoader); mImageCurves.setMaster(mImageShow); @@ -463,6 +471,10 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, if (mainPanelWidth == 0) { mainPanelWidth = mainViewWidth; } + int filtersPanelWidth = findViewById(R.id.filtersPanel).getWidth(); + if (mainPanelWidth < filtersPanelWidth) { + mainPanelWidth = filtersPanelWidth; + } int leftOver = mainViewWidth - mainPanelWidth - accessoryPanelWidth; if (leftOver < 0) { return -accessoryPanelWidth; @@ -704,19 +716,29 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, // TODO: use listview // TODO: load the borders straight from the filesystem int p = 0; - ImageFilter[] borders = new ImageFilter[7]; + ImageFilter[] borders = new ImageFilter[12]; borders[p++] = new ImageFilterBorder(null); Drawable npd1 = getResources().getDrawable(R.drawable.filtershow_border_4x5); borders[p++] = new ImageFilterBorder(npd1); Drawable npd2 = getResources().getDrawable(R.drawable.filtershow_border_brush); borders[p++] = new ImageFilterBorder(npd2); + Drawable npd3 = getResources().getDrawable(R.drawable.filtershow_border_grunge); + borders[p++] = new ImageFilterBorder(npd3); + Drawable npd4 = getResources().getDrawable(R.drawable.filtershow_border_sumi_e); + borders[p++] = new ImageFilterBorder(npd4); + Drawable npd5 = getResources().getDrawable(R.drawable.filtershow_border_tape); + borders[p++] = new ImageFilterBorder(npd5); borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, 0); borders[p++] = new ImageFilterParametricBorder(Color.BLACK, mImageBorderSize, mImageBorderSize); borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, 0); borders[p++] = new ImageFilterParametricBorder(Color.WHITE, mImageBorderSize, mImageBorderSize); + int creamColor = Color.argb(255, 237, 237, 227); + borders[p++] = new ImageFilterParametricBorder(creamColor, mImageBorderSize, 0); + borders[p++] = new ImageFilterParametricBorder(creamColor, mImageBorderSize, + mImageBorderSize); ImageSmallFilter previousFilter = null; for (int i = 0; i < p; i++) { @@ -779,6 +801,22 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, } } + public void disableFilterButtons() { + for (ImageButton b : mBottomPanelButtons) { + b.setEnabled(false); + b.setClickable(false); + b.setAlpha(0.4f); + } + } + + public void enableFilterButtons() { + for (ImageButton b : mBottomPanelButtons) { + b.setEnabled(true); + b.setClickable(true); + b.setAlpha(1.0f); + } + } + // ////////////////////////////////////////////////////////////////////////////// // imageState panel... @@ -860,7 +898,7 @@ public class FilterShowActivity extends Activity implements OnItemClickListener, invalidateOptionsMenu(); } - private void resetHistory() { + void resetHistory() { mNullFxFilter.onClick(mNullFxFilter); mNullBorderFilter.onClick(mNullBorderFilter); diff --git a/src/com/android/gallery3d/filtershow/PanelController.java b/src/com/android/gallery3d/filtershow/PanelController.java index 03a9d8bd5..e92c54936 100644 --- a/src/com/android/gallery3d/filtershow/PanelController.java +++ b/src/com/android/gallery3d/filtershow/PanelController.java @@ -41,7 +41,6 @@ import com.android.gallery3d.filtershow.filters.ImageFilterVibrance; import com.android.gallery3d.filtershow.filters.ImageFilterVignette; import com.android.gallery3d.filtershow.filters.ImageFilterWBalance; import com.android.gallery3d.filtershow.imageshow.ImageCrop; -import com.android.gallery3d.filtershow.imageshow.ImageGeometry; import com.android.gallery3d.filtershow.imageshow.ImageShow; import com.android.gallery3d.filtershow.presets.ImagePreset; import com.android.gallery3d.filtershow.ui.FramedTextButton; @@ -57,6 +56,7 @@ public class PanelController implements OnClickListener { private static int HORIZONTAL_MOVE = 1; private static final int ANIM_DURATION = 200; private static final String LOGTAG = "PanelController"; + private boolean mDisableFilterButtons = false; class Panel { private final View mView; @@ -158,38 +158,52 @@ public class PanelController implements OnClickListener { ImageCrop imageCrop = (ImageCrop) mCurrentImage; switch (itemId) { case R.id.crop_menu_1to1: { - button.setText(mContext.getString(R.string.aspect1to1_effect)); + String t = mContext.getString(R.string.aspect1to1_effect); + button.setText(t); imageCrop.apply(1, 1); + imageCrop.setAspectString(t); break; } case R.id.crop_menu_4to3: { - button.setText(mContext.getString(R.string.aspect4to3_effect)); + String t = mContext.getString(R.string.aspect4to3_effect); + button.setText(t); imageCrop.apply(4, 3); + imageCrop.setAspectString(t); break; } case R.id.crop_menu_3to4: { - button.setText(mContext.getString(R.string.aspect3to4_effect)); + String t = mContext.getString(R.string.aspect3to4_effect); + button.setText(t); imageCrop.apply(3, 4); + imageCrop.setAspectString(t); break; } case R.id.crop_menu_5to7: { - button.setText(mContext.getString(R.string.aspect5to7_effect)); + String t = mContext.getString(R.string.aspect5to7_effect); + button.setText(t); imageCrop.apply(5, 7); + imageCrop.setAspectString(t); break; } case R.id.crop_menu_7to5: { - button.setText(mContext.getString(R.string.aspect7to5_effect)); + String t = mContext.getString(R.string.aspect7to5_effect); + button.setText(t); imageCrop.apply(7, 5); + imageCrop.setAspectString(t); break; } case R.id.crop_menu_none: { - button.setText(mContext.getString(R.string.aspectNone_effect)); + String t = mContext.getString(R.string.aspectNone_effect); + button.setText(t); imageCrop.applyClear(); + imageCrop.setAspectString(t); break; } case R.id.crop_menu_original: { - button.setText(mContext.getString(R.string.aspectOriginal_effect)); + String t = mContext.getString(R.string.aspectOriginal_effect); + button.setText(t); imageCrop.applyOriginal(); + imageCrop.setAspectString(t); break; } } @@ -332,6 +346,10 @@ public class PanelController implements OnClickListener { mCurrentImage.resetParameter(); mCurrentImage.select(); } + if (mDisableFilterButtons) { + mActivity.enableFilterButtons(); + mDisableFilterButtons = false; + } } public boolean onBackPressed() { @@ -343,6 +361,11 @@ public class PanelController implements OnClickListener { mMasterImage.onItemClick(position); showPanel(mCurrentPanel); mCurrentImage.select(); + if (mDisableFilterButtons) { + mActivity.enableFilterButtons(); + mActivity.resetHistory(); + mDisableFilterButtons = false; + } return false; } @@ -580,6 +603,10 @@ public class PanelController implements OnClickListener { String ename = mCurrentImage.getContext().getString(R.string.tinyplanet); mUtilityPanel.setEffectName(ename); ensureFilter(ename); + if (!mDisableFilterButtons) { + mActivity.disableFilterButtons(); + mDisableFilterButtons = true; + } break; } case R.id.straightenButton: { @@ -594,7 +621,7 @@ public class PanelController implements OnClickListener { mUtilityPanel.setEffectName(ename); mUtilityPanel.setShowParameter(false); if (mCurrentImage instanceof ImageCrop && mUtilityPanel.firstTimeCropDisplayed){ - ((ImageCrop) mCurrentImage).applyOriginal(); + ((ImageCrop) mCurrentImage).applyClear(); mUtilityPanel.firstTimeCropDisplayed = false; } mUtilityPanel.showAspectButtons(); diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java index a89199602..afef58aad 100644 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java @@ -50,6 +50,7 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.Vector; +import java.util.concurrent.locks.ReentrantLock; public class ImageLoader { @@ -83,6 +84,8 @@ public class ImageLoader { private Rect mOriginalBounds = null; private static int mZoomOrientation = ORI_NORMAL; + private ReentrantLock mLoadingLock = new ReentrantLock(); + public ImageLoader(FilterShowActivity activity, Context context) { mActivity = activity; mContext = context; @@ -99,6 +102,7 @@ public class ImageLoader { } public void loadBitmap(Uri uri,int size) { + mLoadingLock.lock(); mUri = uri; mOrientation = getOrientation(mContext, uri); mOriginalBitmapSmall = loadScaledBitmap(uri, 160); @@ -108,6 +112,7 @@ public class ImageLoader { } mOriginalBitmapLarge = loadScaledBitmap(uri, size); updateBitmaps(); + mLoadingLock.unlock(); } public Uri getUri() { @@ -146,6 +151,8 @@ public class ImageLoader { } } catch (SQLiteException e){ return ExifInterface.ORIENTATION_UNDEFINED; + } catch (IllegalArgumentException e) { + return ExifInterface.ORIENTATION_UNDEFINED; } finally { Utils.closeSilently(cursor); } @@ -308,10 +315,12 @@ public class ImageLoader { } public void addListener(ImageShow imageShow) { + mLoadingLock.lock(); if (!mListeners.contains(imageShow)) { mListeners.add(imageShow); } mHiresCache.addObserver(imageShow); + mLoadingLock.unlock(); } private void warnListeners() { @@ -333,6 +342,7 @@ public class ImageLoader { // move this to a background thread. public Bitmap getScaleOneImageForPreset(ImageShow caller, ImagePreset imagePreset, Rect bounds, boolean force) { + mLoadingLock.lock(); Bitmap bmp = mZoomCache.getImage(imagePreset, bounds); if (force || bmp == null) { bmp = loadRegionBitmap(mUri, bounds); @@ -347,12 +357,14 @@ public class ImageLoader { return bmp2; } } + mLoadingLock.unlock(); return bmp; } // Caching method public Bitmap getImageForPreset(ImageShow caller, ImagePreset imagePreset, boolean hiRes) { + mLoadingLock.lock(); if (mOriginalBitmapSmall == null) { return null; } @@ -377,13 +389,16 @@ public class ImageLoader { mCache.addObserver(caller); } } + mLoadingLock.unlock(); return filteredImage; } public void resetImageForPreset(ImagePreset imagePreset, ImageShow caller) { + mLoadingLock.lock(); mHiresCache.reset(imagePreset); mCache.reset(imagePreset); mZoomCache.reset(imagePreset); + mLoadingLock.unlock(); } public void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java index d00c7e31b..7f4d5ed2a 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java @@ -130,6 +130,9 @@ public class ImageFilter implements Cloneable { } public boolean same(ImageFilter filter) { + if (filter == null) { + return false; + } if (!filter.getName().equalsIgnoreCase(getName())) { return false; } diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java index a310358ce..1d198e45c 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java @@ -51,6 +51,9 @@ public class ImageFilterBorder extends ImageFilter { if (!isBorderFilter) { return false; } + if (!(filter instanceof ImageFilterBorder)) { + return false; + } ImageFilterBorder borderFilter = (ImageFilterBorder) filter; if (mNinePatch != borderFilter.mNinePatch) { return false; diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java index bdcb0ea4e..d74a6faab 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterGeometry.java @@ -72,7 +72,7 @@ public class ImageFilterGeometry extends ImageFilter { Rect cropBounds = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); RectF crop = mGeometry.getCropBounds(bitmap); if (crop.width() > 0 && crop.height() > 0) - crop.roundOut(cropBounds); + cropBounds = GeometryMath.roundNearest(crop); Bitmap temp = null; if (mGeometry.hasSwitchedWidthHeight()) { temp = Bitmap.createBitmap(cropBounds.height(), cropBounds.width(), mConfig); diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java index 3d6954691..ade3cb26b 100644 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java +++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java @@ -56,6 +56,9 @@ public class ImageFilterParametricBorder extends ImageFilter { if (!isBorderFilter) { return false; } + if (!(filter instanceof ImageFilterParametricBorder)) { + return false; + } ImageFilterParametricBorder borderFilter = (ImageFilterParametricBorder) filter; if (borderFilter.mBorderColor != mBorderColor) { return false; diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java index 33a3f73cb..55f791820 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java +++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMath.java @@ -16,6 +16,7 @@ package com.android.gallery3d.filtershow.imageshow; +import android.graphics.Rect; import android.graphics.RectF; public class GeometryMath { @@ -99,4 +100,10 @@ public class GeometryMath { return Math.min(newWidth / oldWidth , newHeight / oldHeight); } + public static Rect roundNearest(RectF r){ + Rect q = new Rect(Math.round(r.left), Math.round(r.top), Math.round(r.right), + Math.round(r.bottom)); + return q; + } + } diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java index cf52b15ca..dffdc2449 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java +++ b/src/com/android/gallery3d/filtershow/imageshow/GeometryMetadata.java @@ -59,10 +59,8 @@ public class GeometryMetadata { if (mStraightenRotation != 0) { return true; } - Rect cropBounds = new Rect(); - mCropBounds.roundOut(cropBounds); - Rect photoBounds = new Rect(); - mPhotoBounds.roundOut(photoBounds); + Rect cropBounds = GeometryMath.roundNearest(mCropBounds); + Rect photoBounds = GeometryMath.roundNearest(mPhotoBounds); if (!cropBounds.equals(photoBounds)) { return true; } diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java index 35e8ad4b7..a352a16e7 100644 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java +++ b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java @@ -62,6 +62,17 @@ public class ImageCrop extends ImageGeometry { private static final String LOGTAG = "ImageCrop"; + private String mAspect = ""; + private int mAspectTextSize = 24; + + public void setAspectTextSize(int textSize){ + mAspectTextSize = textSize; + } + + public void setAspectString(String a){ + mAspect = a; + } + private static final Paint gPaint = new Paint(); public ImageCrop(Context context) { @@ -581,7 +592,7 @@ public class ImageCrop extends ImageGeometry { public void imageLoaded() { super.imageLoaded(); syncLocalToMasterGeometry(); - applyOriginal(); + applyClear(); invalidate(); } @@ -642,6 +653,35 @@ public class ImageCrop extends ImageGeometry { gPaint.setStyle(Paint.Style.STROKE); drawRuleOfThird(canvas, crop, gPaint); + if (mFixAspectRatio){ + float w = crop.width(); + float h = crop.height(); + float diag = (float) Math.sqrt(w*w + h*h); + + float dash_len = 20; + int num_intervals = (int) (diag / dash_len); + float [] tl = { crop.left, crop.top }; + float centX = tl[0] + w/2; + float centY = tl[1] + h/2 + 5; + float [] br = { crop.right, crop.bottom }; + float [] vec = GeometryMath.getUnitVectorFromPoints(tl, br); + + float [] counter = tl; + for (int x = 0; x < num_intervals; x++ ){ + float tempX = counter[0] + vec[0] * dash_len; + float tempY = counter[1] + vec[1] * dash_len; + if ((x % 2) == 0 && Math.abs(x - num_intervals / 2) > 2){ + canvas.drawLine(counter[0], counter[1], tempX, tempY, gPaint); + } + counter[0] = tempX; + counter[1] = tempY; + } + + gPaint.setTextAlign(Paint.Align.CENTER); + gPaint.setTextSize(mAspectTextSize); + canvas.drawText(mAspect, centX, centY, gPaint); + } + gPaint.setColor(mBorderColor); gPaint.setStrokeWidth(3); gPaint.setStyle(Paint.Style.STROKE); diff --git a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java index 8943f30de..2522c8966 100644 --- a/src/com/android/gallery3d/filtershow/presets/ImagePreset.java +++ b/src/com/android/gallery3d/filtershow/presets/ImagePreset.java @@ -181,7 +181,7 @@ public class ImagePreset { return false; } - if (mImageBorder != preset.mImageBorder) { + if (mDoApplyGeometry && mImageBorder != preset.mImageBorder) { return false; } @@ -292,7 +292,7 @@ public class ImagePreset { } } - if (mImageBorder != null) { + if (mImageBorder != null && mDoApplyGeometry) { bitmap = mImageBorder.apply(bitmap, mScaleFactor, mIsHighQuality); } diff --git a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java b/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java index 17453d070..c717b6e61 100644 --- a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java +++ b/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java @@ -20,6 +20,7 @@ import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; +import android.graphics.Path; import android.graphics.Rect; import android.util.AttributeSet; import android.widget.ImageButton; @@ -32,6 +33,10 @@ public class FramedTextButton extends ImageButton { private static int mTextSize = 24; private static int mTextPadding = 20; private static Paint gPaint = new Paint(); + private static Path gPath = new Path(); + private static int mTrianglePadding = 2; + private static int mTriangleSize = 30; + private Context mContext = null; public static void setTextSize(int value) { @@ -42,6 +47,14 @@ public class FramedTextButton extends ImageButton { mTextPadding = value; } + public static void setTrianglePadding(int value) { + mTrianglePadding = value; + } + + public static void setTriangleSize(int value) { + mTriangleSize = value; + } + public void setText(String text) { mText = text; invalidate(); @@ -84,11 +97,25 @@ public class FramedTextButton extends ImageButton { @Override public void onDraw(Canvas canvas) { - gPaint.setARGB(255, 255, 255, 255); + gPaint.setARGB(96, 255, 255, 255); gPaint.setStrokeWidth(2); gPaint.setStyle(Paint.Style.STROKE); - canvas.drawRect(mTextPadding, mTextPadding, getWidth() - mTextPadding, - getHeight() - mTextPadding, gPaint); + int w = getWidth(); + int h = getHeight(); + canvas.drawRect(mTextPadding, mTextPadding, w - mTextPadding, + h - mTextPadding, gPaint); + gPath.reset(); + gPath.moveTo(w - mTextPadding - mTrianglePadding - mTriangleSize, + h - mTextPadding - mTrianglePadding); + gPath.lineTo(w - mTextPadding - mTrianglePadding, + h - mTextPadding - mTrianglePadding - mTriangleSize); + gPath.lineTo(w - mTextPadding - mTrianglePadding, + h - mTextPadding - mTrianglePadding); + gPath.close(); + gPaint.setARGB(128, 255, 255, 255); + gPaint.setStrokeWidth(1); + gPaint.setStyle(Paint.Style.FILL_AND_STROKE); + canvas.drawPath(gPath, gPaint); if (mText != null) { gPaint.reset(); gPaint.setARGB(255, 255, 255, 255); @@ -96,8 +123,8 @@ public class FramedTextButton extends ImageButton { float textWidth = gPaint.measureText(mText); Rect bounds = new Rect(); gPaint.getTextBounds(mText, 0, mText.length(), bounds); - int x = (int) ((getWidth() - textWidth) / 2); - int y = (getHeight() + bounds.height()) / 2; + int x = (int) ((w - textWidth) / 2); + int y = (h + bounds.height()) / 2; canvas.drawText(mText, x, y, gPaint); } diff --git a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java index c4ca900e1..7b04133ce 100644 --- a/src/com/android/gallery3d/filtershow/ui/ImageCurves.java +++ b/src/com/android/gallery3d/filtershow/ui/ImageCurves.java @@ -43,6 +43,7 @@ public class ImageCurves extends ImageSlave { private boolean mDidAddPoint = false; private boolean mDidDelete = false; private ControlPoint mCurrentControlPoint = null; + private int mCurrentPick = -1; private ImagePreset mLastPreset = null; int[] redHistogram = new int[256]; int[] greenHistogram = new int[256]; @@ -186,6 +187,7 @@ public class ImageCurves extends ImageSlave { if (e.getActionMasked() == MotionEvent.ACTION_UP) { mCurrentControlPoint = null; + mCurrentPick = -1; updateCachedImage(); mDidAddPoint = false; if (mDidDelete) { @@ -205,8 +207,9 @@ public class ImageCurves extends ImageSlave { } Spline spline = getSpline(mCurrentCurveIndex); - int pick = pickControlPoint(posX, posY); + int pick = mCurrentPick; if (mCurrentControlPoint == null) { + pick = pickControlPoint(posX, posY); if (pick == -1) { mCurrentControlPoint = new ControlPoint(posX, posY); pick = spline.addPoint(mCurrentControlPoint); @@ -214,10 +217,10 @@ public class ImageCurves extends ImageSlave { } else { mCurrentControlPoint = spline.getPoint(pick); } + mCurrentPick = pick; } if (spline.isPointContained(posX, pick)) { - spline.didMovePoint(mCurrentControlPoint); spline.movePoint(pick, posX, posY); } else if (pick != -1 && spline.getNbPoints() > 2) { spline.deletePoint(pick); @@ -275,8 +278,9 @@ public class ImageCurves extends ImageSlave { max = histogram[i]; } } - float w = getWidth(); - float h = getHeight(); + float w = getWidth() - Spline.curveHandleSize(); + float h = getHeight() - Spline.curveHandleSize() / 2.0f; + float dx = Spline.curveHandleSize() / 2.0f; float wl = w / histogram.length; float wh = (0.3f * h) / max; Paint paint = new Paint(); @@ -288,12 +292,12 @@ public class ImageCurves extends ImageSlave { paint2.setStrokeWidth(6); paint2.setXfermode(new PorterDuffXfermode(mode)); gHistoPath.reset(); - gHistoPath.moveTo(0, h); + gHistoPath.moveTo(dx, h); boolean firstPointEncountered = false; float prev = 0; float last = 0; for (int i = 0; i < histogram.length; i++) { - float x = i * wl; + float x = i * wl + dx; float l = histogram[i] * wh; if (l != 0) { float v = h - (l + prev) / 2.0f; diff --git a/src/com/android/gallery3d/filtershow/ui/Spline.java b/src/com/android/gallery3d/filtershow/ui/Spline.java index dd9aac1be..83341772b 100644 --- a/src/com/android/gallery3d/filtershow/ui/Spline.java +++ b/src/com/android/gallery3d/filtershow/ui/Spline.java @@ -49,7 +49,11 @@ public class Spline { mPoints = new Vector<ControlPoint>(); for (int i = 0; i < spline.mPoints.size(); i++) { ControlPoint p = spline.mPoints.elementAt(i); - mPoints.add(new ControlPoint(p)); + ControlPoint newPoint = new ControlPoint(p); + mPoints.add(newPoint); + if (spline.mCurrentControlPoint == p) { + mCurrentControlPoint = newPoint; + } } Collections.sort(mPoints); } @@ -79,7 +83,7 @@ public class Spline { return Color.WHITE; } - public void didMovePoint(ControlPoint point) { + private void didMovePoint(ControlPoint point) { mCurrentControlPoint = point; } @@ -90,6 +94,7 @@ public class Spline { ControlPoint point = mPoints.elementAt(pick); point.x = x; point.y = y; + didMovePoint(point); } public boolean isOriginal() { @@ -121,13 +126,20 @@ public class Spline { } double[] derivatives = solveSystem(points); int start = 0; + int end = 256; if (points[0].x != 0) { start = (int) (points[0].x * 256); } + if (points[points.length - 1].x != 1) { + end = (int) (points[points.length - 1].x * 256); + } for (int i = 0; i < start; i++) { curve[i] = 1.0f - points[0].y; } - for (int i = start; i < 256; i++) { + for (int i = end; i < 256; i++) { + curve[i] = 1.0f - points[points.length - 1].y; + } + for (int i = start; i < end; i++) { ControlPoint cur = null; ControlPoint next = null; double x = i / 256.0; diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java index ea457f7fa..b7c48bf2e 100644 --- a/src/com/android/gallery3d/ui/GLRootView.java +++ b/src/com/android/gallery3d/ui/GLRootView.java @@ -392,7 +392,11 @@ public class GLRootView extends GLSurfaceView mRenderRequested = false; - if ((mFlags & FLAG_NEED_LAYOUT) != 0) layoutContentPane(); + if ((mOrientationSource != null + && mDisplayRotation != mOrientationSource.getDisplayRotation()) + || (mFlags & FLAG_NEED_LAYOUT) != 0) { + layoutContentPane(); + } mCanvas.save(GLCanvas.SAVE_FLAG_ALL); rotateCanvas(-mCompensation); diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java index 0758656a1..6dcae4ca4 100644 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ b/src/com/android/gallery3d/ui/PhotoView.java @@ -205,6 +205,7 @@ public class PhotoView extends GLView { private boolean mFullScreenCamera; private Rect mCameraRelativeFrame = new Rect(); private Rect mCameraRect = new Rect(); + private boolean mFirst = true; // [mPrevBound, mNextBound] is the range of index for all pictures in the // model, if we assume the index of current focused picture is 0. So if @@ -1406,8 +1407,9 @@ public class PhotoView extends GLView { boolean full = !mFilmMode && mPictures.get(0).isCamera() && mPositionController.isCenter() && mPositionController.isAtMinimalScale(); - if (full != mFullScreenCamera) { + if (mFirst || full != mFullScreenCamera) { mFullScreenCamera = full; + mFirst = false; mListener.onFullScreenChanged(full); if (full) mHandler.sendEmptyMessage(MSG_UNDO_BAR_FULL_CAMERA); } diff --git a/src/com/android/gallery3d/ui/TiledTexture.java b/src/com/android/gallery3d/ui/TiledTexture.java index ce3fcc617..02bde9f4f 100644 --- a/src/com/android/gallery3d/ui/TiledTexture.java +++ b/src/com/android/gallery3d/ui/TiledTexture.java @@ -55,7 +55,8 @@ public class TiledTexture implements Texture { private int mUploadIndex = 0; - private final Tile[] mTiles; + private final Tile[] mTiles; // Can be modified in different threads. + // Should be protected by "synchronized." private final int mWidth; private final int mHeight; private final RectF mSrcRect = new RectF(); @@ -91,7 +92,7 @@ public class TiledTexture implements Texture { synchronized (this) { long now = SystemClock.uptimeMillis(); long dueTime = now + UPLOAD_TILE_LIMIT; - while(now < dueTime && !deque.isEmpty()) { + while (now < dueTime && !deque.isEmpty()) { TiledTexture t = deque.peekFirst(); if (t.uploadNextTile(canvas)) { deque.removeFirst(); @@ -130,7 +131,7 @@ public class TiledTexture implements Texture { int x = BORDER_SIZE - offsetX; int y = BORDER_SIZE - offsetY; int r = bitmap.getWidth() + x; - int b = bitmap.getHeight() + y ; + int b = bitmap.getHeight() + y; sCanvas.drawBitmap(bitmap, x, y, sBitmapPaint); bitmap = null; @@ -171,19 +172,21 @@ public class TiledTexture implements Texture { private boolean uploadNextTile(GLCanvas canvas) { if (mUploadIndex == mTiles.length) return true; - Tile next = mTiles[mUploadIndex++]; + synchronized (mTiles) { + Tile next = mTiles[mUploadIndex++]; - // Make sure tile has not already been recycled by the time - // this is called (race condition in onGLIdle) - if (next.bitmap != null) { - boolean hasBeenLoad = next.isLoaded(); - next.updateContent(canvas); + // Make sure tile has not already been recycled by the time + // this is called (race condition in onGLIdle) + if (next.bitmap != null) { + boolean hasBeenLoad = next.isLoaded(); + next.updateContent(canvas); - // It will take some time for a texture to be drawn for the first - // time. When scrolling, we need to draw several tiles on the screen - // at the same time. It may cause a UI jank even these textures has - // been uploaded. - if (!hasBeenLoad) next.draw(canvas, 0, 0); + // It will take some time for a texture to be drawn for the first + // time. When scrolling, we need to draw several tiles on the screen + // at the same time. It may cause a UI jank even these textures has + // been uploaded. + if (!hasBeenLoad) next.draw(canvas, 0, 0); + } } return mUploadIndex == mTiles.length; } @@ -212,9 +215,12 @@ public class TiledTexture implements Texture { return mUploadIndex == mTiles.length; } + // Can be called in UI thread. public void recycle() { - for (int i = 0, n = mTiles.length; i < n; ++i) { - freeTile(mTiles[i]); + synchronized (mTiles) { + for (int i = 0, n = mTiles.length; i < n; ++i) { + freeTile(mTiles[i]); + } } } @@ -263,15 +269,17 @@ public class TiledTexture implements Texture { int x, int y, int width, int height) { RectF src = mSrcRect; RectF dest = mDestRect; - float scaleX = (float) width / mWidth ; + float scaleX = (float) width / mWidth; float scaleY = (float) height / mHeight; - for (int i = 0, n = mTiles.length; i < n; ++i) { - Tile t = mTiles[i]; - src.set(0, 0, t.contentWidth, t.contentHeight); - src.offset(t.offsetX, t.offsetY); - mapRect(dest, src, 0, 0, x, y, scaleX, scaleY); - src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); - canvas.drawMixed(t, color, ratio, mSrcRect, mDestRect); + synchronized (mTiles) { + for (int i = 0, n = mTiles.length; i < n; ++i) { + Tile t = mTiles[i]; + src.set(0, 0, t.contentWidth, t.contentHeight); + src.offset(t.offsetX, t.offsetY); + mapRect(dest, src, 0, 0, x, y, scaleX, scaleY); + src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); + canvas.drawMixed(t, color, ratio, mSrcRect, mDestRect); + } } } @@ -280,15 +288,17 @@ public class TiledTexture implements Texture { public void draw(GLCanvas canvas, int x, int y, int width, int height) { RectF src = mSrcRect; RectF dest = mDestRect; - float scaleX = (float) width / mWidth ; + float scaleX = (float) width / mWidth; float scaleY = (float) height / mHeight; - for (int i = 0, n = mTiles.length; i < n; ++i) { - Tile t = mTiles[i]; - src.set(0, 0, t.contentWidth, t.contentHeight); - src.offset(t.offsetX, t.offsetY); - mapRect(dest, src, 0, 0, x, y, scaleX, scaleY); - src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); - canvas.drawTexture(t, mSrcRect, mDestRect); + synchronized (mTiles) { + for (int i = 0, n = mTiles.length; i < n; ++i) { + Tile t = mTiles[i]; + src.set(0, 0, t.contentWidth, t.contentHeight); + src.offset(t.offsetX, t.offsetY); + mapRect(dest, src, 0, 0, x, y, scaleX, scaleY); + src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); + canvas.drawTexture(t, mSrcRect, mDestRect); + } } } @@ -303,14 +313,16 @@ public class TiledTexture implements Texture { float scaleX = target.width() / source.width(); float scaleY = target.height() / source.height(); - for (int i = 0, n = mTiles.length; i < n; ++i) { - Tile t = mTiles[i]; - src.set(0, 0, t.contentWidth, t.contentHeight); - src.offset(t.offsetX, t.offsetY); - if (!src.intersect(source)) continue; - mapRect(dest, src, x0, y0, x, y, scaleX, scaleY); - src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); - canvas.drawTexture(t, src, dest); + synchronized (mTiles) { + for (int i = 0, n = mTiles.length; i < n; ++i) { + Tile t = mTiles[i]; + src.set(0, 0, t.contentWidth, t.contentHeight); + src.offset(t.offsetX, t.offsetY); + if (!src.intersect(source)) continue; + mapRect(dest, src, x0, y0, x, y, scaleX, scaleY); + src.offset(BORDER_SIZE - t.offsetX, BORDER_SIZE - t.offsetY); + canvas.drawTexture(t, src, dest); + } } } |