diff options
author | Sascha Haeberling <haeberling@google.com> | 2013-08-06 11:43:02 -0700 |
---|---|---|
committer | Sascha Haeberling <haeberling@google.com> | 2013-08-06 11:43:02 -0700 |
commit | 8e963a5a6016d246184ed65906f9d103e92b17e2 (patch) | |
tree | 02eb244ea4a20d9aa8e43916a40b876be8935d11 /src/com | |
parent | 4fc90b07dcf316c7ce6c5313af8202e84bc85603 (diff) | |
download | android_packages_apps_Snap-8e963a5a6016d246184ed65906f9d103e92b17e2.tar.gz android_packages_apps_Snap-8e963a5a6016d246184ed65906f9d103e92b17e2.tar.bz2 android_packages_apps_Snap-8e963a5a6016d246184ed65906f9d103e92b17e2.zip |
This removes all non-Camera stuff from Camera2.
Note: Camera2 is a clone of Gallery2 right now.
Note 2: I will bring .mk files back later.
Change-Id: Ida958654296f5ebaacb6bb0ff59d52a7c37ce6fc
Diffstat (limited to 'src/com')
512 files changed, 948 insertions, 82252 deletions
diff --git a/src/com/android/camera/AndroidCameraManagerImpl.java b/src/com/android/camera/AndroidCameraManagerImpl.java index 897aa9252..667630609 100644 --- a/src/com/android/camera/AndroidCameraManagerImpl.java +++ b/src/com/android/camera/AndroidCameraManagerImpl.java @@ -18,6 +18,8 @@ package com.android.camera; import static com.android.camera.Util.Assert; +import java.io.IOException; + import android.annotation.TargetApi; import android.graphics.SurfaceTexture; import android.hardware.Camera; @@ -37,9 +39,7 @@ import android.os.Message; import android.util.Log; import android.view.SurfaceHolder; -import com.android.gallery3d.common.ApiHelper; - -import java.io.IOException; +import com.android.camera.support.common.ApiHelper; /** * A class to implement {@link CameraManager} of the Android camera framework. diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java index 7f71d5f31..e110327d8 100644 --- a/src/com/android/camera/CameraActivity.java +++ b/src/com/android/camera/CameraActivity.java @@ -47,14 +47,14 @@ import com.android.camera.data.FixedFirstDataAdapter; import com.android.camera.data.FixedLastDataAdapter; import com.android.camera.data.LocalData; import com.android.camera.data.LocalDataAdapter; +import com.android.camera.support.common.ApiHelper; import com.android.camera.ui.CameraSwitcher; import com.android.camera.ui.CameraSwitcher.CameraSwitchListener; import com.android.camera.ui.FilmStripView; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.RefocusHelper; -import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper; +import com.android.camera.util.PhotoSphereHelper; +import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper; +import com.android.camera.util.RefocusHelper; +import com.android.camera2.R; public class CameraActivity extends Activity implements CameraSwitchListener { @@ -279,7 +279,6 @@ public class CameraActivity extends Activity mCameraPreviewData = new CameraPreviewData(rootLayout, FilmStripView.ImageData.SIZE_FULL, FilmStripView.ImageData.SIZE_FULL); - // Put a CameraPreviewData at the first position. mWrappedDataAdapter = new FixedFirstDataAdapter( new CameraDataAdapter(new ColorDrawable( getResources().getColor(R.color.photo_placeholder))), @@ -297,25 +296,6 @@ public class CameraActivity extends Activity mOrientationListener = new MyOrientationEventListener(this); mMainHandler = new Handler(getMainLooper()); bindMediaSaveService(); - - if (!mSecureCamera) { - mDataAdapter = mWrappedDataAdapter; - mDataAdapter.requestLoad(getContentResolver()); - } else { - // Put a lock placeholder as the last image by setting its date to 0. - ImageView v = (ImageView) getLayoutInflater().inflate( - R.layout.secure_album_placeholder, null); - mDataAdapter = new FixedLastDataAdapter( - mWrappedDataAdapter, - new LocalData.LocalViewData( - v, - v.getDrawable().getIntrinsicWidth(), - v.getDrawable().getIntrinsicHeight(), - 0, 0)); - // Flush out all the original data. - mDataAdapter.flush(); - } - mFilmStripView.setDataAdapter(mDataAdapter); } private void setRotationAnimation() { @@ -363,6 +343,25 @@ public class CameraActivity extends Activity public void onStart() { super.onStart(); + // The loading is done in background and will update the filmstrip later. + if (!mSecureCamera) { + mDataAdapter = mWrappedDataAdapter; + mDataAdapter.requestLoad(getContentResolver()); + mFilmStripView.setDataAdapter(mDataAdapter); + } else { + // Put a lock placeholder as the last image by setting its date to 0. + ImageView v = (ImageView) getLayoutInflater().inflate( + R.layout.secure_album_placeholder, null); + mDataAdapter = new FixedLastDataAdapter( + mWrappedDataAdapter, + new LocalData.LocalViewData( + v, + v.getDrawable().getIntrinsicWidth(), + v.getDrawable().getIntrinsicHeight(), + 0, 0)); + // Flush out all the original data. + mDataAdapter.flush(); + } mPanoramaViewHelper.onStart(); } @@ -497,7 +496,7 @@ public class CameraActivity extends Activity mCurrentModule = new PhotoModule(); break; case CameraSwitcher.LIGHTCYCLE_MODULE_INDEX: - mCurrentModule = LightCycleHelper.createPanoramaModule(); + mCurrentModule = PhotoSphereHelper.createPanoramaModule(); break; case CameraSwitcher.REFOCUS_MODULE_INDEX: mCurrentModule = RefocusHelper.createRefocusModule(); diff --git a/src/com/android/camera/CameraManager.java b/src/com/android/camera/CameraManager.java index 90a838ca6..fd9b2ced3 100644 --- a/src/com/android/camera/CameraManager.java +++ b/src/com/android/camera/CameraManager.java @@ -16,6 +16,8 @@ package com.android.camera; +import java.io.IOException; + import android.annotation.TargetApi; import android.graphics.SurfaceTexture; import android.hardware.Camera; @@ -25,9 +27,7 @@ import android.hardware.Camera.Parameters; import android.os.Handler; import android.view.SurfaceHolder; -import com.android.gallery3d.common.ApiHelper; - -import java.io.IOException; +import com.android.camera.support.common.ApiHelper; /** * An interface which provides possible camera device operations. diff --git a/src/com/android/camera/CameraPreference.java b/src/com/android/camera/CameraPreference.java index 5ddd86dbc..407c1408c 100644 --- a/src/com/android/camera/CameraPreference.java +++ b/src/com/android/camera/CameraPreference.java @@ -21,7 +21,7 @@ import android.content.SharedPreferences; import android.content.res.TypedArray; import android.util.AttributeSet; -import com.android.gallery3d.R; +import com.android.camera2.R; /** * The base class of all Preferences used in Camera. The preferences can be diff --git a/src/com/android/camera/CameraScreenNail.java b/src/com/android/camera/CameraScreenNail.java index 993a7d336..9fe2c067a 100644 --- a/src/com/android/camera/CameraScreenNail.java +++ b/src/com/android/camera/CameraScreenNail.java @@ -16,16 +16,16 @@ package com.android.camera; +import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.content.Context; import android.graphics.SurfaceTexture; import android.opengl.Matrix; import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.SurfaceTextureScreenNail; +import com.android.camera.support.common.ApiHelper; +import com.android.camera.support.glrenderer.GLCanvas; +import com.android.camera.support.glrenderer.RawTexture; +import com.android.camera.support.ui.SurfaceTextureScreenNail; /* * This is a ScreenNail which can display camera's preview. @@ -313,11 +313,13 @@ public class CameraScreenNail extends SurfaceTextureScreenNail { Matrix.translateM(matrix, 0, -.5f, -.5f, 0); } - public void directDraw(GLCanvas canvas, int x, int y, int width, int height) { + @SuppressLint("WrongCall") + public void directDraw(GLCanvas canvas, int x, int y, int width, int height) { DrawClient draw; synchronized (mLock) { draw = mDraw; } + // TODO: Should this call draw or onDraw? draw.onDraw(canvas, x, y, width, height); } diff --git a/src/com/android/camera/CameraSettings.java b/src/com/android/camera/CameraSettings.java index 3558014cc..9e01d5c9b 100644 --- a/src/com/android/camera/CameraSettings.java +++ b/src/com/android/camera/CameraSettings.java @@ -16,7 +16,6 @@ package com.android.camera; -import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.content.SharedPreferences; @@ -30,8 +29,8 @@ import android.media.CamcorderProfile; import android.util.FloatMath; import android.util.Log; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; +import com.android.camera2.R; +import com.android.camera.support.common.ApiHelper; import java.util.ArrayList; import java.util.List; diff --git a/src/com/android/camera/CaptureAnimManager.java b/src/com/android/camera/CaptureAnimManager.java index 6e8092566..3510d7528 100644 --- a/src/com/android/camera/CaptureAnimManager.java +++ b/src/com/android/camera/CaptureAnimManager.java @@ -23,10 +23,10 @@ import android.os.SystemClock; import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; -import com.android.gallery3d.R; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.NinePatchTexture; -import com.android.gallery3d.glrenderer.RawTexture; +import com.android.camera.support.glrenderer.GLCanvas; +import com.android.camera.support.glrenderer.NinePatchTexture; +import com.android.camera.support.glrenderer.RawTexture; +import com.android.camera2.R; /** * Class to handle the capture animation. diff --git a/src/com/android/camera/ComboPreferences.java b/src/com/android/camera/ComboPreferences.java index e17e47aa8..142f6984c 100644 --- a/src/com/android/camera/ComboPreferences.java +++ b/src/com/android/camera/ComboPreferences.java @@ -22,13 +22,13 @@ import android.content.SharedPreferences; import android.content.SharedPreferences.OnSharedPreferenceChangeListener; import android.preference.PreferenceManager; -import com.android.gallery3d.util.UsageStatistics; - import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import com.android.camera.util.UsageStatistics; + public class ComboPreferences implements SharedPreferences, OnSharedPreferenceChangeListener { diff --git a/src/com/android/camera/CountDownTimerPreference.java b/src/com/android/camera/CountDownTimerPreference.java index 9c66dda8c..9a7e44bfb 100644 --- a/src/com/android/camera/CountDownTimerPreference.java +++ b/src/com/android/camera/CountDownTimerPreference.java @@ -19,7 +19,7 @@ package com.android.camera; import android.content.Context; import android.util.AttributeSet; -import com.android.gallery3d.R; +import com.android.camera2.R; public class CountDownTimerPreference extends ListPreference { private static final int[] DURATIONS = { diff --git a/src/com/android/camera/EffectsRecorder.java b/src/com/android/camera/EffectsRecorder.java index 4bf8d411e..901226364 100644 --- a/src/com/android/camera/EffectsRecorder.java +++ b/src/com/android/camera/EffectsRecorder.java @@ -16,6 +16,13 @@ package com.android.camera; +import java.io.FileDescriptor; +import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + import android.annotation.TargetApi; import android.content.Context; import android.graphics.SurfaceTexture; @@ -26,15 +33,8 @@ import android.os.Handler; import android.os.Looper; import android.util.Log; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.io.FileDescriptor; -import java.io.Serializable; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; +import com.android.camera.support.common.ApiHelper; +import com.android.camera2.R; /** diff --git a/src/com/android/camera/FocusOverlayManager.java b/src/com/android/camera/FocusOverlayManager.java index 8bcb52fe5..7a9e1dd6d 100644 --- a/src/com/android/camera/FocusOverlayManager.java +++ b/src/com/android/camera/FocusOverlayManager.java @@ -16,6 +16,9 @@ package com.android.camera; +import java.util.ArrayList; +import java.util.List; + import android.annotation.TargetApi; import android.graphics.Matrix; import android.graphics.Rect; @@ -27,10 +30,7 @@ import android.os.Looper; import android.os.Message; import android.util.Log; -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; -import java.util.List; +import com.android.camera.support.common.ApiHelper; /* A class that handles everything about focus in still picture mode. * This also handles the metering area because it is the same as focus area. diff --git a/src/com/android/camera/IconListPreference.java b/src/com/android/camera/IconListPreference.java index e5f75d3a5..97e729d0e 100644 --- a/src/com/android/camera/IconListPreference.java +++ b/src/com/android/camera/IconListPreference.java @@ -16,14 +16,14 @@ package com.android.camera; +import java.util.List; + import android.content.Context; import android.content.res.Resources; import android.content.res.TypedArray; import android.util.AttributeSet; -import com.android.gallery3d.R; - -import java.util.List; +import com.android.camera2.R; /** A {@code ListPreference} where each entry has a corresponding icon. */ public class IconListPreference extends ListPreference { diff --git a/src/com/android/camera/ListPreference.java b/src/com/android/camera/ListPreference.java index 38866de9d..f593b35e5 100644 --- a/src/com/android/camera/ListPreference.java +++ b/src/com/android/camera/ListPreference.java @@ -16,6 +16,9 @@ package com.android.camera; +import java.util.ArrayList; +import java.util.List; + import android.content.Context; import android.content.SharedPreferences; import android.content.res.TypedArray; @@ -23,10 +26,7 @@ import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.List; +import com.android.camera2.R; /** * A type of <code>CameraPreference</code> whose number of possible values diff --git a/src/com/android/camera/OnScreenHint.java b/src/com/android/camera/OnScreenHint.java index 4d7fa7088..f47d9d8cb 100644 --- a/src/com/android/camera/OnScreenHint.java +++ b/src/com/android/camera/OnScreenHint.java @@ -25,7 +25,7 @@ import android.view.View; import android.view.WindowManager; import android.widget.TextView; -import com.android.gallery3d.R; +import com.android.camera2.R; /** * A on-screen hint is a view containing a little message for the user and will diff --git a/src/com/android/camera/OnScreenIndicators.java b/src/com/android/camera/OnScreenIndicators.java index 77c8fafc0..1ddea1c17 100644 --- a/src/com/android/camera/OnScreenIndicators.java +++ b/src/com/android/camera/OnScreenIndicators.java @@ -23,7 +23,7 @@ import android.hardware.Camera.Parameters; import android.view.View; import android.widget.ImageView; -import com.android.gallery3d.R; +import com.android.camera2.R; /** * The on-screen indicators of the pie menu button. They show the camera diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java index 6c1e2d085..6f47e136a 100644 --- a/src/com/android/camera/PhotoMenu.java +++ b/src/com/android/camera/PhotoMenu.java @@ -16,6 +16,8 @@ package com.android.camera; +import java.util.Locale; + import android.content.res.Resources; import android.hardware.Camera.Parameters; @@ -25,9 +27,7 @@ import com.android.camera.ui.ListPrefSettingPopup; import com.android.camera.ui.PieItem; import com.android.camera.ui.PieItem.OnClickListener; import com.android.camera.ui.PieRenderer; -import com.android.gallery3d.R; - -import java.util.Locale; +import com.android.camera2.R; public class PhotoMenu extends PieController implements CountdownTimerPopup.Listener, diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java index c65a49ef9..89833b3b5 100644 --- a/src/com/android/camera/PhotoModule.java +++ b/src/com/android/camera/PhotoModule.java @@ -16,6 +16,15 @@ package com.android.camera; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Formatter; +import java.util.List; + import android.annotation.TargetApi; import android.app.Activity; import android.content.ContentProviderClient; @@ -56,26 +65,16 @@ import com.android.camera.CameraManager.CameraAFMoveCallback; import com.android.camera.CameraManager.CameraPictureCallback; import com.android.camera.CameraManager.CameraProxy; import com.android.camera.CameraManager.CameraShutterCallback; +import com.android.camera.support.common.ApiHelper; +import com.android.camera.support.filtershow.crop.CropExtras; import com.android.camera.ui.CountDownView.OnCountDownFinishedListener; import com.android.camera.ui.PopupManager; import com.android.camera.ui.RotateTextToast; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; +import com.android.camera.util.UsageStatistics; +import com.android.camera2.R; import com.android.gallery3d.exif.ExifInterface; import com.android.gallery3d.exif.ExifTag; import com.android.gallery3d.exif.Rational; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.filtershow.crop.CropExtras; -import com.android.gallery3d.util.UsageStatistics; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Formatter; -import java.util.List; public class PhotoModule implements CameraModule, @@ -1131,7 +1130,9 @@ public class PhotoModule newExtras.putBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, true); } - Intent cropIntent = new Intent(CropActivity.CROP_ACTION); + // TODO ... + final String CROP_ACTION = "com.android.camera.action.CROP"; + Intent cropIntent = new Intent(CROP_ACTION); cropIntent.setData(tempUri); cropIntent.putExtras(newExtras); diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java index d58ed7f13..e10570a08 100644 --- a/src/com/android/camera/PhotoUI.java +++ b/src/com/android/camera/PhotoUI.java @@ -17,6 +17,8 @@ package com.android.camera; +import java.util.List; + import android.animation.Animator; import android.animation.ObjectAnimator; import android.animation.ValueAnimator; @@ -26,7 +28,6 @@ import android.graphics.Matrix; import android.graphics.SurfaceTexture; import android.hardware.Camera; import android.hardware.Camera.Face; -import android.hardware.Camera.FaceDetectionListener; import android.hardware.Camera.Size; import android.os.Handler; import android.os.Message; @@ -57,11 +58,9 @@ import com.android.camera.ui.PieRenderer; import com.android.camera.ui.PieRenderer.PieListener; import com.android.camera.ui.RenderOverlay; import com.android.camera.ui.ZoomRenderer; -import com.android.gallery3d.R; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; -import java.util.List; - public class PhotoUI implements PieListener, PreviewGestures.SingleTapListener, FocusUI, TextureView.SurfaceTextureListener, diff --git a/src/com/android/camera/PreviewFrameLayout.java b/src/com/android/camera/PreviewFrameLayout.java index 03ef91c60..cc2d28099 100644 --- a/src/com/android/camera/PreviewFrameLayout.java +++ b/src/com/android/camera/PreviewFrameLayout.java @@ -16,17 +16,15 @@ package com.android.camera; +import android.annotation.SuppressLint; import android.content.Context; -import android.content.res.Configuration; import android.util.AttributeSet; import android.view.View; -import android.view.ViewStub; import android.widget.RelativeLayout; - +import com.android.camera.support.common.ApiHelper; import com.android.camera.ui.LayoutChangeHelper; import com.android.camera.ui.LayoutChangeNotifier; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; +import com.android.camera2.R; /** * A layout which handles the preview aspect ratio. @@ -128,9 +126,11 @@ public class PreviewFrameLayout extends RelativeLayout implements LayoutChangeNo mLayoutChangeHelper.setOnLayoutChangeListener(listener); } - @Override + @SuppressLint("WrongCall") + @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); + // TODO: Suspicious call! mLayoutChangeHelper.onLayout(changed, l, t, r, b); } } diff --git a/src/com/android/camera/RotateDialogController.java b/src/com/android/camera/RotateDialogController.java index 5d5e5e70f..45163f196 100644 --- a/src/com/android/camera/RotateDialogController.java +++ b/src/com/android/camera/RotateDialogController.java @@ -28,7 +28,7 @@ import android.widget.TextView; import com.android.camera.ui.Rotatable; import com.android.camera.ui.RotateLayout; -import com.android.gallery3d.R; +import com.android.camera2.R; public class RotateDialogController implements Rotatable { diff --git a/src/com/android/camera/SoundClips.java b/src/com/android/camera/SoundClips.java index 8155c03dc..b5cfeddaa 100644 --- a/src/com/android/camera/SoundClips.java +++ b/src/com/android/camera/SoundClips.java @@ -23,7 +23,7 @@ import android.media.MediaActionSound; import android.media.SoundPool; import android.util.Log; -import com.android.gallery3d.R; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; /* diff --git a/src/com/android/camera/StaticBitmapScreenNail.java b/src/com/android/camera/StaticBitmapScreenNail.java index 10788c0fb..91ac35c31 100644 --- a/src/com/android/camera/StaticBitmapScreenNail.java +++ b/src/com/android/camera/StaticBitmapScreenNail.java @@ -18,7 +18,7 @@ package com.android.camera; import android.graphics.Bitmap; -import com.android.gallery3d.ui.BitmapScreenNail; +import com.android.camera.support.ui.BitmapScreenNail; public class StaticBitmapScreenNail extends BitmapScreenNail { public StaticBitmapScreenNail(Bitmap bitmap) { diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java index ba995edef..4e5a7dd0e 100644 --- a/src/com/android/camera/Storage.java +++ b/src/com/android/camera/Storage.java @@ -16,6 +16,9 @@ package com.android.camera; +import java.io.File; +import java.io.FileOutputStream; + import android.annotation.TargetApi; import android.content.ContentResolver; import android.content.ContentValues; @@ -29,12 +32,9 @@ import android.provider.MediaStore.Images.ImageColumns; import android.provider.MediaStore.MediaColumns; import android.util.Log; -import com.android.gallery3d.common.ApiHelper; +import com.android.camera.support.common.ApiHelper; import com.android.gallery3d.exif.ExifInterface; -import java.io.File; -import java.io.FileOutputStream; - public class Storage { private static final String TAG = "CameraStorage"; diff --git a/src/com/android/camera/SwitchAnimManager.java b/src/com/android/camera/SwitchAnimManager.java index 6ec88223e..20a4bfd97 100644 --- a/src/com/android/camera/SwitchAnimManager.java +++ b/src/com/android/camera/SwitchAnimManager.java @@ -19,8 +19,8 @@ package com.android.camera; import android.os.SystemClock; import android.util.Log; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; +import com.android.camera.support.glrenderer.GLCanvas; +import com.android.camera.support.glrenderer.RawTexture; /** * Class to handle the animation when switching between back and front cameras. diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java index ccc2d9079..43ad22e17 100644 --- a/src/com/android/camera/Util.java +++ b/src/com/android/camera/Util.java @@ -16,6 +16,15 @@ package com.android.camera; +import java.io.Closeable; +import java.io.IOException; +import java.lang.reflect.Method; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.StringTokenizer; + +import com.android.camera2.R; import android.annotation.TargetApi; import android.app.Activity; import android.app.AlertDialog; @@ -38,7 +47,6 @@ import android.hardware.Camera.Size; import android.location.Location; import android.net.Uri; import android.os.Build; -import android.os.Handler; import android.os.ParcelFileDescriptor; import android.telephony.TelephonyManager; import android.util.DisplayMetrics; @@ -54,17 +62,7 @@ import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.Toast; -import com.android.gallery3d.R; -import com.android.gallery3d.app.MovieActivity; -import com.android.gallery3d.common.ApiHelper; - -import java.io.Closeable; -import java.io.IOException; -import java.lang.reflect.Method; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.StringTokenizer; +import com.android.camera.support.common.ApiHelper; /** * Collection of utility functions used in this package. @@ -90,6 +88,9 @@ public class Util { public static final String SCENE_MODE_HDR = "hdr"; public static final String TRUE = "true"; public static final String FALSE = "false"; + + /** Has to by in sync with the receiving MovieActivity. */ + public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back"; public static boolean isSupported(String value, List<String> supported) { return supported == null ? false : supported.indexOf(value) >= 0; @@ -794,7 +795,7 @@ public class Util { Intent intent = new Intent(Intent.ACTION_VIEW) .setDataAndType(uri, "video/*") .putExtra(Intent.EXTRA_TITLE, title) - .putExtra(MovieActivity.KEY_TREAT_UP_AS_BACK, true); + .putExtra(KEY_TREAT_UP_AS_BACK, true); context.startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(context, context.getString(R.string.video_err), diff --git a/src/com/android/camera/VideoMenu.java b/src/com/android/camera/VideoMenu.java index da0bde10e..f0c7db272 100644 --- a/src/com/android/camera/VideoMenu.java +++ b/src/com/android/camera/VideoMenu.java @@ -16,7 +16,6 @@ package com.android.camera; -import android.app.Activity; import android.content.Context; import android.view.LayoutInflater; @@ -27,7 +26,7 @@ import com.android.camera.ui.PieItem; import com.android.camera.ui.PieItem.OnClickListener; import com.android.camera.ui.PieRenderer; import com.android.camera.ui.TimeIntervalPopup; -import com.android.gallery3d.R; +import com.android.camera2.R; public class VideoMenu extends PieController implements MoreSettingPopup.Listener, diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java index 956890e5e..aa085af0e 100644 --- a/src/com/android/camera/VideoModule.java +++ b/src/com/android/camera/VideoModule.java @@ -16,6 +16,13 @@ package com.android.camera; +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Iterator; +import java.util.List; + import android.annotation.TargetApi; import android.app.Activity; import android.content.ActivityNotFoundException; @@ -56,21 +63,14 @@ import android.widget.Toast; import com.android.camera.CameraManager.CameraPictureCallback; import com.android.camera.CameraManager.CameraProxy; +import com.android.camera.support.app.OrientationManager; +import com.android.camera.support.util.AccessibilityUtils; import com.android.camera.ui.PopupManager; import com.android.camera.ui.RotateTextToast; -import com.android.gallery3d.R; -import com.android.gallery3d.app.OrientationManager; +import com.android.camera.util.UsageStatistics; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.util.AccessibilityUtils; -import com.android.gallery3d.util.UsageStatistics; - -import java.io.File; -import java.io.IOException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Iterator; -import java.util.List; public class VideoModule implements CameraModule, VideoController, diff --git a/src/com/android/camera/VideoUI.java b/src/com/android/camera/VideoUI.java index 551b72596..06c9795f3 100644 --- a/src/com/android/camera/VideoUI.java +++ b/src/com/android/camera/VideoUI.java @@ -16,6 +16,8 @@ package com.android.camera; +import java.util.List; + import android.graphics.Bitmap; import android.graphics.Matrix; import android.graphics.SurfaceTexture; @@ -48,11 +50,9 @@ import com.android.camera.ui.PieRenderer; import com.android.camera.ui.RenderOverlay; import com.android.camera.ui.RotateLayout; import com.android.camera.ui.ZoomRenderer; -import com.android.gallery3d.R; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; -import java.util.List; - public class VideoUI implements PieRenderer.PieListener, PreviewGestures.SingleTapListener, CameraRootView.MyDisplayListener, diff --git a/src/com/android/camera/app/CameraApp.java b/src/com/android/camera/app/CameraApp.java new file mode 100644 index 000000000..f020a8441 --- /dev/null +++ b/src/com/android/camera/app/CameraApp.java @@ -0,0 +1,11 @@ +package com.android.camera.app; + +import android.app.Application; + +public class CameraApp extends Application { + @Override + public void onCreate() { + super.onCreate(); + com.android.camera.Util.initialize(this); + } +} diff --git a/src/com/android/camera/data/CameraDataAdapter.java b/src/com/android/camera/data/CameraDataAdapter.java index 3605f7190..e384b1512 100644 --- a/src/com/android/camera/data/CameraDataAdapter.java +++ b/src/com/android/camera/data/CameraDataAdapter.java @@ -16,6 +16,11 @@ package com.android.camera.data; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; @@ -28,12 +33,6 @@ import android.view.View; import com.android.camera.Storage; import com.android.camera.ui.FilmStripView.ImageData; -import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; /** * A {@link LocalDataAdapter} that provides data in the camera folder. diff --git a/src/com/android/camera/data/LocalData.java b/src/com/android/camera/data/LocalData.java index efccfe332..eb2212c2a 100644 --- a/src/com/android/camera/data/LocalData.java +++ b/src/com/android/camera/data/LocalData.java @@ -16,6 +16,10 @@ package com.android.camera.data; +import java.io.File; +import java.util.Comparator; +import java.util.Date; + import android.content.ContentResolver; import android.content.Context; import android.database.Cursor; @@ -42,13 +46,9 @@ import android.widget.ImageView; import com.android.camera.Util; import com.android.camera.data.PanoramaMetadataLoader.PanoramaMetadataCallback; import com.android.camera.ui.FilmStripView; -import com.android.gallery3d.R; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; -import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper; - -import java.io.File; -import java.util.Comparator; -import java.util.Date; +import com.android.camera.util.PhotoSphereHelper.PanoramaMetadata; +import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper; +import com.android.camera2.R; /** * An abstract interface that represents the local media data. Also implements @@ -101,16 +101,10 @@ public interface LocalData extends FilmStripView.ImageData { // Implementations below. /** -<<<<<<< HEAD * A base class for all the local media files. The bitmap is loaded in * background thread. Subclasses should implement their own background * loading thread by subclassing BitmapLoadTask and overriding * doInBackground() to return a bitmap. -======= - * A base class for all the local media files. The bitmap is loaded in background - * thread. Subclasses should implement their own background loading thread by - * sub-classing BitmapLoadTask and overriding doInBackground() to return a bitmap. ->>>>>>> Add LocalDataAdapter and wrappers. */ abstract static class LocalMediaData implements LocalData { protected long id; diff --git a/src/com/android/camera/data/PanoramaMetadataLoader.java b/src/com/android/camera/data/PanoramaMetadataLoader.java index 21b5f8a3d..fda684861 100644 --- a/src/com/android/camera/data/PanoramaMetadataLoader.java +++ b/src/com/android/camera/data/PanoramaMetadataLoader.java @@ -16,13 +16,13 @@ package com.android.camera.data; +import java.util.ArrayList; + import android.content.Context; import android.net.Uri; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; - -import java.util.ArrayList; +import com.android.camera.util.PhotoSphereHelper; +import com.android.camera.util.PhotoSphereHelper.PanoramaMetadata; /** * This class breaks out the off-thread panorama support. @@ -72,7 +72,7 @@ public class PanoramaMetadataLoader { (new Thread() { @Override public void run() { - onLoadingDone(LightCycleHelper.getPanoramaMetadata(context, + onLoadingDone(PhotoSphereHelper.getPanoramaMetadata(context, mMediaUri)); } }).start(); @@ -96,7 +96,7 @@ public class PanoramaMetadataLoader { mPanoramaMetadata = metadata; if (mPanoramaMetadata == null) { // Error getting panorama data from file. Treat as not panorama. - mPanoramaMetadata = LightCycleHelper.NOT_PANORAMA; + mPanoramaMetadata = PhotoSphereHelper.NOT_PANORAMA; } for (PanoramaMetadataCallback cb : mCallbacksWaiting) { cb.onPanoramaMetadataLoaded(mPanoramaMetadata); diff --git a/src/com/android/gallery3d/app/OrientationManager.java b/src/com/android/camera/support/app/OrientationManager.java index f2f632c9f..850d46591 100644 --- a/src/com/android/gallery3d/app/OrientationManager.java +++ b/src/com/android/camera/support/app/OrientationManager.java @@ -1,20 +1,5 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; +package com.android.camera.support.app; + import android.app.Activity; import android.content.ContentResolver; @@ -22,11 +7,12 @@ import android.content.Context; import android.content.pm.ActivityInfo; import android.content.res.Configuration; import android.provider.Settings; +import android.util.Log; import android.view.OrientationEventListener; import android.view.Surface; +import com.android.camera.support.ui.OrientationSource; import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.ui.OrientationSource; public class OrientationManager implements OrientationSource { private static final String TAG = "OrientationManager"; @@ -163,4 +149,4 @@ public class OrientationManager implements OrientationSource { } return 0; } -} +}
\ No newline at end of file diff --git a/src/com/android/camera/support/app/StitchingChangeListener.java b/src/com/android/camera/support/app/StitchingChangeListener.java new file mode 100644 index 000000000..f67fb3963 --- /dev/null +++ b/src/com/android/camera/support/app/StitchingChangeListener.java @@ -0,0 +1,11 @@ +package com.android.camera.support.app; + +import android.net.Uri; + +public interface StitchingChangeListener { + public void onStitchingQueued(Uri uri); + + public void onStitchingResult(Uri uri); + + public void onStitchingProgress(Uri uri, int progress); +} diff --git a/src/com/android/camera/support/common/ApiHelper.java b/src/com/android/camera/support/common/ApiHelper.java new file mode 100644 index 000000000..e6c1f5fb6 --- /dev/null +++ b/src/com/android/camera/support/common/ApiHelper.java @@ -0,0 +1,219 @@ +package com.android.camera.support.common; + + +import android.app.admin.DevicePolicyManager; +import android.content.ComponentName; +import android.hardware.Camera; +import android.os.Build; +import android.provider.MediaStore.MediaColumns; +import android.view.View; +import android.view.WindowManager; + +import java.lang.reflect.Field; + +public class ApiHelper { + public static interface VERSION_CODES { + // These value are copied from Build.VERSION_CODES + public static final int GINGERBREAD_MR1 = 10; + public static final int HONEYCOMB = 11; + public static final int HONEYCOMB_MR1 = 12; + public static final int HONEYCOMB_MR2 = 13; + public static final int ICE_CREAM_SANDWICH = 14; + public static final int ICE_CREAM_SANDWICH_MR1 = 15; + public static final int JELLY_BEAN = 16; + public static final int JELLY_BEAN_MR1 = 17; + public static final int JELLY_BEAN_MR2 = 18; + } + + public static final boolean AT_LEAST_16 = Build.VERSION.SDK_INT >= 16; + + public static final boolean USE_888_PIXEL_FORMAT = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean ENABLE_PHOTO_EDITOR = + Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + + public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE = + hasField(View.class, "SYSTEM_UI_FLAG_LAYOUT_STABLE"); + + public static final boolean HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION = + hasField(View.class, "SYSTEM_UI_FLAG_HIDE_NAVIGATION"); + + public static final boolean HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT = + hasField(MediaColumns.class, "WIDTH"); + + public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_REUSING_BITMAP_IN_BITMAP_FACTORY = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_SET_BEAM_PUSH_URIS = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_SET_DEFALT_BUFFER_SIZE = hasMethod( + "android.graphics.SurfaceTexture", "setDefaultBufferSize", + int.class, int.class); + + public static final boolean HAS_RELEASE_SURFACE_TEXTURE = hasMethod( + "android.graphics.SurfaceTexture", "release"); + + public static final boolean HAS_SURFACE_TEXTURE = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_MTP = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1; + + public static final boolean HAS_AUTO_FOCUS_MOVE_CALLBACK = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_REMOTE_VIEWS_SERVICE = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_INTENT_EXTRA_LOCAL_ONLY = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_SET_SYSTEM_UI_VISIBILITY = + hasMethod(View.class, "setSystemUiVisibility", int.class); + + public static final boolean HAS_FACE_DETECTION; + static { + boolean hasFaceDetection = false; + try { + Class<?> listenerClass = Class.forName( + "android.hardware.Camera$FaceDetectionListener"); + hasFaceDetection = + hasMethod(Camera.class, "setFaceDetectionListener", listenerClass) && + hasMethod(Camera.class, "startFaceDetection") && + hasMethod(Camera.class, "stopFaceDetection") && + hasMethod(Camera.Parameters.class, "getMaxNumDetectedFaces"); + } catch (Throwable t) { + } + HAS_FACE_DETECTION = hasFaceDetection; + } + + public static final boolean HAS_GET_CAMERA_DISABLED = + hasMethod(DevicePolicyManager.class, "getCameraDisabled", ComponentName.class); + + public static final boolean HAS_MEDIA_ACTION_SOUND = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_TIME_LAPSE_RECORDING = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_ZOOM_WHEN_RECORDING = + Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + + public static final boolean HAS_CAMERA_FOCUS_AREA = + Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + + public static final boolean HAS_CAMERA_METERING_AREA = + Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + + public static final boolean HAS_MOTION_EVENT_TRANSFORM = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_EFFECTS_RECORDING = false; + + // "Background" filter does not have "context" input port in jelly bean. + public static final boolean HAS_EFFECTS_RECORDING_CONTEXT_INPUT = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1; + + public static final boolean HAS_GET_SUPPORTED_VIDEO_SIZE = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_SET_ICON_ATTRIBUTE = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_MEDIA_PROVIDER_FILES_TABLE = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_SURFACE_TEXTURE_RECORDING = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_ACTION_BAR = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + // Ex: View.setTranslationX. + public static final boolean HAS_VIEW_TRANSFORM_PROPERTIES = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_CAMERA_HDR = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1; + + public static final boolean HAS_OPTIONS_IN_MUTABLE = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean CAN_START_PREVIEW_IN_JPEG_CALLBACK = + Build.VERSION.SDK_INT >= VERSION_CODES.ICE_CREAM_SANDWICH; + + public static final boolean HAS_VIEW_PROPERTY_ANIMATOR = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1; + + public static final boolean HAS_POST_ON_ANIMATION = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_ANNOUNCE_FOR_ACCESSIBILITY = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_OBJECT_ANIMATION = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_GLES20_REQUIRED = + Build.VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB; + + public static final boolean HAS_ROTATION_ANIMATION = + hasField(WindowManager.LayoutParams.class, "rotationAnimation"); + + public static final boolean HAS_ORIENTATION_LOCK = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2; + + public static final boolean HAS_CANCELLATION_SIGNAL = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; + + public static final boolean HAS_MEDIA_MUXER = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR2; + + public static final boolean HAS_DISPLAY_LISTENER = + Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN_MR1; + + public static int getIntFieldIfExists(Class<?> klass, String fieldName, + Class<?> obj, int defaultVal) { + try { + Field f = klass.getDeclaredField(fieldName); + return f.getInt(obj); + } catch (Exception e) { + return defaultVal; + } + } + + private static boolean hasField(Class<?> klass, String fieldName) { + try { + klass.getDeclaredField(fieldName); + return true; + } catch (NoSuchFieldException e) { + return false; + } + } + + private static boolean hasMethod(String className, String methodName, + Class<?>... parameterTypes) { + try { + Class<?> klass = Class.forName(className); + klass.getDeclaredMethod(methodName, parameterTypes); + return true; + } catch (Throwable th) { + return false; + } + } + + private static boolean hasMethod( + Class<?> klass, String methodName, Class<?> ... paramTypes) { + try { + klass.getDeclaredMethod(methodName, paramTypes); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } +} diff --git a/src/com/android/camera/support/common/Utils.java b/src/com/android/camera/support/common/Utils.java new file mode 100644 index 000000000..f36d6adcd --- /dev/null +++ b/src/com/android/camera/support/common/Utils.java @@ -0,0 +1,325 @@ +package com.android.camera.support.common; + + +import android.content.Context; +import android.content.pm.PackageInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.database.Cursor; +import android.os.Build; +import android.os.ParcelFileDescriptor; +import android.text.TextUtils; +import android.util.Log; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InterruptedIOException; + +public class Utils { + private static final String TAG = "Utils"; + private static final String DEBUG_TAG = "GalleryDebug"; + + private static final long POLY64REV = 0x95AC9329AC4BC9B5L; + private static final long INITIALCRC = 0xFFFFFFFFFFFFFFFFL; + + private static long[] sCrcTable = new long[256]; + + private static final boolean IS_DEBUG_BUILD = + Build.TYPE.equals("eng") || Build.TYPE.equals("userdebug"); + + private static final String MASK_STRING = "********************************"; + + // Throws AssertionError if the input is false. + public static void assertTrue(boolean cond) { + if (!cond) { + throw new AssertionError(); + } + } + + // Throws AssertionError with the message. We had a method having the form + // assertTrue(boolean cond, String message, Object ... args); + // However a call to that method will cause memory allocation even if the + // condition is false (due to autoboxing generated by "Object ... args"), + // so we don't use that anymore. + public static void fail(String message, Object ... args) { + throw new AssertionError( + args.length == 0 ? message : String.format(message, args)); + } + + // Throws NullPointerException if the input is null. + public static <T> T checkNotNull(T object) { + if (object == null) throw new NullPointerException(); + return object; + } + + // Returns true if two input Object are both null or equal + // to each other. + public static boolean equals(Object a, Object b) { + return (a == b) || (a == null ? false : a.equals(b)); + } + + // Returns the next power of two. + // Returns the input if it is already power of 2. + // Throws IllegalArgumentException if the input is <= 0 or + // the answer overflows. + public static int nextPowerOf2(int n) { + if (n <= 0 || n > (1 << 30)) throw new IllegalArgumentException("n is invalid: " + n); + n -= 1; + n |= n >> 16; + n |= n >> 8; + n |= n >> 4; + n |= n >> 2; + n |= n >> 1; + return n + 1; + } + + // Returns the previous power of two. + // Returns the input if it is already power of 2. + // Throws IllegalArgumentException if the input is <= 0 + public static int prevPowerOf2(int n) { + if (n <= 0) throw new IllegalArgumentException(); + return Integer.highestOneBit(n); + } + + // Returns the input value x clamped to the range [min, max]. + public static int clamp(int x, int min, int max) { + if (x > max) return max; + if (x < min) return min; + return x; + } + + // Returns the input value x clamped to the range [min, max]. + public static float clamp(float x, float min, float max) { + if (x > max) return max; + if (x < min) return min; + return x; + } + + // Returns the input value x clamped to the range [min, max]. + public static long clamp(long x, long min, long max) { + if (x > max) return max; + if (x < min) return min; + return x; + } + + public static boolean isOpaque(int color) { + return color >>> 24 == 0xFF; + } + + public static void swap(int[] array, int i, int j) { + int temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } + + /** + * A function thats returns a 64-bit crc for string + * + * @param in input string + * @return a 64-bit crc value + */ + public static final long crc64Long(String in) { + if (in == null || in.length() == 0) { + return 0; + } + return crc64Long(getBytes(in)); + } + + static { + // http://bioinf.cs.ucl.ac.uk/downloads/crc64/crc64.c + long part; + for (int i = 0; i < 256; i++) { + part = i; + for (int j = 0; j < 8; j++) { + long x = ((int) part & 1) != 0 ? POLY64REV : 0; + part = (part >> 1) ^ x; + } + sCrcTable[i] = part; + } + } + + public static final long crc64Long(byte[] buffer) { + long crc = INITIALCRC; + for (int k = 0, n = buffer.length; k < n; ++k) { + crc = sCrcTable[(((int) crc) ^ buffer[k]) & 0xff] ^ (crc >> 8); + } + return crc; + } + + public static byte[] getBytes(String in) { + byte[] result = new byte[in.length() * 2]; + int output = 0; + for (char ch : in.toCharArray()) { + result[output++] = (byte) (ch & 0xFF); + result[output++] = (byte) (ch >> 8); + } + return result; + } + + public static void closeSilently(Closeable c) { + if (c == null) return; + try { + c.close(); + } catch (IOException t) { + Log.w(TAG, "close fail ", t); + } + } + + public static int compare(long a, long b) { + return a < b ? -1 : a == b ? 0 : 1; + } + + public static int ceilLog2(float value) { + int i; + for (i = 0; i < 31; i++) { + if ((1 << i) >= value) break; + } + return i; + } + + public static int floorLog2(float value) { + int i; + for (i = 0; i < 31; i++) { + if ((1 << i) > value) break; + } + return i - 1; + } + + public static void closeSilently(ParcelFileDescriptor fd) { + try { + if (fd != null) fd.close(); + } catch (Throwable t) { + Log.w(TAG, "fail to close", t); + } + } + + public static void closeSilently(Cursor cursor) { + try { + if (cursor != null) cursor.close(); + } catch (Throwable t) { + Log.w(TAG, "fail to close", t); + } + } + + public static float interpolateAngle( + float source, float target, float progress) { + // interpolate the angle from source to target + // We make the difference in the range of [-179, 180], this is the + // shortest path to change source to target. + float diff = target - source; + if (diff < 0) diff += 360f; + if (diff > 180) diff -= 360f; + + float result = source + diff * progress; + return result < 0 ? result + 360f : result; + } + + public static float interpolateScale( + float source, float target, float progress) { + return source + progress * (target - source); + } + + public static String ensureNotNull(String value) { + return value == null ? "" : value; + } + + public static float parseFloatSafely(String content, float defaultValue) { + if (content == null) return defaultValue; + try { + return Float.parseFloat(content); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + public static int parseIntSafely(String content, int defaultValue) { + if (content == null) return defaultValue; + try { + return Integer.parseInt(content); + } catch (NumberFormatException e) { + return defaultValue; + } + } + + public static boolean isNullOrEmpty(String exifMake) { + return TextUtils.isEmpty(exifMake); + } + + public static void waitWithoutInterrupt(Object object) { + try { + object.wait(); + } catch (InterruptedException e) { + Log.w(TAG, "unexpected interrupt: " + object); + } + } + + public static boolean handleInterrruptedException(Throwable e) { + // A helper to deal with the interrupt exception + // If an interrupt detected, we will setup the bit again. + if (e instanceof InterruptedIOException + || e instanceof InterruptedException) { + Thread.currentThread().interrupt(); + return true; + } + return false; + } + + /** + * @return String with special XML characters escaped. + */ + public static String escapeXml(String s) { + StringBuilder sb = new StringBuilder(); + for (int i = 0, len = s.length(); i < len; ++i) { + char c = s.charAt(i); + switch (c) { + case '<': sb.append("<"); break; + case '>': sb.append(">"); break; + case '\"': sb.append("""); break; + case '\'': sb.append("'"); break; + case '&': sb.append("&"); break; + default: sb.append(c); + } + } + return sb.toString(); + } + + public static String getUserAgent(Context context) { + PackageInfo packageInfo; + try { + packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); + } catch (NameNotFoundException e) { + throw new IllegalStateException("getPackageInfo failed"); + } + return String.format("%s/%s; %s/%s/%s/%s; %s/%s/%s", + packageInfo.packageName, + packageInfo.versionName, + Build.BRAND, + Build.DEVICE, + Build.MODEL, + Build.ID, + Build.VERSION.SDK_INT, + Build.VERSION.RELEASE, + Build.VERSION.INCREMENTAL); + } + + public static String[] copyOf(String[] source, int newSize) { + String[] result = new String[newSize]; + newSize = Math.min(source.length, newSize); + System.arraycopy(source, 0, result, 0, newSize); + return result; + } + + // Mask information for debugging only. It returns <code>info.toString()</code> directly + // for debugging build (i.e., 'eng' and 'userdebug') and returns a mask ("****") + // in release build to protect the information (e.g. for privacy issue). + public static String maskDebugInfo(Object info) { + if (info == null) return null; + String s = info.toString(); + int length = Math.min(s.length(), MASK_STRING.length()); + return IS_DEBUG_BUILD ? s : MASK_STRING.substring(0, length); + } + + // This method should be ONLY used for debugging. + public static void debug(String message, Object ... args) { + Log.v(DEBUG_TAG, String.format(message, args)); + } +}
\ No newline at end of file diff --git a/src/com/android/gallery3d/filtershow/crop/CropExtras.java b/src/com/android/camera/support/filtershow/crop/CropExtras.java index 60fe9af53..6250a3573 100644 --- a/src/com/android/gallery3d/filtershow/crop/CropExtras.java +++ b/src/com/android/camera/support/filtershow/crop/CropExtras.java @@ -1,20 +1,5 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.crop; +package com.android.camera.support.filtershow.crop; + import android.net.Uri; @@ -118,4 +103,4 @@ public class CropExtras { public float getSpotlightY() { return mSpotlightY; } -} +}
\ No newline at end of file diff --git a/src/com/android/gallery3d/glrenderer/BasicTexture.java b/src/com/android/camera/support/glrenderer/BasicTexture.java index 2e77b903f..39cc519c2 100644 --- a/src/com/android/gallery3d/glrenderer/BasicTexture.java +++ b/src/com/android/camera/support/glrenderer/BasicTexture.java @@ -1,27 +1,12 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; +package com.android.camera.support.glrenderer; -import android.util.Log; - -import com.android.gallery3d.common.Utils; import java.util.WeakHashMap; +import com.android.camera.support.common.Utils; + +import android.util.Log; + // BasicTexture is a Texture corresponds to a real GL texture. // The state of a BasicTexture indicates whether its data is loaded to GL memory. // If a BasicTexture is loaded into GL memory, it has a GL texture id. diff --git a/src/com/android/gallery3d/glrenderer/BitmapTexture.java b/src/com/android/camera/support/glrenderer/BitmapTexture.java index 100b0b3b9..b62a44436 100644 --- a/src/com/android/gallery3d/glrenderer/BitmapTexture.java +++ b/src/com/android/camera/support/glrenderer/BitmapTexture.java @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; +package com.android.camera.support.glrenderer; import android.graphics.Bitmap; diff --git a/src/com/android/camera/support/glrenderer/ExtTexture.java b/src/com/android/camera/support/glrenderer/ExtTexture.java new file mode 100644 index 000000000..121e17d5f --- /dev/null +++ b/src/com/android/camera/support/glrenderer/ExtTexture.java @@ -0,0 +1,45 @@ +package com.android.camera.support.glrenderer; + + +//ExtTexture is a texture whose content comes from a external texture. +//Before drawing, setSize() should be called. +public class ExtTexture extends BasicTexture { + + private int mTarget; + + public ExtTexture(GLCanvas canvas, int target) { + GLId glId = canvas.getGLId(); + mId = glId.generateTexture(); + mTarget = target; + } + + private void uploadToCanvas(GLCanvas canvas) { + canvas.setTextureParameters(this); + setAssociatedCanvas(canvas); + mState = STATE_LOADED; + } + + @Override + protected boolean onBind(GLCanvas canvas) { + if (!isLoaded()) { + uploadToCanvas(canvas); + } + + return true; + } + + @Override + public int getTarget() { + return mTarget; + } + + @Override + public boolean isOpaque() { + return true; + } + + @Override + public void yield() { + // we cannot free the texture because we have no backup. + } +} diff --git a/src/com/android/gallery3d/glrenderer/GLCanvas.java b/src/com/android/camera/support/glrenderer/GLCanvas.java index 305e90521..1e4ec2f16 100644 --- a/src/com/android/gallery3d/glrenderer/GLCanvas.java +++ b/src/com/android/camera/support/glrenderer/GLCanvas.java @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; +package com.android.camera.support.glrenderer; import android.graphics.Bitmap; import android.graphics.Rect; @@ -214,4 +198,4 @@ public interface GLCanvas { * @param height The height of the input rectangle. */ public abstract void getBounds(Rect bounds, int x, int y, int width, int height); -} +}
\ No newline at end of file diff --git a/src/com/android/camera/support/glrenderer/GLId.java b/src/com/android/camera/support/glrenderer/GLId.java new file mode 100644 index 000000000..695343b12 --- /dev/null +++ b/src/com/android/camera/support/glrenderer/GLId.java @@ -0,0 +1,17 @@ +package com.android.camera.support.glrenderer; + +import javax.microedition.khronos.opengles.GL11; +import javax.microedition.khronos.opengles.GL11ExtensionPack; + +// This mimics corresponding GL functions. +public interface GLId { + public int generateTexture(); + + public void glGenBuffers(int n, int[] buffers, int offset); + + public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset); + + public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset); + + public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset); +} diff --git a/src/com/android/camera/support/glrenderer/GLPaint.java b/src/com/android/camera/support/glrenderer/GLPaint.java new file mode 100644 index 000000000..7c6af73eb --- /dev/null +++ b/src/com/android/camera/support/glrenderer/GLPaint.java @@ -0,0 +1,26 @@ +package com.android.camera.support.glrenderer; + + +import junit.framework.Assert; + +public class GLPaint { + private float mLineWidth = 1f; + private int mColor = 0; + + public void setColor(int color) { + mColor = color; + } + + public int getColor() { + return mColor; + } + + public void setLineWidth(float width) { + Assert.assertTrue(width >= 0); + mLineWidth = width; + } + + public float getLineWidth() { + return mLineWidth; + } +} diff --git a/src/com/android/gallery3d/glrenderer/NinePatchChunk.java b/src/com/android/camera/support/glrenderer/NinePatchChunk.java index 9dc326622..f7deb1864 100644 --- a/src/com/android/gallery3d/glrenderer/NinePatchChunk.java +++ b/src/com/android/camera/support/glrenderer/NinePatchChunk.java @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; +package com.android.camera.support.glrenderer; import android.graphics.Rect; diff --git a/src/com/android/gallery3d/glrenderer/NinePatchTexture.java b/src/com/android/camera/support/glrenderer/NinePatchTexture.java index d0ddc46c3..c69afd682 100644 --- a/src/com/android/gallery3d/glrenderer/NinePatchTexture.java +++ b/src/com/android/camera/support/glrenderer/NinePatchTexture.java @@ -1,31 +1,15 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; +package com.android.camera.support.glrenderer; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Rect; -import com.android.gallery3d.common.Utils; - -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; +import com.android.camera.support.common.Utils; // NinePatchTexture is a texture backed by a NinePatch resource. // @@ -421,4 +405,4 @@ class NinePatchInstance { mXyBufferName = -1; } } -} +}
\ No newline at end of file diff --git a/src/com/android/gallery3d/glrenderer/RawTexture.java b/src/com/android/camera/support/glrenderer/RawTexture.java index 93f0fdff9..b86282d0e 100644 --- a/src/com/android/gallery3d/glrenderer/RawTexture.java +++ b/src/com/android/camera/support/glrenderer/RawTexture.java @@ -1,20 +1,5 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +package com.android.camera.support.glrenderer; -package com.android.gallery3d.glrenderer; import android.util.Log; diff --git a/src/com/android/gallery3d/glrenderer/ResourceTexture.java b/src/com/android/camera/support/glrenderer/ResourceTexture.java index eb8e8a517..121c184cd 100644 --- a/src/com/android/gallery3d/glrenderer/ResourceTexture.java +++ b/src/com/android/camera/support/glrenderer/ResourceTexture.java @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; +package com.android.camera.support.glrenderer; import android.content.Context; import android.graphics.Bitmap; diff --git a/src/com/android/camera/support/glrenderer/Texture.java b/src/com/android/camera/support/glrenderer/Texture.java new file mode 100644 index 000000000..4d1a49d2b --- /dev/null +++ b/src/com/android/camera/support/glrenderer/Texture.java @@ -0,0 +1,27 @@ +package com.android.camera.support.glrenderer; + +//Texture is a rectangular image which can be drawn on GLCanvas. +//The isOpaque() function gives a hint about whether the texture is opaque, +//so the drawing can be done faster. +// +//This is the current texture hierarchy: +// +//Texture +//-- ColorTexture +//-- FadeInTexture +//-- BasicTexture +// -- UploadedTexture +// -- BitmapTexture +// -- Tile +// -- ResourceTexture +// -- NinePatchTexture +// -- CanvasTexture +// -- StringTexture +// +public interface Texture { + public int getWidth(); + public int getHeight(); + public void draw(GLCanvas canvas, int x, int y); + public void draw(GLCanvas canvas, int x, int y, int w, int h); + public boolean isOpaque(); +} diff --git a/src/com/android/gallery3d/glrenderer/UploadedTexture.java b/src/com/android/camera/support/glrenderer/UploadedTexture.java index f41a979b7..106aa4ef3 100644 --- a/src/com/android/gallery3d/glrenderer/UploadedTexture.java +++ b/src/com/android/camera/support/glrenderer/UploadedTexture.java @@ -1,20 +1,5 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; +package com.android.camera.support.glrenderer; + import android.graphics.Bitmap; import android.graphics.Bitmap.Config; @@ -295,4 +280,4 @@ public abstract class UploadedTexture extends BasicTexture { super.recycle(); if (mBitmap != null) freeBitmap(); } -} +}
\ No newline at end of file diff --git a/src/com/android/gallery3d/ui/BitmapScreenNail.java b/src/com/android/camera/support/ui/BitmapScreenNail.java index a3d403946..a0252b9a5 100644 --- a/src/com/android/gallery3d/ui/BitmapScreenNail.java +++ b/src/com/android/camera/support/ui/BitmapScreenNail.java @@ -1,26 +1,10 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; +package com.android.camera.support.ui; import android.graphics.Bitmap; import android.graphics.RectF; -import com.android.gallery3d.glrenderer.BitmapTexture; -import com.android.gallery3d.glrenderer.GLCanvas; +import com.android.camera.support.glrenderer.BitmapTexture; +import com.android.camera.support.glrenderer.GLCanvas; public class BitmapScreenNail implements ScreenNail { private final BitmapTexture mBitmapTexture; diff --git a/src/com/android/camera/support/ui/OrientationSource.java b/src/com/android/camera/support/ui/OrientationSource.java new file mode 100644 index 000000000..a2841eec4 --- /dev/null +++ b/src/com/android/camera/support/ui/OrientationSource.java @@ -0,0 +1,6 @@ +package com.android.camera.support.ui; + +public interface OrientationSource { + public int getDisplayRotation(); + public int getCompensation(); +} diff --git a/src/com/android/camera/support/ui/ScreenNail.java b/src/com/android/camera/support/ui/ScreenNail.java new file mode 100644 index 000000000..67b2f58c5 --- /dev/null +++ b/src/com/android/camera/support/ui/ScreenNail.java @@ -0,0 +1,21 @@ +package com.android.camera.support.ui; + + +import android.graphics.RectF; + +import com.android.camera.support.glrenderer.GLCanvas; + +public interface ScreenNail { + public int getWidth(); + public int getHeight(); + public void draw(GLCanvas canvas, int x, int y, int width, int height); + + // We do not need to draw this ScreenNail in this frame. + public void noDraw(); + + // This ScreenNail will not be used anymore. Release related resources. + public void recycle(); + + // This is only used by TileImageView to back up the tiles not yet loaded. + public void draw(GLCanvas canvas, RectF source, RectF dest); +} diff --git a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java b/src/com/android/camera/support/ui/SurfaceTextureScreenNail.java index 18121e63b..d78b1ba4a 100644 --- a/src/com/android/gallery3d/ui/SurfaceTextureScreenNail.java +++ b/src/com/android/camera/support/ui/SurfaceTextureScreenNail.java @@ -1,28 +1,14 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; +package com.android.camera.support.ui; + import android.annotation.TargetApi; import android.graphics.RectF; import android.graphics.SurfaceTexture; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.glrenderer.ExtTexture; -import com.android.gallery3d.glrenderer.GLCanvas; +import com.android.camera.support.common.ApiHelper; +import com.android.camera.support.glrenderer.ExtTexture; +import com.android.camera.support.glrenderer.GLCanvas; + @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) public abstract class SurfaceTextureScreenNail implements ScreenNail, @@ -139,4 +125,4 @@ public abstract class SurfaceTextureScreenNail implements ScreenNail, @Override abstract public void onFrameAvailable(SurfaceTexture surfaceTexture); -} +}
\ No newline at end of file diff --git a/src/com/android/gallery3d/util/AccessibilityUtils.java b/src/com/android/camera/support/util/AccessibilityUtils.java index 9df8e4ece..e758e2f7e 100644 --- a/src/com/android/gallery3d/util/AccessibilityUtils.java +++ b/src/com/android/camera/support/util/AccessibilityUtils.java @@ -1,20 +1,4 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; +package com.android.camera.support.util; import android.content.Context; import android.support.v4.view.accessibility.AccessibilityRecordCompat; @@ -22,7 +6,7 @@ import android.view.View; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; -import com.android.gallery3d.common.ApiHelper; +import com.android.camera.support.common.ApiHelper; /** * AccessibilityUtils provides functions needed in accessibility mode. All the functions diff --git a/src/com/android/gallery3d/util/MotionEventHelper.java b/src/com/android/camera/support/util/MotionEventHelper.java index 715f7fa69..2a3340e28 100644 --- a/src/com/android/gallery3d/util/MotionEventHelper.java +++ b/src/com/android/camera/support/util/MotionEventHelper.java @@ -1,19 +1,4 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.util; +package com.android.camera.support.util; import android.annotation.TargetApi; import android.graphics.Matrix; diff --git a/src/com/android/camera/ui/AbstractSettingPopup.java b/src/com/android/camera/ui/AbstractSettingPopup.java index 783b6c771..a3cf298b5 100644 --- a/src/com/android/camera/ui/AbstractSettingPopup.java +++ b/src/com/android/camera/ui/AbstractSettingPopup.java @@ -21,7 +21,7 @@ import android.util.AttributeSet; import android.view.ViewGroup; import android.widget.TextView; -import com.android.gallery3d.R; +import com.android.camera2.R; // A popup window that shows one or more camera settings. abstract public class AbstractSettingPopup extends RotateLayout { diff --git a/src/com/android/camera/ui/CameraControls.java b/src/com/android/camera/ui/CameraControls.java index 7fa6890a7..ed281398b 100644 --- a/src/com/android/camera/ui/CameraControls.java +++ b/src/com/android/camera/ui/CameraControls.java @@ -16,17 +16,13 @@ package com.android.camera.ui; -import android.app.Activity; import android.content.Context; -import android.content.res.Configuration; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.widget.FrameLayout; -import com.android.camera.Util; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; +import com.android.camera2.R; public class CameraControls extends RotatableLayout { diff --git a/src/com/android/camera/ui/CameraRootView.java b/src/com/android/camera/ui/CameraRootView.java index adda70697..5186ea24c 100644 --- a/src/com/android/camera/ui/CameraRootView.java +++ b/src/com/android/camera/ui/CameraRootView.java @@ -16,6 +16,7 @@ package com.android.camera.ui; +import android.annotation.SuppressLint; import android.app.Activity; import android.content.Context; import android.content.res.Configuration; @@ -27,8 +28,9 @@ import android.view.View; import android.widget.FrameLayout; import com.android.camera.Util; -import com.android.gallery3d.common.ApiHelper; +import com.android.camera.support.common.ApiHelper; +@SuppressLint("NewApi") public class CameraRootView extends FrameLayout { private int mTopMargin = 0; diff --git a/src/com/android/camera/ui/CameraSwitcher.java b/src/com/android/camera/ui/CameraSwitcher.java index 6e4321571..f9e78f069 100644 --- a/src/com/android/camera/ui/CameraSwitcher.java +++ b/src/com/android/camera/ui/CameraSwitcher.java @@ -35,10 +35,10 @@ import android.widget.FrameLayout.LayoutParams; import android.widget.LinearLayout; import com.android.camera.Util; -import com.android.gallery3d.R; +import com.android.camera.util.PhotoSphereHelper; +import com.android.camera.util.UsageStatistics; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.UsageStatistics; public class CameraSwitcher extends RotateImageView implements OnClickListener, OnTouchListener { @@ -96,14 +96,14 @@ public class CameraSwitcher extends RotateImageView } public void initializeDrawables(Context context) { - int totaldrawid = (LightCycleHelper.hasLightCycleCapture(context) + int totaldrawid = (PhotoSphereHelper.hasLightCycleCapture(context) ? DRAW_IDS.length : DRAW_IDS.length - 1); int[] drawids = new int[totaldrawid]; int[] moduleids = new int[totaldrawid]; int ix = 0; for (int i = 0; i < DRAW_IDS.length; i++) { - if (i == LIGHTCYCLE_MODULE_INDEX && !LightCycleHelper.hasLightCycleCapture(context)) { + if (i == LIGHTCYCLE_MODULE_INDEX && !PhotoSphereHelper.hasLightCycleCapture(context)) { continue; // not enabled, so don't add to UI } moduleids[ix] = i; diff --git a/src/com/android/camera/ui/CountDownView.java b/src/com/android/camera/ui/CountDownView.java index 907d33508..6f4ae8cda 100644 --- a/src/com/android/camera/ui/CountDownView.java +++ b/src/com/android/camera/ui/CountDownView.java @@ -31,7 +31,7 @@ import android.view.animation.AnimationUtils; import android.widget.FrameLayout; import android.widget.TextView; -import com.android.gallery3d.R; +import com.android.camera2.R; public class CountDownView extends FrameLayout { diff --git a/src/com/android/camera/ui/CountdownTimerPopup.java b/src/com/android/camera/ui/CountdownTimerPopup.java index 7c3572b55..3f3a1ac7d 100644 --- a/src/com/android/camera/ui/CountdownTimerPopup.java +++ b/src/com/android/camera/ui/CountdownTimerPopup.java @@ -16,6 +16,8 @@ package com.android.camera.ui; +import java.util.Locale; + import android.content.Context; import android.util.AttributeSet; import android.util.Log; @@ -26,9 +28,7 @@ import android.widget.NumberPicker; import android.widget.NumberPicker.OnValueChangeListener; import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -import java.util.Locale; +import com.android.camera2.R; /** * This is a popup window that allows users to specify a countdown timer diff --git a/src/com/android/camera/ui/EffectSettingPopup.java b/src/com/android/camera/ui/EffectSettingPopup.java index 568781a01..d51803a83 100644 --- a/src/com/android/camera/ui/EffectSettingPopup.java +++ b/src/com/android/camera/ui/EffectSettingPopup.java @@ -16,6 +16,9 @@ package com.android.camera.ui; +import java.util.ArrayList; +import java.util.HashMap; + import android.annotation.TargetApi; import android.content.Context; import android.util.AttributeSet; @@ -26,13 +29,9 @@ import android.widget.GridView; import android.widget.SimpleAdapter; import com.android.camera.IconListPreference; - -import com.android.gallery3d.R; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; -import java.util.ArrayList; -import java.util.HashMap; - // A popup window that shows video effect setting. It has two grid view. // One shows the goofy face effects. The other shows the background replacer // effects. diff --git a/src/com/android/camera/ui/FaceView.java b/src/com/android/camera/ui/FaceView.java index 7d66dc079..1a539665e 100644 --- a/src/com/android/camera/ui/FaceView.java +++ b/src/com/android/camera/ui/FaceView.java @@ -33,7 +33,7 @@ import android.view.View; import com.android.camera.PhotoUI; import com.android.camera.Util; -import com.android.gallery3d.R; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) diff --git a/src/com/android/camera/ui/FilmStripView.java b/src/com/android/camera/ui/FilmStripView.java index 8a1a85a55..79f58c7be 100644 --- a/src/com/android/camera/ui/FilmStripView.java +++ b/src/com/android/camera/ui/FilmStripView.java @@ -33,8 +33,8 @@ import android.widget.ImageButton; import android.widget.Scroller; import com.android.camera.ui.FilmStripView.ImageData.PanoramaSupportCallback; -import com.android.gallery3d.R; -import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper; +import com.android.camera.util.PhotoSphereHelper.PanoramaViewHelper; +import com.android.camera2.R; public class FilmStripView extends ViewGroup { @SuppressWarnings("unused") diff --git a/src/com/android/camera/ui/InLineSettingCheckBox.java b/src/com/android/camera/ui/InLineSettingCheckBox.java index c1aa5a91c..c3cd1979d 100644 --- a/src/com/android/camera/ui/InLineSettingCheckBox.java +++ b/src/com/android/camera/ui/InLineSettingCheckBox.java @@ -23,9 +23,8 @@ import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; - import com.android.camera.ListPreference; -import com.android.gallery3d.R; +import com.android.camera2.R; /* A check box setting control which turns on/off the setting. */ public class InLineSettingCheckBox extends InLineSettingItem { diff --git a/src/com/android/camera/ui/InLineSettingItem.java b/src/com/android/camera/ui/InLineSettingItem.java index 839a77fd0..288781fda 100644 --- a/src/com/android/camera/ui/InLineSettingItem.java +++ b/src/com/android/camera/ui/InLineSettingItem.java @@ -23,7 +23,7 @@ import android.widget.LinearLayout; import android.widget.TextView; import com.android.camera.ListPreference; -import com.android.gallery3d.R; +import com.android.camera2.R; /** * A one-line camera setting could be one of three types: knob, switch or restore diff --git a/src/com/android/camera/ui/InLineSettingMenu.java b/src/com/android/camera/ui/InLineSettingMenu.java index 8e45c3e38..1d80741b5 100644 --- a/src/com/android/camera/ui/InLineSettingMenu.java +++ b/src/com/android/camera/ui/InLineSettingMenu.java @@ -23,7 +23,7 @@ import android.view.accessibility.AccessibilityEvent; import android.widget.TextView; import com.android.camera.ListPreference; -import com.android.gallery3d.R; +import com.android.camera2.R; /* Setting menu item that will bring up a menu when you click on it. */ public class InLineSettingMenu extends InLineSettingItem { diff --git a/src/com/android/camera/ui/ListPrefSettingPopup.java b/src/com/android/camera/ui/ListPrefSettingPopup.java index cfef73f49..ff4d995a0 100644 --- a/src/com/android/camera/ui/ListPrefSettingPopup.java +++ b/src/com/android/camera/ui/ListPrefSettingPopup.java @@ -16,23 +16,23 @@ package com.android.camera.ui; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.View; -import android.widget.ListView; import android.widget.AdapterView; import android.widget.ImageView; +import android.widget.ListView; import android.widget.SimpleAdapter; import com.android.camera.IconListPreference; import com.android.camera.ListPreference; -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import com.android.camera2.R; // A popup window that shows one camera setting. The title is the name of the // setting (ex: white-balance). The entries are the supported values (ex: diff --git a/src/com/android/camera/ui/MoreSettingPopup.java b/src/com/android/camera/ui/MoreSettingPopup.java index 5900058df..8da26c946 100644 --- a/src/com/android/camera/ui/MoreSettingPopup.java +++ b/src/com/android/camera/ui/MoreSettingPopup.java @@ -16,6 +16,8 @@ package com.android.camera.ui; +import java.util.ArrayList; + import android.content.Context; import android.util.AttributeSet; import android.util.Log; @@ -28,9 +30,7 @@ import android.widget.ListView; import com.android.camera.ListPreference; import com.android.camera.PreferenceGroup; -import com.android.gallery3d.R; - -import java.util.ArrayList; +import com.android.camera2.R; /* A popup window that contains several camera settings. */ public class MoreSettingPopup extends AbstractSettingPopup diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java index c78107ce9..666fa13b1 100644 --- a/src/com/android/camera/ui/PieRenderer.java +++ b/src/com/android/camera/ui/PieRenderer.java @@ -16,6 +16,9 @@ package com.android.camera.ui; +import java.util.ArrayList; +import java.util.List; + import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.ValueAnimator; @@ -37,10 +40,7 @@ import android.view.animation.Animation; import android.view.animation.Transformation; import com.android.camera.drawable.TextDrawable; -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.List; +import com.android.camera2.R; public class PieRenderer extends OverlayRenderer implements FocusIndicator { diff --git a/src/com/android/camera/ui/RotateLayout.java b/src/com/android/camera/ui/RotateLayout.java index 86f5c814d..5d6debb17 100644 --- a/src/com/android/camera/ui/RotateLayout.java +++ b/src/com/android/camera/ui/RotateLayout.java @@ -27,8 +27,8 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; +import com.android.camera.support.util.MotionEventHelper; import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.MotionEventHelper; // A RotateLayout is designed to display a single item and provides the // capabilities to rotate the item. diff --git a/src/com/android/camera/ui/RotateTextToast.java b/src/com/android/camera/ui/RotateTextToast.java index c78a258b0..16382442e 100644 --- a/src/com/android/camera/ui/RotateTextToast.java +++ b/src/com/android/camera/ui/RotateTextToast.java @@ -24,7 +24,7 @@ import android.view.ViewGroup; import android.widget.TextView; import com.android.camera.Util; -import com.android.gallery3d.R; +import com.android.camera2.R; public class RotateTextToast { private static final int TOAST_DURATION = 5000; // milliseconds diff --git a/src/com/android/camera/ui/Switch.java b/src/com/android/camera/ui/Switch.java index ac21758a7..9191242f6 100644 --- a/src/com/android/camera/ui/Switch.java +++ b/src/com/android/camera/ui/Switch.java @@ -20,11 +20,9 @@ import android.annotation.TargetApi; import android.content.Context; import android.content.res.ColorStateList; import android.content.res.Resources; -import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; -import android.graphics.Typeface; import android.graphics.drawable.Drawable; import android.text.Layout; import android.text.StaticLayout; @@ -32,8 +30,6 @@ import android.text.TextPaint; import android.text.TextUtils; import android.util.AttributeSet; import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; import android.view.Gravity; import android.view.MotionEvent; import android.view.VelocityTracker; @@ -42,11 +38,9 @@ import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; import android.widget.CompoundButton; -import com.android.gallery3d.R; +import com.android.camera2.R; import com.android.gallery3d.common.ApiHelper; -import java.util.Arrays; - /** * A Switch is a two-state toggle switch widget that can select between two * options. The user may drag the "thumb" back and forth to choose the selected option, diff --git a/src/com/android/camera/ui/TimeIntervalPopup.java b/src/com/android/camera/ui/TimeIntervalPopup.java index 18ad9f5da..f35f24193 100644 --- a/src/com/android/camera/ui/TimeIntervalPopup.java +++ b/src/com/android/camera/ui/TimeIntervalPopup.java @@ -28,7 +28,7 @@ import android.widget.TextView; import com.android.camera.IconListPreference; import com.android.camera.ListPreference; -import com.android.gallery3d.R; +import com.android.camera2.R; /** * This is a popup window that allows users to turn on/off time lapse feature, diff --git a/src/com/android/camera/ui/ZoomRenderer.java b/src/com/android/camera/ui/ZoomRenderer.java index 86b82b459..e708d3eea 100644 --- a/src/com/android/camera/ui/ZoomRenderer.java +++ b/src/com/android/camera/ui/ZoomRenderer.java @@ -24,7 +24,7 @@ import android.graphics.Paint; import android.graphics.Rect; import android.view.ScaleGestureDetector; -import com.android.gallery3d.R; +import com.android.camera2.R; public class ZoomRenderer extends OverlayRenderer implements ScaleGestureDetector.OnScaleGestureListener { diff --git a/src/com/android/gallery3d/anim/AlphaAnimation.java b/src/com/android/gallery3d/anim/AlphaAnimation.java deleted file mode 100644 index f9f4cbd2c..000000000 --- a/src/com/android/gallery3d/anim/AlphaAnimation.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.anim; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.GLCanvas; - -public class AlphaAnimation extends CanvasAnimation { - private final float mStartAlpha; - private final float mEndAlpha; - private float mCurrentAlpha; - - public AlphaAnimation(float from, float to) { - mStartAlpha = from; - mEndAlpha = to; - mCurrentAlpha = from; - } - - @Override - public void apply(GLCanvas canvas) { - canvas.multiplyAlpha(mCurrentAlpha); - } - - @Override - public int getCanvasSaveFlags() { - return GLCanvas.SAVE_FLAG_ALPHA; - } - - @Override - protected void onCalculate(float progress) { - mCurrentAlpha = Utils.clamp(mStartAlpha - + (mEndAlpha - mStartAlpha) * progress, 0f, 1f); - } -} diff --git a/src/com/android/gallery3d/anim/Animation.java b/src/com/android/gallery3d/anim/Animation.java deleted file mode 100644 index cc117bbce..000000000 --- a/src/com/android/gallery3d/anim/Animation.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.anim; - -import android.view.animation.Interpolator; - -import com.android.gallery3d.common.Utils; - -// Animation calculates a value according to the current input time. -// -// 1. First we need to use setDuration(int) to set the duration of the -// animation. The duration is in milliseconds. -// 2. Then we should call start(). The actual start time is the first value -// passed to calculate(long). -// 3. Each time we want to get an animation value, we call -// calculate(long currentTimeMillis) to ask the Animation to calculate it. -// The parameter passed to calculate(long) should be nonnegative. -// 4. Use get() to get that value. -// -// In step 3, onCalculate(float progress) is called so subclasses can calculate -// the value according to progress (progress is a value in [0,1]). -// -// Before onCalculate(float) is called, There is an optional interpolator which -// can change the progress value. The interpolator can be set by -// setInterpolator(Interpolator). If the interpolator is used, the value passed -// to onCalculate may be (for example, the overshoot effect). -// -// The isActive() method returns true after the animation start() is called and -// before calculate is passed a value which reaches the duration of the -// animation. -// -// The start() method can be called again to restart the Animation. -// -abstract public class Animation { - private static final long ANIMATION_START = -1; - private static final long NO_ANIMATION = -2; - - private long mStartTime = NO_ANIMATION; - private int mDuration; - private Interpolator mInterpolator; - - public void setInterpolator(Interpolator interpolator) { - mInterpolator = interpolator; - } - - public void setDuration(int duration) { - mDuration = duration; - } - - public void start() { - mStartTime = ANIMATION_START; - } - - public void setStartTime(long time) { - mStartTime = time; - } - - public boolean isActive() { - return mStartTime != NO_ANIMATION; - } - - public void forceStop() { - mStartTime = NO_ANIMATION; - } - - public boolean calculate(long currentTimeMillis) { - if (mStartTime == NO_ANIMATION) return false; - if (mStartTime == ANIMATION_START) mStartTime = currentTimeMillis; - int elapse = (int) (currentTimeMillis - mStartTime); - float x = Utils.clamp((float) elapse / mDuration, 0f, 1f); - Interpolator i = mInterpolator; - onCalculate(i != null ? i.getInterpolation(x) : x); - if (elapse >= mDuration) mStartTime = NO_ANIMATION; - return mStartTime != NO_ANIMATION; - } - - abstract protected void onCalculate(float progress); -} diff --git a/src/com/android/gallery3d/anim/CanvasAnimation.java b/src/com/android/gallery3d/anim/CanvasAnimation.java deleted file mode 100644 index cdc66c6ba..000000000 --- a/src/com/android/gallery3d/anim/CanvasAnimation.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.anim; - -import com.android.gallery3d.glrenderer.GLCanvas; - -public abstract class CanvasAnimation extends Animation { - - public abstract int getCanvasSaveFlags(); - public abstract void apply(GLCanvas canvas); -} diff --git a/src/com/android/gallery3d/anim/FloatAnimation.java b/src/com/android/gallery3d/anim/FloatAnimation.java deleted file mode 100644 index 1294ec2f4..000000000 --- a/src/com/android/gallery3d/anim/FloatAnimation.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.anim; - -public class FloatAnimation extends Animation { - - private final float mFrom; - private final float mTo; - private float mCurrent; - - public FloatAnimation(float from, float to, int duration) { - mFrom = from; - mTo = to; - mCurrent = from; - setDuration(duration); - } - - @Override - protected void onCalculate(float progress) { - mCurrent = mFrom + (mTo - mFrom) * progress; - } - - public float get() { - return mCurrent; - } -} diff --git a/src/com/android/gallery3d/anim/StateTransitionAnimation.java b/src/com/android/gallery3d/anim/StateTransitionAnimation.java deleted file mode 100644 index bf8a54405..000000000 --- a/src/com/android/gallery3d/anim/StateTransitionAnimation.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.anim; - -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.TiledScreenNail; - -public class StateTransitionAnimation extends Animation { - - public static class Spec { - public static final Spec OUTGOING; - public static final Spec INCOMING; - public static final Spec PHOTO_INCOMING; - - private static final Interpolator DEFAULT_INTERPOLATOR = - new DecelerateInterpolator(); - - public int duration = 330; - public float backgroundAlphaFrom = 0; - public float backgroundAlphaTo = 0; - public float backgroundScaleFrom = 0; - public float backgroundScaleTo = 0; - public float contentAlphaFrom = 1; - public float contentAlphaTo = 1; - public float contentScaleFrom = 1; - public float contentScaleTo = 1; - public float overlayAlphaFrom = 0; - public float overlayAlphaTo = 0; - public float overlayScaleFrom = 0; - public float overlayScaleTo = 0; - public Interpolator interpolator = DEFAULT_INTERPOLATOR; - - static { - OUTGOING = new Spec(); - OUTGOING.backgroundAlphaFrom = 0.5f; - OUTGOING.backgroundAlphaTo = 0f; - OUTGOING.backgroundScaleFrom = 1f; - OUTGOING.backgroundScaleTo = 0f; - OUTGOING.contentAlphaFrom = 0.5f; - OUTGOING.contentAlphaTo = 1f; - OUTGOING.contentScaleFrom = 3f; - OUTGOING.contentScaleTo = 1f; - - INCOMING = new Spec(); - INCOMING.overlayAlphaFrom = 1f; - INCOMING.overlayAlphaTo = 0f; - INCOMING.overlayScaleFrom = 1f; - INCOMING.overlayScaleTo = 3f; - INCOMING.contentAlphaFrom = 0f; - INCOMING.contentAlphaTo = 1f; - INCOMING.contentScaleFrom = 0.25f; - INCOMING.contentScaleTo = 1f; - - PHOTO_INCOMING = INCOMING; - } - - private static Spec specForTransition(Transition t) { - switch (t) { - case Outgoing: - return Spec.OUTGOING; - case Incoming: - return Spec.INCOMING; - case PhotoIncoming: - return Spec.PHOTO_INCOMING; - case None: - default: - return null; - } - } - } - - public static enum Transition { None, Outgoing, Incoming, PhotoIncoming } - - private final Spec mTransitionSpec; - private float mCurrentContentScale; - private float mCurrentContentAlpha; - private float mCurrentBackgroundScale; - private float mCurrentBackgroundAlpha; - private float mCurrentOverlayScale; - private float mCurrentOverlayAlpha; - private RawTexture mOldScreenTexture; - - public StateTransitionAnimation(Transition t, RawTexture oldScreen) { - this(Spec.specForTransition(t), oldScreen); - } - - public StateTransitionAnimation(Spec spec, RawTexture oldScreen) { - mTransitionSpec = spec != null ? spec : Spec.OUTGOING; - setDuration(mTransitionSpec.duration); - setInterpolator(mTransitionSpec.interpolator); - mOldScreenTexture = oldScreen; - TiledScreenNail.disableDrawPlaceholder(); - } - - @Override - public boolean calculate(long currentTimeMillis) { - boolean retval = super.calculate(currentTimeMillis); - if (!isActive()) { - if (mOldScreenTexture != null) { - mOldScreenTexture.recycle(); - mOldScreenTexture = null; - } - TiledScreenNail.enableDrawPlaceholder(); - } - return retval; - } - - @Override - protected void onCalculate(float progress) { - mCurrentContentScale = mTransitionSpec.contentScaleFrom - + (mTransitionSpec.contentScaleTo - mTransitionSpec.contentScaleFrom) * progress; - mCurrentContentAlpha = mTransitionSpec.contentAlphaFrom - + (mTransitionSpec.contentAlphaTo - mTransitionSpec.contentAlphaFrom) * progress; - mCurrentBackgroundAlpha = mTransitionSpec.backgroundAlphaFrom - + (mTransitionSpec.backgroundAlphaTo - mTransitionSpec.backgroundAlphaFrom) - * progress; - mCurrentBackgroundScale = mTransitionSpec.backgroundScaleFrom - + (mTransitionSpec.backgroundScaleTo - mTransitionSpec.backgroundScaleFrom) - * progress; - mCurrentOverlayScale = mTransitionSpec.overlayScaleFrom - + (mTransitionSpec.overlayScaleTo - mTransitionSpec.overlayScaleFrom) * progress; - mCurrentOverlayAlpha = mTransitionSpec.overlayAlphaFrom - + (mTransitionSpec.overlayAlphaTo - mTransitionSpec.overlayAlphaFrom) * progress; - } - - private void applyOldTexture(GLView view, GLCanvas canvas, float alpha, float scale, boolean clear) { - if (mOldScreenTexture == null) - return; - if (clear) canvas.clearBuffer(view.getBackgroundColor()); - canvas.save(); - canvas.setAlpha(alpha); - int xOffset = view.getWidth() / 2; - int yOffset = view.getHeight() / 2; - canvas.translate(xOffset, yOffset); - canvas.scale(scale, scale, 1); - mOldScreenTexture.draw(canvas, -xOffset, -yOffset); - canvas.restore(); - } - - public void applyBackground(GLView view, GLCanvas canvas) { - if (mCurrentBackgroundAlpha > 0f) { - applyOldTexture(view, canvas, mCurrentBackgroundAlpha, mCurrentBackgroundScale, true); - } - } - - public void applyContentTransform(GLView view, GLCanvas canvas) { - int xOffset = view.getWidth() / 2; - int yOffset = view.getHeight() / 2; - canvas.translate(xOffset, yOffset); - canvas.scale(mCurrentContentScale, mCurrentContentScale, 1); - canvas.translate(-xOffset, -yOffset); - canvas.setAlpha(mCurrentContentAlpha); - } - - public void applyOverlay(GLView view, GLCanvas canvas) { - if (mCurrentOverlayAlpha > 0f) { - applyOldTexture(view, canvas, mCurrentOverlayAlpha, mCurrentOverlayScale, false); - } - } -} diff --git a/src/com/android/gallery3d/app/AbstractGalleryActivity.java b/src/com/android/gallery3d/app/AbstractGalleryActivity.java deleted file mode 100644 index ac39aa560..000000000 --- a/src/com/android/gallery3d/app/AbstractGalleryActivity.java +++ /dev/null @@ -1,343 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.BroadcastReceiver; -import android.content.ComponentName; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.ServiceConnection; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.IBinder; -import android.view.Menu; -import android.view.MenuItem; -import android.view.Window; -import android.view.WindowManager; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLRootView; -import com.android.gallery3d.util.LightCycleHelper.PanoramaViewHelper; -import com.android.gallery3d.util.ThreadPool; -import com.android.photos.data.GalleryBitmapPool; - -public class AbstractGalleryActivity extends Activity implements GalleryContext { - @SuppressWarnings("unused") - private static final String TAG = "AbstractGalleryActivity"; - private GLRootView mGLRootView; - private StateManager mStateManager; - private GalleryActionBar mActionBar; - private OrientationManager mOrientationManager; - private TransitionStore mTransitionStore = new TransitionStore(); - private boolean mDisableToggleStatusBar; - private PanoramaViewHelper mPanoramaViewHelper; - - private AlertDialog mAlertDialog = null; - private BroadcastReceiver mMountReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (getExternalCacheDir() != null) onStorageReady(); - } - }; - private IntentFilter mMountFilter = new IntentFilter(Intent.ACTION_MEDIA_MOUNTED); - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mOrientationManager = new OrientationManager(this); - toggleStatusBarByOrientation(); - getWindow().setBackgroundDrawable(null); - mPanoramaViewHelper = new PanoramaViewHelper(this); - mPanoramaViewHelper.onCreate(); - doBindBatchService(); - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - mGLRootView.lockRenderThread(); - try { - super.onSaveInstanceState(outState); - getStateManager().saveState(outState); - } finally { - mGLRootView.unlockRenderThread(); - } - } - - @Override - public void onConfigurationChanged(Configuration config) { - super.onConfigurationChanged(config); - mStateManager.onConfigurationChange(config); - getGalleryActionBar().onConfigurationChanged(); - invalidateOptionsMenu(); - toggleStatusBarByOrientation(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - return getStateManager().createOptionsMenu(menu); - } - - @Override - public Context getAndroidContext() { - return this; - } - - @Override - public DataManager getDataManager() { - return ((GalleryApp) getApplication()).getDataManager(); - } - - @Override - public ThreadPool getThreadPool() { - return ((GalleryApp) getApplication()).getThreadPool(); - } - - public synchronized StateManager getStateManager() { - if (mStateManager == null) { - mStateManager = new StateManager(this); - } - return mStateManager; - } - - public GLRoot getGLRoot() { - return mGLRootView; - } - - public OrientationManager getOrientationManager() { - return mOrientationManager; - } - - @Override - public void setContentView(int resId) { - super.setContentView(resId); - mGLRootView = (GLRootView) findViewById(R.id.gl_root_view); - } - - protected void onStorageReady() { - if (mAlertDialog != null) { - mAlertDialog.dismiss(); - mAlertDialog = null; - unregisterReceiver(mMountReceiver); - } - } - - @Override - protected void onStart() { - super.onStart(); - if (getExternalCacheDir() == null) { - OnCancelListener onCancel = new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - finish(); - } - }; - OnClickListener onClick = new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - dialog.cancel(); - } - }; - AlertDialog.Builder builder = new AlertDialog.Builder(this) - .setTitle(R.string.no_external_storage_title) - .setMessage(R.string.no_external_storage) - .setNegativeButton(android.R.string.cancel, onClick) - .setOnCancelListener(onCancel); - if (ApiHelper.HAS_SET_ICON_ATTRIBUTE) { - setAlertDialogIconAttribute(builder); - } else { - builder.setIcon(android.R.drawable.ic_dialog_alert); - } - mAlertDialog = builder.show(); - registerReceiver(mMountReceiver, mMountFilter); - } - mPanoramaViewHelper.onStart(); - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private static void setAlertDialogIconAttribute( - AlertDialog.Builder builder) { - builder.setIconAttribute(android.R.attr.alertDialogIcon); - } - - @Override - protected void onStop() { - super.onStop(); - if (mAlertDialog != null) { - unregisterReceiver(mMountReceiver); - mAlertDialog.dismiss(); - mAlertDialog = null; - } - mPanoramaViewHelper.onStop(); - } - - @Override - protected void onResume() { - super.onResume(); - mGLRootView.lockRenderThread(); - try { - getStateManager().resume(); - getDataManager().resume(); - } finally { - mGLRootView.unlockRenderThread(); - } - mGLRootView.onResume(); - mOrientationManager.resume(); - } - - @Override - protected void onPause() { - super.onPause(); - mOrientationManager.pause(); - mGLRootView.onPause(); - mGLRootView.lockRenderThread(); - try { - getStateManager().pause(); - getDataManager().pause(); - } finally { - mGLRootView.unlockRenderThread(); - } - GalleryBitmapPool.getInstance().clear(); - MediaItem.getBytesBufferPool().clear(); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mGLRootView.lockRenderThread(); - try { - getStateManager().destroy(); - } finally { - mGLRootView.unlockRenderThread(); - } - doUnbindBatchService(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - mGLRootView.lockRenderThread(); - try { - getStateManager().notifyActivityResult( - requestCode, resultCode, data); - } finally { - mGLRootView.unlockRenderThread(); - } - } - - @Override - public void onBackPressed() { - // send the back event to the top sub-state - GLRoot root = getGLRoot(); - root.lockRenderThread(); - try { - getStateManager().onBackPressed(); - } finally { - root.unlockRenderThread(); - } - } - - public GalleryActionBar getGalleryActionBar() { - if (mActionBar == null) { - mActionBar = new GalleryActionBar(this); - } - return mActionBar; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - GLRoot root = getGLRoot(); - root.lockRenderThread(); - try { - return getStateManager().itemSelected(item); - } finally { - root.unlockRenderThread(); - } - } - - protected void disableToggleStatusBar() { - mDisableToggleStatusBar = true; - } - - // Shows status bar in portrait view, hide in landscape view - private void toggleStatusBarByOrientation() { - if (mDisableToggleStatusBar) return; - - Window win = getWindow(); - if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { - win.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } else { - win.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - } - - public TransitionStore getTransitionStore() { - return mTransitionStore; - } - - public PanoramaViewHelper getPanoramaViewHelper() { - return mPanoramaViewHelper; - } - - protected boolean isFullscreen() { - return (getWindow().getAttributes().flags - & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0; - } - - private BatchService mBatchService; - private boolean mBatchServiceIsBound = false; - private ServiceConnection mBatchServiceConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - mBatchService = ((BatchService.LocalBinder)service).getService(); - } - - public void onServiceDisconnected(ComponentName className) { - mBatchService = null; - } - }; - - private void doBindBatchService() { - bindService(new Intent(this, BatchService.class), mBatchServiceConnection, Context.BIND_AUTO_CREATE); - mBatchServiceIsBound = true; - } - - private void doUnbindBatchService() { - if (mBatchServiceIsBound) { - // Detach our existing connection. - unbindService(mBatchServiceConnection); - mBatchServiceIsBound = false; - } - } - - public ThreadPool getBatchServiceThreadPoolIfAvailable() { - if (mBatchServiceIsBound && mBatchService != null) { - return mBatchService.getThreadPool(); - } else { - throw new RuntimeException("Batch service unavailable"); - } - } -} diff --git a/src/com/android/gallery3d/app/ActivityState.java b/src/com/android/gallery3d/app/ActivityState.java deleted file mode 100644 index 2f1e0c9d9..000000000 --- a/src/com/android/gallery3d/app/ActivityState.java +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.ActionBar; -import android.app.Activity; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.res.Configuration; -import android.os.BatteryManager; -import android.os.Bundle; -import android.view.HapticFeedbackConstants; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.Window; -import android.view.WindowManager; - -import com.android.gallery3d.R; -import com.android.gallery3d.anim.StateTransitionAnimation; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.PreparePageFadeoutTexture; -import com.android.gallery3d.util.GalleryUtils; - -abstract public class ActivityState { - protected static final int FLAG_HIDE_ACTION_BAR = 1; - protected static final int FLAG_HIDE_STATUS_BAR = 2; - protected static final int FLAG_SCREEN_ON_WHEN_PLUGGED = 4; - protected static final int FLAG_SCREEN_ON_ALWAYS = 8; - protected static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON = 16; - protected static final int FLAG_SHOW_WHEN_LOCKED = 32; - - protected AbstractGalleryActivity mActivity; - protected Bundle mData; - protected int mFlags; - - protected ResultEntry mReceivedResults; - protected ResultEntry mResult; - - protected static class ResultEntry { - public int requestCode; - public int resultCode = Activity.RESULT_CANCELED; - public Intent resultData; - } - - private boolean mDestroyed = false; - private boolean mPlugged = false; - boolean mIsFinishing = false; - - private static final String KEY_TRANSITION_IN = "transition-in"; - - private StateTransitionAnimation.Transition mNextTransition = - StateTransitionAnimation.Transition.None; - private StateTransitionAnimation mIntroAnimation; - private GLView mContentPane; - - protected ActivityState() { - } - - protected void setContentPane(GLView content) { - mContentPane = content; - if (mIntroAnimation != null) { - mContentPane.setIntroAnimation(mIntroAnimation); - mIntroAnimation = null; - } - mContentPane.setBackgroundColor(getBackgroundColor()); - mActivity.getGLRoot().setContentPane(mContentPane); - } - - void initialize(AbstractGalleryActivity activity, Bundle data) { - mActivity = activity; - mData = data; - } - - public Bundle getData() { - return mData; - } - - protected void onBackPressed() { - mActivity.getStateManager().finishState(this); - } - - protected void setStateResult(int resultCode, Intent data) { - if (mResult == null) return; - mResult.resultCode = resultCode; - mResult.resultData = data; - } - - protected void onConfigurationChanged(Configuration config) { - } - - protected void onSaveState(Bundle outState) { - } - - protected void onStateResult(int requestCode, int resultCode, Intent data) { - } - - protected float[] mBackgroundColor; - - protected int getBackgroundColorId() { - return R.color.default_background; - } - - protected float[] getBackgroundColor() { - return mBackgroundColor; - } - - protected void onCreate(Bundle data, Bundle storedState) { - mBackgroundColor = GalleryUtils.intColorToFloatARGBArray( - mActivity.getResources().getColor(getBackgroundColorId())); - } - - protected void clearStateResult() { - } - - BroadcastReceiver mPowerIntentReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - final String action = intent.getAction(); - if (Intent.ACTION_BATTERY_CHANGED.equals(action)) { - boolean plugged = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0)); - - if (plugged != mPlugged) { - mPlugged = plugged; - setScreenFlags(); - } - } - } - }; - - private void setScreenFlags() { - final Window win = mActivity.getWindow(); - final WindowManager.LayoutParams params = win.getAttributes(); - if ((0 != (mFlags & FLAG_SCREEN_ON_ALWAYS)) || - (mPlugged && 0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED))) { - params.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - } else { - params.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; - } - if (0 != (mFlags & FLAG_ALLOW_LOCK_WHILE_SCREEN_ON)) { - params.flags |= WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; - } else { - params.flags &= ~WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON; - } - if (0 != (mFlags & FLAG_SHOW_WHEN_LOCKED)) { - params.flags |= WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; - } else { - params.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED; - } - win.setAttributes(params); - } - - protected void transitionOnNextPause(Class<? extends ActivityState> outgoing, - Class<? extends ActivityState> incoming, StateTransitionAnimation.Transition hint) { - if (outgoing == SinglePhotoPage.class && incoming == AlbumPage.class) { - mNextTransition = StateTransitionAnimation.Transition.Outgoing; - } else if (outgoing == AlbumPage.class && incoming == SinglePhotoPage.class) { - mNextTransition = StateTransitionAnimation.Transition.PhotoIncoming; - } else { - mNextTransition = hint; - } - } - - protected void performHapticFeedback(int feedbackConstant) { - mActivity.getWindow().getDecorView().performHapticFeedback(feedbackConstant, - HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); - } - - protected void onPause() { - if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) { - ((Activity) mActivity).unregisterReceiver(mPowerIntentReceiver); - } - if (mNextTransition != StateTransitionAnimation.Transition.None) { - mActivity.getTransitionStore().put(KEY_TRANSITION_IN, mNextTransition); - PreparePageFadeoutTexture.prepareFadeOutTexture(mActivity, mContentPane); - mNextTransition = StateTransitionAnimation.Transition.None; - } - } - - // should only be called by StateManager - void resume() { - AbstractGalleryActivity activity = mActivity; - ActionBar actionBar = activity.getActionBar(); - if (actionBar != null) { - if ((mFlags & FLAG_HIDE_ACTION_BAR) != 0) { - actionBar.hide(); - } else { - actionBar.show(); - } - int stateCount = mActivity.getStateManager().getStateCount(); - mActivity.getGalleryActionBar().setDisplayOptions(stateCount > 1, true); - // Default behavior, this can be overridden in ActivityState's onResume. - actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - - activity.invalidateOptionsMenu(); - - setScreenFlags(); - - boolean lightsOut = ((mFlags & FLAG_HIDE_STATUS_BAR) != 0); - mActivity.getGLRoot().setLightsOutMode(lightsOut); - - ResultEntry entry = mReceivedResults; - if (entry != null) { - mReceivedResults = null; - onStateResult(entry.requestCode, entry.resultCode, entry.resultData); - } - - if (0 != (mFlags & FLAG_SCREEN_ON_WHEN_PLUGGED)) { - // we need to know whether the device is plugged in to do this correctly - final IntentFilter filter = new IntentFilter(); - filter.addAction(Intent.ACTION_BATTERY_CHANGED); - activity.registerReceiver(mPowerIntentReceiver, filter); - } - - onResume(); - - // the transition store should be cleared after resume; - mActivity.getTransitionStore().clear(); - } - - // a subclass of ActivityState should override the method to resume itself - protected void onResume() { - RawTexture fade = mActivity.getTransitionStore().get( - PreparePageFadeoutTexture.KEY_FADE_TEXTURE); - mNextTransition = mActivity.getTransitionStore().get( - KEY_TRANSITION_IN, StateTransitionAnimation.Transition.None); - if (mNextTransition != StateTransitionAnimation.Transition.None) { - mIntroAnimation = new StateTransitionAnimation(mNextTransition, fade); - mNextTransition = StateTransitionAnimation.Transition.None; - } - } - - protected boolean onCreateActionBar(Menu menu) { - // TODO: we should return false if there is no menu to show - // this is a workaround for a bug in system - return true; - } - - protected boolean onItemSelected(MenuItem item) { - return false; - } - - protected void onDestroy() { - mDestroyed = true; - } - - boolean isDestroyed() { - return mDestroyed; - } - - public boolean isFinishing() { - return mIsFinishing; - } - - protected MenuInflater getSupportMenuInflater() { - return mActivity.getMenuInflater(); - } -} diff --git a/src/com/android/gallery3d/app/AlbumDataLoader.java b/src/com/android/gallery3d/app/AlbumDataLoader.java deleted file mode 100644 index 28a822830..000000000 --- a/src/com/android/gallery3d/app/AlbumDataLoader.java +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.os.Handler; -import android.os.Message; -import android.os.Process; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.SynchronizedHandler; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -public class AlbumDataLoader { - @SuppressWarnings("unused") - private static final String TAG = "AlbumDataAdapter"; - private static final int DATA_CACHE_SIZE = 1000; - - private static final int MSG_LOAD_START = 1; - private static final int MSG_LOAD_FINISH = 2; - private static final int MSG_RUN_OBJECT = 3; - - private static final int MIN_LOAD_COUNT = 32; - private static final int MAX_LOAD_COUNT = 64; - - private final MediaItem[] mData; - private final long[] mItemVersion; - private final long[] mSetVersion; - - public static interface DataListener { - public void onContentChanged(int index); - public void onSizeChanged(int size); - } - - private int mActiveStart = 0; - private int mActiveEnd = 0; - - private int mContentStart = 0; - private int mContentEnd = 0; - - private final MediaSet mSource; - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - - private final Handler mMainHandler; - private int mSize = 0; - - private DataListener mDataListener; - private MySourceListener mSourceListener = new MySourceListener(); - private LoadingListener mLoadingListener; - - private ReloadTask mReloadTask; - // the data version on which last loading failed - private long mFailedVersion = MediaObject.INVALID_DATA_VERSION; - - public AlbumDataLoader(AbstractGalleryActivity context, MediaSet mediaSet) { - mSource = mediaSet; - - mData = new MediaItem[DATA_CACHE_SIZE]; - mItemVersion = new long[DATA_CACHE_SIZE]; - mSetVersion = new long[DATA_CACHE_SIZE]; - Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION); - Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION); - - mMainHandler = new SynchronizedHandler(context.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_RUN_OBJECT: - ((Runnable) message.obj).run(); - return; - case MSG_LOAD_START: - if (mLoadingListener != null) mLoadingListener.onLoadingStarted(); - return; - case MSG_LOAD_FINISH: - if (mLoadingListener != null) { - boolean loadingFailed = - (mFailedVersion != MediaObject.INVALID_DATA_VERSION); - mLoadingListener.onLoadingFinished(loadingFailed); - } - return; - } - } - }; - } - - public void resume() { - mSource.addContentListener(mSourceListener); - mReloadTask = new ReloadTask(); - mReloadTask.start(); - } - - public void pause() { - mReloadTask.terminate(); - mReloadTask = null; - mSource.removeContentListener(mSourceListener); - } - - public MediaItem get(int index) { - if (!isActive(index)) { - return mSource.getMediaItem(index, 1).get(0); - } - return mData[index % mData.length]; - } - - public int getActiveStart() { - return mActiveStart; - } - - public boolean isActive(int index) { - return index >= mActiveStart && index < mActiveEnd; - } - - public int size() { - return mSize; - } - - // Returns the index of the MediaItem with the given path or - // -1 if the path is not cached - public int findItem(Path id) { - for (int i = mContentStart; i < mContentEnd; i++) { - MediaItem item = mData[i % DATA_CACHE_SIZE]; - if (item != null && id == item.getPath()) { - return i; - } - } - return -1; - } - - private void clearSlot(int slotIndex) { - mData[slotIndex] = null; - mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - } - - private void setContentWindow(int contentStart, int contentEnd) { - if (contentStart == mContentStart && contentEnd == mContentEnd) return; - int end = mContentEnd; - int start = mContentStart; - - // We need change the content window before calling reloadData(...) - synchronized (this) { - mContentStart = contentStart; - mContentEnd = contentEnd; - } - long[] itemVersion = mItemVersion; - long[] setVersion = mSetVersion; - if (contentStart >= end || start >= contentEnd) { - for (int i = start, n = end; i < n; ++i) { - clearSlot(i % DATA_CACHE_SIZE); - } - } else { - for (int i = start; i < contentStart; ++i) { - clearSlot(i % DATA_CACHE_SIZE); - } - for (int i = contentEnd, n = end; i < n; ++i) { - clearSlot(i % DATA_CACHE_SIZE); - } - } - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - - public void setActiveWindow(int start, int end) { - if (start == mActiveStart && end == mActiveEnd) return; - - Utils.assertTrue(start <= end - && end - start <= mData.length && end <= mSize); - - int length = mData.length; - mActiveStart = start; - mActiveEnd = end; - - // If no data is visible, keep the cache content - if (start == end) return; - - int contentStart = Utils.clamp((start + end) / 2 - length / 2, - 0, Math.max(0, mSize - length)); - int contentEnd = Math.min(contentStart + length, mSize); - if (mContentStart > start || mContentEnd < end - || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) { - setContentWindow(contentStart, contentEnd); - } - } - - private class MySourceListener implements ContentListener { - @Override - public void onContentDirty() { - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - public void setDataListener(DataListener listener) { - mDataListener = listener; - } - - public void setLoadingListener(LoadingListener listener) { - mLoadingListener = listener; - } - - private <T> T executeAndWait(Callable<T> callable) { - FutureTask<T> task = new FutureTask<T>(callable); - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); - try { - return task.get(); - } catch (InterruptedException e) { - return null; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - private static class UpdateInfo { - public long version; - public int reloadStart; - public int reloadCount; - - public int size; - public ArrayList<MediaItem> items; - } - - private class GetUpdateInfo implements Callable<UpdateInfo> { - private final long mVersion; - - public GetUpdateInfo(long version) { - mVersion = version; - } - - @Override - public UpdateInfo call() throws Exception { - if (mFailedVersion == mVersion) { - // previous loading failed, return null to pause loading - return null; - } - UpdateInfo info = new UpdateInfo(); - long version = mVersion; - info.version = mSourceVersion; - info.size = mSize; - long setVersion[] = mSetVersion; - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - int index = i % DATA_CACHE_SIZE; - if (setVersion[index] != version) { - info.reloadStart = i; - info.reloadCount = Math.min(MAX_LOAD_COUNT, n - i); - return info; - } - } - return mSourceVersion == mVersion ? null : info; - } - } - - private class UpdateContent implements Callable<Void> { - - private UpdateInfo mUpdateInfo; - - public UpdateContent(UpdateInfo info) { - mUpdateInfo = info; - } - - @Override - public Void call() throws Exception { - UpdateInfo info = mUpdateInfo; - mSourceVersion = info.version; - if (mSize != info.size) { - mSize = info.size; - if (mDataListener != null) mDataListener.onSizeChanged(mSize); - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - - ArrayList<MediaItem> items = info.items; - - mFailedVersion = MediaObject.INVALID_DATA_VERSION; - if ((items == null) || items.isEmpty()) { - if (info.reloadCount > 0) { - mFailedVersion = info.version; - Log.d(TAG, "loading failed: " + mFailedVersion); - } - return null; - } - int start = Math.max(info.reloadStart, mContentStart); - int end = Math.min(info.reloadStart + items.size(), mContentEnd); - - for (int i = start; i < end; ++i) { - int index = i % DATA_CACHE_SIZE; - mSetVersion[index] = info.version; - MediaItem updateItem = items.get(i - info.reloadStart); - long itemVersion = updateItem.getDataVersion(); - if (mItemVersion[index] != itemVersion) { - mItemVersion[index] = itemVersion; - mData[index] = updateItem; - if (mDataListener != null && i >= mActiveStart && i < mActiveEnd) { - mDataListener.onContentChanged(i); - } - } - } - return null; - } - } - - /* - * The thread model of ReloadTask - * * - * [Reload Task] [Main Thread] - * | | - * getUpdateInfo() --> | (synchronous call) - * (wait) <---- getUpdateInfo() - * | | - * Load Data | - * | | - * updateContent() --> | (synchronous call) - * (wait) updateContent() - * | | - * | | - */ - private class ReloadTask extends Thread { - - private volatile boolean mActive = true; - private volatile boolean mDirty = true; - private boolean mIsLoading = false; - - private void updateLoading(boolean loading) { - if (mIsLoading == loading) return; - mIsLoading = loading; - mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); - } - - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - - boolean updateComplete = false; - while (mActive) { - synchronized (this) { - if (mActive && !mDirty && updateComplete) { - updateLoading(false); - if (mFailedVersion != MediaObject.INVALID_DATA_VERSION) { - Log.d(TAG, "reload pause"); - } - Utils.waitWithoutInterrupt(this); - if (mActive && (mFailedVersion != MediaObject.INVALID_DATA_VERSION)) { - Log.d(TAG, "reload resume"); - } - continue; - } - mDirty = false; - } - updateLoading(true); - long version = mSource.reload(); - UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); - updateComplete = info == null; - if (updateComplete) continue; - if (info.version != version) { - info.size = mSource.getMediaItemCount(); - info.version = version; - } - if (info.reloadCount > 0) { - info.items = mSource.getMediaItem(info.reloadStart, info.reloadCount); - } - executeAndWait(new UpdateContent(info)); - } - updateLoading(false); - } - - public synchronized void notifyDirty() { - mDirty = true; - notifyAll(); - } - - public synchronized void terminate() { - mActive = false; - notifyAll(); - } - } -} diff --git a/src/com/android/gallery3d/app/AlbumPage.java b/src/com/android/gallery3d/app/AlbumPage.java deleted file mode 100644 index 658abbbd4..000000000 --- a/src/com/android/gallery3d/app/AlbumPage.java +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.Rect; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.provider.MediaStore; -import android.view.HapticFeedbackConstants; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.filtershow.crop.CropExtras; -import com.android.gallery3d.glrenderer.FadeTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.ui.ActionModeHandler; -import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; -import com.android.gallery3d.ui.AlbumSlotRenderer; -import com.android.gallery3d.ui.DetailsHelper; -import com.android.gallery3d.ui.DetailsHelper.CloseListener; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.PhotoFallbackEffect; -import com.android.gallery3d.ui.RelativePosition; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SlotView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.MediaSetUtils; - - -public class AlbumPage extends ActivityState implements GalleryActionBar.ClusterRunner, - SelectionManager.SelectionListener, MediaSet.SyncListener, GalleryActionBar.OnAlbumModeSelectedListener { - @SuppressWarnings("unused") - private static final String TAG = "AlbumPage"; - - public static final String KEY_MEDIA_PATH = "media-path"; - public static final String KEY_PARENT_MEDIA_PATH = "parent-media-path"; - public static final String KEY_SET_CENTER = "set-center"; - public static final String KEY_AUTO_SELECT_ALL = "auto-select-all"; - public static final String KEY_SHOW_CLUSTER_MENU = "cluster-menu"; - public static final String KEY_EMPTY_ALBUM = "empty-album"; - public static final String KEY_RESUME_ANIMATION = "resume_animation"; - - private static final int REQUEST_SLIDESHOW = 1; - public static final int REQUEST_PHOTO = 2; - private static final int REQUEST_DO_ANIMATION = 3; - - private static final int BIT_LOADING_RELOAD = 1; - private static final int BIT_LOADING_SYNC = 2; - - private static final float USER_DISTANCE_METER = 0.3f; - - private boolean mIsActive = false; - private AlbumSlotRenderer mAlbumView; - private Path mMediaSetPath; - private String mParentMediaSetString; - private SlotView mSlotView; - - private AlbumDataLoader mAlbumDataAdapter; - - protected SelectionManager mSelectionManager; - - private boolean mGetContent; - private boolean mShowClusterMenu; - - private ActionModeHandler mActionModeHandler; - private int mFocusIndex = 0; - private DetailsHelper mDetailsHelper; - private MyDetailsSource mDetailsSource; - private MediaSet mMediaSet; - private boolean mShowDetails; - private float mUserDistance; // in pixel - private Future<Integer> mSyncTask = null; - private boolean mLaunchedFromPhotoPage; - private boolean mInCameraApp; - private boolean mInCameraAndWantQuitOnPause; - - private int mLoadingBits = 0; - private boolean mInitialSynced = false; - private int mSyncResult; - private boolean mLoadingFailed; - private RelativePosition mOpenCenter = new RelativePosition(); - - private Handler mHandler; - private static final int MSG_PICK_PHOTO = 0; - - private PhotoFallbackEffect mResumeEffect; - private PhotoFallbackEffect.PositionProvider mPositionProvider = - new PhotoFallbackEffect.PositionProvider() { - @Override - public Rect getPosition(int index) { - Rect rect = mSlotView.getSlotRect(index); - Rect bounds = mSlotView.bounds(); - rect.offset(bounds.left - mSlotView.getScrollX(), - bounds.top - mSlotView.getScrollY()); - return rect; - } - - @Override - public int getItemIndex(Path path) { - int start = mSlotView.getVisibleStart(); - int end = mSlotView.getVisibleEnd(); - for (int i = start; i < end; ++i) { - MediaItem item = mAlbumDataAdapter.get(i); - if (item != null && item.getPath() == path) return i; - } - return -1; - } - }; - - @Override - protected int getBackgroundColorId() { - return R.color.album_background; - } - - private final GLView mRootPane = new GLView() { - private final float mMatrix[] = new float[16]; - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - - int slotViewTop = mActivity.getGalleryActionBar().getHeight(); - int slotViewBottom = bottom - top; - int slotViewRight = right - left; - - if (mShowDetails) { - mDetailsHelper.layout(left, slotViewTop, right, bottom); - } else { - mAlbumView.setHighlightItemPath(null); - } - - // Set the mSlotView as a reference point to the open animation - mOpenCenter.setReferencePosition(0, slotViewTop); - mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom); - GalleryUtils.setViewPointMatrix(mMatrix, - (right - left) / 2, (bottom - top) / 2, -mUserDistance); - } - - @Override - protected void render(GLCanvas canvas) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - canvas.multiplyMatrix(mMatrix, 0); - super.render(canvas); - - if (mResumeEffect != null) { - boolean more = mResumeEffect.draw(canvas); - if (!more) { - mResumeEffect = null; - mAlbumView.setSlotFilter(null); - } - // We want to render one more time even when no more effect - // required. So that the animated thumbnails could be draw - // with declarations in super.render(). - invalidate(); - } - canvas.restore(); - } - }; - - // This are the transitions we want: - // - // +--------+ +------------+ +-------+ +----------+ - // | Camera |---------->| Fullscreen |--->| Album |--->| AlbumSet | - // | View | thumbnail | Photo | up | Page | up | Page | - // +--------+ +------------+ +-------+ +----------+ - // ^ | | ^ | - // | | | | | close - // +----------back--------+ +----back----+ +--back-> app - // - @Override - protected void onBackPressed() { - if (mShowDetails) { - hideDetails(); - } else if (mSelectionManager.inSelectionMode()) { - mSelectionManager.leaveSelectionMode(); - } else { - if(mLaunchedFromPhotoPage) { - mActivity.getTransitionStore().putIfNotPresent( - PhotoPage.KEY_ALBUMPAGE_TRANSITION, - PhotoPage.MSG_ALBUMPAGE_RESUMED); - } - // TODO: fix this regression - // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); - if (mInCameraApp) { - super.onBackPressed(); - } else { - onUpPressed(); - } - } - } - - private void onUpPressed() { - if (mInCameraApp) { - GalleryUtils.startGalleryActivity(mActivity); - } else if (mActivity.getStateManager().getStateCount() > 1) { - super.onBackPressed(); - } else if (mParentMediaSetString != null) { - Bundle data = new Bundle(getData()); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, mParentMediaSetString); - mActivity.getStateManager().switchState( - this, AlbumSetPage.class, data); - } - } - - private void onDown(int index) { - mAlbumView.setPressedIndex(index); - } - - private void onUp(boolean followedByLongPress) { - if (followedByLongPress) { - // Avoid showing press-up animations for long-press. - mAlbumView.setPressedIndex(-1); - } else { - mAlbumView.setPressedUp(); - } - } - - private void onSingleTapUp(int slotIndex) { - if (!mIsActive) return; - - if (mSelectionManager.inSelectionMode()) { - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; // Item not ready yet, ignore the click - mSelectionManager.toggle(item.getPath()); - mSlotView.invalidate(); - } else { - // Render transition in pressed state - mAlbumView.setPressedIndex(slotIndex); - mAlbumView.setPressedUp(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_PHOTO, slotIndex, 0), - FadeTexture.DURATION); - } - } - - private void pickPhoto(int slotIndex) { - pickPhoto(slotIndex, false); - } - - private void pickPhoto(int slotIndex, boolean startInFilmstrip) { - if (!mIsActive) return; - - if (!startInFilmstrip) { - // Launch photos in lights out mode - mActivity.getGLRoot().setLightsOutMode(true); - } - - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; // Item not ready yet, ignore the click - if (mGetContent) { - onGetContent(item); - } else if (mLaunchedFromPhotoPage) { - TransitionStore transitions = mActivity.getTransitionStore(); - transitions.put( - PhotoPage.KEY_ALBUMPAGE_TRANSITION, - PhotoPage.MSG_ALBUMPAGE_PICKED); - transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); - onBackPressed(); - } else { - // Get into the PhotoPage. - // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); - Bundle data = new Bundle(); - data.putInt(PhotoPage.KEY_INDEX_HINT, slotIndex); - data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT, - mSlotView.getSlotRect(slotIndex, mRootPane)); - data.putString(PhotoPage.KEY_MEDIA_SET_PATH, - mMediaSetPath.toString()); - data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, - item.getPath().toString()); - data.putInt(PhotoPage.KEY_ALBUMPAGE_TRANSITION, - PhotoPage.MSG_ALBUMPAGE_STARTED); - data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, - startInFilmstrip); - data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, mMediaSet.isCameraRoll()); - if (startInFilmstrip) { - mActivity.getStateManager().switchState(this, FilmstripPage.class, data); - } else { - mActivity.getStateManager().startStateForResult( - SinglePhotoPage.class, REQUEST_PHOTO, data); - } - } - } - - private void onGetContent(final MediaItem item) { - DataManager dm = mActivity.getDataManager(); - Activity activity = mActivity; - if (mData.getString(Gallery.EXTRA_CROP) != null) { - Uri uri = dm.getContentUri(item.getPath()); - Intent intent = new Intent(CropActivity.CROP_ACTION, uri) - .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) - .putExtras(getData()); - if (mData.getParcelable(MediaStore.EXTRA_OUTPUT) == null) { - intent.putExtra(CropExtras.KEY_RETURN_DATA, true); - } - activity.startActivity(intent); - activity.finish(); - } else { - Intent intent = new Intent(null, item.getContentUri()) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - activity.setResult(Activity.RESULT_OK, intent); - activity.finish(); - } - } - - public void onLongTap(int slotIndex) { - if (mGetContent) return; - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; - mSelectionManager.setAutoLeaveSelectionMode(true); - mSelectionManager.toggle(item.getPath()); - mSlotView.invalidate(); - } - - @Override - public void doCluster(int clusterType) { - String basePath = mMediaSet.getPath().toString(); - String newPath = FilterUtils.newClusterPath(basePath, clusterType); - Bundle data = new Bundle(getData()); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath); - if (mShowClusterMenu) { - Context context = mActivity.getAndroidContext(); - data.putString(AlbumSetPage.KEY_SET_TITLE, mMediaSet.getName()); - data.putString(AlbumSetPage.KEY_SET_SUBTITLE, - GalleryActionBar.getClusterByTypeString(context, clusterType)); - } - - // mAlbumView.savePositions(PositionRepository.getInstance(mActivity)); - mActivity.getStateManager().startStateForResult( - AlbumSetPage.class, REQUEST_DO_ANIMATION, data); - } - - @Override - protected void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER); - initializeViews(); - initializeData(data); - mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false); - mShowClusterMenu = data.getBoolean(KEY_SHOW_CLUSTER_MENU, false); - mDetailsSource = new MyDetailsSource(); - Context context = mActivity.getAndroidContext(); - - if (data.getBoolean(KEY_AUTO_SELECT_ALL)) { - mSelectionManager.selectAll(); - } - - mLaunchedFromPhotoPage = - mActivity.getStateManager().hasStateClass(FilmstripPage.class); - mInCameraApp = data.getBoolean(PhotoPage.KEY_APP_BRIDGE, false); - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_PICK_PHOTO: { - pickPhoto(message.arg1); - break; - } - default: - throw new AssertionError(message.what); - } - } - }; - } - - @Override - protected void onResume() { - super.onResume(); - mIsActive = true; - - mResumeEffect = mActivity.getTransitionStore().get(KEY_RESUME_ANIMATION); - if (mResumeEffect != null) { - mAlbumView.setSlotFilter(mResumeEffect); - mResumeEffect.setPositionProvider(mPositionProvider); - mResumeEffect.start(); - } - - setContentPane(mRootPane); - - boolean enableHomeButton = (mActivity.getStateManager().getStateCount() > 1) | - mParentMediaSetString != null; - GalleryActionBar actionBar = mActivity.getGalleryActionBar(); - actionBar.setDisplayOptions(enableHomeButton, false); - if (!mGetContent) { - actionBar.enableAlbumModeMenu(GalleryActionBar.ALBUM_GRID_MODE_SELECTED, this); - } - - // Set the reload bit here to prevent it exit this page in clearLoadingBit(). - setLoadingBit(BIT_LOADING_RELOAD); - mLoadingFailed = false; - mAlbumDataAdapter.resume(); - - mAlbumView.resume(); - mAlbumView.setPressedIndex(-1); - mActionModeHandler.resume(); - if (!mInitialSynced) { - setLoadingBit(BIT_LOADING_SYNC); - mSyncTask = mMediaSet.requestSync(this); - } - mInCameraAndWantQuitOnPause = mInCameraApp; - } - - @Override - protected void onPause() { - super.onPause(); - mIsActive = false; - - if (mSelectionManager.inSelectionMode()) { - mSelectionManager.leaveSelectionMode(); - } - mAlbumView.setSlotFilter(null); - mActionModeHandler.pause(); - mAlbumDataAdapter.pause(); - mAlbumView.pause(); - DetailsHelper.pause(); - if (!mGetContent) { - mActivity.getGalleryActionBar().disableAlbumModeMenu(true); - } - - if (mSyncTask != null) { - mSyncTask.cancel(); - mSyncTask = null; - clearLoadingBit(BIT_LOADING_SYNC); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - if (mAlbumDataAdapter != null) { - mAlbumDataAdapter.setLoadingListener(null); - } - mActionModeHandler.destroy(); - } - - private void initializeViews() { - mSelectionManager = new SelectionManager(mActivity, false); - mSelectionManager.setSelectionListener(this); - Config.AlbumPage config = Config.AlbumPage.get(mActivity); - mSlotView = new SlotView(mActivity, config.slotViewSpec); - mAlbumView = new AlbumSlotRenderer(mActivity, mSlotView, - mSelectionManager, config.placeholderColor); - mSlotView.setSlotRenderer(mAlbumView); - mRootPane.addComponent(mSlotView); - mSlotView.setListener(new SlotView.SimpleListener() { - @Override - public void onDown(int index) { - AlbumPage.this.onDown(index); - } - - @Override - public void onUp(boolean followedByLongPress) { - AlbumPage.this.onUp(followedByLongPress); - } - - @Override - public void onSingleTapUp(int slotIndex) { - AlbumPage.this.onSingleTapUp(slotIndex); - } - - @Override - public void onLongTap(int slotIndex) { - AlbumPage.this.onLongTap(slotIndex); - } - }); - mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager); - mActionModeHandler.setActionModeListener(new ActionModeListener() { - @Override - public boolean onActionItemClicked(MenuItem item) { - return onItemSelected(item); - } - }); - } - - private void initializeData(Bundle data) { - mMediaSetPath = Path.fromString(data.getString(KEY_MEDIA_PATH)); - mParentMediaSetString = data.getString(KEY_PARENT_MEDIA_PATH); - mMediaSet = mActivity.getDataManager().getMediaSet(mMediaSetPath); - if (mMediaSet == null) { - Utils.fail("MediaSet is null. Path = %s", mMediaSetPath); - } - mSelectionManager.setSourceMediaSet(mMediaSet); - mAlbumDataAdapter = new AlbumDataLoader(mActivity, mMediaSet); - mAlbumDataAdapter.setLoadingListener(new MyLoadingListener()); - mAlbumView.setModel(mAlbumDataAdapter); - } - - private void showDetails() { - mShowDetails = true; - if (mDetailsHelper == null) { - mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource); - mDetailsHelper.setCloseListener(new CloseListener() { - @Override - public void onClose() { - hideDetails(); - } - }); - } - mDetailsHelper.show(); - } - - private void hideDetails() { - mShowDetails = false; - mDetailsHelper.hide(); - mAlbumView.setHighlightItemPath(null); - mSlotView.invalidate(); - } - - @Override - protected boolean onCreateActionBar(Menu menu) { - GalleryActionBar actionBar = mActivity.getGalleryActionBar(); - MenuInflater inflator = getSupportMenuInflater(); - if (mGetContent) { - inflator.inflate(R.menu.pickup, menu); - int typeBits = mData.getInt(Gallery.KEY_TYPE_BITS, - DataManager.INCLUDE_IMAGE); - actionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); - } else { - inflator.inflate(R.menu.album, menu); - actionBar.setTitle(mMediaSet.getName()); - - FilterUtils.setupMenuItems(actionBar, mMediaSetPath, true); - - menu.findItem(R.id.action_group_by).setVisible(mShowClusterMenu); - menu.findItem(R.id.action_camera).setVisible( - MediaSetUtils.isCameraSource(mMediaSetPath) - && GalleryUtils.isCameraAvailable(mActivity)); - - } - actionBar.setSubtitle(null); - return true; - } - - private void prepareAnimationBackToFilmstrip(int slotIndex) { - if (mAlbumDataAdapter == null || !mAlbumDataAdapter.isActive(slotIndex)) return; - MediaItem item = mAlbumDataAdapter.get(slotIndex); - if (item == null) return; - TransitionStore transitions = mActivity.getTransitionStore(); - transitions.put(PhotoPage.KEY_INDEX_HINT, slotIndex); - transitions.put(PhotoPage.KEY_OPEN_ANIMATION_RECT, - mSlotView.getSlotRect(slotIndex, mRootPane)); - } - - private void switchToFilmstrip() { - if (mAlbumDataAdapter.size() < 1) return; - int targetPhoto = mSlotView.getVisibleStart(); - prepareAnimationBackToFilmstrip(targetPhoto); - if(mLaunchedFromPhotoPage) { - onBackPressed(); - } else { - pickPhoto(targetPhoto, true); - } - } - - @Override - protected boolean onItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: { - onUpPressed(); - return true; - } - case R.id.action_cancel: - mActivity.getStateManager().finishState(this); - return true; - case R.id.action_select: - mSelectionManager.setAutoLeaveSelectionMode(false); - mSelectionManager.enterSelectionMode(); - return true; - case R.id.action_group_by: { - mActivity.getGalleryActionBar().showClusterDialog(this); - return true; - } - case R.id.action_slideshow: { - mInCameraAndWantQuitOnPause = false; - Bundle data = new Bundle(); - data.putString(SlideshowPage.KEY_SET_PATH, - mMediaSetPath.toString()); - data.putBoolean(SlideshowPage.KEY_REPEAT, true); - mActivity.getStateManager().startStateForResult( - SlideshowPage.class, REQUEST_SLIDESHOW, data); - return true; - } - case R.id.action_details: { - if (mShowDetails) { - hideDetails(); - } else { - showDetails(); - } - return true; - } - case R.id.action_camera: { - GalleryUtils.startCameraActivity(mActivity); - return true; - } - default: - return false; - } - } - - @Override - protected void onStateResult(int request, int result, Intent data) { - switch (request) { - case REQUEST_SLIDESHOW: { - // data could be null, if there is no images in the album - if (data == null) return; - mFocusIndex = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); - mSlotView.setCenterIndex(mFocusIndex); - break; - } - case REQUEST_PHOTO: { - if (data == null) return; - mFocusIndex = data.getIntExtra(PhotoPage.KEY_RETURN_INDEX_HINT, 0); - mSlotView.makeSlotVisible(mFocusIndex); - break; - } - case REQUEST_DO_ANIMATION: { - mSlotView.startRisingAnimation(); - break; - } - } - } - - @Override - public void onSelectionModeChange(int mode) { - switch (mode) { - case SelectionManager.ENTER_SELECTION_MODE: { - mActionModeHandler.startActionMode(); - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - break; - } - case SelectionManager.LEAVE_SELECTION_MODE: { - mActionModeHandler.finishActionMode(); - mRootPane.invalidate(); - break; - } - case SelectionManager.SELECT_ALL_MODE: { - mActionModeHandler.updateSupportedOperation(); - mRootPane.invalidate(); - break; - } - } - } - - @Override - public void onSelectionChange(Path path, boolean selected) { - int count = mSelectionManager.getSelectedCount(); - String format = mActivity.getResources().getQuantityString( - R.plurals.number_of_items_selected, count); - mActionModeHandler.setTitle(String.format(format, count)); - mActionModeHandler.updateSupportedOperation(path, selected); - } - - @Override - public void onSyncDone(final MediaSet mediaSet, final int resultCode) { - Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result=" - + resultCode); - ((Activity) mActivity).runOnUiThread(new Runnable() { - @Override - public void run() { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - mSyncResult = resultCode; - try { - if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) { - mInitialSynced = true; - } - clearLoadingBit(BIT_LOADING_SYNC); - showSyncErrorIfNecessary(mLoadingFailed); - } finally { - root.unlockRenderThread(); - } - } - }); - } - - // Show sync error toast when all the following conditions are met: - // (1) both loading and sync are done, - // (2) sync result is error, - // (3) the page is still active, and - // (4) no photo is shown or loading fails. - private void showSyncErrorIfNecessary(boolean loadingFailed) { - if ((mLoadingBits == 0) && (mSyncResult == MediaSet.SYNC_RESULT_ERROR) && mIsActive - && (loadingFailed || (mAlbumDataAdapter.size() == 0))) { - Toast.makeText(mActivity, R.string.sync_album_error, - Toast.LENGTH_LONG).show(); - } - } - - private void setLoadingBit(int loadTaskBit) { - mLoadingBits |= loadTaskBit; - } - - private void clearLoadingBit(int loadTaskBit) { - mLoadingBits &= ~loadTaskBit; - if (mLoadingBits == 0 && mIsActive) { - if (mAlbumDataAdapter.size() == 0) { - Intent result = new Intent(); - result.putExtra(KEY_EMPTY_ALBUM, true); - setStateResult(Activity.RESULT_OK, result); - mActivity.getStateManager().finishState(this); - } - } - } - - private class MyLoadingListener implements LoadingListener { - @Override - public void onLoadingStarted() { - setLoadingBit(BIT_LOADING_RELOAD); - mLoadingFailed = false; - } - - @Override - public void onLoadingFinished(boolean loadingFailed) { - clearLoadingBit(BIT_LOADING_RELOAD); - mLoadingFailed = loadingFailed; - showSyncErrorIfNecessary(loadingFailed); - } - } - - private class MyDetailsSource implements DetailsHelper.DetailsSource { - private int mIndex; - - @Override - public int size() { - return mAlbumDataAdapter.size(); - } - - @Override - public int setIndex() { - Path id = mSelectionManager.getSelected(false).get(0); - mIndex = mAlbumDataAdapter.findItem(id); - return mIndex; - } - - @Override - public MediaDetails getDetails() { - // this relies on setIndex() being called beforehand - MediaObject item = mAlbumDataAdapter.get(mIndex); - if (item != null) { - mAlbumView.setHighlightItemPath(item.getPath()); - return item.getDetails(); - } else { - return null; - } - } - } - - @Override - public void onAlbumModeSelected(int mode) { - if (mode == GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED) { - switchToFilmstrip(); - } - } -} diff --git a/src/com/android/gallery3d/app/AlbumPicker.java b/src/com/android/gallery3d/app/AlbumPicker.java deleted file mode 100644 index 65eb77291..000000000 --- a/src/com/android/gallery3d/app/AlbumPicker.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Intent; -import android.os.Bundle; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.DataManager; - -public class AlbumPicker extends PickerActivity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle(R.string.select_album); - Intent intent = getIntent(); - Bundle extras = intent.getExtras(); - Bundle data = extras == null ? new Bundle() : new Bundle(extras); - - data.putBoolean(Gallery.KEY_GET_ALBUM, true); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(DataManager.INCLUDE_IMAGE)); - getStateManager().startState(AlbumSetPage.class, data); - } -} diff --git a/src/com/android/gallery3d/app/AlbumSetDataLoader.java b/src/com/android/gallery3d/app/AlbumSetDataLoader.java deleted file mode 100644 index cf380f812..000000000 --- a/src/com/android/gallery3d/app/AlbumSetDataLoader.java +++ /dev/null @@ -1,393 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.os.Handler; -import android.os.Message; -import android.os.Process; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.SynchronizedHandler; - -import java.util.Arrays; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -public class AlbumSetDataLoader { - @SuppressWarnings("unused") - private static final String TAG = "AlbumSetDataAdapter"; - - private static final int INDEX_NONE = -1; - - private static final int MIN_LOAD_COUNT = 4; - - private static final int MSG_LOAD_START = 1; - private static final int MSG_LOAD_FINISH = 2; - private static final int MSG_RUN_OBJECT = 3; - - public static interface DataListener { - public void onContentChanged(int index); - public void onSizeChanged(int size); - } - - private final MediaSet[] mData; - private final MediaItem[] mCoverItem; - private final int[] mTotalCount; - private final long[] mItemVersion; - private final long[] mSetVersion; - - private int mActiveStart = 0; - private int mActiveEnd = 0; - - private int mContentStart = 0; - private int mContentEnd = 0; - - private final MediaSet mSource; - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - private int mSize; - - private DataListener mDataListener; - private LoadingListener mLoadingListener; - private ReloadTask mReloadTask; - - private final Handler mMainHandler; - - private final MySourceListener mSourceListener = new MySourceListener(); - - public AlbumSetDataLoader(AbstractGalleryActivity activity, MediaSet albumSet, int cacheSize) { - mSource = Utils.checkNotNull(albumSet); - mCoverItem = new MediaItem[cacheSize]; - mData = new MediaSet[cacheSize]; - mTotalCount = new int[cacheSize]; - mItemVersion = new long[cacheSize]; - mSetVersion = new long[cacheSize]; - Arrays.fill(mItemVersion, MediaObject.INVALID_DATA_VERSION); - Arrays.fill(mSetVersion, MediaObject.INVALID_DATA_VERSION); - - mMainHandler = new SynchronizedHandler(activity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_RUN_OBJECT: - ((Runnable) message.obj).run(); - return; - case MSG_LOAD_START: - if (mLoadingListener != null) mLoadingListener.onLoadingStarted(); - return; - case MSG_LOAD_FINISH: - if (mLoadingListener != null) mLoadingListener.onLoadingFinished(false); - return; - } - } - }; - } - - public void pause() { - mReloadTask.terminate(); - mReloadTask = null; - mSource.removeContentListener(mSourceListener); - } - - public void resume() { - mSource.addContentListener(mSourceListener); - mReloadTask = new ReloadTask(); - mReloadTask.start(); - } - - private void assertIsActive(int index) { - if (index < mActiveStart && index >= mActiveEnd) { - throw new IllegalArgumentException(String.format( - "%s not in (%s, %s)", index, mActiveStart, mActiveEnd)); - } - } - - public MediaSet getMediaSet(int index) { - assertIsActive(index); - return mData[index % mData.length]; - } - - public MediaItem getCoverItem(int index) { - assertIsActive(index); - return mCoverItem[index % mCoverItem.length]; - } - - public int getTotalCount(int index) { - assertIsActive(index); - return mTotalCount[index % mTotalCount.length]; - } - - public int getActiveStart() { - return mActiveStart; - } - - public boolean isActive(int index) { - return index >= mActiveStart && index < mActiveEnd; - } - - public int size() { - return mSize; - } - - // Returns the index of the MediaSet with the given path or - // -1 if the path is not cached - public int findSet(Path id) { - int length = mData.length; - for (int i = mContentStart; i < mContentEnd; i++) { - MediaSet set = mData[i % length]; - if (set != null && id == set.getPath()) { - return i; - } - } - return -1; - } - - private void clearSlot(int slotIndex) { - mData[slotIndex] = null; - mCoverItem[slotIndex] = null; - mTotalCount[slotIndex] = 0; - mItemVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - mSetVersion[slotIndex] = MediaObject.INVALID_DATA_VERSION; - } - - private void setContentWindow(int contentStart, int contentEnd) { - if (contentStart == mContentStart && contentEnd == mContentEnd) return; - int length = mCoverItem.length; - - int start = this.mContentStart; - int end = this.mContentEnd; - - mContentStart = contentStart; - mContentEnd = contentEnd; - - if (contentStart >= end || start >= contentEnd) { - for (int i = start, n = end; i < n; ++i) { - clearSlot(i % length); - } - } else { - for (int i = start; i < contentStart; ++i) { - clearSlot(i % length); - } - for (int i = contentEnd, n = end; i < n; ++i) { - clearSlot(i % length); - } - } - mReloadTask.notifyDirty(); - } - - public void setActiveWindow(int start, int end) { - if (start == mActiveStart && end == mActiveEnd) return; - - Utils.assertTrue(start <= end - && end - start <= mCoverItem.length && end <= mSize); - - mActiveStart = start; - mActiveEnd = end; - - int length = mCoverItem.length; - // If no data is visible, keep the cache content - if (start == end) return; - - int contentStart = Utils.clamp((start + end) / 2 - length / 2, - 0, Math.max(0, mSize - length)); - int contentEnd = Math.min(contentStart + length, mSize); - if (mContentStart > start || mContentEnd < end - || Math.abs(contentStart - mContentStart) > MIN_LOAD_COUNT) { - setContentWindow(contentStart, contentEnd); - } - } - - private class MySourceListener implements ContentListener { - @Override - public void onContentDirty() { - mReloadTask.notifyDirty(); - } - } - - public void setModelListener(DataListener listener) { - mDataListener = listener; - } - - public void setLoadingListener(LoadingListener listener) { - mLoadingListener = listener; - } - - private static class UpdateInfo { - public long version; - public int index; - - public int size; - public MediaSet item; - public MediaItem cover; - public int totalCount; - } - - private class GetUpdateInfo implements Callable<UpdateInfo> { - - private final long mVersion; - - public GetUpdateInfo(long version) { - mVersion = version; - } - - private int getInvalidIndex(long version) { - long setVersion[] = mSetVersion; - int length = setVersion.length; - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - int index = i % length; - if (setVersion[i % length] != version) return i; - } - return INDEX_NONE; - } - - @Override - public UpdateInfo call() throws Exception { - int index = getInvalidIndex(mVersion); - if (index == INDEX_NONE && mSourceVersion == mVersion) return null; - UpdateInfo info = new UpdateInfo(); - info.version = mSourceVersion; - info.index = index; - info.size = mSize; - return info; - } - } - - private class UpdateContent implements Callable<Void> { - private final UpdateInfo mUpdateInfo; - - public UpdateContent(UpdateInfo info) { - mUpdateInfo = info; - } - - @Override - public Void call() { - // Avoid notifying listeners of status change after pause - // Otherwise gallery will be in inconsistent state after resume. - if (mReloadTask == null) return null; - UpdateInfo info = mUpdateInfo; - mSourceVersion = info.version; - if (mSize != info.size) { - mSize = info.size; - if (mDataListener != null) mDataListener.onSizeChanged(mSize); - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - // Note: info.index could be INDEX_NONE, i.e., -1 - if (info.index >= mContentStart && info.index < mContentEnd) { - int pos = info.index % mCoverItem.length; - mSetVersion[pos] = info.version; - long itemVersion = info.item.getDataVersion(); - if (mItemVersion[pos] == itemVersion) return null; - mItemVersion[pos] = itemVersion; - mData[pos] = info.item; - mCoverItem[pos] = info.cover; - mTotalCount[pos] = info.totalCount; - if (mDataListener != null - && info.index >= mActiveStart && info.index < mActiveEnd) { - mDataListener.onContentChanged(info.index); - } - } - return null; - } - } - - private <T> T executeAndWait(Callable<T> callable) { - FutureTask<T> task = new FutureTask<T>(callable); - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); - try { - return task.get(); - } catch (InterruptedException e) { - return null; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - // TODO: load active range first - private class ReloadTask extends Thread { - private volatile boolean mActive = true; - private volatile boolean mDirty = true; - private volatile boolean mIsLoading = false; - - private void updateLoading(boolean loading) { - if (mIsLoading == loading) return; - mIsLoading = loading; - mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); - } - - @Override - public void run() { - Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); - - boolean updateComplete = false; - while (mActive) { - synchronized (this) { - if (mActive && !mDirty && updateComplete) { - if (!mSource.isLoading()) updateLoading(false); - Utils.waitWithoutInterrupt(this); - continue; - } - } - mDirty = false; - updateLoading(true); - - long version = mSource.reload(); - UpdateInfo info = executeAndWait(new GetUpdateInfo(version)); - updateComplete = info == null; - if (updateComplete) continue; - if (info.version != version) { - info.version = version; - info.size = mSource.getSubMediaSetCount(); - - // If the size becomes smaller after reload(), we may - // receive from GetUpdateInfo an index which is too - // big. Because the main thread is not aware of the size - // change until we call UpdateContent. - if (info.index >= info.size) { - info.index = INDEX_NONE; - } - } - if (info.index != INDEX_NONE) { - info.item = mSource.getSubMediaSet(info.index); - if (info.item == null) continue; - info.cover = info.item.getCoverMediaItem(); - info.totalCount = info.item.getTotalMediaItemCount(); - } - executeAndWait(new UpdateContent(info)); - } - updateLoading(false); - } - - public synchronized void notifyDirty() { - mDirty = true; - notifyAll(); - } - - public synchronized void terminate() { - mActive = false; - notifyAll(); - } - } -} - - diff --git a/src/com/android/gallery3d/app/AlbumSetPage.java b/src/com/android/gallery3d/app/AlbumSetPage.java deleted file mode 100644 index dd9d8ec41..000000000 --- a/src/com/android/gallery3d/app/AlbumSetPage.java +++ /dev/null @@ -1,764 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.graphics.Rect; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.view.HapticFeedbackConstants; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.RelativeLayout; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.FadeTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.settings.GallerySettings; -import com.android.gallery3d.ui.ActionModeHandler; -import com.android.gallery3d.ui.ActionModeHandler.ActionModeListener; -import com.android.gallery3d.ui.AlbumSetSlotRenderer; -import com.android.gallery3d.ui.DetailsHelper; -import com.android.gallery3d.ui.DetailsHelper.CloseListener; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SlotView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.HelpUtils; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -public class AlbumSetPage extends ActivityState implements - SelectionManager.SelectionListener, GalleryActionBar.ClusterRunner, - EyePosition.EyePositionListener, MediaSet.SyncListener { - @SuppressWarnings("unused") - private static final String TAG = "AlbumSetPage"; - - private static final int MSG_PICK_ALBUM = 1; - - public static final String KEY_MEDIA_PATH = "media-path"; - public static final String KEY_SET_TITLE = "set-title"; - public static final String KEY_SET_SUBTITLE = "set-subtitle"; - public static final String KEY_SELECTED_CLUSTER_TYPE = "selected-cluster"; - - private static final int DATA_CACHE_SIZE = 256; - private static final int REQUEST_DO_ANIMATION = 1; - - private static final int BIT_LOADING_RELOAD = 1; - private static final int BIT_LOADING_SYNC = 2; - - private boolean mIsActive = false; - private SlotView mSlotView; - private AlbumSetSlotRenderer mAlbumSetView; - private Config.AlbumSetPage mConfig; - - private MediaSet mMediaSet; - private String mTitle; - private String mSubtitle; - private boolean mShowClusterMenu; - private GalleryActionBar mActionBar; - private int mSelectedAction; - - protected SelectionManager mSelectionManager; - private AlbumSetDataLoader mAlbumSetDataAdapter; - - private boolean mGetContent; - private boolean mGetAlbum; - private ActionModeHandler mActionModeHandler; - private DetailsHelper mDetailsHelper; - private MyDetailsSource mDetailsSource; - private boolean mShowDetails; - private EyePosition mEyePosition; - private Handler mHandler; - - // The eyes' position of the user, the origin is at the center of the - // device and the unit is in pixels. - private float mX; - private float mY; - private float mZ; - - private Future<Integer> mSyncTask = null; - - private int mLoadingBits = 0; - private boolean mInitialSynced = false; - - private Button mCameraButton; - private boolean mShowedEmptyToastForSelf = false; - - @Override - protected int getBackgroundColorId() { - return R.color.albumset_background; - } - - private final GLView mRootPane = new GLView() { - private final float mMatrix[] = new float[16]; - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - mEyePosition.resetPosition(); - - int slotViewTop = mActionBar.getHeight() + mConfig.paddingTop; - int slotViewBottom = bottom - top - mConfig.paddingBottom; - int slotViewRight = right - left; - - if (mShowDetails) { - mDetailsHelper.layout(left, slotViewTop, right, bottom); - } else { - mAlbumSetView.setHighlightItemPath(null); - } - - mSlotView.layout(0, slotViewTop, slotViewRight, slotViewBottom); - } - - @Override - protected void render(GLCanvas canvas) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - GalleryUtils.setViewPointMatrix(mMatrix, - getWidth() / 2 + mX, getHeight() / 2 + mY, mZ); - canvas.multiplyMatrix(mMatrix, 0); - super.render(canvas); - canvas.restore(); - } - }; - - @Override - public void onEyePositionChanged(float x, float y, float z) { - mRootPane.lockRendering(); - mX = x; - mY = y; - mZ = z; - mRootPane.unlockRendering(); - mRootPane.invalidate(); - } - - @Override - public void onBackPressed() { - if (mShowDetails) { - hideDetails(); - } else if (mSelectionManager.inSelectionMode()) { - mSelectionManager.leaveSelectionMode(); - } else { - super.onBackPressed(); - } - } - - private void getSlotCenter(int slotIndex, int center[]) { - Rect offset = new Rect(); - mRootPane.getBoundsOf(mSlotView, offset); - Rect r = mSlotView.getSlotRect(slotIndex); - int scrollX = mSlotView.getScrollX(); - int scrollY = mSlotView.getScrollY(); - center[0] = offset.left + (r.left + r.right) / 2 - scrollX; - center[1] = offset.top + (r.top + r.bottom) / 2 - scrollY; - } - - public void onSingleTapUp(int slotIndex) { - if (!mIsActive) return; - - if (mSelectionManager.inSelectionMode()) { - MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (targetSet == null) return; // Content is dirty, we shall reload soon - mSelectionManager.toggle(targetSet.getPath()); - mSlotView.invalidate(); - } else { - // Show pressed-up animation for the single-tap. - mAlbumSetView.setPressedIndex(slotIndex); - mAlbumSetView.setPressedUp(); - mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_PICK_ALBUM, slotIndex, 0), - FadeTexture.DURATION); - } - } - - private static boolean albumShouldOpenInFilmstrip(MediaSet album) { - int itemCount = album.getMediaItemCount(); - ArrayList<MediaItem> list = (itemCount == 1) ? album.getMediaItem(0, 1) : null; - // open in film strip only if there's one item in the album and the item exists - return (list != null && !list.isEmpty()); - } - - WeakReference<Toast> mEmptyAlbumToast = null; - - private void showEmptyAlbumToast(int toastLength) { - Toast toast; - if (mEmptyAlbumToast != null) { - toast = mEmptyAlbumToast.get(); - if (toast != null) { - toast.show(); - return; - } - } - toast = Toast.makeText(mActivity, R.string.empty_album, toastLength); - mEmptyAlbumToast = new WeakReference<Toast>(toast); - toast.show(); - } - - private void hideEmptyAlbumToast() { - if (mEmptyAlbumToast != null) { - Toast toast = mEmptyAlbumToast.get(); - if (toast != null) toast.cancel(); - } - } - - private void pickAlbum(int slotIndex) { - if (!mIsActive) return; - - MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (targetSet == null) return; // Content is dirty, we shall reload soon - if (targetSet.getTotalMediaItemCount() == 0) { - showEmptyAlbumToast(Toast.LENGTH_SHORT); - return; - } - hideEmptyAlbumToast(); - - String mediaPath = targetSet.getPath().toString(); - - Bundle data = new Bundle(getData()); - int[] center = new int[2]; - getSlotCenter(slotIndex, center); - data.putIntArray(AlbumPage.KEY_SET_CENTER, center); - if (mGetAlbum && targetSet.isLeafAlbum()) { - Activity activity = mActivity; - Intent result = new Intent() - .putExtra(AlbumPicker.KEY_ALBUM_PATH, targetSet.getPath().toString()); - activity.setResult(Activity.RESULT_OK, result); - activity.finish(); - } else if (targetSet.getSubMediaSetCount() > 0) { - data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath); - mActivity.getStateManager().startStateForResult( - AlbumSetPage.class, REQUEST_DO_ANIMATION, data); - } else { - if (!mGetContent && albumShouldOpenInFilmstrip(targetSet)) { - data.putParcelable(PhotoPage.KEY_OPEN_ANIMATION_RECT, - mSlotView.getSlotRect(slotIndex, mRootPane)); - data.putInt(PhotoPage.KEY_INDEX_HINT, 0); - data.putString(PhotoPage.KEY_MEDIA_SET_PATH, - mediaPath); - data.putBoolean(PhotoPage.KEY_START_IN_FILMSTRIP, true); - data.putBoolean(PhotoPage.KEY_IN_CAMERA_ROLL, targetSet.isCameraRoll()); - mActivity.getStateManager().startStateForResult( - FilmstripPage.class, AlbumPage.REQUEST_PHOTO, data); - return; - } - data.putString(AlbumPage.KEY_MEDIA_PATH, mediaPath); - - // We only show cluster menu in the first AlbumPage in stack - boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); - data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum); - mActivity.getStateManager().startStateForResult( - AlbumPage.class, REQUEST_DO_ANIMATION, data); - } - } - - private void onDown(int index) { - mAlbumSetView.setPressedIndex(index); - } - - private void onUp(boolean followedByLongPress) { - if (followedByLongPress) { - // Avoid showing press-up animations for long-press. - mAlbumSetView.setPressedIndex(-1); - } else { - mAlbumSetView.setPressedUp(); - } - } - - public void onLongTap(int slotIndex) { - if (mGetContent || mGetAlbum) return; - MediaSet set = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (set == null) return; - mSelectionManager.setAutoLeaveSelectionMode(true); - mSelectionManager.toggle(set.getPath()); - mSlotView.invalidate(); - } - - @Override - public void doCluster(int clusterType) { - String basePath = mMediaSet.getPath().toString(); - String newPath = FilterUtils.switchClusterPath(basePath, clusterType); - Bundle data = new Bundle(getData()); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, newPath); - data.putInt(KEY_SELECTED_CLUSTER_TYPE, clusterType); - mActivity.getStateManager().switchState(this, AlbumSetPage.class, data); - } - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - initializeViews(); - initializeData(data); - Context context = mActivity.getAndroidContext(); - mGetContent = data.getBoolean(Gallery.KEY_GET_CONTENT, false); - mGetAlbum = data.getBoolean(Gallery.KEY_GET_ALBUM, false); - mTitle = data.getString(AlbumSetPage.KEY_SET_TITLE); - mSubtitle = data.getString(AlbumSetPage.KEY_SET_SUBTITLE); - mEyePosition = new EyePosition(context, this); - mDetailsSource = new MyDetailsSource(); - mActionBar = mActivity.getGalleryActionBar(); - mSelectedAction = data.getInt(AlbumSetPage.KEY_SELECTED_CLUSTER_TYPE, - FilterUtils.CLUSTER_BY_ALBUM); - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_PICK_ALBUM: { - pickAlbum(message.arg1); - break; - } - default: throw new AssertionError(message.what); - } - } - }; - } - - @Override - public void onDestroy() { - super.onDestroy(); - cleanupCameraButton(); - mActionModeHandler.destroy(); - } - - private boolean setupCameraButton() { - if (!GalleryUtils.isCameraAvailable(mActivity)) return false; - RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) - .findViewById(R.id.gallery_root); - if (galleryRoot == null) return false; - - mCameraButton = new Button(mActivity); - mCameraButton.setText(R.string.camera_label); - mCameraButton.setCompoundDrawablesWithIntrinsicBounds(0, R.drawable.frame_overlay_gallery_camera, 0, 0); - mCameraButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - GalleryUtils.startCameraActivity(mActivity); - } - }); - RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams( - RelativeLayout.LayoutParams.WRAP_CONTENT, - RelativeLayout.LayoutParams.WRAP_CONTENT); - lp.addRule(RelativeLayout.CENTER_IN_PARENT); - galleryRoot.addView(mCameraButton, lp); - return true; - } - - private void cleanupCameraButton() { - if (mCameraButton == null) return; - RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) - .findViewById(R.id.gallery_root); - if (galleryRoot == null) return; - galleryRoot.removeView(mCameraButton); - mCameraButton = null; - } - - private void showCameraButton() { - if (mCameraButton == null && !setupCameraButton()) return; - mCameraButton.setVisibility(View.VISIBLE); - } - - private void hideCameraButton() { - if (mCameraButton == null) return; - mCameraButton.setVisibility(View.GONE); - } - - private void clearLoadingBit(int loadingBit) { - mLoadingBits &= ~loadingBit; - if (mLoadingBits == 0 && mIsActive) { - if (mAlbumSetDataAdapter.size() == 0) { - // If this is not the top of the gallery folder hierarchy, - // tell the parent AlbumSetPage instance to handle displaying - // the empty album toast, otherwise show it within this - // instance - if (mActivity.getStateManager().getStateCount() > 1) { - Intent result = new Intent(); - result.putExtra(AlbumPage.KEY_EMPTY_ALBUM, true); - setStateResult(Activity.RESULT_OK, result); - mActivity.getStateManager().finishState(this); - } else { - mShowedEmptyToastForSelf = true; - showEmptyAlbumToast(Toast.LENGTH_LONG); - mSlotView.invalidate(); - showCameraButton(); - } - return; - } - } - // Hide the empty album toast if we are in the root instance of - // AlbumSetPage and the album is no longer empty (for instance, - // after a sync is completed and web albums have been synced) - if (mShowedEmptyToastForSelf) { - mShowedEmptyToastForSelf = false; - hideEmptyAlbumToast(); - hideCameraButton(); - } - } - - private void setLoadingBit(int loadingBit) { - mLoadingBits |= loadingBit; - } - - @Override - public void onPause() { - super.onPause(); - mIsActive = false; - mAlbumSetDataAdapter.pause(); - mAlbumSetView.pause(); - mActionModeHandler.pause(); - mEyePosition.pause(); - DetailsHelper.pause(); - // Call disableClusterMenu to avoid receiving callback after paused. - // Don't hide menu here otherwise the list menu will disappear earlier than - // the action bar, which is janky and unwanted behavior. - mActionBar.disableClusterMenu(false); - if (mSyncTask != null) { - mSyncTask.cancel(); - mSyncTask = null; - clearLoadingBit(BIT_LOADING_SYNC); - } - } - - @Override - public void onResume() { - super.onResume(); - mIsActive = true; - setContentPane(mRootPane); - - // Set the reload bit here to prevent it exit this page in clearLoadingBit(). - setLoadingBit(BIT_LOADING_RELOAD); - mAlbumSetDataAdapter.resume(); - - mAlbumSetView.resume(); - mEyePosition.resume(); - mActionModeHandler.resume(); - if (mShowClusterMenu) { - mActionBar.enableClusterMenu(mSelectedAction, this); - } - if (!mInitialSynced) { - setLoadingBit(BIT_LOADING_SYNC); - mSyncTask = mMediaSet.requestSync(AlbumSetPage.this); - } - } - - private void initializeData(Bundle data) { - String mediaPath = data.getString(AlbumSetPage.KEY_MEDIA_PATH); - mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath); - mSelectionManager.setSourceMediaSet(mMediaSet); - mAlbumSetDataAdapter = new AlbumSetDataLoader( - mActivity, mMediaSet, DATA_CACHE_SIZE); - mAlbumSetDataAdapter.setLoadingListener(new MyLoadingListener()); - mAlbumSetView.setModel(mAlbumSetDataAdapter); - } - - private void initializeViews() { - mSelectionManager = new SelectionManager(mActivity, true); - mSelectionManager.setSelectionListener(this); - - mConfig = Config.AlbumSetPage.get(mActivity); - mSlotView = new SlotView(mActivity, mConfig.slotViewSpec); - mAlbumSetView = new AlbumSetSlotRenderer( - mActivity, mSelectionManager, mSlotView, mConfig.labelSpec, - mConfig.placeholderColor); - mSlotView.setSlotRenderer(mAlbumSetView); - mSlotView.setListener(new SlotView.SimpleListener() { - @Override - public void onDown(int index) { - AlbumSetPage.this.onDown(index); - } - - @Override - public void onUp(boolean followedByLongPress) { - AlbumSetPage.this.onUp(followedByLongPress); - } - - @Override - public void onSingleTapUp(int slotIndex) { - AlbumSetPage.this.onSingleTapUp(slotIndex); - } - - @Override - public void onLongTap(int slotIndex) { - AlbumSetPage.this.onLongTap(slotIndex); - } - }); - - mActionModeHandler = new ActionModeHandler(mActivity, mSelectionManager); - mActionModeHandler.setActionModeListener(new ActionModeListener() { - @Override - public boolean onActionItemClicked(MenuItem item) { - return onItemSelected(item); - } - }); - mRootPane.addComponent(mSlotView); - } - - @Override - protected boolean onCreateActionBar(Menu menu) { - Activity activity = mActivity; - final boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); - MenuInflater inflater = getSupportMenuInflater(); - - if (mGetContent) { - inflater.inflate(R.menu.pickup, menu); - int typeBits = mData.getInt( - Gallery.KEY_TYPE_BITS, DataManager.INCLUDE_IMAGE); - mActionBar.setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); - } else if (mGetAlbum) { - inflater.inflate(R.menu.pickup, menu); - mActionBar.setTitle(R.string.select_album); - } else { - inflater.inflate(R.menu.albumset, menu); - boolean wasShowingClusterMenu = mShowClusterMenu; - mShowClusterMenu = !inAlbum; - boolean selectAlbums = !inAlbum && - mActionBar.getClusterTypeAction() == FilterUtils.CLUSTER_BY_ALBUM; - MenuItem selectItem = menu.findItem(R.id.action_select); - selectItem.setTitle(activity.getString( - selectAlbums ? R.string.select_album : R.string.select_group)); - - MenuItem cameraItem = menu.findItem(R.id.action_camera); - cameraItem.setVisible(GalleryUtils.isCameraAvailable(activity)); - - FilterUtils.setupMenuItems(mActionBar, mMediaSet.getPath(), false); - - Intent helpIntent = HelpUtils.getHelpIntent(activity); - - MenuItem helpItem = menu.findItem(R.id.action_general_help); - helpItem.setVisible(helpIntent != null); - if (helpIntent != null) helpItem.setIntent(helpIntent); - - mActionBar.setTitle(mTitle); - mActionBar.setSubtitle(mSubtitle); - if (mShowClusterMenu != wasShowingClusterMenu) { - if (mShowClusterMenu) { - mActionBar.enableClusterMenu(mSelectedAction, this); - } else { - mActionBar.disableClusterMenu(true); - } - } - } - return true; - } - - @Override - protected boolean onItemSelected(MenuItem item) { - Activity activity = mActivity; - switch (item.getItemId()) { - case R.id.action_cancel: - activity.setResult(Activity.RESULT_CANCELED); - activity.finish(); - return true; - case R.id.action_select: - mSelectionManager.setAutoLeaveSelectionMode(false); - mSelectionManager.enterSelectionMode(); - return true; - case R.id.action_details: - if (mAlbumSetDataAdapter.size() != 0) { - if (mShowDetails) { - hideDetails(); - } else { - showDetails(); - } - } else { - Toast.makeText(activity, - activity.getText(R.string.no_albums_alert), - Toast.LENGTH_SHORT).show(); - } - return true; - case R.id.action_camera: { - GalleryUtils.startCameraActivity(activity); - return true; - } - case R.id.action_manage_offline: { - Bundle data = new Bundle(); - String mediaPath = mActivity.getDataManager().getTopSetPath( - DataManager.INCLUDE_ALL); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, mediaPath); - mActivity.getStateManager().startState(ManageCachePage.class, data); - return true; - } - case R.id.action_sync_picasa_albums: { - PicasaSource.requestSync(activity); - return true; - } - case R.id.action_settings: { - activity.startActivity(new Intent(activity, GallerySettings.class)); - return true; - } - default: - return false; - } - } - - @Override - protected void onStateResult(int requestCode, int resultCode, Intent data) { - if (data != null && data.getBooleanExtra(AlbumPage.KEY_EMPTY_ALBUM, false)) { - showEmptyAlbumToast(Toast.LENGTH_SHORT); - } - switch (requestCode) { - case REQUEST_DO_ANIMATION: { - mSlotView.startRisingAnimation(); - } - } - } - - private String getSelectedString() { - int count = mSelectionManager.getSelectedCount(); - int action = mActionBar.getClusterTypeAction(); - int string = action == FilterUtils.CLUSTER_BY_ALBUM - ? R.plurals.number_of_albums_selected - : R.plurals.number_of_groups_selected; - String format = mActivity.getResources().getQuantityString(string, count); - return String.format(format, count); - } - - @Override - public void onSelectionModeChange(int mode) { - switch (mode) { - case SelectionManager.ENTER_SELECTION_MODE: { - mActionBar.disableClusterMenu(true); - mActionModeHandler.startActionMode(); - performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); - break; - } - case SelectionManager.LEAVE_SELECTION_MODE: { - mActionModeHandler.finishActionMode(); - if (mShowClusterMenu) { - mActionBar.enableClusterMenu(mSelectedAction, this); - } - mRootPane.invalidate(); - break; - } - case SelectionManager.SELECT_ALL_MODE: { - mActionModeHandler.updateSupportedOperation(); - mRootPane.invalidate(); - break; - } - } - } - - @Override - public void onSelectionChange(Path path, boolean selected) { - mActionModeHandler.setTitle(getSelectedString()); - mActionModeHandler.updateSupportedOperation(path, selected); - } - - private void hideDetails() { - mShowDetails = false; - mDetailsHelper.hide(); - mAlbumSetView.setHighlightItemPath(null); - mSlotView.invalidate(); - } - - private void showDetails() { - mShowDetails = true; - if (mDetailsHelper == null) { - mDetailsHelper = new DetailsHelper(mActivity, mRootPane, mDetailsSource); - mDetailsHelper.setCloseListener(new CloseListener() { - @Override - public void onClose() { - hideDetails(); - } - }); - } - mDetailsHelper.show(); - } - - @Override - public void onSyncDone(final MediaSet mediaSet, final int resultCode) { - if (resultCode == MediaSet.SYNC_RESULT_ERROR) { - Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) + " result=" - + resultCode); - } - ((Activity) mActivity).runOnUiThread(new Runnable() { - @Override - public void run() { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - if (resultCode == MediaSet.SYNC_RESULT_SUCCESS) { - mInitialSynced = true; - } - clearLoadingBit(BIT_LOADING_SYNC); - if (resultCode == MediaSet.SYNC_RESULT_ERROR && mIsActive) { - Log.w(TAG, "failed to load album set"); - } - } finally { - root.unlockRenderThread(); - } - } - }); - } - - private class MyLoadingListener implements LoadingListener { - @Override - public void onLoadingStarted() { - setLoadingBit(BIT_LOADING_RELOAD); - } - - @Override - public void onLoadingFinished(boolean loadingFailed) { - clearLoadingBit(BIT_LOADING_RELOAD); - } - } - - private class MyDetailsSource implements DetailsHelper.DetailsSource { - private int mIndex; - - @Override - public int size() { - return mAlbumSetDataAdapter.size(); - } - - @Override - public int setIndex() { - Path id = mSelectionManager.getSelected(false).get(0); - mIndex = mAlbumSetDataAdapter.findSet(id); - return mIndex; - } - - @Override - public MediaDetails getDetails() { - MediaObject item = mAlbumSetDataAdapter.getMediaSet(mIndex); - if (item != null) { - mAlbumSetView.setHighlightItemPath(item.getPath()); - return item.getDetails(); - } else { - return null; - } - } - } -} diff --git a/src/com/android/gallery3d/app/AppBridge.java b/src/com/android/gallery3d/app/AppBridge.java deleted file mode 100644 index ee55fa6db..000000000 --- a/src/com/android/gallery3d/app/AppBridge.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.app; - -import android.graphics.Rect; -import android.os.Parcel; -import android.os.Parcelable; - -import com.android.gallery3d.ui.ScreenNail; - -// This is the bridge to connect a PhotoPage to the external environment. -public abstract class AppBridge implements Parcelable { - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - } - - ////////////////////////////////////////////////////////////////////////// - // These are requests sent from PhotoPage to the app - ////////////////////////////////////////////////////////////////////////// - - public abstract boolean isPanorama(); - public abstract boolean isStaticCamera(); - public abstract ScreenNail attachScreenNail(); - public abstract void detachScreenNail(); - - // Return true if the tap is consumed. - public abstract boolean onSingleTapUp(int x, int y); - - // This is used to notify that the screen nail will be drawn in full screen - // or not in next draw() call. - public abstract void onFullScreenChanged(boolean full); - - ////////////////////////////////////////////////////////////////////////// - // These are requests send from app to PhotoPage - ////////////////////////////////////////////////////////////////////////// - - public interface Server { - // Set the camera frame relative to GLRootView. - public void setCameraRelativeFrame(Rect frame); - // Switch to the previous or next picture using the capture animation. - // The offset is -1 to switch to the previous picture, 1 to switch to - // the next picture. - public boolean switchWithCaptureAnimation(int offset); - // Enable or disable the swiping gestures (the default is enabled). - public void setSwipingEnabled(boolean enabled); - // Notify that the ScreenNail is changed. - public void notifyScreenNailChanged(); - // Add a new media item to the secure album. - public void addSecureAlbumItem(boolean isVideo, int id); - } - - // If server is null, the services are not available. - public abstract void setServer(Server server); -} diff --git a/src/com/android/gallery3d/app/BatchService.java b/src/com/android/gallery3d/app/BatchService.java deleted file mode 100644 index 564001d5b..000000000 --- a/src/com/android/gallery3d/app/BatchService.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Service; -import android.content.Intent; -import android.os.Binder; -import android.os.IBinder; - -import com.android.gallery3d.util.ThreadPool; - -public class BatchService extends Service { - - public class LocalBinder extends Binder { - BatchService getService() { - return BatchService.this; - } - } - - private final IBinder mBinder = new LocalBinder(); - private ThreadPool mThreadPool = new ThreadPool(1, 1); - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - // The threadpool returned by getThreadPool must have only 1 thread - // running at a time, as MenuExecutor (atrociously) depends on this - // guarantee for synchronization. - public ThreadPool getThreadPool() { - return mThreadPool; - } -} diff --git a/src/com/android/gallery3d/app/CommonControllerOverlay.java b/src/com/android/gallery3d/app/CommonControllerOverlay.java deleted file mode 100644 index 9adb4e7a8..000000000 --- a/src/com/android/gallery3d/app/CommonControllerOverlay.java +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Rect; -import android.view.Gravity; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.FrameLayout; -import android.widget.ImageView; -import android.widget.ImageView.ScaleType; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RelativeLayout; -import android.widget.TextView; - -import com.android.gallery3d.R; - -/** - * The common playback controller for the Movie Player or Video Trimming. - */ -public abstract class CommonControllerOverlay extends FrameLayout implements - ControllerOverlay, - OnClickListener, - TimeBar.Listener { - - protected enum State { - PLAYING, - PAUSED, - ENDED, - ERROR, - LOADING - } - - private static final float ERROR_MESSAGE_RELATIVE_PADDING = 1.0f / 6; - - protected Listener mListener; - - protected final View mBackground; - protected TimeBar mTimeBar; - - protected View mMainView; - protected final LinearLayout mLoadingView; - protected final TextView mErrorView; - protected final ImageView mPlayPauseReplayView; - - protected State mState; - - protected boolean mCanReplay = true; - - public void setSeekable(boolean canSeek) { - mTimeBar.setSeekable(canSeek); - } - - public CommonControllerOverlay(Context context) { - super(context); - - mState = State.LOADING; - // TODO: Move the following layout code into xml file. - LayoutParams wrapContent = - new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); - LayoutParams matchParent = - new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - - mBackground = new View(context); - mBackground.setBackgroundColor(context.getResources().getColor(R.color.darker_transparent)); - addView(mBackground, matchParent); - - // Depending on the usage, the timeBar can show a single scrubber, or - // multiple ones for trimming. - createTimeBar(context); - addView(mTimeBar, wrapContent); - mTimeBar.setContentDescription( - context.getResources().getString(R.string.accessibility_time_bar)); - mLoadingView = new LinearLayout(context); - mLoadingView.setOrientation(LinearLayout.VERTICAL); - mLoadingView.setGravity(Gravity.CENTER_HORIZONTAL); - ProgressBar spinner = new ProgressBar(context); - spinner.setIndeterminate(true); - mLoadingView.addView(spinner, wrapContent); - TextView loadingText = createOverlayTextView(context); - loadingText.setText(R.string.loading_video); - mLoadingView.addView(loadingText, wrapContent); - addView(mLoadingView, wrapContent); - - mPlayPauseReplayView = new ImageView(context); - mPlayPauseReplayView.setImageResource(R.drawable.ic_vidcontrol_play); - mPlayPauseReplayView.setContentDescription( - context.getResources().getString(R.string.accessibility_play_video)); - mPlayPauseReplayView.setBackgroundResource(R.drawable.bg_vidcontrol); - mPlayPauseReplayView.setScaleType(ScaleType.CENTER); - mPlayPauseReplayView.setFocusable(true); - mPlayPauseReplayView.setClickable(true); - mPlayPauseReplayView.setOnClickListener(this); - addView(mPlayPauseReplayView, wrapContent); - - mErrorView = createOverlayTextView(context); - addView(mErrorView, matchParent); - - RelativeLayout.LayoutParams params = - new RelativeLayout.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); - setLayoutParams(params); - hide(); - } - - abstract protected void createTimeBar(Context context); - - private TextView createOverlayTextView(Context context) { - TextView view = new TextView(context); - view.setGravity(Gravity.CENTER); - view.setTextColor(0xFFFFFFFF); - view.setPadding(0, 15, 0, 15); - return view; - } - - @Override - public void setListener(Listener listener) { - this.mListener = listener; - } - - @Override - public void setCanReplay(boolean canReplay) { - this.mCanReplay = canReplay; - } - - @Override - public View getView() { - return this; - } - - @Override - public void showPlaying() { - mState = State.PLAYING; - showMainView(mPlayPauseReplayView); - } - - @Override - public void showPaused() { - mState = State.PAUSED; - showMainView(mPlayPauseReplayView); - } - - @Override - public void showEnded() { - mState = State.ENDED; - if (mCanReplay) showMainView(mPlayPauseReplayView); - } - - @Override - public void showLoading() { - mState = State.LOADING; - showMainView(mLoadingView); - } - - @Override - public void showErrorMessage(String message) { - mState = State.ERROR; - int padding = (int) (getMeasuredWidth() * ERROR_MESSAGE_RELATIVE_PADDING); - mErrorView.setPadding( - padding, mErrorView.getPaddingTop(), padding, mErrorView.getPaddingBottom()); - mErrorView.setText(message); - showMainView(mErrorView); - } - - @Override - public void setTimes(int currentTime, int totalTime, - int trimStartTime, int trimEndTime) { - mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime); - } - - public void hide() { - mPlayPauseReplayView.setVisibility(View.INVISIBLE); - mLoadingView.setVisibility(View.INVISIBLE); - mBackground.setVisibility(View.INVISIBLE); - mTimeBar.setVisibility(View.INVISIBLE); - setVisibility(View.INVISIBLE); - setFocusable(true); - requestFocus(); - } - - private void showMainView(View view) { - mMainView = view; - mErrorView.setVisibility(mMainView == mErrorView ? View.VISIBLE : View.INVISIBLE); - mLoadingView.setVisibility(mMainView == mLoadingView ? View.VISIBLE : View.INVISIBLE); - mPlayPauseReplayView.setVisibility( - mMainView == mPlayPauseReplayView ? View.VISIBLE : View.INVISIBLE); - show(); - } - - @Override - public void show() { - updateViews(); - setVisibility(View.VISIBLE); - setFocusable(false); - } - - @Override - public void onClick(View view) { - if (mListener != null) { - if (view == mPlayPauseReplayView) { - if (mState == State.ENDED) { - if (mCanReplay) { - mListener.onReplay(); - } - } else if (mState == State.PAUSED || mState == State.PLAYING) { - mListener.onPlayPause(); - } - } - } - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (super.onTouchEvent(event)) { - return true; - } - return false; - } - - // The paddings of 4 sides which covered by system components. E.g. - // +-----------------+\ - // | Action Bar | insets.top - // +-----------------+/ - // | | - // | Content Area | insets.right = insets.left = 0 - // | | - // +-----------------+\ - // | Navigation Bar | insets.bottom - // +-----------------+/ - // Please see View.fitSystemWindows() for more details. - private final Rect mWindowInsets = new Rect(); - - @Override - protected boolean fitSystemWindows(Rect insets) { - // We don't set the paddings of this View, otherwise, - // the content will get cropped outside window - mWindowInsets.set(insets); - return true; - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - Rect insets = mWindowInsets; - int pl = insets.left; // the left paddings - int pr = insets.right; - int pt = insets.top; - int pb = insets.bottom; - - int h = bottom - top; - int w = right - left; - boolean error = mErrorView.getVisibility() == View.VISIBLE; - - int y = h - pb; - // Put both TimeBar and Background just above the bottom system - // component. - // But extend the background to the width of the screen, since we don't - // care if it will be covered by a system component and it looks better. - mBackground.layout(0, y - mTimeBar.getBarHeight(), w, y); - mTimeBar.layout(pl, y - mTimeBar.getPreferredHeight(), w - pr, y); - - // Put the play/pause/next/ previous button in the center of the screen - layoutCenteredView(mPlayPauseReplayView, 0, 0, w, h); - - if (mMainView != null) { - layoutCenteredView(mMainView, 0, 0, w, h); - } - } - - private void layoutCenteredView(View view, int l, int t, int r, int b) { - int cw = view.getMeasuredWidth(); - int ch = view.getMeasuredHeight(); - int cl = (r - l - cw) / 2; - int ct = (b - t - ch) / 2; - view.layout(cl, ct, cl + cw, ct + ch); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - measureChildren(widthMeasureSpec, heightMeasureSpec); - } - - protected void updateViews() { - mBackground.setVisibility(View.VISIBLE); - mTimeBar.setVisibility(View.VISIBLE); - Resources resources = getContext().getResources(); - int imageResource = R.drawable.ic_vidcontrol_reload; - String contentDescription = resources.getString(R.string.accessibility_reload_video); - if (mState == State.PAUSED) { - imageResource = R.drawable.ic_vidcontrol_play; - contentDescription = resources.getString(R.string.accessibility_play_video); - } else if (mState == State.PLAYING) { - imageResource = R.drawable.ic_vidcontrol_pause; - contentDescription = resources.getString(R.string.accessibility_pause_video); - } - - mPlayPauseReplayView.setImageResource(imageResource); - mPlayPauseReplayView.setContentDescription(contentDescription); - mPlayPauseReplayView.setVisibility( - (mState != State.LOADING && mState != State.ERROR && - !(mState == State.ENDED && !mCanReplay)) - ? View.VISIBLE : View.GONE); - requestLayout(); - } - - // TimeBar listener - - @Override - public void onScrubbingStart() { - mListener.onSeekStart(); - } - - @Override - public void onScrubbingMove(int time) { - mListener.onSeekMove(time); - } - - @Override - public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) { - mListener.onSeekEnd(time, trimStartTime, trimEndTime); - } -} diff --git a/src/com/android/gallery3d/app/Config.java b/src/com/android/gallery3d/app/Config.java deleted file mode 100644 index 7183acc33..000000000 --- a/src/com/android/gallery3d/app/Config.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.content.res.Resources; - -import com.android.gallery3d.R; -import com.android.gallery3d.ui.AlbumSetSlotRenderer; -import com.android.gallery3d.ui.SlotView; - -final class Config { - public static class AlbumSetPage { - private static AlbumSetPage sInstance; - - public SlotView.Spec slotViewSpec; - public AlbumSetSlotRenderer.LabelSpec labelSpec; - public int paddingTop; - public int paddingBottom; - public int placeholderColor; - - public static synchronized AlbumSetPage get(Context context) { - if (sInstance == null) { - sInstance = new AlbumSetPage(context); - } - return sInstance; - } - - private AlbumSetPage(Context context) { - Resources r = context.getResources(); - - placeholderColor = r.getColor(R.color.albumset_placeholder); - - slotViewSpec = new SlotView.Spec(); - slotViewSpec.rowsLand = r.getInteger(R.integer.albumset_rows_land); - slotViewSpec.rowsPort = r.getInteger(R.integer.albumset_rows_port); - slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.albumset_slot_gap); - slotViewSpec.slotHeightAdditional = 0; - - paddingTop = r.getDimensionPixelSize(R.dimen.albumset_padding_top); - paddingBottom = r.getDimensionPixelSize(R.dimen.albumset_padding_bottom); - - labelSpec = new AlbumSetSlotRenderer.LabelSpec(); - labelSpec.labelBackgroundHeight = r.getDimensionPixelSize( - R.dimen.albumset_label_background_height); - labelSpec.titleOffset = r.getDimensionPixelSize( - R.dimen.albumset_title_offset); - labelSpec.countOffset = r.getDimensionPixelSize( - R.dimen.albumset_count_offset); - labelSpec.titleFontSize = r.getDimensionPixelSize( - R.dimen.albumset_title_font_size); - labelSpec.countFontSize = r.getDimensionPixelSize( - R.dimen.albumset_count_font_size); - labelSpec.leftMargin = r.getDimensionPixelSize( - R.dimen.albumset_left_margin); - labelSpec.titleRightMargin = r.getDimensionPixelSize( - R.dimen.albumset_title_right_margin); - labelSpec.iconSize = r.getDimensionPixelSize( - R.dimen.albumset_icon_size); - labelSpec.backgroundColor = r.getColor( - R.color.albumset_label_background); - labelSpec.titleColor = r.getColor(R.color.albumset_label_title); - labelSpec.countColor = r.getColor(R.color.albumset_label_count); - } - } - - public static class AlbumPage { - private static AlbumPage sInstance; - - public SlotView.Spec slotViewSpec; - public int placeholderColor; - - public static synchronized AlbumPage get(Context context) { - if (sInstance == null) { - sInstance = new AlbumPage(context); - } - return sInstance; - } - - private AlbumPage(Context context) { - Resources r = context.getResources(); - - placeholderColor = r.getColor(R.color.album_placeholder); - - slotViewSpec = new SlotView.Spec(); - slotViewSpec.rowsLand = r.getInteger(R.integer.album_rows_land); - slotViewSpec.rowsPort = r.getInteger(R.integer.album_rows_port); - slotViewSpec.slotGap = r.getDimensionPixelSize(R.dimen.album_slot_gap); - } - } - - public static class ManageCachePage extends AlbumSetPage { - private static ManageCachePage sInstance; - - public final int cachePinSize; - public final int cachePinMargin; - - public static synchronized ManageCachePage get(Context context) { - if (sInstance == null) { - sInstance = new ManageCachePage(context); - } - return sInstance; - } - - public ManageCachePage(Context context) { - super(context); - Resources r = context.getResources(); - cachePinSize = r.getDimensionPixelSize(R.dimen.cache_pin_size); - cachePinMargin = r.getDimensionPixelSize(R.dimen.cache_pin_margin); - } - } -} - diff --git a/src/com/android/gallery3d/app/ControllerOverlay.java b/src/com/android/gallery3d/app/ControllerOverlay.java deleted file mode 100644 index 078f59e28..000000000 --- a/src/com/android/gallery3d/app/ControllerOverlay.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.view.View; - -public interface ControllerOverlay { - - interface Listener { - void onPlayPause(); - void onSeekStart(); - void onSeekMove(int time); - void onSeekEnd(int time, int trimStartTime, int trimEndTime); - void onShown(); - void onHidden(); - void onReplay(); - } - - void setListener(Listener listener); - - void setCanReplay(boolean canReplay); - - /** - * @return The overlay view that should be added to the player. - */ - View getView(); - - void show(); - - void showPlaying(); - - void showPaused(); - - void showEnded(); - - void showLoading(); - - void showErrorMessage(String message); - - void setTimes(int currentTime, int totalTime, - int trimStartTime, int trimEndTime); -} diff --git a/src/com/android/gallery3d/app/DialogPicker.java b/src/com/android/gallery3d/app/DialogPicker.java deleted file mode 100644 index 7ca86e5b4..000000000 --- a/src/com/android/gallery3d/app/DialogPicker.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Intent; -import android.os.Bundle; - -import com.android.gallery3d.util.GalleryUtils; - -public class DialogPicker extends PickerActivity { - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - int typeBits = GalleryUtils.determineTypeBits(this, getIntent()); - setTitle(GalleryUtils.getSelectionModePrompt(typeBits)); - Intent intent = getIntent(); - Bundle extras = intent.getExtras(); - Bundle data = extras == null ? new Bundle() : new Bundle(extras); - - data.putBoolean(Gallery.KEY_GET_CONTENT, true); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(typeBits)); - getStateManager().startState(AlbumSetPage.class, data); - } -} diff --git a/src/com/android/gallery3d/app/EyePosition.java b/src/com/android/gallery3d/app/EyePosition.java deleted file mode 100644 index d99d97b0e..000000000 --- a/src/com/android/gallery3d/app/EyePosition.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.hardware.Sensor; -import android.hardware.SensorEvent; -import android.hardware.SensorEventListener; -import android.hardware.SensorManager; -import android.os.SystemClock; -import android.util.FloatMath; -import android.view.Display; -import android.view.Surface; -import android.view.WindowManager; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.GalleryUtils; - -public class EyePosition { - @SuppressWarnings("unused") - private static final String TAG = "EyePosition"; - - public interface EyePositionListener { - public void onEyePositionChanged(float x, float y, float z); - } - - private static final float GYROSCOPE_THRESHOLD = 0.15f; - private static final float GYROSCOPE_LIMIT = 10f; - private static final int GYROSCOPE_SETTLE_DOWN = 15; - private static final float GYROSCOPE_RESTORE_FACTOR = 0.995f; - - private static final float USER_ANGEL = (float) Math.toRadians(10); - private static final float USER_ANGEL_COS = FloatMath.cos(USER_ANGEL); - private static final float USER_ANGEL_SIN = FloatMath.sin(USER_ANGEL); - private static final float MAX_VIEW_RANGE = (float) 0.5; - private static final int NOT_STARTED = -1; - - private static final float USER_DISTANCE_METER = 0.3f; - - private Context mContext; - private EyePositionListener mListener; - private Display mDisplay; - // The eyes' position of the user, the origin is at the center of the - // device and the unit is in pixels. - private float mX; - private float mY; - private float mZ; - - private final float mUserDistance; // in pixel - private final float mLimit; - private long mStartTime = NOT_STARTED; - private Sensor mSensor; - private PositionListener mPositionListener = new PositionListener(); - - private int mGyroscopeCountdown = 0; - - public EyePosition(Context context, EyePositionListener listener) { - mContext = context; - mListener = listener; - mUserDistance = GalleryUtils.meterToPixel(USER_DISTANCE_METER); - mLimit = mUserDistance * MAX_VIEW_RANGE; - - WindowManager wManager = (WindowManager) mContext - .getSystemService(Context.WINDOW_SERVICE); - mDisplay = wManager.getDefaultDisplay(); - - // The 3D effect where the photo albums fan out in 3D based on angle - // of device tilt is currently disabled. -/* - SensorManager sManager = (SensorManager) mContext - .getSystemService(Context.SENSOR_SERVICE); - mSensor = sManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE); - if (mSensor == null) { - Log.w(TAG, "no gyroscope, use accelerometer instead"); - mSensor = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); - } - if (mSensor == null) { - Log.w(TAG, "no sensor available"); - } -*/ - } - - public void resetPosition() { - mStartTime = NOT_STARTED; - mX = mY = 0; - mZ = -mUserDistance; - mListener.onEyePositionChanged(mX, mY, mZ); - } - - /* - * We assume the user is at the following position - * - * /|\ user's eye - * | / - * -G(gravity) | / - * |_/ - * / |/_____\ -Y (-y direction of device) - * user angel - */ - private void onAccelerometerChanged(float gx, float gy, float gz) { - - float x = gx, y = gy, z = gz; - - switch (mDisplay.getRotation()) { - case Surface.ROTATION_90: x = -gy; y= gx; break; - case Surface.ROTATION_180: x = -gx; y = -gy; break; - case Surface.ROTATION_270: x = gy; y = -gx; break; - } - - float temp = x * x + y * y + z * z; - float t = -y /temp; - - float tx = t * x; - float ty = -1 + t * y; - float tz = t * z; - - float length = FloatMath.sqrt(tx * tx + ty * ty + tz * tz); - float glength = FloatMath.sqrt(temp); - - mX = Utils.clamp((x * USER_ANGEL_COS / glength - + tx * USER_ANGEL_SIN / length) * mUserDistance, - -mLimit, mLimit); - mY = -Utils.clamp((y * USER_ANGEL_COS / glength - + ty * USER_ANGEL_SIN / length) * mUserDistance, - -mLimit, mLimit); - mZ = -FloatMath.sqrt( - mUserDistance * mUserDistance - mX * mX - mY * mY); - mListener.onEyePositionChanged(mX, mY, mZ); - } - - private void onGyroscopeChanged(float gx, float gy, float gz) { - long now = SystemClock.elapsedRealtime(); - float distance = (gx > 0 ? gx : -gx) + (gy > 0 ? gy : - gy); - if (distance < GYROSCOPE_THRESHOLD - || distance > GYROSCOPE_LIMIT || mGyroscopeCountdown > 0) { - --mGyroscopeCountdown; - mStartTime = now; - float limit = mUserDistance / 20f; - if (mX > limit || mX < -limit || mY > limit || mY < -limit) { - mX *= GYROSCOPE_RESTORE_FACTOR; - mY *= GYROSCOPE_RESTORE_FACTOR; - mZ = (float) -Math.sqrt( - mUserDistance * mUserDistance - mX * mX - mY * mY); - mListener.onEyePositionChanged(mX, mY, mZ); - } - return; - } - - float t = (now - mStartTime) / 1000f * mUserDistance * (-mZ); - mStartTime = now; - - float x = -gy, y = -gx; - switch (mDisplay.getRotation()) { - case Surface.ROTATION_90: x = -gx; y= gy; break; - case Surface.ROTATION_180: x = gy; y = gx; break; - case Surface.ROTATION_270: x = gx; y = -gy; break; - } - - mX = Utils.clamp((float) (mX + x * t / Math.hypot(mZ, mX)), - -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR; - mY = Utils.clamp((float) (mY + y * t / Math.hypot(mZ, mY)), - -mLimit, mLimit) * GYROSCOPE_RESTORE_FACTOR; - - mZ = -FloatMath.sqrt( - mUserDistance * mUserDistance - mX * mX - mY * mY); - mListener.onEyePositionChanged(mX, mY, mZ); - } - - private class PositionListener implements SensorEventListener { - @Override - public void onAccuracyChanged(Sensor sensor, int accuracy) { - } - - @Override - public void onSensorChanged(SensorEvent event) { - switch (event.sensor.getType()) { - case Sensor.TYPE_GYROSCOPE: { - onGyroscopeChanged( - event.values[0], event.values[1], event.values[2]); - break; - } - case Sensor.TYPE_ACCELEROMETER: { - onAccelerometerChanged( - event.values[0], event.values[1], event.values[2]); - } - } - } - } - - public void pause() { - if (mSensor != null) { - SensorManager sManager = (SensorManager) mContext - .getSystemService(Context.SENSOR_SERVICE); - sManager.unregisterListener(mPositionListener); - } - } - - public void resume() { - if (mSensor != null) { - SensorManager sManager = (SensorManager) mContext - .getSystemService(Context.SENSOR_SERVICE); - sManager.registerListener(mPositionListener, - mSensor, SensorManager.SENSOR_DELAY_GAME); - } - - mStartTime = NOT_STARTED; - mGyroscopeCountdown = GYROSCOPE_SETTLE_DOWN; - mX = mY = 0; - mZ = -mUserDistance; - mListener.onEyePositionChanged(mX, mY, mZ); - } -} diff --git a/src/com/android/gallery3d/app/FilmstripPage.java b/src/com/android/gallery3d/app/FilmstripPage.java deleted file mode 100644 index a9726cdc9..000000000 --- a/src/com/android/gallery3d/app/FilmstripPage.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -public class FilmstripPage extends PhotoPage { - -} diff --git a/src/com/android/gallery3d/app/FilterUtils.java b/src/com/android/gallery3d/app/FilterUtils.java deleted file mode 100644 index bc28a9cc1..000000000 --- a/src/com/android/gallery3d/app/FilterUtils.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; - -// This class handles filtering and clustering. -// -// We allow at most only one filter operation at a time (Currently it -// doesn't make sense to use more than one). Also each clustering operation -// can be applied at most once. In addition, there is one more constraint -// ("fixed set constraint") described below. -// -// A clustered album (not including album set) and its base sets are fixed. -// For example, -// -// /cluster/{base_set}/time/7 -// -// This set and all sets inside base_set (recursively) are fixed because -// 1. We can not change this set to use another clustering condition (like -// changing "time" to "location"). -// 2. Neither can we change any set in the base_set. -// The reason is in both cases the 7th set may not exist in the new clustering. -// --------------------- -// newPath operation: create a new path based on a source path and put an extra -// condition on top of it: -// -// T = newFilterPath(S, filterType); -// T = newClusterPath(S, clusterType); -// -// Similar functions can be used to replace the current condition (if there is one). -// -// T = switchFilterPath(S, filterType); -// T = switchClusterPath(S, clusterType); -// -// For all fixed set in the path defined above, if some clusterType and -// filterType are already used, they cannot not be used as parameter for these -// functions. setupMenuItems() makes sure those types cannot be selected. -// -public class FilterUtils { - @SuppressWarnings("unused") - private static final String TAG = "FilterUtils"; - - public static final int CLUSTER_BY_ALBUM = 1; - public static final int CLUSTER_BY_TIME = 2; - public static final int CLUSTER_BY_LOCATION = 4; - public static final int CLUSTER_BY_TAG = 8; - public static final int CLUSTER_BY_SIZE = 16; - public static final int CLUSTER_BY_FACE = 32; - - public static final int FILTER_IMAGE_ONLY = 1; - public static final int FILTER_VIDEO_ONLY = 2; - public static final int FILTER_ALL = 4; - - // These are indices of the return values of getAppliedFilters(). - // The _F suffix means "fixed". - private static final int CLUSTER_TYPE = 0; - private static final int FILTER_TYPE = 1; - private static final int CLUSTER_TYPE_F = 2; - private static final int FILTER_TYPE_F = 3; - private static final int CLUSTER_CURRENT_TYPE = 4; - private static final int FILTER_CURRENT_TYPE = 5; - - public static void setupMenuItems(GalleryActionBar actionBar, Path path, boolean inAlbum) { - int[] result = new int[6]; - getAppliedFilters(path, result); - int ctype = result[CLUSTER_TYPE]; - int ftype = result[FILTER_TYPE]; - int ftypef = result[FILTER_TYPE_F]; - int ccurrent = result[CLUSTER_CURRENT_TYPE]; - int fcurrent = result[FILTER_CURRENT_TYPE]; - - setMenuItemApplied(actionBar, CLUSTER_BY_TIME, - (ctype & CLUSTER_BY_TIME) != 0, (ccurrent & CLUSTER_BY_TIME) != 0); - setMenuItemApplied(actionBar, CLUSTER_BY_LOCATION, - (ctype & CLUSTER_BY_LOCATION) != 0, (ccurrent & CLUSTER_BY_LOCATION) != 0); - setMenuItemApplied(actionBar, CLUSTER_BY_TAG, - (ctype & CLUSTER_BY_TAG) != 0, (ccurrent & CLUSTER_BY_TAG) != 0); - setMenuItemApplied(actionBar, CLUSTER_BY_FACE, - (ctype & CLUSTER_BY_FACE) != 0, (ccurrent & CLUSTER_BY_FACE) != 0); - - actionBar.setClusterItemVisibility(CLUSTER_BY_ALBUM, !inAlbum || ctype == 0); - - setMenuItemApplied(actionBar, R.id.action_cluster_album, ctype == 0, - ccurrent == 0); - - // A filtering is available if it's not applied, and the old filtering - // (if any) is not fixed. - setMenuItemAppliedEnabled(actionBar, R.string.show_images_only, - (ftype & FILTER_IMAGE_ONLY) != 0, - (ftype & FILTER_IMAGE_ONLY) == 0 && ftypef == 0, - (fcurrent & FILTER_IMAGE_ONLY) != 0); - setMenuItemAppliedEnabled(actionBar, R.string.show_videos_only, - (ftype & FILTER_VIDEO_ONLY) != 0, - (ftype & FILTER_VIDEO_ONLY) == 0 && ftypef == 0, - (fcurrent & FILTER_VIDEO_ONLY) != 0); - setMenuItemAppliedEnabled(actionBar, R.string.show_all, - ftype == 0, ftype != 0 && ftypef == 0, fcurrent == 0); - } - - // Gets the filters applied in the path. - private static void getAppliedFilters(Path path, int[] result) { - getAppliedFilters(path, result, false); - } - - private static void getAppliedFilters(Path path, int[] result, boolean underCluster) { - String[] segments = path.split(); - // Recurse into sub media sets. - for (int i = 0; i < segments.length; i++) { - if (segments[i].startsWith("{")) { - String[] sets = Path.splitSequence(segments[i]); - for (int j = 0; j < sets.length; j++) { - Path sub = Path.fromString(sets[j]); - getAppliedFilters(sub, result, underCluster); - } - } - } - - // update current selection - if (segments[0].equals("cluster")) { - // if this is a clustered album, set underCluster to true. - if (segments.length == 4) { - underCluster = true; - } - - int ctype = toClusterType(segments[2]); - result[CLUSTER_TYPE] |= ctype; - result[CLUSTER_CURRENT_TYPE] = ctype; - if (underCluster) { - result[CLUSTER_TYPE_F] |= ctype; - } - } - } - - private static int toClusterType(String s) { - if (s.equals("time")) { - return CLUSTER_BY_TIME; - } else if (s.equals("location")) { - return CLUSTER_BY_LOCATION; - } else if (s.equals("tag")) { - return CLUSTER_BY_TAG; - } else if (s.equals("size")) { - return CLUSTER_BY_SIZE; - } else if (s.equals("face")) { - return CLUSTER_BY_FACE; - } - return 0; - } - - private static void setMenuItemApplied( - GalleryActionBar model, int id, boolean applied, boolean updateTitle) { - model.setClusterItemEnabled(id, !applied); - } - - private static void setMenuItemAppliedEnabled(GalleryActionBar model, int id, boolean applied, boolean enabled, boolean updateTitle) { - model.setClusterItemEnabled(id, enabled); - } - - // Add a specified filter to the path. - public static String newFilterPath(String base, int filterType) { - int mediaType; - switch (filterType) { - case FILTER_IMAGE_ONLY: - mediaType = MediaObject.MEDIA_TYPE_IMAGE; - break; - case FILTER_VIDEO_ONLY: - mediaType = MediaObject.MEDIA_TYPE_VIDEO; - break; - default: /* FILTER_ALL */ - return base; - } - - return "/filter/mediatype/" + mediaType + "/{" + base + "}"; - } - - // Add a specified clustering to the path. - public static String newClusterPath(String base, int clusterType) { - String kind; - switch (clusterType) { - case CLUSTER_BY_TIME: - kind = "time"; - break; - case CLUSTER_BY_LOCATION: - kind = "location"; - break; - case CLUSTER_BY_TAG: - kind = "tag"; - break; - case CLUSTER_BY_SIZE: - kind = "size"; - break; - case CLUSTER_BY_FACE: - kind = "face"; - break; - default: /* CLUSTER_BY_ALBUM */ - return base; - } - - return "/cluster/{" + base + "}/" + kind; - } - - // Change the topmost clustering to the specified type. - public static String switchClusterPath(String base, int clusterType) { - return newClusterPath(removeOneClusterFromPath(base), clusterType); - } - - // Remove the topmost clustering (if any) from the path. - private static String removeOneClusterFromPath(String base) { - boolean[] done = new boolean[1]; - return removeOneClusterFromPath(base, done); - } - - private static String removeOneClusterFromPath(String base, boolean[] done) { - if (done[0]) return base; - - String[] segments = Path.split(base); - if (segments[0].equals("cluster")) { - done[0] = true; - return Path.splitSequence(segments[1])[0]; - } - - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < segments.length; i++) { - sb.append("/"); - if (segments[i].startsWith("{")) { - sb.append("{"); - String[] sets = Path.splitSequence(segments[i]); - for (int j = 0; j < sets.length; j++) { - if (j > 0) { - sb.append(","); - } - sb.append(removeOneClusterFromPath(sets[j], done)); - } - sb.append("}"); - } else { - sb.append(segments[i]); - } - } - return sb.toString(); - } -} diff --git a/src/com/android/gallery3d/app/Gallery.java b/src/com/android/gallery3d/app/Gallery.java deleted file mode 100644 index baef56b44..000000000 --- a/src/com/android/gallery3d/app/Gallery.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Dialog; -import android.content.ContentResolver; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.view.InputDevice; -import android.view.MotionEvent; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.util.GalleryUtils; - -public final class Gallery extends AbstractGalleryActivity implements OnCancelListener { - public static final String EXTRA_SLIDESHOW = "slideshow"; - public static final String EXTRA_DREAM = "dream"; - public static final String EXTRA_CROP = "crop"; - - public static final String ACTION_REVIEW = "com.android.camera.action.REVIEW"; - public static final String KEY_GET_CONTENT = "get-content"; - public static final String KEY_GET_ALBUM = "get-album"; - public static final String KEY_TYPE_BITS = "type-bits"; - public static final String KEY_MEDIA_TYPES = "mediaTypes"; - public static final String KEY_DISMISS_KEYGUARD = "dismiss-keyguard"; - - private static final String TAG = "Gallery"; - private Dialog mVersionCheckDialog; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - - if (getIntent().getBooleanExtra(KEY_DISMISS_KEYGUARD, false)) { - getWindow().addFlags( - WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); - } - - setContentView(R.layout.main); - - if (savedInstanceState != null) { - getStateManager().restoreFromState(savedInstanceState); - } else { - initializeByIntent(); - } - } - - private void initializeByIntent() { - Intent intent = getIntent(); - String action = intent.getAction(); - - if (Intent.ACTION_GET_CONTENT.equalsIgnoreCase(action)) { - startGetContent(intent); - } else if (Intent.ACTION_PICK.equalsIgnoreCase(action)) { - // We do NOT really support the PICK intent. Handle it as - // the GET_CONTENT. However, we need to translate the type - // in the intent here. - Log.w(TAG, "action PICK is not supported"); - String type = Utils.ensureNotNull(intent.getType()); - if (type.startsWith("vnd.android.cursor.dir/")) { - if (type.endsWith("/image")) intent.setType("image/*"); - if (type.endsWith("/video")) intent.setType("video/*"); - } - startGetContent(intent); - } else if (Intent.ACTION_VIEW.equalsIgnoreCase(action) - || ACTION_REVIEW.equalsIgnoreCase(action)){ - startViewAction(intent); - } else { - startDefaultPage(); - } - } - - public void startDefaultPage() { - PicasaSource.showSignInReminder(this); - Bundle data = new Bundle(); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(DataManager.INCLUDE_ALL)); - getStateManager().startState(AlbumSetPage.class, data); - mVersionCheckDialog = PicasaSource.getVersionCheckDialog(this); - if (mVersionCheckDialog != null) { - mVersionCheckDialog.setOnCancelListener(this); - } - } - - private void startGetContent(Intent intent) { - Bundle data = intent.getExtras() != null - ? new Bundle(intent.getExtras()) - : new Bundle(); - data.putBoolean(KEY_GET_CONTENT, true); - int typeBits = GalleryUtils.determineTypeBits(this, intent); - data.putInt(KEY_TYPE_BITS, typeBits); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(typeBits)); - getStateManager().startState(AlbumSetPage.class, data); - } - - private String getContentType(Intent intent) { - String type = intent.getType(); - if (type != null) { - return GalleryUtils.MIME_TYPE_PANORAMA360.equals(type) - ? MediaItem.MIME_TYPE_JPEG : type; - } - - Uri uri = intent.getData(); - try { - return getContentResolver().getType(uri); - } catch (Throwable t) { - Log.w(TAG, "get type fail", t); - return null; - } - } - - private void startViewAction(Intent intent) { - Boolean slideshow = intent.getBooleanExtra(EXTRA_SLIDESHOW, false); - if (slideshow) { - getActionBar().hide(); - DataManager manager = getDataManager(); - Path path = manager.findPathByUri(intent.getData(), intent.getType()); - if (path == null || manager.getMediaObject(path) - instanceof MediaItem) { - path = Path.fromString( - manager.getTopSetPath(DataManager.INCLUDE_IMAGE)); - } - Bundle data = new Bundle(); - data.putString(SlideshowPage.KEY_SET_PATH, path.toString()); - data.putBoolean(SlideshowPage.KEY_RANDOM_ORDER, true); - data.putBoolean(SlideshowPage.KEY_REPEAT, true); - if (intent.getBooleanExtra(EXTRA_DREAM, false)) { - data.putBoolean(SlideshowPage.KEY_DREAM, true); - } - getStateManager().startState(SlideshowPage.class, data); - } else { - Bundle data = new Bundle(); - DataManager dm = getDataManager(); - Uri uri = intent.getData(); - String contentType = getContentType(intent); - if (contentType == null) { - Toast.makeText(this, - R.string.no_such_item, Toast.LENGTH_LONG).show(); - finish(); - return; - } - if (uri == null) { - int typeBits = GalleryUtils.determineTypeBits(this, intent); - data.putInt(KEY_TYPE_BITS, typeBits); - data.putString(AlbumSetPage.KEY_MEDIA_PATH, - getDataManager().getTopSetPath(typeBits)); - getStateManager().startState(AlbumSetPage.class, data); - } else if (contentType.startsWith( - ContentResolver.CURSOR_DIR_BASE_TYPE)) { - int mediaType = intent.getIntExtra(KEY_MEDIA_TYPES, 0); - if (mediaType != 0) { - uri = uri.buildUpon().appendQueryParameter( - KEY_MEDIA_TYPES, String.valueOf(mediaType)) - .build(); - } - Path setPath = dm.findPathByUri(uri, null); - MediaSet mediaSet = null; - if (setPath != null) { - mediaSet = (MediaSet) dm.getMediaObject(setPath); - } - if (mediaSet != null) { - if (mediaSet.isLeafAlbum()) { - data.putString(AlbumPage.KEY_MEDIA_PATH, setPath.toString()); - data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, - dm.getTopSetPath(DataManager.INCLUDE_ALL)); - getStateManager().startState(AlbumPage.class, data); - } else { - data.putString(AlbumSetPage.KEY_MEDIA_PATH, setPath.toString()); - getStateManager().startState(AlbumSetPage.class, data); - } - } else { - startDefaultPage(); - } - } else { - Path itemPath = dm.findPathByUri(uri, contentType); - Path albumPath = dm.getDefaultSetOf(itemPath); - - data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, itemPath.toString()); - - // TODO: Make the parameter "SingleItemOnly" public so other - // activities can reference it. - boolean singleItemOnly = (albumPath == null) - || intent.getBooleanExtra("SingleItemOnly", false); - if (!singleItemOnly) { - data.putString(PhotoPage.KEY_MEDIA_SET_PATH, albumPath.toString()); - // when FLAG_ACTIVITY_NEW_TASK is set, (e.g. when intent is fired - // from notification), back button should behave the same as up button - // rather than taking users back to the home screen - if (intent.getBooleanExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, false) - || ((intent.getFlags() & Intent.FLAG_ACTIVITY_NEW_TASK) != 0)) { - data.putBoolean(PhotoPage.KEY_TREAT_BACK_AS_UP, true); - } - } - - getStateManager().startState(SinglePhotoPage.class, data); - } - } - } - - @Override - protected void onResume() { - Utils.assertTrue(getStateManager().getStateCount() > 0); - super.onResume(); - if (mVersionCheckDialog != null) { - mVersionCheckDialog.show(); - } - } - - @Override - protected void onPause() { - super.onPause(); - if (mVersionCheckDialog != null) { - mVersionCheckDialog.dismiss(); - } - } - - @Override - public void onCancel(DialogInterface dialog) { - if (dialog == mVersionCheckDialog) { - mVersionCheckDialog = null; - } - } - - @Override - public boolean onGenericMotionEvent(MotionEvent event) { - final boolean isTouchPad = (event.getSource() - & InputDevice.SOURCE_CLASS_POSITION) != 0; - if (isTouchPad) { - float maxX = event.getDevice().getMotionRange(MotionEvent.AXIS_X).getMax(); - float maxY = event.getDevice().getMotionRange(MotionEvent.AXIS_Y).getMax(); - View decor = getWindow().getDecorView(); - float scaleX = decor.getWidth() / maxX; - float scaleY = decor.getHeight() / maxY; - float x = event.getX() * scaleX; - //x = decor.getWidth() - x; // invert x - float y = event.getY() * scaleY; - //y = decor.getHeight() - y; // invert y - MotionEvent touchEvent = MotionEvent.obtain(event.getDownTime(), - event.getEventTime(), event.getAction(), x, y, event.getMetaState()); - return dispatchTouchEvent(touchEvent); - } - return super.onGenericMotionEvent(event); - } -} diff --git a/src/com/android/gallery3d/app/GalleryActionBar.java b/src/com/android/gallery3d/app/GalleryActionBar.java deleted file mode 100644 index 588f5842a..000000000 --- a/src/com/android/gallery3d/app/GalleryActionBar.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.ActionBar.OnMenuVisibilityListener; -import android.app.ActionBar.OnNavigationListener; -import android.app.Activity; -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.res.Resources; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ShareActionProvider; -import android.widget.TextView; -import android.widget.TwoLineListItem; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; - -public class GalleryActionBar implements OnNavigationListener { - @SuppressWarnings("unused") - private static final String TAG = "GalleryActionBar"; - - private ClusterRunner mClusterRunner; - private CharSequence[] mTitles; - private ArrayList<Integer> mActions; - private Context mContext; - private LayoutInflater mInflater; - private AbstractGalleryActivity mActivity; - private ActionBar mActionBar; - private int mCurrentIndex; - private ClusterAdapter mAdapter = new ClusterAdapter(); - - private AlbumModeAdapter mAlbumModeAdapter; - private OnAlbumModeSelectedListener mAlbumModeListener; - private int mLastAlbumModeSelected; - private CharSequence [] mAlbumModes; - public static final int ALBUM_FILMSTRIP_MODE_SELECTED = 0; - public static final int ALBUM_GRID_MODE_SELECTED = 1; - - public interface ClusterRunner { - public void doCluster(int id); - } - - public interface OnAlbumModeSelectedListener { - public void onAlbumModeSelected(int mode); - } - - private static class ActionItem { - public int action; - public boolean enabled; - public boolean visible; - public int spinnerTitle; - public int dialogTitle; - public int clusterBy; - - public ActionItem(int action, boolean applied, boolean enabled, int title, - int clusterBy) { - this(action, applied, enabled, title, title, clusterBy); - } - - public ActionItem(int action, boolean applied, boolean enabled, int spinnerTitle, - int dialogTitle, int clusterBy) { - this.action = action; - this.enabled = enabled; - this.spinnerTitle = spinnerTitle; - this.dialogTitle = dialogTitle; - this.clusterBy = clusterBy; - this.visible = true; - } - } - - private static final ActionItem[] sClusterItems = new ActionItem[] { - new ActionItem(FilterUtils.CLUSTER_BY_ALBUM, true, false, R.string.albums, - R.string.group_by_album), - new ActionItem(FilterUtils.CLUSTER_BY_LOCATION, true, false, - R.string.locations, R.string.location, R.string.group_by_location), - new ActionItem(FilterUtils.CLUSTER_BY_TIME, true, false, R.string.times, - R.string.time, R.string.group_by_time), - new ActionItem(FilterUtils.CLUSTER_BY_FACE, true, false, R.string.people, - R.string.group_by_faces), - new ActionItem(FilterUtils.CLUSTER_BY_TAG, true, false, R.string.tags, - R.string.group_by_tags) - }; - - private class ClusterAdapter extends BaseAdapter { - - @Override - public int getCount() { - return sClusterItems.length; - } - - @Override - public Object getItem(int position) { - return sClusterItems[position]; - } - - @Override - public long getItemId(int position) { - return sClusterItems[position].action; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(R.layout.action_bar_text, - parent, false); - } - TextView view = (TextView) convertView; - view.setText(sClusterItems[position].spinnerTitle); - return convertView; - } - } - - private class AlbumModeAdapter extends BaseAdapter { - @Override - public int getCount() { - return mAlbumModes.length; - } - - @Override - public Object getItem(int position) { - return mAlbumModes[position]; - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(R.layout.action_bar_two_line_text, - parent, false); - } - TwoLineListItem view = (TwoLineListItem) convertView; - view.getText1().setText(mActionBar.getTitle()); - view.getText2().setText((CharSequence) getItem(position)); - return convertView; - } - - @Override - public View getDropDownView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = mInflater.inflate(R.layout.action_bar_text, - parent, false); - } - TextView view = (TextView) convertView; - view.setText((CharSequence) getItem(position)); - return convertView; - } - } - - public static String getClusterByTypeString(Context context, int type) { - for (ActionItem item : sClusterItems) { - if (item.action == type) { - return context.getString(item.clusterBy); - } - } - return null; - } - - public GalleryActionBar(AbstractGalleryActivity activity) { - mActionBar = activity.getActionBar(); - mContext = activity.getAndroidContext(); - mActivity = activity; - mInflater = ((Activity) mActivity).getLayoutInflater(); - mCurrentIndex = 0; - } - - private void createDialogData() { - ArrayList<CharSequence> titles = new ArrayList<CharSequence>(); - mActions = new ArrayList<Integer>(); - for (ActionItem item : sClusterItems) { - if (item.enabled && item.visible) { - titles.add(mContext.getString(item.dialogTitle)); - mActions.add(item.action); - } - } - mTitles = new CharSequence[titles.size()]; - titles.toArray(mTitles); - } - - public int getHeight() { - return mActionBar != null ? mActionBar.getHeight() : 0; - } - - public void setClusterItemEnabled(int id, boolean enabled) { - for (ActionItem item : sClusterItems) { - if (item.action == id) { - item.enabled = enabled; - return; - } - } - } - - public void setClusterItemVisibility(int id, boolean visible) { - for (ActionItem item : sClusterItems) { - if (item.action == id) { - item.visible = visible; - return; - } - } - } - - public int getClusterTypeAction() { - return sClusterItems[mCurrentIndex].action; - } - - public void enableClusterMenu(int action, ClusterRunner runner) { - if (mActionBar != null) { - // Don't set cluster runner until action bar is ready. - mClusterRunner = null; - mActionBar.setListNavigationCallbacks(mAdapter, this); - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); - setSelectedAction(action); - mClusterRunner = runner; - } - } - - // The only use case not to hideMenu in this method is to ensure - // all elements disappear at the same time when exiting gallery. - // hideMenu should always be true in all other cases. - public void disableClusterMenu(boolean hideMenu) { - if (mActionBar != null) { - mClusterRunner = null; - if (hideMenu) { - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - } - } - - public void onConfigurationChanged() { - if (mActionBar != null && mAlbumModeListener != null) { - OnAlbumModeSelectedListener listener = mAlbumModeListener; - enableAlbumModeMenu(mLastAlbumModeSelected, listener); - } - } - - public void enableAlbumModeMenu(int selected, OnAlbumModeSelectedListener listener) { - if (mActionBar != null) { - if (mAlbumModeAdapter == null) { - // Initialize the album mode options if they haven't been already - Resources res = mActivity.getResources(); - mAlbumModes = new CharSequence[] { - res.getString(R.string.switch_photo_filmstrip), - res.getString(R.string.switch_photo_grid)}; - mAlbumModeAdapter = new AlbumModeAdapter(); - } - mAlbumModeListener = null; - mLastAlbumModeSelected = selected; - mActionBar.setListNavigationCallbacks(mAlbumModeAdapter, this); - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); - mActionBar.setSelectedNavigationItem(selected); - mAlbumModeListener = listener; - } - } - - public void disableAlbumModeMenu(boolean hideMenu) { - if (mActionBar != null) { - mAlbumModeListener = null; - if (hideMenu) { - mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD); - } - } - } - - public void showClusterDialog(final ClusterRunner clusterRunner) { - createDialogData(); - final ArrayList<Integer> actions = mActions; - new AlertDialog.Builder(mContext).setTitle(R.string.group_by).setItems( - mTitles, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - // Need to lock rendering when operations invoked by system UI (main thread) are - // modifying slot data used in GL thread for rendering. - mActivity.getGLRoot().lockRenderThread(); - try { - clusterRunner.doCluster(actions.get(which).intValue()); - } finally { - mActivity.getGLRoot().unlockRenderThread(); - } - } - }).create().show(); - } - - @TargetApi(ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) - private void setHomeButtonEnabled(boolean enabled) { - if (mActionBar != null) mActionBar.setHomeButtonEnabled(enabled); - } - - public void setDisplayOptions(boolean displayHomeAsUp, boolean showTitle) { - if (mActionBar == null) return; - int options = 0; - if (displayHomeAsUp) options |= ActionBar.DISPLAY_HOME_AS_UP; - if (showTitle) options |= ActionBar.DISPLAY_SHOW_TITLE; - - mActionBar.setDisplayOptions(options, - ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_TITLE); - mActionBar.setHomeButtonEnabled(displayHomeAsUp); - } - - public void setTitle(String title) { - if (mActionBar != null) mActionBar.setTitle(title); - } - - public void setTitle(int titleId) { - if (mActionBar != null) { - mActionBar.setTitle(mContext.getString(titleId)); - } - } - - public void setSubtitle(String title) { - if (mActionBar != null) mActionBar.setSubtitle(title); - } - - public void show() { - if (mActionBar != null) mActionBar.show(); - } - - public void hide() { - if (mActionBar != null) mActionBar.hide(); - } - - public void addOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - if (mActionBar != null) mActionBar.addOnMenuVisibilityListener(listener); - } - - public void removeOnMenuVisibilityListener(OnMenuVisibilityListener listener) { - if (mActionBar != null) mActionBar.removeOnMenuVisibilityListener(listener); - } - - public boolean setSelectedAction(int type) { - if (mActionBar == null) return false; - - for (int i = 0, n = sClusterItems.length; i < n; i++) { - ActionItem item = sClusterItems[i]; - if (item.action == type) { - mActionBar.setSelectedNavigationItem(i); - mCurrentIndex = i; - return true; - } - } - return false; - } - - @Override - public boolean onNavigationItemSelected(int itemPosition, long itemId) { - if (itemPosition != mCurrentIndex && mClusterRunner != null - || mAlbumModeListener != null) { - // Need to lock rendering when operations invoked by system UI (main thread) are - // modifying slot data used in GL thread for rendering. - mActivity.getGLRoot().lockRenderThread(); - try { - if (mAlbumModeListener != null) { - mAlbumModeListener.onAlbumModeSelected(itemPosition); - } else { - mClusterRunner.doCluster(sClusterItems[itemPosition].action); - } - } finally { - mActivity.getGLRoot().unlockRenderThread(); - } - } - return false; - } - - private Menu mActionBarMenu; - private ShareActionProvider mSharePanoramaActionProvider; - private ShareActionProvider mShareActionProvider; - private Intent mSharePanoramaIntent; - private Intent mShareIntent; - - public void createActionBarMenu(int menuRes, Menu menu) { - mActivity.getMenuInflater().inflate(menuRes, menu); - mActionBarMenu = menu; - - MenuItem item = menu.findItem(R.id.action_share_panorama); - if (item != null) { - mSharePanoramaActionProvider = (ShareActionProvider) - item.getActionProvider(); - mSharePanoramaActionProvider - .setShareHistoryFileName("panorama_share_history.xml"); - mSharePanoramaActionProvider.setShareIntent(mSharePanoramaIntent); - } - - item = menu.findItem(R.id.action_share); - if (item != null) { - mShareActionProvider = (ShareActionProvider) - item.getActionProvider(); - mShareActionProvider - .setShareHistoryFileName("share_history.xml"); - mShareActionProvider.setShareIntent(mShareIntent); - } - } - - public Menu getMenu() { - return mActionBarMenu; - } - - public void setShareIntents(Intent sharePanoramaIntent, Intent shareIntent, - ShareActionProvider.OnShareTargetSelectedListener onShareListener) { - mSharePanoramaIntent = sharePanoramaIntent; - if (mSharePanoramaActionProvider != null) { - mSharePanoramaActionProvider.setShareIntent(sharePanoramaIntent); - } - mShareIntent = shareIntent; - if (mShareActionProvider != null) { - mShareActionProvider.setShareIntent(shareIntent); - mShareActionProvider.setOnShareTargetSelectedListener( - onShareListener); - } - } -} diff --git a/src/com/android/gallery3d/app/GalleryApp.java b/src/com/android/gallery3d/app/GalleryApp.java deleted file mode 100644 index b56b8a82c..000000000 --- a/src/com/android/gallery3d/app/GalleryApp.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.res.Resources; -import android.os.Looper; - -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.DownloadCache; -import com.android.gallery3d.data.ImageCacheService; -import com.android.gallery3d.util.ThreadPool; - -public interface GalleryApp { - public DataManager getDataManager(); - - public StitchingProgressManager getStitchingProgressManager(); - public ImageCacheService getImageCacheService(); - public DownloadCache getDownloadCache(); - public ThreadPool getThreadPool(); - - public Context getAndroidContext(); - public Looper getMainLooper(); - public ContentResolver getContentResolver(); - public Resources getResources(); -} diff --git a/src/com/android/gallery3d/app/GalleryAppImpl.java b/src/com/android/gallery3d/app/GalleryAppImpl.java deleted file mode 100644 index 2abdaa0c1..000000000 --- a/src/com/android/gallery3d/app/GalleryAppImpl.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Application; -import android.content.Context; -import android.os.AsyncTask; - -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.DownloadCache; -import com.android.gallery3d.data.ImageCacheService; -import com.android.gallery3d.gadget.WidgetUtils; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.UsageStatistics; -import com.android.photos.data.MediaCache; - -import java.io.File; - -public class GalleryAppImpl extends Application implements GalleryApp { - - private static final String DOWNLOAD_FOLDER = "download"; - private static final long DOWNLOAD_CAPACITY = 64 * 1024 * 1024; // 64M - - private ImageCacheService mImageCacheService; - private Object mLock = new Object(); - private DataManager mDataManager; - private ThreadPool mThreadPool; - private DownloadCache mDownloadCache; - private StitchingProgressManager mStitchingProgressManager; - - @Override - public void onCreate() { - super.onCreate(); - com.android.camera.Util.initialize(this); - initializeAsyncTask(); - GalleryUtils.initialize(this); - WidgetUtils.initialize(this); - PicasaSource.initialize(this); - UsageStatistics.initialize(this); - MediaCache.initialize(this); - - mStitchingProgressManager = LightCycleHelper.createStitchingManagerInstance(this); - if (mStitchingProgressManager != null) { - mStitchingProgressManager.addChangeListener(getDataManager()); - } - } - - @Override - public Context getAndroidContext() { - return this; - } - - @Override - public synchronized DataManager getDataManager() { - if (mDataManager == null) { - mDataManager = new DataManager(this); - mDataManager.initializeSourceMap(); - } - return mDataManager; - } - - @Override - public StitchingProgressManager getStitchingProgressManager() { - return mStitchingProgressManager; - } - - @Override - public ImageCacheService getImageCacheService() { - // This method may block on file I/O so a dedicated lock is needed here. - synchronized (mLock) { - if (mImageCacheService == null) { - mImageCacheService = new ImageCacheService(getAndroidContext()); - } - return mImageCacheService; - } - } - - @Override - public synchronized ThreadPool getThreadPool() { - if (mThreadPool == null) { - mThreadPool = new ThreadPool(); - } - return mThreadPool; - } - - @Override - public synchronized DownloadCache getDownloadCache() { - if (mDownloadCache == null) { - File cacheDir = new File(getExternalCacheDir(), DOWNLOAD_FOLDER); - - if (!cacheDir.isDirectory()) cacheDir.mkdirs(); - - if (!cacheDir.isDirectory()) { - throw new RuntimeException( - "fail to create: " + cacheDir.getAbsolutePath()); - } - mDownloadCache = new DownloadCache(this, cacheDir, DOWNLOAD_CAPACITY); - } - return mDownloadCache; - } - - private void initializeAsyncTask() { - // AsyncTask class needs to be loaded in UI thread. - // So we load it here to comply the rule. - try { - Class.forName(AsyncTask.class.getName()); - } catch (ClassNotFoundException e) { - } - } -} diff --git a/src/com/android/gallery3d/app/GalleryContext.java b/src/com/android/gallery3d/app/GalleryContext.java deleted file mode 100644 index 06f4fe4d1..000000000 --- a/src/com/android/gallery3d/app/GalleryContext.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.content.res.Resources; -import android.os.Looper; - -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.util.ThreadPool; - -public interface GalleryContext { - public DataManager getDataManager(); - - public Context getAndroidContext(); - - public Looper getMainLooper(); - public Resources getResources(); - public ThreadPool getThreadPool(); -} diff --git a/src/com/android/gallery3d/app/LoadingListener.java b/src/com/android/gallery3d/app/LoadingListener.java deleted file mode 100644 index e94df9307..000000000 --- a/src/com/android/gallery3d/app/LoadingListener.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -public interface LoadingListener { - public void onLoadingStarted(); - /** - * Called when loading is complete or no further progress can be made. - * - * @param loadingFailed true if data source cannot provide requested data - */ - public void onLoadingFinished(boolean loadingFailed); -} diff --git a/src/com/android/gallery3d/app/Log.java b/src/com/android/gallery3d/app/Log.java deleted file mode 100644 index 07a8ea588..000000000 --- a/src/com/android/gallery3d/app/Log.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -public class Log { - public static int v(String tag, String msg) { - return android.util.Log.v(tag, msg); - } - public static int v(String tag, String msg, Throwable tr) { - return android.util.Log.v(tag, msg, tr); - } - public static int d(String tag, String msg) { - return android.util.Log.d(tag, msg); - } - public static int d(String tag, String msg, Throwable tr) { - return android.util.Log.d(tag, msg, tr); - } - public static int i(String tag, String msg) { - return android.util.Log.i(tag, msg); - } - public static int i(String tag, String msg, Throwable tr) { - return android.util.Log.i(tag, msg, tr); - } - public static int w(String tag, String msg) { - return android.util.Log.w(tag, msg); - } - public static int w(String tag, String msg, Throwable tr) { - return android.util.Log.w(tag, msg, tr); - } - public static int w(String tag, Throwable tr) { - return android.util.Log.w(tag, tr); - } - public static int e(String tag, String msg) { - return android.util.Log.e(tag, msg); - } - public static int e(String tag, String msg, Throwable tr) { - return android.util.Log.e(tag, msg, tr); - } -} diff --git a/src/com/android/gallery3d/app/ManageCachePage.java b/src/com/android/gallery3d/app/ManageCachePage.java deleted file mode 100644 index 4f5c35819..000000000 --- a/src/com/android/gallery3d/app/ManageCachePage.java +++ /dev/null @@ -1,419 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.text.format.Formatter; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.FrameLayout; -import android.widget.ProgressBar; -import android.widget.TextView; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.ui.CacheStorageUsageInfo; -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.ManageCacheDrawer; -import com.android.gallery3d.ui.MenuExecutor; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SlotView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; - -public class ManageCachePage extends ActivityState implements - SelectionManager.SelectionListener, MenuExecutor.ProgressListener, - EyePosition.EyePositionListener, OnClickListener { - public static final String KEY_MEDIA_PATH = "media-path"; - - @SuppressWarnings("unused") - private static final String TAG = "ManageCachePage"; - - private static final int DATA_CACHE_SIZE = 256; - private static final int MSG_REFRESH_STORAGE_INFO = 1; - private static final int MSG_REQUEST_LAYOUT = 2; - private static final int PROGRESS_BAR_MAX = 10000; - - private SlotView mSlotView; - private MediaSet mMediaSet; - - protected SelectionManager mSelectionManager; - protected ManageCacheDrawer mSelectionDrawer; - private AlbumSetDataLoader mAlbumSetDataAdapter; - - private EyePosition mEyePosition; - - // The eyes' position of the user, the origin is at the center of the - // device and the unit is in pixels. - private float mX; - private float mY; - private float mZ; - - private int mAlbumCountToMakeAvailableOffline; - private View mFooterContent; - private CacheStorageUsageInfo mCacheStorageInfo; - private Future<Void> mUpdateStorageInfo; - private Handler mHandler; - private boolean mLayoutReady = false; - - @Override - protected int getBackgroundColorId() { - return R.color.cache_background; - } - - private GLView mRootPane = new GLView() { - private float mMatrix[] = new float[16]; - - @Override - protected void renderBackground(GLCanvas view) { - view.clearBuffer(getBackgroundColor()); - } - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - // Hack: our layout depends on other components on the screen. - // We assume the other components will complete before we get a change - // to run a message in main thread. - if (!mLayoutReady) { - mHandler.sendEmptyMessage(MSG_REQUEST_LAYOUT); - return; - } - mLayoutReady = false; - - mEyePosition.resetPosition(); - int slotViewTop = mActivity.getGalleryActionBar().getHeight(); - int slotViewBottom = bottom - top; - - View footer = mActivity.findViewById(R.id.footer); - if (footer != null) { - int location[] = {0, 0}; - footer.getLocationOnScreen(location); - slotViewBottom = location[1]; - } - - mSlotView.layout(0, slotViewTop, right - left, slotViewBottom); - } - - @Override - protected void render(GLCanvas canvas) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - GalleryUtils.setViewPointMatrix(mMatrix, - getWidth() / 2 + mX, getHeight() / 2 + mY, mZ); - canvas.multiplyMatrix(mMatrix, 0); - super.render(canvas); - canvas.restore(); - } - }; - - @Override - public void onEyePositionChanged(float x, float y, float z) { - mRootPane.lockRendering(); - mX = x; - mY = y; - mZ = z; - mRootPane.unlockRendering(); - mRootPane.invalidate(); - } - - private void onDown(int index) { - mSelectionDrawer.setPressedIndex(index); - } - - private void onUp() { - mSelectionDrawer.setPressedIndex(-1); - } - - public void onSingleTapUp(int slotIndex) { - MediaSet targetSet = mAlbumSetDataAdapter.getMediaSet(slotIndex); - if (targetSet == null) return; // Content is dirty, we shall reload soon - - // ignore selection action if the target set does not support cache - // operation (like a local album). - if ((targetSet.getSupportedOperations() - & MediaSet.SUPPORT_CACHE) == 0) { - showToastForLocalAlbum(); - return; - } - - Path path = targetSet.getPath(); - boolean isFullyCached = - (targetSet.getCacheFlag() == MediaObject.CACHE_FLAG_FULL); - boolean isSelected = mSelectionManager.isItemSelected(path); - - if (!isFullyCached) { - // We only count the media sets that will be made available offline - // in this session. - if (isSelected) { - --mAlbumCountToMakeAvailableOffline; - } else { - ++mAlbumCountToMakeAvailableOffline; - } - } - - long sizeOfTarget = targetSet.getCacheSize(); - mCacheStorageInfo.increaseTargetCacheSize( - (isFullyCached ^ isSelected) ? -sizeOfTarget : sizeOfTarget); - refreshCacheStorageInfo(); - - mSelectionManager.toggle(path); - mSlotView.invalidate(); - } - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mCacheStorageInfo = new CacheStorageUsageInfo(mActivity); - initializeViews(); - initializeData(data); - mEyePosition = new EyePosition(mActivity.getAndroidContext(), this); - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_REFRESH_STORAGE_INFO: - refreshCacheStorageInfo(); - break; - case MSG_REQUEST_LAYOUT: { - mLayoutReady = true; - removeMessages(MSG_REQUEST_LAYOUT); - mRootPane.requestLayout(); - break; - } - } - } - }; - } - - @Override - public void onConfigurationChanged(Configuration config) { - // We use different layout resources for different configs - initializeFooterViews(); - FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer); - if (layout.getVisibility() == View.VISIBLE) { - layout.removeAllViews(); - layout.addView(mFooterContent); - } - } - - @Override - public void onPause() { - super.onPause(); - mAlbumSetDataAdapter.pause(); - mSelectionDrawer.pause(); - mEyePosition.pause(); - - if (mUpdateStorageInfo != null) { - mUpdateStorageInfo.cancel(); - mUpdateStorageInfo = null; - } - mHandler.removeMessages(MSG_REFRESH_STORAGE_INFO); - - FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer); - layout.removeAllViews(); - layout.setVisibility(View.INVISIBLE); - } - - private Job<Void> mUpdateStorageInfoJob = new Job<Void>() { - @Override - public Void run(JobContext jc) { - mCacheStorageInfo.loadStorageInfo(jc); - if (!jc.isCancelled()) { - mHandler.sendEmptyMessage(MSG_REFRESH_STORAGE_INFO); - } - return null; - } - }; - - @Override - public void onResume() { - super.onResume(); - setContentPane(mRootPane); - mAlbumSetDataAdapter.resume(); - mSelectionDrawer.resume(); - mEyePosition.resume(); - mUpdateStorageInfo = mActivity.getThreadPool().submit(mUpdateStorageInfoJob); - FrameLayout layout = (FrameLayout) ((Activity) mActivity).findViewById(R.id.footer); - layout.addView(mFooterContent); - layout.setVisibility(View.VISIBLE); - } - - private void initializeData(Bundle data) { - String mediaPath = data.getString(ManageCachePage.KEY_MEDIA_PATH); - mMediaSet = mActivity.getDataManager().getMediaSet(mediaPath); - mSelectionManager.setSourceMediaSet(mMediaSet); - - // We will always be in selection mode in this page. - mSelectionManager.setAutoLeaveSelectionMode(false); - mSelectionManager.enterSelectionMode(); - - mAlbumSetDataAdapter = new AlbumSetDataLoader( - mActivity, mMediaSet, DATA_CACHE_SIZE); - mSelectionDrawer.setModel(mAlbumSetDataAdapter); - } - - private void initializeViews() { - Activity activity = mActivity; - - mSelectionManager = new SelectionManager(mActivity, true); - mSelectionManager.setSelectionListener(this); - - Config.ManageCachePage config = Config.ManageCachePage.get(activity); - mSlotView = new SlotView(mActivity, config.slotViewSpec); - mSelectionDrawer = new ManageCacheDrawer(mActivity, mSelectionManager, mSlotView, - config.labelSpec, config.cachePinSize, config.cachePinMargin); - mSlotView.setSlotRenderer(mSelectionDrawer); - mSlotView.setListener(new SlotView.SimpleListener() { - @Override - public void onDown(int index) { - ManageCachePage.this.onDown(index); - } - - @Override - public void onUp(boolean followedByLongPress) { - ManageCachePage.this.onUp(); - } - - @Override - public void onSingleTapUp(int slotIndex) { - ManageCachePage.this.onSingleTapUp(slotIndex); - } - }); - mRootPane.addComponent(mSlotView); - initializeFooterViews(); - } - - private void initializeFooterViews() { - Activity activity = mActivity; - - LayoutInflater inflater = activity.getLayoutInflater(); - mFooterContent = inflater.inflate(R.layout.manage_offline_bar, null); - - mFooterContent.findViewById(R.id.done).setOnClickListener(this); - refreshCacheStorageInfo(); - } - - @Override - public void onClick(View view) { - Utils.assertTrue(view.getId() == R.id.done); - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - ArrayList<Path> ids = mSelectionManager.getSelected(false); - if (ids.size() == 0) { - onBackPressed(); - return; - } - showToast(); - - MenuExecutor menuExecutor = new MenuExecutor(mActivity, mSelectionManager); - menuExecutor.startAction(R.id.action_toggle_full_caching, - R.string.process_caching_requests, this); - } finally { - root.unlockRenderThread(); - } - } - - private void showToast() { - if (mAlbumCountToMakeAvailableOffline > 0) { - Activity activity = mActivity; - Toast.makeText(activity, activity.getResources().getQuantityString( - R.plurals.make_albums_available_offline, - mAlbumCountToMakeAvailableOffline), - Toast.LENGTH_SHORT).show(); - } - } - - private void showToastForLocalAlbum() { - Activity activity = mActivity; - Toast.makeText(activity, activity.getResources().getString( - R.string.try_to_set_local_album_available_offline), - Toast.LENGTH_SHORT).show(); - } - - private void refreshCacheStorageInfo() { - ProgressBar progressBar = (ProgressBar) mFooterContent.findViewById(R.id.progress); - TextView status = (TextView) mFooterContent.findViewById(R.id.status); - progressBar.setMax(PROGRESS_BAR_MAX); - long totalBytes = mCacheStorageInfo.getTotalBytes(); - long usedBytes = mCacheStorageInfo.getUsedBytes(); - long expectedBytes = mCacheStorageInfo.getExpectedUsedBytes(); - long freeBytes = mCacheStorageInfo.getFreeBytes(); - - Activity activity = mActivity; - if (totalBytes == 0) { - progressBar.setProgress(0); - progressBar.setSecondaryProgress(0); - - // TODO: get the string translated - String label = activity.getString(R.string.free_space_format, "-"); - status.setText(label); - } else { - progressBar.setProgress((int) (usedBytes * PROGRESS_BAR_MAX / totalBytes)); - progressBar.setSecondaryProgress( - (int) (expectedBytes * PROGRESS_BAR_MAX / totalBytes)); - String label = activity.getString(R.string.free_space_format, - Formatter.formatFileSize(activity, freeBytes)); - status.setText(label); - } - } - - @Override - public void onProgressComplete(int result) { - onBackPressed(); - } - - @Override - public void onProgressUpdate(int index) { - } - - @Override - public void onSelectionModeChange(int mode) { - } - - @Override - public void onSelectionChange(Path path, boolean selected) { - } - - @Override - public void onConfirmDialogDismissed(boolean confirmed) { - } - - @Override - public void onConfirmDialogShown() { - } - - @Override - public void onProgressStart() { - } -} diff --git a/src/com/android/gallery3d/app/MovieActivity.java b/src/com/android/gallery3d/app/MovieActivity.java deleted file mode 100644 index 40edbbe4d..000000000 --- a/src/com/android/gallery3d/app/MovieActivity.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.ActionBar; -import android.app.Activity; -import android.content.AsyncQueryHandler; -import android.content.ContentResolver; -import android.content.Intent; -import android.content.pm.ActivityInfo; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.drawable.BitmapDrawable; -import android.media.AudioManager; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.provider.MediaStore; -import android.provider.OpenableColumns; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.view.WindowManager; -import android.widget.ShareActionProvider; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; - -/** - * This activity plays a video from a specified URI. - * - * The client of this activity can pass a logo bitmap in the intent (KEY_LOGO_BITMAP) - * to set the action bar logo so the playback process looks more seamlessly integrated with - * the original activity. - */ -public class MovieActivity extends Activity { - @SuppressWarnings("unused") - private static final String TAG = "MovieActivity"; - public static final String KEY_LOGO_BITMAP = "logo-bitmap"; - public static final String KEY_TREAT_UP_AS_BACK = "treat-up-as-back"; - - private MoviePlayer mPlayer; - private boolean mFinishOnCompletion; - private Uri mUri; - private boolean mTreatUpAsBack; - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void setSystemUiVisibility(View rootView) { - if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) { - rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE - | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); - } - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - - setContentView(R.layout.movie_view); - View rootView = findViewById(R.id.movie_view_root); - - setSystemUiVisibility(rootView); - - Intent intent = getIntent(); - initializeActionBar(intent); - mFinishOnCompletion = intent.getBooleanExtra( - MediaStore.EXTRA_FINISH_ON_COMPLETION, true); - mTreatUpAsBack = intent.getBooleanExtra(KEY_TREAT_UP_AS_BACK, false); - mPlayer = new MoviePlayer(rootView, this, intent.getData(), savedInstanceState, - !mFinishOnCompletion) { - @Override - public void onCompletion() { - if (mFinishOnCompletion) { - finish(); - } - } - }; - if (intent.hasExtra(MediaStore.EXTRA_SCREEN_ORIENTATION)) { - int orientation = intent.getIntExtra( - MediaStore.EXTRA_SCREEN_ORIENTATION, - ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); - if (orientation != getRequestedOrientation()) { - setRequestedOrientation(orientation); - } - } - Window win = getWindow(); - WindowManager.LayoutParams winParams = win.getAttributes(); - winParams.buttonBrightness = WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_OFF; - winParams.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; - win.setAttributes(winParams); - - // We set the background in the theme to have the launching animation. - // But for the performance (and battery), we remove the background here. - win.setBackgroundDrawable(null); - } - - private void setActionBarLogoFromIntent(Intent intent) { - Bitmap logo = intent.getParcelableExtra(KEY_LOGO_BITMAP); - if (logo != null) { - getActionBar().setLogo( - new BitmapDrawable(getResources(), logo)); - } - } - - private void initializeActionBar(Intent intent) { - mUri = intent.getData(); - final ActionBar actionBar = getActionBar(); - if (actionBar == null) { - return; - } - setActionBarLogoFromIntent(intent); - actionBar.setDisplayOptions( - ActionBar.DISPLAY_HOME_AS_UP, - ActionBar.DISPLAY_HOME_AS_UP); - - String title = intent.getStringExtra(Intent.EXTRA_TITLE); - if (title != null) { - actionBar.setTitle(title); - } else { - // Displays the filename as title, reading the filename from the - // interface: {@link android.provider.OpenableColumns#DISPLAY_NAME}. - AsyncQueryHandler queryHandler = - new AsyncQueryHandler(getContentResolver()) { - @Override - protected void onQueryComplete(int token, Object cookie, - Cursor cursor) { - try { - if ((cursor != null) && cursor.moveToFirst()) { - String displayName = cursor.getString(0); - - // Just show empty title if other apps don't set - // DISPLAY_NAME - actionBar.setTitle((displayName == null) ? "" : - displayName); - } - } finally { - Utils.closeSilently(cursor); - } - } - }; - queryHandler.startQuery(0, null, mUri, - new String[] {OpenableColumns.DISPLAY_NAME}, null, null, - null); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - super.onCreateOptionsMenu(menu); - getMenuInflater().inflate(R.menu.movie, menu); - - // Document says EXTRA_STREAM should be a content: Uri - // So, we only share the video if it's "content:". - MenuItem shareItem = menu.findItem(R.id.action_share); - if (ContentResolver.SCHEME_CONTENT.equals(mUri.getScheme())) { - shareItem.setVisible(true); - ((ShareActionProvider) shareItem.getActionProvider()) - .setShareIntent(createShareIntent()); - } else { - shareItem.setVisible(false); - } - return true; - } - - private Intent createShareIntent() { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.setType("video/*"); - intent.putExtra(Intent.EXTRA_STREAM, mUri); - return intent; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - int id = item.getItemId(); - if (id == android.R.id.home) { - if (mTreatUpAsBack) { - finish(); - } else { - startActivity(new Intent(this, Gallery.class)); - finish(); - } - return true; - } else if (id == R.id.action_share) { - startActivity(Intent.createChooser(createShareIntent(), - getString(R.string.share))); - return true; - } - return false; - } - - @Override - public void onStart() { - ((AudioManager) getSystemService(AUDIO_SERVICE)) - .requestAudioFocus(null, AudioManager.STREAM_MUSIC, - AudioManager.AUDIOFOCUS_GAIN_TRANSIENT); - super.onStart(); - } - - @Override - protected void onStop() { - ((AudioManager) getSystemService(AUDIO_SERVICE)) - .abandonAudioFocus(null); - super.onStop(); - } - - @Override - public void onPause() { - mPlayer.onPause(); - super.onPause(); - } - - @Override - public void onResume() { - mPlayer.onResume(); - super.onResume(); - } - - @Override - public void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - mPlayer.onSaveInstanceState(outState); - } - - @Override - public void onDestroy() { - mPlayer.onDestroy(); - super.onDestroy(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - return mPlayer.onKeyDown(keyCode, event) - || super.onKeyDown(keyCode, event); - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - return mPlayer.onKeyUp(keyCode, event) - || super.onKeyUp(keyCode, event); - } -} diff --git a/src/com/android/gallery3d/app/MovieControllerOverlay.java b/src/com/android/gallery3d/app/MovieControllerOverlay.java deleted file mode 100644 index f01e619c6..000000000 --- a/src/com/android/gallery3d/app/MovieControllerOverlay.java +++ /dev/null @@ -1,185 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.os.Handler; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.animation.Animation; -import android.view.animation.Animation.AnimationListener; -import android.view.animation.AnimationUtils; -import com.android.gallery3d.R; - -/** - * The playback controller for the Movie Player. - */ -public class MovieControllerOverlay extends CommonControllerOverlay implements - AnimationListener { - - private boolean hidden; - - private final Handler handler; - private final Runnable startHidingRunnable; - private final Animation hideAnimation; - - public MovieControllerOverlay(Context context) { - super(context); - - handler = new Handler(); - startHidingRunnable = new Runnable() { - @Override - public void run() { - startHiding(); - } - }; - - hideAnimation = AnimationUtils.loadAnimation(context, R.anim.player_out); - hideAnimation.setAnimationListener(this); - - hide(); - } - - @Override - protected void createTimeBar(Context context) { - mTimeBar = new TimeBar(context, this); - } - - @Override - public void hide() { - boolean wasHidden = hidden; - hidden = true; - super.hide(); - if (mListener != null && wasHidden != hidden) { - mListener.onHidden(); - } - } - - - @Override - public void show() { - boolean wasHidden = hidden; - hidden = false; - super.show(); - if (mListener != null && wasHidden != hidden) { - mListener.onShown(); - } - maybeStartHiding(); - } - - private void maybeStartHiding() { - cancelHiding(); - if (mState == State.PLAYING) { - handler.postDelayed(startHidingRunnable, 2500); - } - } - - private void startHiding() { - startHideAnimation(mBackground); - startHideAnimation(mTimeBar); - startHideAnimation(mPlayPauseReplayView); - } - - private void startHideAnimation(View view) { - if (view.getVisibility() == View.VISIBLE) { - view.startAnimation(hideAnimation); - } - } - - private void cancelHiding() { - handler.removeCallbacks(startHidingRunnable); - mBackground.setAnimation(null); - mTimeBar.setAnimation(null); - mPlayPauseReplayView.setAnimation(null); - } - - @Override - public void onAnimationStart(Animation animation) { - // Do nothing. - } - - @Override - public void onAnimationRepeat(Animation animation) { - // Do nothing. - } - - @Override - public void onAnimationEnd(Animation animation) { - hide(); - } - - @Override - public boolean onKeyDown(int keyCode, KeyEvent event) { - if (hidden) { - show(); - } - return super.onKeyDown(keyCode, event); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (super.onTouchEvent(event)) { - return true; - } - - if (hidden) { - show(); - return true; - } - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - cancelHiding(); - if (mState == State.PLAYING || mState == State.PAUSED) { - mListener.onPlayPause(); - } - break; - case MotionEvent.ACTION_UP: - maybeStartHiding(); - break; - } - return true; - } - - @Override - protected void updateViews() { - if (hidden) { - return; - } - super.updateViews(); - } - - // TimeBar listener - - @Override - public void onScrubbingStart() { - cancelHiding(); - super.onScrubbingStart(); - } - - @Override - public void onScrubbingMove(int time) { - cancelHiding(); - super.onScrubbingMove(time); - } - - @Override - public void onScrubbingEnd(int time, int trimStartTime, int trimEndTime) { - maybeStartHiding(); - super.onScrubbingEnd(time, trimStartTime, trimEndTime); - } -} diff --git a/src/com/android/gallery3d/app/MoviePlayer.java b/src/com/android/gallery3d/app/MoviePlayer.java deleted file mode 100644 index ce9183483..000000000 --- a/src/com/android/gallery3d/app/MoviePlayer.java +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.AlertDialog; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.content.IntentFilter; -import android.media.AudioManager; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.view.KeyEvent; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.VideoView; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.BlobCache; -import com.android.gallery3d.util.CacheManager; -import com.android.gallery3d.util.GalleryUtils; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; - -public class MoviePlayer implements - MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener, - ControllerOverlay.Listener { - @SuppressWarnings("unused") - private static final String TAG = "MoviePlayer"; - - private static final String KEY_VIDEO_POSITION = "video-position"; - private static final String KEY_RESUMEABLE_TIME = "resumeable-timeout"; - - // These are constants in KeyEvent, appearing on API level 11. - private static final int KEYCODE_MEDIA_PLAY = 126; - private static final int KEYCODE_MEDIA_PAUSE = 127; - - // Copied from MediaPlaybackService in the Music Player app. - private static final String SERVICECMD = "com.android.music.musicservicecommand"; - private static final String CMDNAME = "command"; - private static final String CMDPAUSE = "pause"; - - private static final long BLACK_TIMEOUT = 500; - - // If we resume the acitivty with in RESUMEABLE_TIMEOUT, we will keep playing. - // Otherwise, we pause the player. - private static final long RESUMEABLE_TIMEOUT = 3 * 60 * 1000; // 3 mins - - private Context mContext; - private final VideoView mVideoView; - private final View mRootView; - private final Bookmarker mBookmarker; - private final Uri mUri; - private final Handler mHandler = new Handler(); - private final AudioBecomingNoisyReceiver mAudioBecomingNoisyReceiver; - private final MovieControllerOverlay mController; - - private long mResumeableTime = Long.MAX_VALUE; - private int mVideoPosition = 0; - private boolean mHasPaused = false; - private int mLastSystemUiVis = 0; - - // If the time bar is being dragged. - private boolean mDragging; - - // If the time bar is visible. - private boolean mShowing; - - private final Runnable mPlayingChecker = new Runnable() { - @Override - public void run() { - if (mVideoView.isPlaying()) { - mController.showPlaying(); - } else { - mHandler.postDelayed(mPlayingChecker, 250); - } - } - }; - - private final Runnable mProgressChecker = new Runnable() { - @Override - public void run() { - int pos = setProgress(); - mHandler.postDelayed(mProgressChecker, 1000 - (pos % 1000)); - } - }; - - public MoviePlayer(View rootView, final MovieActivity movieActivity, - Uri videoUri, Bundle savedInstance, boolean canReplay) { - mContext = movieActivity.getApplicationContext(); - mRootView = rootView; - mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); - mBookmarker = new Bookmarker(movieActivity); - mUri = videoUri; - - mController = new MovieControllerOverlay(mContext); - ((ViewGroup)rootView).addView(mController.getView()); - mController.setListener(this); - mController.setCanReplay(canReplay); - - mVideoView.setOnErrorListener(this); - mVideoView.setOnCompletionListener(this); - mVideoView.setVideoURI(mUri); - mVideoView.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - mController.show(); - return true; - } - }); - mVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { - @Override - public void onPrepared(MediaPlayer player) { - if (!mVideoView.canSeekForward() || !mVideoView.canSeekBackward()) { - mController.setSeekable(false); - } else { - mController.setSeekable(true); - } - setProgress(); - } - }); - - // The SurfaceView is transparent before drawing the first frame. - // This makes the UI flashing when open a video. (black -> old screen - // -> video) However, we have no way to know the timing of the first - // frame. So, we hide the VideoView for a while to make sure the - // video has been drawn on it. - mVideoView.postDelayed(new Runnable() { - @Override - public void run() { - mVideoView.setVisibility(View.VISIBLE); - } - }, BLACK_TIMEOUT); - - setOnSystemUiVisibilityChangeListener(); - // Hide system UI by default - showSystemUi(false); - - mAudioBecomingNoisyReceiver = new AudioBecomingNoisyReceiver(); - mAudioBecomingNoisyReceiver.register(); - - Intent i = new Intent(SERVICECMD); - i.putExtra(CMDNAME, CMDPAUSE); - movieActivity.sendBroadcast(i); - - if (savedInstance != null) { // this is a resumed activity - mVideoPosition = savedInstance.getInt(KEY_VIDEO_POSITION, 0); - mResumeableTime = savedInstance.getLong(KEY_RESUMEABLE_TIME, Long.MAX_VALUE); - mVideoView.start(); - mVideoView.suspend(); - mHasPaused = true; - } else { - final Integer bookmark = mBookmarker.getBookmark(mUri); - if (bookmark != null) { - showResumeDialog(movieActivity, bookmark); - } else { - startVideo(); - } - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void setOnSystemUiVisibilityChangeListener() { - if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_HIDE_NAVIGATION) return; - - // When the user touches the screen or uses some hard key, the framework - // will change system ui visibility from invisible to visible. We show - // the media control and enable system UI (e.g. ActionBar) to be visible at this point - mVideoView.setOnSystemUiVisibilityChangeListener( - new View.OnSystemUiVisibilityChangeListener() { - @Override - public void onSystemUiVisibilityChange(int visibility) { - int diff = mLastSystemUiVis ^ visibility; - mLastSystemUiVis = visibility; - if ((diff & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0 - && (visibility & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { - mController.show(); - } - } - }); - } - - @SuppressWarnings("deprecation") - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void showSystemUi(boolean visible) { - if (!ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) return; - - int flag = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN - | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION - | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; - if (!visible) { - // We used the deprecated "STATUS_BAR_HIDDEN" for unbundling - flag |= View.STATUS_BAR_HIDDEN | View.SYSTEM_UI_FLAG_FULLSCREEN - | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION; - } - mVideoView.setSystemUiVisibility(flag); - } - - public void onSaveInstanceState(Bundle outState) { - outState.putInt(KEY_VIDEO_POSITION, mVideoPosition); - outState.putLong(KEY_RESUMEABLE_TIME, mResumeableTime); - } - - private void showResumeDialog(Context context, final int bookmark) { - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle(R.string.resume_playing_title); - builder.setMessage(String.format( - context.getString(R.string.resume_playing_message), - GalleryUtils.formatDuration(context, bookmark / 1000))); - builder.setOnCancelListener(new OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - onCompletion(); - } - }); - builder.setPositiveButton( - R.string.resume_playing_resume, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - mVideoView.seekTo(bookmark); - startVideo(); - } - }); - builder.setNegativeButton( - R.string.resume_playing_restart, new OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - startVideo(); - } - }); - builder.show(); - } - - public void onPause() { - mHasPaused = true; - mHandler.removeCallbacksAndMessages(null); - mVideoPosition = mVideoView.getCurrentPosition(); - mBookmarker.setBookmark(mUri, mVideoPosition, mVideoView.getDuration()); - mVideoView.suspend(); - mResumeableTime = System.currentTimeMillis() + RESUMEABLE_TIMEOUT; - } - - public void onResume() { - if (mHasPaused) { - mVideoView.seekTo(mVideoPosition); - mVideoView.resume(); - - // If we have slept for too long, pause the play - if (System.currentTimeMillis() > mResumeableTime) { - pauseVideo(); - } - } - mHandler.post(mProgressChecker); - } - - public void onDestroy() { - mVideoView.stopPlayback(); - mAudioBecomingNoisyReceiver.unregister(); - } - - // This updates the time bar display (if necessary). It is called every - // second by mProgressChecker and also from places where the time bar needs - // to be updated immediately. - private int setProgress() { - if (mDragging || !mShowing) { - return 0; - } - int position = mVideoView.getCurrentPosition(); - int duration = mVideoView.getDuration(); - mController.setTimes(position, duration, 0, 0); - return position; - } - - private void startVideo() { - // For streams that we expect to be slow to start up, show a - // progress spinner until playback starts. - String scheme = mUri.getScheme(); - if ("http".equalsIgnoreCase(scheme) || "rtsp".equalsIgnoreCase(scheme)) { - mController.showLoading(); - mHandler.removeCallbacks(mPlayingChecker); - mHandler.postDelayed(mPlayingChecker, 250); - } else { - mController.showPlaying(); - mController.hide(); - } - - mVideoView.start(); - setProgress(); - } - - private void playVideo() { - mVideoView.start(); - mController.showPlaying(); - setProgress(); - } - - private void pauseVideo() { - mVideoView.pause(); - mController.showPaused(); - } - - // Below are notifications from VideoView - @Override - public boolean onError(MediaPlayer player, int arg1, int arg2) { - mHandler.removeCallbacksAndMessages(null); - // VideoView will show an error dialog if we return false, so no need - // to show more message. - mController.showErrorMessage(""); - return false; - } - - @Override - public void onCompletion(MediaPlayer mp) { - mController.showEnded(); - onCompletion(); - } - - public void onCompletion() { - } - - // Below are notifications from ControllerOverlay - @Override - public void onPlayPause() { - if (mVideoView.isPlaying()) { - pauseVideo(); - } else { - playVideo(); - } - } - - @Override - public void onSeekStart() { - mDragging = true; - } - - @Override - public void onSeekMove(int time) { - mVideoView.seekTo(time); - } - - @Override - public void onSeekEnd(int time, int start, int end) { - mDragging = false; - mVideoView.seekTo(time); - setProgress(); - } - - @Override - public void onShown() { - mShowing = true; - setProgress(); - showSystemUi(true); - } - - @Override - public void onHidden() { - mShowing = false; - showSystemUi(false); - } - - @Override - public void onReplay() { - startVideo(); - } - - // Below are key events passed from MovieActivity. - public boolean onKeyDown(int keyCode, KeyEvent event) { - - // Some headsets will fire off 7-10 events on a single click - if (event.getRepeatCount() > 0) { - return isMediaKey(keyCode); - } - - switch (keyCode) { - case KeyEvent.KEYCODE_HEADSETHOOK: - case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE: - if (mVideoView.isPlaying()) { - pauseVideo(); - } else { - playVideo(); - } - return true; - case KEYCODE_MEDIA_PAUSE: - if (mVideoView.isPlaying()) { - pauseVideo(); - } - return true; - case KEYCODE_MEDIA_PLAY: - if (!mVideoView.isPlaying()) { - playVideo(); - } - return true; - case KeyEvent.KEYCODE_MEDIA_PREVIOUS: - case KeyEvent.KEYCODE_MEDIA_NEXT: - // TODO: Handle next / previous accordingly, for now we're - // just consuming the events. - return true; - } - return false; - } - - public boolean onKeyUp(int keyCode, KeyEvent event) { - return isMediaKey(keyCode); - } - - private static boolean isMediaKey(int keyCode) { - return keyCode == KeyEvent.KEYCODE_HEADSETHOOK - || keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS - || keyCode == KeyEvent.KEYCODE_MEDIA_NEXT - || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE - || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY - || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE; - } - - // We want to pause when the headset is unplugged. - private class AudioBecomingNoisyReceiver extends BroadcastReceiver { - - public void register() { - mContext.registerReceiver(this, - new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); - } - - public void unregister() { - mContext.unregisterReceiver(this); - } - - @Override - public void onReceive(Context context, Intent intent) { - if (mVideoView.isPlaying()) pauseVideo(); - } - } -} - -class Bookmarker { - private static final String TAG = "Bookmarker"; - - private static final String BOOKMARK_CACHE_FILE = "bookmark"; - private static final int BOOKMARK_CACHE_MAX_ENTRIES = 100; - private static final int BOOKMARK_CACHE_MAX_BYTES = 10 * 1024; - private static final int BOOKMARK_CACHE_VERSION = 1; - - private static final int HALF_MINUTE = 30 * 1000; - private static final int TWO_MINUTES = 4 * HALF_MINUTE; - - private final Context mContext; - - public Bookmarker(Context context) { - mContext = context; - } - - public void setBookmark(Uri uri, int bookmark, int duration) { - try { - BlobCache cache = CacheManager.getCache(mContext, - BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES, - BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION); - - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(bos); - dos.writeUTF(uri.toString()); - dos.writeInt(bookmark); - dos.writeInt(duration); - dos.flush(); - cache.insert(uri.hashCode(), bos.toByteArray()); - } catch (Throwable t) { - Log.w(TAG, "setBookmark failed", t); - } - } - - public Integer getBookmark(Uri uri) { - try { - BlobCache cache = CacheManager.getCache(mContext, - BOOKMARK_CACHE_FILE, BOOKMARK_CACHE_MAX_ENTRIES, - BOOKMARK_CACHE_MAX_BYTES, BOOKMARK_CACHE_VERSION); - - byte[] data = cache.lookup(uri.hashCode()); - if (data == null) return null; - - DataInputStream dis = new DataInputStream( - new ByteArrayInputStream(data)); - - String uriString = DataInputStream.readUTF(dis); - int bookmark = dis.readInt(); - int duration = dis.readInt(); - - if (!uriString.equals(uri.toString())) { - return null; - } - - if ((bookmark < HALF_MINUTE) || (duration < TWO_MINUTES) - || (bookmark > (duration - HALF_MINUTE))) { - return null; - } - return Integer.valueOf(bookmark); - } catch (Throwable t) { - Log.w(TAG, "getBookmark failed", t); - } - return null; - } -} diff --git a/src/com/android/gallery3d/app/MuteVideo.java b/src/com/android/gallery3d/app/MuteVideo.java deleted file mode 100644 index d3f3aa594..000000000 --- a/src/com/android/gallery3d/app/MuteVideo.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Intent; -import android.net.Uri; -import android.os.Handler; -import android.provider.MediaStore; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.util.SaveVideoFileInfo; -import com.android.gallery3d.util.SaveVideoFileUtils; - -import java.io.IOException; - -public class MuteVideo { - - private ProgressDialog mMuteProgress; - - private String mFilePath = null; - private Uri mUri = null; - private SaveVideoFileInfo mDstFileInfo = null; - private Activity mActivity = null; - private final Handler mHandler = new Handler(); - - final String TIME_STAMP_NAME = "'MUTE'_yyyyMMdd_HHmmss"; - - public MuteVideo(String filePath, Uri uri, Activity activity) { - mUri = uri; - mFilePath = filePath; - mActivity = activity; - } - - public void muteInBackground() { - mDstFileInfo = SaveVideoFileUtils.getDstMp4FileInfo(TIME_STAMP_NAME, - mActivity.getContentResolver(), mUri, - mActivity.getString(R.string.folder_download)); - - showProgressDialog(); - new Thread(new Runnable() { - @Override - public void run() { - try { - VideoUtils.startMute(mFilePath, mDstFileInfo); - SaveVideoFileUtils.insertContent( - mDstFileInfo, mActivity.getContentResolver(), mUri); - } catch (IOException e) { - Toast.makeText(mActivity, mActivity.getString(R.string.video_mute_err), - Toast.LENGTH_SHORT).show(); - } - // After muting is done, trigger the UI changed. - mHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(mActivity.getApplicationContext(), - mActivity.getString(R.string.save_into, - mDstFileInfo.mFolderName), - Toast.LENGTH_SHORT) - .show(); - - if (mMuteProgress != null) { - mMuteProgress.dismiss(); - mMuteProgress = null; - - // Show the result only when the activity not - // stopped. - Intent intent = new Intent(android.content.Intent.ACTION_VIEW); - intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*"); - intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false); - mActivity.startActivity(intent); - } - } - }); - } - }).start(); - } - - private void showProgressDialog() { - mMuteProgress = new ProgressDialog(mActivity); - mMuteProgress.setTitle(mActivity.getString(R.string.muting)); - mMuteProgress.setMessage(mActivity.getString(R.string.please_wait)); - mMuteProgress.setCancelable(false); - mMuteProgress.setCanceledOnTouchOutside(false); - mMuteProgress.show(); - } -} diff --git a/src/com/android/gallery3d/app/NotificationIds.java b/src/com/android/gallery3d/app/NotificationIds.java deleted file mode 100644 index d697d854b..000000000 --- a/src/com/android/gallery3d/app/NotificationIds.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -public class NotificationIds { - public static final int INGEST_NOTIFICATION_SCANNING = 10; - public static final int INGEST_NOTIFICATION_IMPORTING = 11; -} diff --git a/src/com/android/gallery3d/app/PackagesMonitor.java b/src/com/android/gallery3d/app/PackagesMonitor.java deleted file mode 100644 index 9b2412f1b..000000000 --- a/src/com/android/gallery3d/app/PackagesMonitor.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.IntentService; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.util.LightCycleHelper; - -public class PackagesMonitor extends BroadcastReceiver { - public static final String KEY_PACKAGES_VERSION = "packages-version"; - - public synchronized static int getPackagesVersion(Context context) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - return prefs.getInt(KEY_PACKAGES_VERSION, 1); - } - - @Override - public void onReceive(final Context context, final Intent intent) { - intent.setClass(context, AsyncService.class); - context.startService(intent); - } - - public static class AsyncService extends IntentService { - public AsyncService() { - super("GalleryPackagesMonitorAsync"); - } - - @Override - protected void onHandleIntent(Intent intent) { - onReceiveAsync(this, intent); - } - } - - // Runs in a background thread. - private static void onReceiveAsync(Context context, Intent intent) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - - int version = prefs.getInt(KEY_PACKAGES_VERSION, 1); - prefs.edit().putInt(KEY_PACKAGES_VERSION, version + 1).commit(); - - String action = intent.getAction(); - String packageName = intent.getData().getSchemeSpecificPart(); - if (Intent.ACTION_PACKAGE_ADDED.equals(action)) { - PicasaSource.onPackageAdded(context, packageName); - } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) { - PicasaSource.onPackageRemoved(context, packageName); - } else if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) { - PicasaSource.onPackageChanged(context, packageName); - } - } -} diff --git a/src/com/android/gallery3d/app/PanoramaMetadataSupport.java b/src/com/android/gallery3d/app/PanoramaMetadataSupport.java deleted file mode 100644 index ba0c9e71a..000000000 --- a/src/com/android/gallery3d/app/PanoramaMetadataSupport.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.app; - -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.PanoramaMetadataJob; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; - -import java.util.ArrayList; - -/** - * This class breaks out the off-thread panorama support checks so that the - * complexity can be shared between UriImage and LocalImage, which need to - * support panoramas. - */ -public class PanoramaMetadataSupport implements FutureListener<PanoramaMetadata> { - private Object mLock = new Object(); - private Future<PanoramaMetadata> mGetPanoMetadataTask; - private PanoramaMetadata mPanoramaMetadata; - private ArrayList<PanoramaSupportCallback> mCallbacksWaiting; - private MediaObject mMediaObject; - - public PanoramaMetadataSupport(MediaObject mediaObject) { - mMediaObject = mediaObject; - } - - public void getPanoramaSupport(GalleryApp app, PanoramaSupportCallback callback) { - synchronized (mLock) { - if (mPanoramaMetadata != null) { - callback.panoramaInfoAvailable(mMediaObject, mPanoramaMetadata.mUsePanoramaViewer, - mPanoramaMetadata.mIsPanorama360); - } else { - if (mCallbacksWaiting == null) { - mCallbacksWaiting = new ArrayList<PanoramaSupportCallback>(); - mGetPanoMetadataTask = app.getThreadPool().submit( - new PanoramaMetadataJob(app.getAndroidContext(), - mMediaObject.getContentUri()), this); - - } - mCallbacksWaiting.add(callback); - } - } - } - - public void clearCachedValues() { - synchronized (mLock) { - if (mPanoramaMetadata != null) { - mPanoramaMetadata = null; - } else if (mGetPanoMetadataTask != null) { - mGetPanoMetadataTask.cancel(); - for (PanoramaSupportCallback cb : mCallbacksWaiting) { - cb.panoramaInfoAvailable(mMediaObject, false, false); - } - mGetPanoMetadataTask = null; - mCallbacksWaiting = null; - } - } - } - - @Override - public void onFutureDone(Future<PanoramaMetadata> future) { - synchronized (mLock) { - mPanoramaMetadata = future.get(); - if (mPanoramaMetadata == null) { - // Error getting panorama data from file. Treat as not panorama. - mPanoramaMetadata = LightCycleHelper.NOT_PANORAMA; - } - for (PanoramaSupportCallback cb : mCallbacksWaiting) { - cb.panoramaInfoAvailable(mMediaObject, mPanoramaMetadata.mUsePanoramaViewer, - mPanoramaMetadata.mIsPanorama360); - } - mGetPanoMetadataTask = null; - mCallbacksWaiting = null; - } - } -} diff --git a/src/com/android/gallery3d/app/PhotoDataAdapter.java b/src/com/android/gallery3d/app/PhotoDataAdapter.java deleted file mode 100644 index fd3a7cf73..000000000 --- a/src/com/android/gallery3d/app/PhotoDataAdapter.java +++ /dev/null @@ -1,1133 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; -import android.os.Handler; -import android.os.Message; - -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.LocalMediaItem; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.TiledTexture; -import com.android.gallery3d.ui.PhotoView; -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.ui.TileImageViewAdapter; -import com.android.gallery3d.ui.TiledScreenNail; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.MediaSetUtils; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.FutureTask; - -public class PhotoDataAdapter implements PhotoPage.Model { - @SuppressWarnings("unused") - private static final String TAG = "PhotoDataAdapter"; - - private static final int MSG_LOAD_START = 1; - private static final int MSG_LOAD_FINISH = 2; - private static final int MSG_RUN_OBJECT = 3; - private static final int MSG_UPDATE_IMAGE_REQUESTS = 4; - - private static final int MIN_LOAD_COUNT = 16; - private static final int DATA_CACHE_SIZE = 256; - private static final int SCREEN_NAIL_MAX = PhotoView.SCREEN_NAIL_MAX; - private static final int IMAGE_CACHE_SIZE = 2 * SCREEN_NAIL_MAX + 1; - - private static final int BIT_SCREEN_NAIL = 1; - private static final int BIT_FULL_IMAGE = 2; - - // sImageFetchSeq is the fetching sequence for images. - // We want to fetch the current screennail first (offset = 0), the next - // screennail (offset = +1), then the previous screennail (offset = -1) etc. - // After all the screennail are fetched, we fetch the full images (only some - // of them because of we don't want to use too much memory). - private static ImageFetch[] sImageFetchSeq; - - private static class ImageFetch { - int indexOffset; - int imageBit; - public ImageFetch(int offset, int bit) { - indexOffset = offset; - imageBit = bit; - } - } - - static { - int k = 0; - sImageFetchSeq = new ImageFetch[1 + (IMAGE_CACHE_SIZE - 1) * 2 + 3]; - sImageFetchSeq[k++] = new ImageFetch(0, BIT_SCREEN_NAIL); - - for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) { - sImageFetchSeq[k++] = new ImageFetch(i, BIT_SCREEN_NAIL); - sImageFetchSeq[k++] = new ImageFetch(-i, BIT_SCREEN_NAIL); - } - - sImageFetchSeq[k++] = new ImageFetch(0, BIT_FULL_IMAGE); - sImageFetchSeq[k++] = new ImageFetch(1, BIT_FULL_IMAGE); - sImageFetchSeq[k++] = new ImageFetch(-1, BIT_FULL_IMAGE); - } - - private final TileImageViewAdapter mTileProvider = new TileImageViewAdapter(); - - // PhotoDataAdapter caches MediaItems (data) and ImageEntries (image). - // - // The MediaItems are stored in the mData array, which has DATA_CACHE_SIZE - // entries. The valid index range are [mContentStart, mContentEnd). We keep - // mContentEnd - mContentStart <= DATA_CACHE_SIZE, so we can use - // (i % DATA_CACHE_SIZE) as index to the array. - // - // The valid MediaItem window size (mContentEnd - mContentStart) may be - // smaller than DATA_CACHE_SIZE because we only update the window and reload - // the MediaItems when there are significant changes to the window position - // (>= MIN_LOAD_COUNT). - private final MediaItem mData[] = new MediaItem[DATA_CACHE_SIZE]; - private int mContentStart = 0; - private int mContentEnd = 0; - - // The ImageCache is a Path-to-ImageEntry map. It only holds the - // ImageEntries in the range of [mActiveStart, mActiveEnd). We also keep - // mActiveEnd - mActiveStart <= IMAGE_CACHE_SIZE. Besides, the - // [mActiveStart, mActiveEnd) range must be contained within - // the [mContentStart, mContentEnd) range. - private HashMap<Path, ImageEntry> mImageCache = - new HashMap<Path, ImageEntry>(); - private int mActiveStart = 0; - private int mActiveEnd = 0; - - // mCurrentIndex is the "center" image the user is viewing. The change of - // mCurrentIndex triggers the data loading and image loading. - private int mCurrentIndex; - - // mChanges keeps the version number (of MediaItem) about the images. If any - // of the version number changes, we notify the view. This is used after a - // database reload or mCurrentIndex changes. - private final long mChanges[] = new long[IMAGE_CACHE_SIZE]; - // mPaths keeps the corresponding Path (of MediaItem) for the images. This - // is used to determine the item movement. - private final Path mPaths[] = new Path[IMAGE_CACHE_SIZE]; - - private final Handler mMainHandler; - private final ThreadPool mThreadPool; - - private final PhotoView mPhotoView; - private final MediaSet mSource; - private ReloadTask mReloadTask; - - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - private int mSize = 0; - private Path mItemPath; - private int mCameraIndex; - private boolean mIsPanorama; - private boolean mIsStaticCamera; - private boolean mIsActive; - private boolean mNeedFullImage; - private int mFocusHintDirection = FOCUS_HINT_NEXT; - private Path mFocusHintPath = null; - - public interface DataListener extends LoadingListener { - public void onPhotoChanged(int index, Path item); - } - - private DataListener mDataListener; - - private final SourceListener mSourceListener = new SourceListener(); - private final TiledTexture.Uploader mUploader; - - // The path of the current viewing item will be stored in mItemPath. - // If mItemPath is not null, mCurrentIndex is only a hint for where we - // can find the item. If mItemPath is null, then we use the mCurrentIndex to - // find the image being viewed. cameraIndex is the index of the camera - // preview. If cameraIndex < 0, there is no camera preview. - public PhotoDataAdapter(AbstractGalleryActivity activity, PhotoView view, - MediaSet mediaSet, Path itemPath, int indexHint, int cameraIndex, - boolean isPanorama, boolean isStaticCamera) { - mSource = Utils.checkNotNull(mediaSet); - mPhotoView = Utils.checkNotNull(view); - mItemPath = Utils.checkNotNull(itemPath); - mCurrentIndex = indexHint; - mCameraIndex = cameraIndex; - mIsPanorama = isPanorama; - mIsStaticCamera = isStaticCamera; - mThreadPool = activity.getThreadPool(); - mNeedFullImage = true; - - Arrays.fill(mChanges, MediaObject.INVALID_DATA_VERSION); - - mUploader = new TiledTexture.Uploader(activity.getGLRoot()); - - mMainHandler = new SynchronizedHandler(activity.getGLRoot()) { - @SuppressWarnings("unchecked") - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_RUN_OBJECT: - ((Runnable) message.obj).run(); - return; - case MSG_LOAD_START: { - if (mDataListener != null) { - mDataListener.onLoadingStarted(); - } - return; - } - case MSG_LOAD_FINISH: { - if (mDataListener != null) { - mDataListener.onLoadingFinished(false); - } - return; - } - case MSG_UPDATE_IMAGE_REQUESTS: { - updateImageRequests(); - return; - } - default: throw new AssertionError(); - } - } - }; - - updateSlidingWindow(); - } - - private MediaItem getItemInternal(int index) { - if (index < 0 || index >= mSize) return null; - if (index >= mContentStart && index < mContentEnd) { - return mData[index % DATA_CACHE_SIZE]; - } - return null; - } - - private long getVersion(int index) { - MediaItem item = getItemInternal(index); - if (item == null) return MediaObject.INVALID_DATA_VERSION; - return item.getDataVersion(); - } - - private Path getPath(int index) { - MediaItem item = getItemInternal(index); - if (item == null) return null; - return item.getPath(); - } - - private void fireDataChange() { - // First check if data actually changed. - boolean changed = false; - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { - long newVersion = getVersion(mCurrentIndex + i); - if (mChanges[i + SCREEN_NAIL_MAX] != newVersion) { - mChanges[i + SCREEN_NAIL_MAX] = newVersion; - changed = true; - } - } - - if (!changed) return; - - // Now calculate the fromIndex array. fromIndex represents the item - // movement. It records the index where the picture come from. The - // special value Integer.MAX_VALUE means it's a new picture. - final int N = IMAGE_CACHE_SIZE; - int fromIndex[] = new int[N]; - - // Remember the old path array. - Path oldPaths[] = new Path[N]; - System.arraycopy(mPaths, 0, oldPaths, 0, N); - - // Update the mPaths array. - for (int i = 0; i < N; ++i) { - mPaths[i] = getPath(mCurrentIndex + i - SCREEN_NAIL_MAX); - } - - // Calculate the fromIndex array. - for (int i = 0; i < N; i++) { - Path p = mPaths[i]; - if (p == null) { - fromIndex[i] = Integer.MAX_VALUE; - continue; - } - - // Try to find the same path in the old array - int j; - for (j = 0; j < N; j++) { - if (oldPaths[j] == p) { - break; - } - } - fromIndex[i] = (j < N) ? j - SCREEN_NAIL_MAX : Integer.MAX_VALUE; - } - - mPhotoView.notifyDataChange(fromIndex, -mCurrentIndex, - mSize - 1 - mCurrentIndex); - } - - public void setDataListener(DataListener listener) { - mDataListener = listener; - } - - private void updateScreenNail(Path path, Future<ScreenNail> future) { - ImageEntry entry = mImageCache.get(path); - ScreenNail screenNail = future.get(); - - if (entry == null || entry.screenNailTask != future) { - if (screenNail != null) screenNail.recycle(); - return; - } - - entry.screenNailTask = null; - - // Combine the ScreenNails if we already have a BitmapScreenNail - if (entry.screenNail instanceof TiledScreenNail) { - TiledScreenNail original = (TiledScreenNail) entry.screenNail; - screenNail = original.combine(screenNail); - } - - if (screenNail == null) { - entry.failToLoad = true; - } else { - entry.failToLoad = false; - entry.screenNail = screenNail; - } - - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { - if (path == getPath(mCurrentIndex + i)) { - if (i == 0) updateTileProvider(entry); - mPhotoView.notifyImageChange(i); - break; - } - } - updateImageRequests(); - updateScreenNailUploadQueue(); - } - - private void updateFullImage(Path path, Future<BitmapRegionDecoder> future) { - ImageEntry entry = mImageCache.get(path); - if (entry == null || entry.fullImageTask != future) { - BitmapRegionDecoder fullImage = future.get(); - if (fullImage != null) fullImage.recycle(); - return; - } - - entry.fullImageTask = null; - entry.fullImage = future.get(); - if (entry.fullImage != null) { - if (path == getPath(mCurrentIndex)) { - updateTileProvider(entry); - mPhotoView.notifyImageChange(0); - } - } - updateImageRequests(); - } - - @Override - public void resume() { - mIsActive = true; - TiledTexture.prepareResources(); - - mSource.addContentListener(mSourceListener); - updateImageCache(); - updateImageRequests(); - - mReloadTask = new ReloadTask(); - mReloadTask.start(); - - fireDataChange(); - } - - @Override - public void pause() { - mIsActive = false; - - mReloadTask.terminate(); - mReloadTask = null; - - mSource.removeContentListener(mSourceListener); - - for (ImageEntry entry : mImageCache.values()) { - if (entry.fullImageTask != null) entry.fullImageTask.cancel(); - if (entry.screenNailTask != null) entry.screenNailTask.cancel(); - if (entry.screenNail != null) entry.screenNail.recycle(); - } - mImageCache.clear(); - mTileProvider.clear(); - - mUploader.clear(); - TiledTexture.freeResources(); - } - - private MediaItem getItem(int index) { - if (index < 0 || index >= mSize || !mIsActive) return null; - Utils.assertTrue(index >= mActiveStart && index < mActiveEnd); - - if (index >= mContentStart && index < mContentEnd) { - return mData[index % DATA_CACHE_SIZE]; - } - return null; - } - - private void updateCurrentIndex(int index) { - if (mCurrentIndex == index) return; - mCurrentIndex = index; - updateSlidingWindow(); - - MediaItem item = mData[index % DATA_CACHE_SIZE]; - mItemPath = item == null ? null : item.getPath(); - - updateImageCache(); - updateImageRequests(); - updateTileProvider(); - - if (mDataListener != null) { - mDataListener.onPhotoChanged(index, mItemPath); - } - - fireDataChange(); - } - - private void uploadScreenNail(int offset) { - int index = mCurrentIndex + offset; - if (index < mActiveStart || index >= mActiveEnd) return; - - MediaItem item = getItem(index); - if (item == null) return; - - ImageEntry e = mImageCache.get(item.getPath()); - if (e == null) return; - - ScreenNail s = e.screenNail; - if (s instanceof TiledScreenNail) { - TiledTexture t = ((TiledScreenNail) s).getTexture(); - if (t != null && !t.isReady()) mUploader.addTexture(t); - } - } - - private void updateScreenNailUploadQueue() { - mUploader.clear(); - uploadScreenNail(0); - for (int i = 1; i < IMAGE_CACHE_SIZE; ++i) { - uploadScreenNail(i); - uploadScreenNail(-i); - } - } - - @Override - public void moveTo(int index) { - updateCurrentIndex(index); - } - - @Override - public ScreenNail getScreenNail(int offset) { - int index = mCurrentIndex + offset; - if (index < 0 || index >= mSize || !mIsActive) return null; - Utils.assertTrue(index >= mActiveStart && index < mActiveEnd); - - MediaItem item = getItem(index); - if (item == null) return null; - - ImageEntry entry = mImageCache.get(item.getPath()); - if (entry == null) return null; - - // Create a default ScreenNail if the real one is not available yet, - // except for camera that a black screen is better than a gray tile. - if (entry.screenNail == null && !isCamera(offset)) { - entry.screenNail = newPlaceholderScreenNail(item); - if (offset == 0) updateTileProvider(entry); - } - - return entry.screenNail; - } - - @Override - public void getImageSize(int offset, PhotoView.Size size) { - MediaItem item = getItem(mCurrentIndex + offset); - if (item == null) { - size.width = 0; - size.height = 0; - } else { - size.width = item.getWidth(); - size.height = item.getHeight(); - } - } - - @Override - public int getImageRotation(int offset) { - MediaItem item = getItem(mCurrentIndex + offset); - return (item == null) ? 0 : item.getFullImageRotation(); - } - - @Override - public void setNeedFullImage(boolean enabled) { - mNeedFullImage = enabled; - mMainHandler.sendEmptyMessage(MSG_UPDATE_IMAGE_REQUESTS); - } - - @Override - public boolean isCamera(int offset) { - return mCurrentIndex + offset == mCameraIndex; - } - - @Override - public boolean isPanorama(int offset) { - return isCamera(offset) && mIsPanorama; - } - - @Override - public boolean isStaticCamera(int offset) { - return isCamera(offset) && mIsStaticCamera; - } - - @Override - public boolean isVideo(int offset) { - MediaItem item = getItem(mCurrentIndex + offset); - return (item == null) - ? false - : item.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO; - } - - @Override - public boolean isDeletable(int offset) { - MediaItem item = getItem(mCurrentIndex + offset); - return (item == null) - ? false - : (item.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0; - } - - @Override - public int getLoadingState(int offset) { - ImageEntry entry = mImageCache.get(getPath(mCurrentIndex + offset)); - if (entry == null) return LOADING_INIT; - if (entry.failToLoad) return LOADING_FAIL; - if (entry.screenNail != null) return LOADING_COMPLETE; - return LOADING_INIT; - } - - @Override - public ScreenNail getScreenNail() { - return getScreenNail(0); - } - - @Override - public int getImageHeight() { - return mTileProvider.getImageHeight(); - } - - @Override - public int getImageWidth() { - return mTileProvider.getImageWidth(); - } - - @Override - public int getLevelCount() { - return mTileProvider.getLevelCount(); - } - - @Override - public Bitmap getTile(int level, int x, int y, int tileSize) { - return mTileProvider.getTile(level, x, y, tileSize); - } - - @Override - public boolean isEmpty() { - return mSize == 0; - } - - @Override - public int getCurrentIndex() { - return mCurrentIndex; - } - - @Override - public MediaItem getMediaItem(int offset) { - int index = mCurrentIndex + offset; - if (index >= mContentStart && index < mContentEnd) { - return mData[index % DATA_CACHE_SIZE]; - } - return null; - } - - @Override - public void setCurrentPhoto(Path path, int indexHint) { - if (mItemPath == path) return; - mItemPath = path; - mCurrentIndex = indexHint; - updateSlidingWindow(); - updateImageCache(); - fireDataChange(); - - // We need to reload content if the path doesn't match. - MediaItem item = getMediaItem(0); - if (item != null && item.getPath() != path) { - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - @Override - public void setFocusHintDirection(int direction) { - mFocusHintDirection = direction; - } - - @Override - public void setFocusHintPath(Path path) { - mFocusHintPath = path; - } - - private void updateTileProvider() { - ImageEntry entry = mImageCache.get(getPath(mCurrentIndex)); - if (entry == null) { // in loading - mTileProvider.clear(); - } else { - updateTileProvider(entry); - } - } - - private void updateTileProvider(ImageEntry entry) { - ScreenNail screenNail = entry.screenNail; - BitmapRegionDecoder fullImage = entry.fullImage; - if (screenNail != null) { - if (fullImage != null) { - mTileProvider.setScreenNail(screenNail, - fullImage.getWidth(), fullImage.getHeight()); - mTileProvider.setRegionDecoder(fullImage); - } else { - int width = screenNail.getWidth(); - int height = screenNail.getHeight(); - mTileProvider.setScreenNail(screenNail, width, height); - } - } else { - mTileProvider.clear(); - } - } - - private void updateSlidingWindow() { - // 1. Update the image window - int start = Utils.clamp(mCurrentIndex - IMAGE_CACHE_SIZE / 2, - 0, Math.max(0, mSize - IMAGE_CACHE_SIZE)); - int end = Math.min(mSize, start + IMAGE_CACHE_SIZE); - - if (mActiveStart == start && mActiveEnd == end) return; - - mActiveStart = start; - mActiveEnd = end; - - // 2. Update the data window - start = Utils.clamp(mCurrentIndex - DATA_CACHE_SIZE / 2, - 0, Math.max(0, mSize - DATA_CACHE_SIZE)); - end = Math.min(mSize, start + DATA_CACHE_SIZE); - if (mContentStart > mActiveStart || mContentEnd < mActiveEnd - || Math.abs(start - mContentStart) > MIN_LOAD_COUNT) { - for (int i = mContentStart; i < mContentEnd; ++i) { - if (i < start || i >= end) { - mData[i % DATA_CACHE_SIZE] = null; - } - } - mContentStart = start; - mContentEnd = end; - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - private void updateImageRequests() { - if (!mIsActive) return; - - int currentIndex = mCurrentIndex; - MediaItem item = mData[currentIndex % DATA_CACHE_SIZE]; - if (item == null || item.getPath() != mItemPath) { - // current item mismatch - don't request image - return; - } - - // 1. Find the most wanted request and start it (if not already started). - Future<?> task = null; - for (int i = 0; i < sImageFetchSeq.length; i++) { - int offset = sImageFetchSeq[i].indexOffset; - int bit = sImageFetchSeq[i].imageBit; - if (bit == BIT_FULL_IMAGE && !mNeedFullImage) continue; - task = startTaskIfNeeded(currentIndex + offset, bit); - if (task != null) break; - } - - // 2. Cancel everything else. - for (ImageEntry entry : mImageCache.values()) { - if (entry.screenNailTask != null && entry.screenNailTask != task) { - entry.screenNailTask.cancel(); - entry.screenNailTask = null; - entry.requestedScreenNail = MediaObject.INVALID_DATA_VERSION; - } - if (entry.fullImageTask != null && entry.fullImageTask != task) { - entry.fullImageTask.cancel(); - entry.fullImageTask = null; - entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION; - } - } - } - - private class ScreenNailJob implements Job<ScreenNail> { - private MediaItem mItem; - - public ScreenNailJob(MediaItem item) { - mItem = item; - } - - @Override - public ScreenNail run(JobContext jc) { - // We try to get a ScreenNail first, if it fails, we fallback to get - // a Bitmap and then wrap it in a BitmapScreenNail instead. - ScreenNail s = mItem.getScreenNail(); - if (s != null) return s; - - // If this is a temporary item, don't try to get its bitmap because - // it won't be available. We will get its bitmap after a data reload. - if (isTemporaryItem(mItem)) { - return newPlaceholderScreenNail(mItem); - } - - Bitmap bitmap = mItem.requestImage(MediaItem.TYPE_THUMBNAIL).run(jc); - if (jc.isCancelled()) return null; - if (bitmap != null) { - bitmap = BitmapUtils.rotateBitmap(bitmap, - mItem.getRotation() - mItem.getFullImageRotation(), true); - } - return bitmap == null ? null : new TiledScreenNail(bitmap); - } - } - - private class FullImageJob implements Job<BitmapRegionDecoder> { - private MediaItem mItem; - - public FullImageJob(MediaItem item) { - mItem = item; - } - - @Override - public BitmapRegionDecoder run(JobContext jc) { - if (isTemporaryItem(mItem)) { - return null; - } - return mItem.requestLargeImage().run(jc); - } - } - - // Returns true if we think this is a temporary item created by Camera. A - // temporary item is an image or a video whose data is still being - // processed, but an incomplete entry is created first in MediaProvider, so - // we can display them (in grey tile) even if they are not saved to disk - // yet. When the image or video data is actually saved, we will get - // notification from MediaProvider, reload data, and show the actual image - // or video data. - private boolean isTemporaryItem(MediaItem mediaItem) { - // Must have camera to create a temporary item. - if (mCameraIndex < 0) return false; - // Must be an item in camera roll. - if (!(mediaItem instanceof LocalMediaItem)) return false; - LocalMediaItem item = (LocalMediaItem) mediaItem; - if (item.getBucketId() != MediaSetUtils.CAMERA_BUCKET_ID) return false; - // Must have no size, but must have width and height information - if (item.getSize() != 0) return false; - if (item.getWidth() == 0) return false; - if (item.getHeight() == 0) return false; - // Must be created in the last 10 seconds. - if (item.getDateInMs() - System.currentTimeMillis() > 10000) return false; - return true; - } - - // Create a default ScreenNail when a ScreenNail is needed, but we don't yet - // have one available (because the image data is still being saved, or the - // Bitmap is still being loaded. - private ScreenNail newPlaceholderScreenNail(MediaItem item) { - int width = item.getWidth(); - int height = item.getHeight(); - return new TiledScreenNail(width, height); - } - - // Returns the task if we started the task or the task is already started. - private Future<?> startTaskIfNeeded(int index, int which) { - if (index < mActiveStart || index >= mActiveEnd) return null; - - ImageEntry entry = mImageCache.get(getPath(index)); - if (entry == null) return null; - MediaItem item = mData[index % DATA_CACHE_SIZE]; - Utils.assertTrue(item != null); - long version = item.getDataVersion(); - - if (which == BIT_SCREEN_NAIL && entry.screenNailTask != null - && entry.requestedScreenNail == version) { - return entry.screenNailTask; - } else if (which == BIT_FULL_IMAGE && entry.fullImageTask != null - && entry.requestedFullImage == version) { - return entry.fullImageTask; - } - - if (which == BIT_SCREEN_NAIL && entry.requestedScreenNail != version) { - entry.requestedScreenNail = version; - entry.screenNailTask = mThreadPool.submit( - new ScreenNailJob(item), - new ScreenNailListener(item)); - // request screen nail - return entry.screenNailTask; - } - if (which == BIT_FULL_IMAGE && entry.requestedFullImage != version - && (item.getSupportedOperations() - & MediaItem.SUPPORT_FULL_IMAGE) != 0) { - entry.requestedFullImage = version; - entry.fullImageTask = mThreadPool.submit( - new FullImageJob(item), - new FullImageListener(item)); - // request full image - return entry.fullImageTask; - } - return null; - } - - private void updateImageCache() { - HashSet<Path> toBeRemoved = new HashSet<Path>(mImageCache.keySet()); - for (int i = mActiveStart; i < mActiveEnd; ++i) { - MediaItem item = mData[i % DATA_CACHE_SIZE]; - if (item == null) continue; - Path path = item.getPath(); - ImageEntry entry = mImageCache.get(path); - toBeRemoved.remove(path); - if (entry != null) { - if (Math.abs(i - mCurrentIndex) > 1) { - if (entry.fullImageTask != null) { - entry.fullImageTask.cancel(); - entry.fullImageTask = null; - } - entry.fullImage = null; - entry.requestedFullImage = MediaObject.INVALID_DATA_VERSION; - } - if (entry.requestedScreenNail != item.getDataVersion()) { - // This ScreenNail is outdated, we want to update it if it's - // still a placeholder. - if (entry.screenNail instanceof TiledScreenNail) { - TiledScreenNail s = (TiledScreenNail) entry.screenNail; - s.updatePlaceholderSize( - item.getWidth(), item.getHeight()); - } - } - } else { - entry = new ImageEntry(); - mImageCache.put(path, entry); - } - } - - // Clear the data and requests for ImageEntries outside the new window. - for (Path path : toBeRemoved) { - ImageEntry entry = mImageCache.remove(path); - if (entry.fullImageTask != null) entry.fullImageTask.cancel(); - if (entry.screenNailTask != null) entry.screenNailTask.cancel(); - if (entry.screenNail != null) entry.screenNail.recycle(); - } - - updateScreenNailUploadQueue(); - } - - private class FullImageListener - implements Runnable, FutureListener<BitmapRegionDecoder> { - private final Path mPath; - private Future<BitmapRegionDecoder> mFuture; - - public FullImageListener(MediaItem item) { - mPath = item.getPath(); - } - - @Override - public void onFutureDone(Future<BitmapRegionDecoder> future) { - mFuture = future; - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, this)); - } - - @Override - public void run() { - updateFullImage(mPath, mFuture); - } - } - - private class ScreenNailListener - implements Runnable, FutureListener<ScreenNail> { - private final Path mPath; - private Future<ScreenNail> mFuture; - - public ScreenNailListener(MediaItem item) { - mPath = item.getPath(); - } - - @Override - public void onFutureDone(Future<ScreenNail> future) { - mFuture = future; - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, this)); - } - - @Override - public void run() { - updateScreenNail(mPath, mFuture); - } - } - - private static class ImageEntry { - public BitmapRegionDecoder fullImage; - public ScreenNail screenNail; - public Future<ScreenNail> screenNailTask; - public Future<BitmapRegionDecoder> fullImageTask; - public long requestedScreenNail = MediaObject.INVALID_DATA_VERSION; - public long requestedFullImage = MediaObject.INVALID_DATA_VERSION; - public boolean failToLoad = false; - } - - private class SourceListener implements ContentListener { - @Override - public void onContentDirty() { - if (mReloadTask != null) mReloadTask.notifyDirty(); - } - } - - private <T> T executeAndWait(Callable<T> callable) { - FutureTask<T> task = new FutureTask<T>(callable); - mMainHandler.sendMessage( - mMainHandler.obtainMessage(MSG_RUN_OBJECT, task)); - try { - return task.get(); - } catch (InterruptedException e) { - return null; - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - private static class UpdateInfo { - public long version; - public boolean reloadContent; - public Path target; - public int indexHint; - public int contentStart; - public int contentEnd; - - public int size; - public ArrayList<MediaItem> items; - } - - private class GetUpdateInfo implements Callable<UpdateInfo> { - - private boolean needContentReload() { - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - if (mData[i % DATA_CACHE_SIZE] == null) return true; - } - MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE]; - return current == null || current.getPath() != mItemPath; - } - - @Override - public UpdateInfo call() throws Exception { - // TODO: Try to load some data in first update - UpdateInfo info = new UpdateInfo(); - info.version = mSourceVersion; - info.reloadContent = needContentReload(); - info.target = mItemPath; - info.indexHint = mCurrentIndex; - info.contentStart = mContentStart; - info.contentEnd = mContentEnd; - info.size = mSize; - return info; - } - } - - private class UpdateContent implements Callable<Void> { - UpdateInfo mUpdateInfo; - - public UpdateContent(UpdateInfo updateInfo) { - mUpdateInfo = updateInfo; - } - - @Override - public Void call() throws Exception { - UpdateInfo info = mUpdateInfo; - mSourceVersion = info.version; - - if (info.size != mSize) { - mSize = info.size; - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - - mCurrentIndex = info.indexHint; - updateSlidingWindow(); - - if (info.items != null) { - int start = Math.max(info.contentStart, mContentStart); - int end = Math.min(info.contentStart + info.items.size(), mContentEnd); - int dataIndex = start % DATA_CACHE_SIZE; - for (int i = start; i < end; ++i) { - mData[dataIndex] = info.items.get(i - info.contentStart); - if (++dataIndex == DATA_CACHE_SIZE) dataIndex = 0; - } - } - - // update mItemPath - MediaItem current = mData[mCurrentIndex % DATA_CACHE_SIZE]; - mItemPath = current == null ? null : current.getPath(); - - updateImageCache(); - updateTileProvider(); - updateImageRequests(); - - if (mDataListener != null) { - mDataListener.onPhotoChanged(mCurrentIndex, mItemPath); - } - - fireDataChange(); - return null; - } - } - - private class ReloadTask extends Thread { - private volatile boolean mActive = true; - private volatile boolean mDirty = true; - - private boolean mIsLoading = false; - - private void updateLoading(boolean loading) { - if (mIsLoading == loading) return; - mIsLoading = loading; - mMainHandler.sendEmptyMessage(loading ? MSG_LOAD_START : MSG_LOAD_FINISH); - } - - @Override - public void run() { - while (mActive) { - synchronized (this) { - if (!mDirty && mActive) { - updateLoading(false); - Utils.waitWithoutInterrupt(this); - continue; - } - } - mDirty = false; - UpdateInfo info = executeAndWait(new GetUpdateInfo()); - updateLoading(true); - long version = mSource.reload(); - if (info.version != version) { - info.reloadContent = true; - info.size = mSource.getMediaItemCount(); - } - if (!info.reloadContent) continue; - info.items = mSource.getMediaItem( - info.contentStart, info.contentEnd); - - int index = MediaSet.INDEX_NOT_FOUND; - - // First try to focus on the given hint path if there is one. - if (mFocusHintPath != null) { - index = findIndexOfPathInCache(info, mFocusHintPath); - mFocusHintPath = null; - } - - // Otherwise try to see if the currently focused item can be found. - if (index == MediaSet.INDEX_NOT_FOUND) { - MediaItem item = findCurrentMediaItem(info); - if (item != null && item.getPath() == info.target) { - index = info.indexHint; - } else { - index = findIndexOfTarget(info); - } - } - - // The image has been deleted. Focus on the next image (keep - // mCurrentIndex unchanged) or the previous image (decrease - // mCurrentIndex by 1). In page mode we want to see the next - // image, so we focus on the next one. In film mode we want the - // later images to shift left to fill the empty space, so we - // focus on the previous image (so it will not move). In any - // case the index needs to be limited to [0, mSize). - if (index == MediaSet.INDEX_NOT_FOUND) { - index = info.indexHint; - int focusHintDirection = mFocusHintDirection; - if (index == (mCameraIndex + 1)) { - focusHintDirection = FOCUS_HINT_NEXT; - } - if (focusHintDirection == FOCUS_HINT_PREVIOUS - && index > 0) { - index--; - } - } - - // Don't change index if mSize == 0 - if (mSize > 0) { - if (index >= mSize) index = mSize - 1; - } - - info.indexHint = index; - - executeAndWait(new UpdateContent(info)); - } - } - - public synchronized void notifyDirty() { - mDirty = true; - notifyAll(); - } - - public synchronized void terminate() { - mActive = false; - notifyAll(); - } - - private MediaItem findCurrentMediaItem(UpdateInfo info) { - ArrayList<MediaItem> items = info.items; - int index = info.indexHint - info.contentStart; - return index < 0 || index >= items.size() ? null : items.get(index); - } - - private int findIndexOfTarget(UpdateInfo info) { - if (info.target == null) return info.indexHint; - ArrayList<MediaItem> items = info.items; - - // First, try to find the item in the data just loaded - if (items != null) { - int i = findIndexOfPathInCache(info, info.target); - if (i != MediaSet.INDEX_NOT_FOUND) return i; - } - - // Not found, find it in mSource. - return mSource.getIndexOfItem(info.target, info.indexHint); - } - - private int findIndexOfPathInCache(UpdateInfo info, Path path) { - ArrayList<MediaItem> items = info.items; - for (int i = 0, n = items.size(); i < n; ++i) { - MediaItem item = items.get(i); - if (item != null && item.getPath() == path) { - return i + info.contentStart; - } - } - return MediaSet.INDEX_NOT_FOUND; - } - } -} diff --git a/src/com/android/gallery3d/app/PhotoPage.java b/src/com/android/gallery3d/app/PhotoPage.java deleted file mode 100644 index 7a71e9109..000000000 --- a/src/com/android/gallery3d/app/PhotoPage.java +++ /dev/null @@ -1,1571 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.ActionBar.OnMenuVisibilityListener; -import android.app.Activity; -import android.content.ActivityNotFoundException; -import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.res.Configuration; -import android.graphics.Rect; -import android.net.Uri; -import android.nfc.NfcAdapter; -import android.nfc.NfcAdapter.CreateBeamUrisCallback; -import android.nfc.NfcEvent; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.SystemClock; -import android.view.Menu; -import android.view.MenuItem; -import android.widget.RelativeLayout; -import android.widget.ShareActionProvider; -import android.widget.Toast; - -import com.android.camera.CameraActivity; -import com.android.camera.ProxyLauncher; -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.ComboAlbum; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.FilterDeleteSet; -import com.android.gallery3d.data.FilterSource; -import com.android.gallery3d.data.LocalImage; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.data.SecureAlbum; -import com.android.gallery3d.data.SecureSource; -import com.android.gallery3d.data.SnailAlbum; -import com.android.gallery3d.data.SnailItem; -import com.android.gallery3d.data.SnailSource; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.ui.DetailsHelper; -import com.android.gallery3d.ui.DetailsHelper.CloseListener; -import com.android.gallery3d.ui.DetailsHelper.DetailsSource; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.MenuExecutor; -import com.android.gallery3d.ui.PhotoView; -import com.android.gallery3d.ui.SelectionManager; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.UsageStatistics; - -public abstract class PhotoPage extends ActivityState implements - PhotoView.Listener, AppBridge.Server, ShareActionProvider.OnShareTargetSelectedListener, - PhotoPageBottomControls.Delegate, GalleryActionBar.OnAlbumModeSelectedListener { - private static final String TAG = "PhotoPage"; - - private static final int MSG_HIDE_BARS = 1; - private static final int MSG_ON_FULL_SCREEN_CHANGED = 4; - private static final int MSG_UPDATE_ACTION_BAR = 5; - private static final int MSG_UNFREEZE_GLROOT = 6; - private static final int MSG_WANT_BARS = 7; - private static final int MSG_REFRESH_BOTTOM_CONTROLS = 8; - private static final int MSG_ON_CAMERA_CENTER = 9; - private static final int MSG_ON_PICTURE_CENTER = 10; - private static final int MSG_REFRESH_IMAGE = 11; - private static final int MSG_UPDATE_PHOTO_UI = 12; - private static final int MSG_UPDATE_PROGRESS = 13; - private static final int MSG_UPDATE_DEFERRED = 14; - private static final int MSG_UPDATE_SHARE_URI = 15; - private static final int MSG_UPDATE_PANORAMA_UI = 16; - - private static final int HIDE_BARS_TIMEOUT = 3500; - private static final int UNFREEZE_GLROOT_TIMEOUT = 250; - - private static final int REQUEST_SLIDESHOW = 1; - private static final int REQUEST_CROP = 2; - private static final int REQUEST_CROP_PICASA = 3; - private static final int REQUEST_EDIT = 4; - private static final int REQUEST_PLAY_VIDEO = 5; - private static final int REQUEST_TRIM = 6; - - public static final String KEY_MEDIA_SET_PATH = "media-set-path"; - public static final String KEY_MEDIA_ITEM_PATH = "media-item-path"; - public static final String KEY_INDEX_HINT = "index-hint"; - public static final String KEY_OPEN_ANIMATION_RECT = "open-animation-rect"; - public static final String KEY_APP_BRIDGE = "app-bridge"; - public static final String KEY_TREAT_BACK_AS_UP = "treat-back-as-up"; - public static final String KEY_START_IN_FILMSTRIP = "start-in-filmstrip"; - public static final String KEY_RETURN_INDEX_HINT = "return-index-hint"; - public static final String KEY_SHOW_WHEN_LOCKED = "show_when_locked"; - public static final String KEY_IN_CAMERA_ROLL = "in_camera_roll"; - - public static final String KEY_ALBUMPAGE_TRANSITION = "albumpage-transition"; - public static final int MSG_ALBUMPAGE_NONE = 0; - public static final int MSG_ALBUMPAGE_STARTED = 1; - public static final int MSG_ALBUMPAGE_RESUMED = 2; - public static final int MSG_ALBUMPAGE_PICKED = 4; - - public static final String ACTION_NEXTGEN_EDIT = "action_nextgen_edit"; - public static final String ACTION_SIMPLE_EDIT = "action_simple_edit"; - - private GalleryApp mApplication; - private SelectionManager mSelectionManager; - - private PhotoView mPhotoView; - private PhotoPage.Model mModel; - private DetailsHelper mDetailsHelper; - private boolean mShowDetails; - - // mMediaSet could be null if there is no KEY_MEDIA_SET_PATH supplied. - // E.g., viewing a photo in gmail attachment - private FilterDeleteSet mMediaSet; - - // The mediaset used by camera launched from secure lock screen. - private SecureAlbum mSecureAlbum; - - private int mCurrentIndex = 0; - private Handler mHandler; - private boolean mShowBars = true; - private volatile boolean mActionBarAllowed = true; - private GalleryActionBar mActionBar; - private boolean mIsMenuVisible; - private boolean mHaveImageEditor; - private PhotoPageBottomControls mBottomControls; - private PhotoPageProgressBar mProgressBar; - private MediaItem mCurrentPhoto = null; - private MenuExecutor mMenuExecutor; - private boolean mIsActive; - private boolean mShowSpinner; - private String mSetPathString; - // This is the original mSetPathString before adding the camera preview item. - private String mOriginalSetPathString; - private AppBridge mAppBridge; - private SnailItem mScreenNailItem; - private SnailAlbum mScreenNailSet; - private OrientationManager mOrientationManager; - private boolean mTreatBackAsUp; - private boolean mStartInFilmstrip; - private boolean mHasCameraScreennailOrPlaceholder = false; - private boolean mRecenterCameraOnResume = true; - - // These are only valid after the panorama callback - private boolean mIsPanorama; - private boolean mIsPanorama360; - - private long mCameraSwitchCutoff = 0; - private boolean mSkipUpdateCurrentPhoto = false; - private static final long CAMERA_SWITCH_CUTOFF_THRESHOLD_MS = 300; - - private static final long DEFERRED_UPDATE_MS = 250; - private boolean mDeferredUpdateWaiting = false; - private long mDeferUpdateUntil = Long.MAX_VALUE; - - // The item that is deleted (but it can still be undeleted before commiting) - private Path mDeletePath; - private boolean mDeleteIsFocus; // whether the deleted item was in focus - - private Uri[] mNfcPushUris = new Uri[1]; - - private final MyMenuVisibilityListener mMenuVisibilityListener = - new MyMenuVisibilityListener(); - private UpdateProgressListener mProgressListener; - - private final PanoramaSupportCallback mUpdatePanoramaMenuItemsCallback = new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - if (mediaObject == mCurrentPhoto) { - mHandler.obtainMessage(MSG_UPDATE_PANORAMA_UI, isPanorama360 ? 1 : 0, 0, - mediaObject).sendToTarget(); - } - } - }; - - private final PanoramaSupportCallback mRefreshBottomControlsCallback = new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - if (mediaObject == mCurrentPhoto) { - mHandler.obtainMessage(MSG_REFRESH_BOTTOM_CONTROLS, isPanorama ? 1 : 0, isPanorama360 ? 1 : 0, - mediaObject).sendToTarget(); - } - } - }; - - private final PanoramaSupportCallback mUpdateShareURICallback = new PanoramaSupportCallback() { - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - if (mediaObject == mCurrentPhoto) { - mHandler.obtainMessage(MSG_UPDATE_SHARE_URI, isPanorama360 ? 1 : 0, 0, mediaObject) - .sendToTarget(); - } - } - }; - - public static interface Model extends PhotoView.Model { - public void resume(); - public void pause(); - public boolean isEmpty(); - public void setCurrentPhoto(Path path, int indexHint); - } - - private class MyMenuVisibilityListener implements OnMenuVisibilityListener { - @Override - public void onMenuVisibilityChanged(boolean isVisible) { - mIsMenuVisible = isVisible; - refreshHidingMessage(); - } - } - - private class UpdateProgressListener implements StitchingChangeListener { - - @Override - public void onStitchingResult(Uri uri) { - sendUpdate(uri, MSG_REFRESH_IMAGE); - } - - @Override - public void onStitchingQueued(Uri uri) { - sendUpdate(uri, MSG_UPDATE_PROGRESS); - } - - @Override - public void onStitchingProgress(Uri uri, final int progress) { - sendUpdate(uri, MSG_UPDATE_PROGRESS); - } - - private void sendUpdate(Uri uri, int message) { - MediaObject currentPhoto = mCurrentPhoto; - boolean isCurrentPhoto = currentPhoto instanceof LocalImage - && currentPhoto.getContentUri().equals(uri); - if (isCurrentPhoto) { - mHandler.sendEmptyMessage(message); - } - } - }; - - @Override - protected int getBackgroundColorId() { - return R.color.photo_background; - } - - private final GLView mRootPane = new GLView() { - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - mPhotoView.layout(0, 0, right - left, bottom - top); - if (mShowDetails) { - mDetailsHelper.layout(left, mActionBar.getHeight(), right, bottom); - } - } - }; - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mActionBar = mActivity.getGalleryActionBar(); - mSelectionManager = new SelectionManager(mActivity, false); - mMenuExecutor = new MenuExecutor(mActivity, mSelectionManager); - - mPhotoView = new PhotoView(mActivity); - mPhotoView.setListener(this); - mRootPane.addComponent(mPhotoView); - mApplication = (GalleryApp) ((Activity) mActivity).getApplication(); - mOrientationManager = mActivity.getOrientationManager(); - mActivity.getGLRoot().setOrientationSource(mOrientationManager); - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_HIDE_BARS: { - hideBars(); - break; - } - case MSG_REFRESH_BOTTOM_CONTROLS: { - if (mCurrentPhoto == message.obj && mBottomControls != null) { - mIsPanorama = message.arg1 == 1; - mIsPanorama360 = message.arg2 == 1; - mBottomControls.refresh(); - } - break; - } - case MSG_ON_FULL_SCREEN_CHANGED: { - if (mAppBridge != null) { - mAppBridge.onFullScreenChanged(message.arg1 == 1); - } - break; - } - case MSG_UPDATE_ACTION_BAR: { - updateBars(); - break; - } - case MSG_WANT_BARS: { - wantBars(); - break; - } - case MSG_UNFREEZE_GLROOT: { - mActivity.getGLRoot().unfreeze(); - break; - } - case MSG_UPDATE_DEFERRED: { - long nextUpdate = mDeferUpdateUntil - SystemClock.uptimeMillis(); - if (nextUpdate <= 0) { - mDeferredUpdateWaiting = false; - updateUIForCurrentPhoto(); - } else { - mHandler.sendEmptyMessageDelayed(MSG_UPDATE_DEFERRED, nextUpdate); - } - break; - } - case MSG_ON_CAMERA_CENTER: { - mSkipUpdateCurrentPhoto = false; - boolean stayedOnCamera = false; - if (!mPhotoView.getFilmMode()) { - stayedOnCamera = true; - } else if (SystemClock.uptimeMillis() < mCameraSwitchCutoff && - mMediaSet.getMediaItemCount() > 1) { - mPhotoView.switchToImage(1); - } else { - if (mAppBridge != null) mPhotoView.setFilmMode(false); - stayedOnCamera = true; - } - - if (stayedOnCamera) { - if (mAppBridge == null && mMediaSet.getTotalMediaItemCount() > 1) { - launchCamera(); - /* We got here by swiping from photo 1 to the - placeholder, so make it be the thing that - is in focus when the user presses back from - the camera app */ - mPhotoView.switchToImage(1); - } else { - updateBars(); - updateCurrentPhoto(mModel.getMediaItem(0)); - } - } - break; - } - case MSG_ON_PICTURE_CENTER: { - if (!mPhotoView.getFilmMode() && mCurrentPhoto != null - && (mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_ACTION) != 0) { - mPhotoView.setFilmMode(true); - } - break; - } - case MSG_REFRESH_IMAGE: { - final MediaItem photo = mCurrentPhoto; - mCurrentPhoto = null; - updateCurrentPhoto(photo); - break; - } - case MSG_UPDATE_PHOTO_UI: { - updateUIForCurrentPhoto(); - break; - } - case MSG_UPDATE_PROGRESS: { - updateProgressBar(); - break; - } - case MSG_UPDATE_SHARE_URI: { - if (mCurrentPhoto == message.obj) { - boolean isPanorama360 = message.arg1 != 0; - Uri contentUri = mCurrentPhoto.getContentUri(); - Intent panoramaIntent = null; - if (isPanorama360) { - panoramaIntent = createSharePanoramaIntent(contentUri); - } - Intent shareIntent = createShareIntent(mCurrentPhoto); - - mActionBar.setShareIntents(panoramaIntent, shareIntent, PhotoPage.this); - setNfcBeamPushUri(contentUri); - } - break; - } - case MSG_UPDATE_PANORAMA_UI: { - if (mCurrentPhoto == message.obj) { - boolean isPanorama360 = message.arg1 != 0; - updatePanoramaUI(isPanorama360); - } - break; - } - default: throw new AssertionError(message.what); - } - } - }; - - mSetPathString = data.getString(KEY_MEDIA_SET_PATH); - mOriginalSetPathString = mSetPathString; - setupNfcBeamPush(); - String itemPathString = data.getString(KEY_MEDIA_ITEM_PATH); - Path itemPath = itemPathString != null ? - Path.fromString(data.getString(KEY_MEDIA_ITEM_PATH)) : - null; - mTreatBackAsUp = data.getBoolean(KEY_TREAT_BACK_AS_UP, false); - mStartInFilmstrip = data.getBoolean(KEY_START_IN_FILMSTRIP, false); - boolean inCameraRoll = data.getBoolean(KEY_IN_CAMERA_ROLL, false); - mCurrentIndex = data.getInt(KEY_INDEX_HINT, 0); - if (mSetPathString != null) { - mShowSpinner = true; - mAppBridge = (AppBridge) data.getParcelable(KEY_APP_BRIDGE); - if (mAppBridge != null) { - mShowBars = false; - mHasCameraScreennailOrPlaceholder = true; - mAppBridge.setServer(this); - - // Get the ScreenNail from AppBridge and register it. - int id = SnailSource.newId(); - Path screenNailSetPath = SnailSource.getSetPath(id); - Path screenNailItemPath = SnailSource.getItemPath(id); - mScreenNailSet = (SnailAlbum) mActivity.getDataManager() - .getMediaObject(screenNailSetPath); - mScreenNailItem = (SnailItem) mActivity.getDataManager() - .getMediaObject(screenNailItemPath); - mScreenNailItem.setScreenNail(mAppBridge.attachScreenNail()); - - if (data.getBoolean(KEY_SHOW_WHEN_LOCKED, false)) { - // Set the flag to be on top of the lock screen. - mFlags |= FLAG_SHOW_WHEN_LOCKED; - } - - // Don't display "empty album" action item for capture intents. - if (!mSetPathString.equals("/local/all/0")) { - // Check if the path is a secure album. - if (SecureSource.isSecurePath(mSetPathString)) { - mSecureAlbum = (SecureAlbum) mActivity.getDataManager() - .getMediaSet(mSetPathString); - mShowSpinner = false; - } - mSetPathString = "/filter/empty/{"+mSetPathString+"}"; - } - - // Combine the original MediaSet with the one for ScreenNail - // from AppBridge. - mSetPathString = "/combo/item/{" + screenNailSetPath + - "," + mSetPathString + "}"; - - // Start from the screen nail. - itemPath = screenNailItemPath; - } else if (inCameraRoll && GalleryUtils.isCameraAvailable(mActivity)) { - mSetPathString = "/combo/item/{" + FilterSource.FILTER_CAMERA_SHORTCUT + - "," + mSetPathString + "}"; - mCurrentIndex++; - mHasCameraScreennailOrPlaceholder = true; - } - - MediaSet originalSet = mActivity.getDataManager() - .getMediaSet(mSetPathString); - if (mHasCameraScreennailOrPlaceholder && originalSet instanceof ComboAlbum) { - // Use the name of the camera album rather than the default - // ComboAlbum behavior - ((ComboAlbum) originalSet).useNameOfChild(1); - } - mSelectionManager.setSourceMediaSet(originalSet); - mSetPathString = "/filter/delete/{" + mSetPathString + "}"; - mMediaSet = (FilterDeleteSet) mActivity.getDataManager() - .getMediaSet(mSetPathString); - if (mMediaSet == null) { - Log.w(TAG, "failed to restore " + mSetPathString); - } - if (itemPath == null) { - int mediaItemCount = mMediaSet.getMediaItemCount(); - if (mediaItemCount > 0) { - if (mCurrentIndex >= mediaItemCount) mCurrentIndex = 0; - itemPath = mMediaSet.getMediaItem(mCurrentIndex, 1) - .get(0).getPath(); - } else { - // Bail out, PhotoPage can't load on an empty album - return; - } - } - PhotoDataAdapter pda = new PhotoDataAdapter( - mActivity, mPhotoView, mMediaSet, itemPath, mCurrentIndex, - mAppBridge == null ? -1 : 0, - mAppBridge == null ? false : mAppBridge.isPanorama(), - mAppBridge == null ? false : mAppBridge.isStaticCamera()); - mModel = pda; - mPhotoView.setModel(mModel); - - pda.setDataListener(new PhotoDataAdapter.DataListener() { - - @Override - public void onPhotoChanged(int index, Path item) { - int oldIndex = mCurrentIndex; - mCurrentIndex = index; - - if (mHasCameraScreennailOrPlaceholder) { - if (mCurrentIndex > 0) { - mSkipUpdateCurrentPhoto = false; - } - - if (oldIndex == 0 && mCurrentIndex > 0 - && !mPhotoView.getFilmMode()) { - mPhotoView.setFilmMode(true); - if (mAppBridge != null) { - UsageStatistics.onEvent("CameraToFilmstrip", - UsageStatistics.TRANSITION_SWIPE, null); - } - } else if (oldIndex == 2 && mCurrentIndex == 1) { - mCameraSwitchCutoff = SystemClock.uptimeMillis() + - CAMERA_SWITCH_CUTOFF_THRESHOLD_MS; - mPhotoView.stopScrolling(); - } else if (oldIndex >= 1 && mCurrentIndex == 0) { - mPhotoView.setWantPictureCenterCallbacks(true); - mSkipUpdateCurrentPhoto = true; - } - } - if (!mSkipUpdateCurrentPhoto) { - if (item != null) { - MediaItem photo = mModel.getMediaItem(0); - if (photo != null) updateCurrentPhoto(photo); - } - updateBars(); - } - // Reset the timeout for the bars after a swipe - refreshHidingMessage(); - } - - @Override - public void onLoadingFinished(boolean loadingFailed) { - if (!mModel.isEmpty()) { - MediaItem photo = mModel.getMediaItem(0); - if (photo != null) updateCurrentPhoto(photo); - } else if (mIsActive) { - // We only want to finish the PhotoPage if there is no - // deletion that the user can undo. - if (mMediaSet.getNumberOfDeletions() == 0) { - mActivity.getStateManager().finishState( - PhotoPage.this); - } - } - } - - @Override - public void onLoadingStarted() { - } - }); - } else { - // Get default media set by the URI - MediaItem mediaItem = (MediaItem) - mActivity.getDataManager().getMediaObject(itemPath); - mModel = new SinglePhotoDataAdapter(mActivity, mPhotoView, mediaItem); - mPhotoView.setModel(mModel); - updateCurrentPhoto(mediaItem); - mShowSpinner = false; - } - - mPhotoView.setFilmMode(mStartInFilmstrip && mMediaSet.getMediaItemCount() > 1); - RelativeLayout galleryRoot = (RelativeLayout) ((Activity) mActivity) - .findViewById(mAppBridge != null ? R.id.content : R.id.gallery_root); - if (galleryRoot != null) { - if (mSecureAlbum == null) { - mBottomControls = new PhotoPageBottomControls(this, mActivity, galleryRoot); - } - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null) { - mProgressBar = new PhotoPageProgressBar(mActivity, galleryRoot); - mProgressListener = new UpdateProgressListener(); - progressManager.addChangeListener(mProgressListener); - if (mSecureAlbum != null) { - progressManager.addChangeListener(mSecureAlbum); - } - } - } - } - - @Override - public void onPictureCenter(boolean isCamera) { - isCamera = isCamera || (mHasCameraScreennailOrPlaceholder && mAppBridge == null); - mPhotoView.setWantPictureCenterCallbacks(false); - mHandler.removeMessages(MSG_ON_CAMERA_CENTER); - mHandler.removeMessages(MSG_ON_PICTURE_CENTER); - mHandler.sendEmptyMessage(isCamera ? MSG_ON_CAMERA_CENTER : MSG_ON_PICTURE_CENTER); - } - - @Override - public boolean canDisplayBottomControls() { - return mIsActive && !mPhotoView.canUndo(); - } - - @Override - public boolean canDisplayBottomControl(int control) { - if (mCurrentPhoto == null) { - return false; - } - switch(control) { - case R.id.photopage_bottom_control_edit: - return mHaveImageEditor && mShowBars - && !mPhotoView.getFilmMode() - && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_EDIT) != 0 - && mCurrentPhoto.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE; - case R.id.photopage_bottom_control_panorama: - return mIsPanorama; - case R.id.photopage_bottom_control_tiny_planet: - return mHaveImageEditor && mShowBars - && mIsPanorama360 && !mPhotoView.getFilmMode(); - default: - return false; - } - } - - @Override - public void onBottomControlClicked(int control) { - switch(control) { - case R.id.photopage_bottom_control_edit: - launchPhotoEditor(); - return; - case R.id.photopage_bottom_control_panorama: - mActivity.getPanoramaViewHelper() - .showPanorama(mCurrentPhoto.getContentUri()); - return; - case R.id.photopage_bottom_control_tiny_planet: - launchTinyPlanet(); - return; - default: - return; - } - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void setupNfcBeamPush() { - if (!ApiHelper.HAS_SET_BEAM_PUSH_URIS) return; - - NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mActivity); - if (adapter != null) { - adapter.setBeamPushUris(null, mActivity); - adapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() { - @Override - public Uri[] createBeamUris(NfcEvent event) { - return mNfcPushUris; - } - }, mActivity); - } - } - - private void setNfcBeamPushUri(Uri uri) { - mNfcPushUris[0] = uri; - } - - private static Intent createShareIntent(MediaObject mediaObject) { - int type = mediaObject.getMediaType(); - return new Intent(Intent.ACTION_SEND) - .setType(MenuExecutor.getMimeType(type)) - .putExtra(Intent.EXTRA_STREAM, mediaObject.getContentUri()) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - - private static Intent createSharePanoramaIntent(Uri contentUri) { - return new Intent(Intent.ACTION_SEND) - .setType(GalleryUtils.MIME_TYPE_PANORAMA360) - .putExtra(Intent.EXTRA_STREAM, contentUri) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - - private void overrideTransitionToEditor() { - ((Activity) mActivity).overridePendingTransition(android.R.anim.fade_in, - android.R.anim.fade_out); - } - - private void launchTinyPlanet() { - // Deep link into tiny planet - MediaItem current = mModel.getMediaItem(0); - Intent intent = new Intent(FilterShowActivity.TINY_PLANET_ACTION); - intent.setClass(mActivity, FilterShowActivity.class); - intent.setDataAndType(current.getContentUri(), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN, - mActivity.isFullscreen()); - mActivity.startActivityForResult(intent, REQUEST_EDIT); - overrideTransitionToEditor(); - } - - private void launchCamera() { - Intent intent = new Intent(mActivity, CameraActivity.class) - .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - mRecenterCameraOnResume = false; - mActivity.startActivity(intent); - } - - private void launchPhotoEditor() { - MediaItem current = mModel.getMediaItem(0); - if (current == null || (current.getSupportedOperations() - & MediaObject.SUPPORT_EDIT) == 0) { - return; - } - - Intent intent = new Intent(ACTION_NEXTGEN_EDIT); - - intent.setDataAndType(current.getContentUri(), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if (mActivity.getPackageManager() - .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() == 0) { - intent.setAction(Intent.ACTION_EDIT); - } - intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN, - mActivity.isFullscreen()); - ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null), - REQUEST_EDIT); - overrideTransitionToEditor(); - } - - private void launchSimpleEditor() { - MediaItem current = mModel.getMediaItem(0); - if (current == null || (current.getSupportedOperations() - & MediaObject.SUPPORT_EDIT) == 0) { - return; - } - - Intent intent = new Intent(ACTION_SIMPLE_EDIT); - - intent.setDataAndType(current.getContentUri(), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - if (mActivity.getPackageManager() - .queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).size() == 0) { - intent.setAction(Intent.ACTION_EDIT); - } - intent.putExtra(FilterShowActivity.LAUNCH_FULLSCREEN, - mActivity.isFullscreen()); - ((Activity) mActivity).startActivityForResult(Intent.createChooser(intent, null), - REQUEST_EDIT); - overrideTransitionToEditor(); - } - - private void requestDeferredUpdate() { - mDeferUpdateUntil = SystemClock.uptimeMillis() + DEFERRED_UPDATE_MS; - if (!mDeferredUpdateWaiting) { - mDeferredUpdateWaiting = true; - mHandler.sendEmptyMessageDelayed(MSG_UPDATE_DEFERRED, DEFERRED_UPDATE_MS); - } - } - - private void updateUIForCurrentPhoto() { - if (mCurrentPhoto == null) return; - - // If by swiping or deletion the user ends up on an action item - // and zoomed in, zoom out so that the context of the action is - // more clear - if ((mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_ACTION) != 0 - && !mPhotoView.getFilmMode()) { - mPhotoView.setWantPictureCenterCallbacks(true); - } - - updateMenuOperations(); - refreshBottomControlsWhenReady(); - if (mShowDetails) { - mDetailsHelper.reloadDetails(); - } - if ((mSecureAlbum == null) - && (mCurrentPhoto.getSupportedOperations() & MediaItem.SUPPORT_SHARE) != 0) { - mCurrentPhoto.getPanoramaSupport(mUpdateShareURICallback); - } - updateProgressBar(); - } - - private void updateCurrentPhoto(MediaItem photo) { - if (mCurrentPhoto == photo) return; - mCurrentPhoto = photo; - if (mPhotoView.getFilmMode()) { - requestDeferredUpdate(); - } else { - updateUIForCurrentPhoto(); - } - } - - private void updateProgressBar() { - if (mProgressBar != null) { - mProgressBar.hideProgress(); - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null && mCurrentPhoto instanceof LocalImage) { - Integer progress = progressManager.getProgress(mCurrentPhoto.getContentUri()); - if (progress != null) { - mProgressBar.setProgress(progress); - } - } - } - } - - private void updateMenuOperations() { - Menu menu = mActionBar.getMenu(); - - // it could be null if onCreateActionBar has not been called yet - if (menu == null) return; - - MenuItem item = menu.findItem(R.id.action_slideshow); - if (item != null) { - item.setVisible((mSecureAlbum == null) && canDoSlideShow()); - } - if (mCurrentPhoto == null) return; - - int supportedOperations = mCurrentPhoto.getSupportedOperations(); - if (mSecureAlbum != null) { - supportedOperations &= MediaObject.SUPPORT_DELETE; - } else { - mCurrentPhoto.getPanoramaSupport(mUpdatePanoramaMenuItemsCallback); - if (!mHaveImageEditor) { - supportedOperations &= ~MediaObject.SUPPORT_EDIT; - } - } - MenuExecutor.updateMenuOperation(menu, supportedOperations); - } - - private boolean canDoSlideShow() { - if (mMediaSet == null || mCurrentPhoto == null) { - return false; - } - if (mCurrentPhoto.getMediaType() != MediaObject.MEDIA_TYPE_IMAGE) { - return false; - } - return true; - } - - ////////////////////////////////////////////////////////////////////////// - // Action Bar show/hide management - ////////////////////////////////////////////////////////////////////////// - - private void showBars() { - if (mShowBars) return; - mShowBars = true; - mOrientationManager.unlockOrientation(); - mActionBar.show(); - mActivity.getGLRoot().setLightsOutMode(false); - refreshHidingMessage(); - refreshBottomControlsWhenReady(); - } - - private void hideBars() { - if (!mShowBars) return; - mShowBars = false; - mActionBar.hide(); - mActivity.getGLRoot().setLightsOutMode(true); - mHandler.removeMessages(MSG_HIDE_BARS); - refreshBottomControlsWhenReady(); - } - - private void refreshHidingMessage() { - mHandler.removeMessages(MSG_HIDE_BARS); - if (!mIsMenuVisible && !mPhotoView.getFilmMode()) { - mHandler.sendEmptyMessageDelayed(MSG_HIDE_BARS, HIDE_BARS_TIMEOUT); - } - } - - private boolean canShowBars() { - // No bars if we are showing camera preview. - if (mAppBridge != null && mCurrentIndex == 0 - && !mPhotoView.getFilmMode()) return false; - - // No bars if it's not allowed. - if (!mActionBarAllowed) return false; - - Configuration config = mActivity.getResources().getConfiguration(); - if (config.touchscreen == Configuration.TOUCHSCREEN_NOTOUCH) { - return false; - } - - return true; - } - - private void wantBars() { - if (canShowBars()) showBars(); - } - - private void toggleBars() { - if (mShowBars) { - hideBars(); - } else { - if (canShowBars()) showBars(); - } - } - - private void updateBars() { - if (!canShowBars()) { - hideBars(); - } - } - - @Override - protected void onBackPressed() { - if (mShowDetails) { - hideDetails(); - } else if (mAppBridge == null || !switchWithCaptureAnimation(-1)) { - // We are leaving this page. Set the result now. - setResult(); - if (mStartInFilmstrip && !mPhotoView.getFilmMode()) { - mPhotoView.setFilmMode(true); - } else if (mTreatBackAsUp) { - onUpPressed(); - } else { - super.onBackPressed(); - } - } - } - - private void onUpPressed() { - if ((mStartInFilmstrip || mAppBridge != null) - && !mPhotoView.getFilmMode()) { - mPhotoView.setFilmMode(true); - return; - } - - if (mActivity.getStateManager().getStateCount() > 1) { - setResult(); - super.onBackPressed(); - return; - } - - if (mOriginalSetPathString == null) return; - - if (mAppBridge == null) { - // We're in view mode so set up the stacks on our own. - Bundle data = new Bundle(getData()); - data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString); - data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, - mActivity.getDataManager().getTopSetPath( - DataManager.INCLUDE_ALL)); - mActivity.getStateManager().switchState(this, AlbumPage.class, data); - } else { - GalleryUtils.startGalleryActivity(mActivity); - } - } - - private void setResult() { - Intent result = null; - result = new Intent(); - result.putExtra(KEY_RETURN_INDEX_HINT, mCurrentIndex); - setStateResult(Activity.RESULT_OK, result); - } - - ////////////////////////////////////////////////////////////////////////// - // AppBridge.Server interface - ////////////////////////////////////////////////////////////////////////// - - @Override - public void setCameraRelativeFrame(Rect frame) { - mPhotoView.setCameraRelativeFrame(frame); - } - - @Override - public boolean switchWithCaptureAnimation(int offset) { - return mPhotoView.switchWithCaptureAnimation(offset); - } - - @Override - public void setSwipingEnabled(boolean enabled) { - mPhotoView.setSwipingEnabled(enabled); - } - - @Override - public void notifyScreenNailChanged() { - mScreenNailItem.setScreenNail(mAppBridge.attachScreenNail()); - mScreenNailSet.notifyChange(); - } - - @Override - public void addSecureAlbumItem(boolean isVideo, int id) { - mSecureAlbum.addMediaItem(isVideo, id); - } - - @Override - protected boolean onCreateActionBar(Menu menu) { - mActionBar.createActionBarMenu(R.menu.photo, menu); - mHaveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*"); - updateMenuOperations(); - mActionBar.setTitle(mMediaSet != null ? mMediaSet.getName() : ""); - return true; - } - - private MenuExecutor.ProgressListener mConfirmDialogListener = - new MenuExecutor.ProgressListener() { - @Override - public void onProgressUpdate(int index) {} - - @Override - public void onProgressComplete(int result) {} - - @Override - public void onConfirmDialogShown() { - mHandler.removeMessages(MSG_HIDE_BARS); - } - - @Override - public void onConfirmDialogDismissed(boolean confirmed) { - refreshHidingMessage(); - } - - @Override - public void onProgressStart() {} - }; - - private void switchToGrid() { - if (mActivity.getStateManager().hasStateClass(AlbumPage.class)) { - onUpPressed(); - } else { - if (mOriginalSetPathString == null) return; - if (mProgressBar != null) { - updateCurrentPhoto(null); - mProgressBar.hideProgress(); - } - Bundle data = new Bundle(getData()); - data.putString(AlbumPage.KEY_MEDIA_PATH, mOriginalSetPathString); - data.putString(AlbumPage.KEY_PARENT_MEDIA_PATH, - mActivity.getDataManager().getTopSetPath( - DataManager.INCLUDE_ALL)); - - // We only show cluster menu in the first AlbumPage in stack - // TODO: Enable this when running from the camera app - boolean inAlbum = mActivity.getStateManager().hasStateClass(AlbumPage.class); - data.putBoolean(AlbumPage.KEY_SHOW_CLUSTER_MENU, !inAlbum - && mAppBridge == null); - - data.putBoolean(PhotoPage.KEY_APP_BRIDGE, mAppBridge != null); - - // Account for live preview being first item - mActivity.getTransitionStore().put(KEY_RETURN_INDEX_HINT, - mAppBridge != null ? mCurrentIndex - 1 : mCurrentIndex); - - if (mHasCameraScreennailOrPlaceholder && mAppBridge != null) { - mActivity.getStateManager().startState(AlbumPage.class, data); - } else { - mActivity.getStateManager().switchState(this, AlbumPage.class, data); - } - } - } - - @Override - protected boolean onItemSelected(MenuItem item) { - if (mModel == null) return true; - refreshHidingMessage(); - MediaItem current = mModel.getMediaItem(0); - - // This is a shield for monkey when it clicks the action bar - // menu when transitioning from filmstrip to camera - if (current instanceof SnailItem) return true; - // TODO: We should check the current photo against the MediaItem - // that the menu was initially created for. We need to fix this - // after PhotoPage being refactored. - if (current == null) { - // item is not ready, ignore - return true; - } - int currentIndex = mModel.getCurrentIndex(); - Path path = current.getPath(); - - DataManager manager = mActivity.getDataManager(); - int action = item.getItemId(); - String confirmMsg = null; - switch (action) { - case android.R.id.home: { - onUpPressed(); - return true; - } - case R.id.action_slideshow: { - Bundle data = new Bundle(); - data.putString(SlideshowPage.KEY_SET_PATH, mMediaSet.getPath().toString()); - data.putString(SlideshowPage.KEY_ITEM_PATH, path.toString()); - data.putInt(SlideshowPage.KEY_PHOTO_INDEX, currentIndex); - data.putBoolean(SlideshowPage.KEY_REPEAT, true); - mActivity.getStateManager().startStateForResult( - SlideshowPage.class, REQUEST_SLIDESHOW, data); - return true; - } - case R.id.action_crop: { - Activity activity = mActivity; - Intent intent = new Intent(CropActivity.CROP_ACTION); - intent.setClass(activity, CropActivity.class); - intent.setDataAndType(manager.getContentUri(path), current.getMimeType()) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - activity.startActivityForResult(intent, PicasaSource.isPicasaImage(current) - ? REQUEST_CROP_PICASA - : REQUEST_CROP); - return true; - } - case R.id.action_trim: { - Intent intent = new Intent(mActivity, TrimVideo.class); - intent.setData(manager.getContentUri(path)); - // We need the file path to wrap this into a RandomAccessFile. - intent.putExtra(KEY_MEDIA_ITEM_PATH, current.getFilePath()); - mActivity.startActivityForResult(intent, REQUEST_TRIM); - return true; - } - case R.id.action_mute: { - MuteVideo muteVideo = new MuteVideo(current.getFilePath(), - manager.getContentUri(path), mActivity); - muteVideo.muteInBackground(); - return true; - } - case R.id.action_edit: { - launchPhotoEditor(); - return true; - } - case R.id.action_simple_edit: { - launchSimpleEditor(); - return true; - } - case R.id.action_details: { - if (mShowDetails) { - hideDetails(); - } else { - showDetails(); - } - return true; - } - case R.id.action_delete: - confirmMsg = mActivity.getResources().getQuantityString( - R.plurals.delete_selection, 1); - case R.id.action_setas: - case R.id.action_rotate_ccw: - case R.id.action_rotate_cw: - case R.id.action_show_on_map: - mSelectionManager.deSelectAll(); - mSelectionManager.toggle(path); - mMenuExecutor.onMenuClicked(item, confirmMsg, mConfirmDialogListener); - return true; - default : - return false; - } - } - - private void hideDetails() { - mShowDetails = false; - mDetailsHelper.hide(); - } - - private void showDetails() { - mShowDetails = true; - if (mDetailsHelper == null) { - mDetailsHelper = new DetailsHelper(mActivity, mRootPane, new MyDetailsSource()); - mDetailsHelper.setCloseListener(new CloseListener() { - @Override - public void onClose() { - hideDetails(); - } - }); - } - mDetailsHelper.show(); - } - - //////////////////////////////////////////////////////////////////////////// - // Callbacks from PhotoView - //////////////////////////////////////////////////////////////////////////// - @Override - public void onSingleTapUp(int x, int y) { - if (mAppBridge != null) { - if (mAppBridge.onSingleTapUp(x, y)) return; - } - - MediaItem item = mModel.getMediaItem(0); - if (item == null || item == mScreenNailItem) { - // item is not ready or it is camera preview, ignore - return; - } - - int supported = item.getSupportedOperations(); - boolean playVideo = ((supported & MediaItem.SUPPORT_PLAY) != 0); - boolean unlock = ((supported & MediaItem.SUPPORT_UNLOCK) != 0); - boolean goBack = ((supported & MediaItem.SUPPORT_BACK) != 0); - boolean launchCamera = ((supported & MediaItem.SUPPORT_CAMERA_SHORTCUT) != 0); - - if (playVideo) { - // determine if the point is at center (1/6) of the photo view. - // (The position of the "play" icon is at center (1/6) of the photo) - int w = mPhotoView.getWidth(); - int h = mPhotoView.getHeight(); - playVideo = (Math.abs(x - w / 2) * 12 <= w) - && (Math.abs(y - h / 2) * 12 <= h); - } - - if (playVideo) { - if (mSecureAlbum == null) { - playVideo(mActivity, item.getPlayUri(), item.getName()); - } else { - mActivity.getStateManager().finishState(this); - } - } else if (goBack) { - onBackPressed(); - } else if (unlock) { - Intent intent = new Intent(mActivity, Gallery.class); - intent.putExtra(Gallery.KEY_DISMISS_KEYGUARD, true); - mActivity.startActivity(intent); - } else if (launchCamera) { - launchCamera(); - } else { - toggleBars(); - } - } - - @Override - public void onActionBarAllowed(boolean allowed) { - mActionBarAllowed = allowed; - mHandler.sendEmptyMessage(MSG_UPDATE_ACTION_BAR); - } - - @Override - public void onActionBarWanted() { - mHandler.sendEmptyMessage(MSG_WANT_BARS); - } - - @Override - public void onFullScreenChanged(boolean full) { - Message m = mHandler.obtainMessage( - MSG_ON_FULL_SCREEN_CHANGED, full ? 1 : 0, 0); - m.sendToTarget(); - } - - // How we do delete/undo: - // - // When the user choose to delete a media item, we just tell the - // FilterDeleteSet to hide that item. If the user choose to undo it, we - // again tell FilterDeleteSet not to hide it. If the user choose to commit - // the deletion, we then actually delete the media item. - @Override - public void onDeleteImage(Path path, int offset) { - onCommitDeleteImage(); // commit the previous deletion - mDeletePath = path; - mDeleteIsFocus = (offset == 0); - mMediaSet.addDeletion(path, mCurrentIndex + offset); - } - - @Override - public void onUndoDeleteImage() { - if (mDeletePath == null) return; - // If the deletion was done on the focused item, we want the model to - // focus on it when it is undeleted. - if (mDeleteIsFocus) mModel.setFocusHintPath(mDeletePath); - mMediaSet.removeDeletion(mDeletePath); - mDeletePath = null; - } - - @Override - public void onCommitDeleteImage() { - if (mDeletePath == null) return; - mMenuExecutor.startSingleItemAction(R.id.action_delete, mDeletePath); - mDeletePath = null; - } - - public void playVideo(Activity activity, Uri uri, String title) { - try { - Intent intent = new Intent(Intent.ACTION_VIEW) - .setDataAndType(uri, "video/*") - .putExtra(Intent.EXTRA_TITLE, title) - .putExtra(MovieActivity.KEY_TREAT_UP_AS_BACK, true); - activity.startActivityForResult(intent, REQUEST_PLAY_VIDEO); - } catch (ActivityNotFoundException e) { - Toast.makeText(activity, activity.getString(R.string.video_err), - Toast.LENGTH_SHORT).show(); - } - } - - private void setCurrentPhotoByIntent(Intent intent) { - if (intent == null) return; - Path path = mApplication.getDataManager() - .findPathByUri(intent.getData(), intent.getType()); - if (path != null) { - Path albumPath = mApplication.getDataManager().getDefaultSetOf(path); - if (!albumPath.equalsIgnoreCase(mOriginalSetPathString)) { - // If the edited image is stored in a different album, we need - // to start a new activity state to show the new image - Bundle data = new Bundle(getData()); - data.putString(KEY_MEDIA_SET_PATH, albumPath.toString()); - data.putString(PhotoPage.KEY_MEDIA_ITEM_PATH, path.toString()); - mActivity.getStateManager().startState(SinglePhotoPage.class, data); - return; - } - mModel.setCurrentPhoto(path, mCurrentIndex); - } - } - - @Override - protected void onStateResult(int requestCode, int resultCode, Intent data) { - if (resultCode == Activity.RESULT_CANCELED) { - // This is a reset, not a canceled - return; - } - if (resultCode == ProxyLauncher.RESULT_USER_CANCELED) { - // Unmap reset vs. canceled - resultCode = Activity.RESULT_CANCELED; - } - mRecenterCameraOnResume = false; - switch (requestCode) { - case REQUEST_EDIT: - setCurrentPhotoByIntent(data); - break; - case REQUEST_CROP: - if (resultCode == Activity.RESULT_OK) { - setCurrentPhotoByIntent(data); - } - break; - case REQUEST_CROP_PICASA: { - if (resultCode == Activity.RESULT_OK) { - Context context = mActivity.getAndroidContext(); - String message = context.getString(R.string.crop_saved, - context.getString(R.string.folder_edited_online_photos)); - Toast.makeText(context, message, Toast.LENGTH_SHORT).show(); - } - break; - } - case REQUEST_SLIDESHOW: { - if (data == null) break; - String path = data.getStringExtra(SlideshowPage.KEY_ITEM_PATH); - int index = data.getIntExtra(SlideshowPage.KEY_PHOTO_INDEX, 0); - if (path != null) { - mModel.setCurrentPhoto(Path.fromString(path), index); - } - } - } - } - - @Override - public void onPause() { - super.onPause(); - mIsActive = false; - - mActivity.getGLRoot().unfreeze(); - mHandler.removeMessages(MSG_UNFREEZE_GLROOT); - - DetailsHelper.pause(); - // Hide the detail dialog on exit - if (mShowDetails) hideDetails(); - if (mModel != null) { - mModel.pause(); - } - mPhotoView.pause(); - mHandler.removeMessages(MSG_HIDE_BARS); - mHandler.removeMessages(MSG_REFRESH_BOTTOM_CONTROLS); - refreshBottomControlsWhenReady(); - mActionBar.removeOnMenuVisibilityListener(mMenuVisibilityListener); - if (mShowSpinner) { - mActionBar.disableAlbumModeMenu(true); - } - onCommitDeleteImage(); - mMenuExecutor.pause(); - if (mMediaSet != null) mMediaSet.clearDeletion(); - } - - @Override - public void onCurrentImageUpdated() { - mActivity.getGLRoot().unfreeze(); - } - - @Override - public void onFilmModeChanged(boolean enabled) { - refreshBottomControlsWhenReady(); - if (mShowSpinner) { - if (enabled) { - mActionBar.enableAlbumModeMenu( - GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this); - } else { - mActionBar.disableAlbumModeMenu(true); - } - } - if (enabled) { - mHandler.removeMessages(MSG_HIDE_BARS); - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_GALLERY, "FilmstripPage"); - } else { - refreshHidingMessage(); - if (mAppBridge == null || mCurrentIndex > 0) { - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_GALLERY, "SinglePhotoPage"); - } else { - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_CAMERA, "Unknown"); // TODO - } - } - } - - private void transitionFromAlbumPageIfNeeded() { - TransitionStore transitions = mActivity.getTransitionStore(); - - int albumPageTransition = transitions.get( - KEY_ALBUMPAGE_TRANSITION, MSG_ALBUMPAGE_NONE); - - if (albumPageTransition == MSG_ALBUMPAGE_NONE && mAppBridge != null - && mRecenterCameraOnResume) { - // Generally, resuming the PhotoPage when in Camera should - // reset to the capture mode to allow quick photo taking - mCurrentIndex = 0; - mPhotoView.resetToFirstPicture(); - } else { - int resumeIndex = transitions.get(KEY_INDEX_HINT, -1); - if (resumeIndex >= 0) { - if (mHasCameraScreennailOrPlaceholder) { - // Account for preview/placeholder being the first item - resumeIndex++; - } - if (resumeIndex < mMediaSet.getMediaItemCount()) { - mCurrentIndex = resumeIndex; - mModel.moveTo(mCurrentIndex); - } - } - } - - if (albumPageTransition == MSG_ALBUMPAGE_RESUMED) { - mPhotoView.setFilmMode(mStartInFilmstrip || mAppBridge != null); - } else if (albumPageTransition == MSG_ALBUMPAGE_PICKED) { - mPhotoView.setFilmMode(false); - } - } - - @Override - protected void onResume() { - super.onResume(); - - if (mModel == null) { - mActivity.getStateManager().finishState(this); - return; - } - transitionFromAlbumPageIfNeeded(); - - mActivity.getGLRoot().freeze(); - mIsActive = true; - setContentPane(mRootPane); - - mModel.resume(); - mPhotoView.resume(); - mActionBar.setDisplayOptions( - ((mSecureAlbum == null) && (mSetPathString != null)), false); - mActionBar.addOnMenuVisibilityListener(mMenuVisibilityListener); - refreshBottomControlsWhenReady(); - if (mShowSpinner && mPhotoView.getFilmMode()) { - mActionBar.enableAlbumModeMenu( - GalleryActionBar.ALBUM_FILMSTRIP_MODE_SELECTED, this); - } - if (!mShowBars) { - mActionBar.hide(); - mActivity.getGLRoot().setLightsOutMode(true); - } - boolean haveImageEditor = GalleryUtils.isEditorAvailable(mActivity, "image/*"); - if (haveImageEditor != mHaveImageEditor) { - mHaveImageEditor = haveImageEditor; - updateMenuOperations(); - } - - mRecenterCameraOnResume = true; - mHandler.sendEmptyMessageDelayed(MSG_UNFREEZE_GLROOT, UNFREEZE_GLROOT_TIMEOUT); - } - - @Override - protected void onDestroy() { - if (mAppBridge != null) { - mAppBridge.setServer(null); - mScreenNailItem.setScreenNail(null); - mAppBridge.detachScreenNail(); - mAppBridge = null; - mScreenNailSet = null; - mScreenNailItem = null; - } - mActivity.getGLRoot().setOrientationSource(null); - if (mBottomControls != null) mBottomControls.cleanup(); - - // Remove all pending messages. - mHandler.removeCallbacksAndMessages(null); - super.onDestroy(); - } - - private class MyDetailsSource implements DetailsSource { - - @Override - public MediaDetails getDetails() { - return mModel.getMediaItem(0).getDetails(); - } - - @Override - public int size() { - return mMediaSet != null ? mMediaSet.getMediaItemCount() : 1; - } - - @Override - public int setIndex() { - return mModel.getCurrentIndex(); - } - } - - @Override - public void onAlbumModeSelected(int mode) { - if (mode == GalleryActionBar.ALBUM_GRID_MODE_SELECTED) { - switchToGrid(); - } - } - - @Override - public void refreshBottomControlsWhenReady() { - if (mBottomControls == null) { - return; - } - MediaObject currentPhoto = mCurrentPhoto; - if (currentPhoto == null) { - mHandler.obtainMessage(MSG_REFRESH_BOTTOM_CONTROLS, 0, 0, currentPhoto).sendToTarget(); - } else { - currentPhoto.getPanoramaSupport(mRefreshBottomControlsCallback); - } - } - - private void updatePanoramaUI(boolean isPanorama360) { - Menu menu = mActionBar.getMenu(); - - // it could be null if onCreateActionBar has not been called yet - if (menu == null) { - return; - } - - MenuExecutor.updateMenuForPanorama(menu, isPanorama360, isPanorama360); - - if (isPanorama360) { - MenuItem item = menu.findItem(R.id.action_share); - if (item != null) { - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - item.setTitle(mActivity.getResources().getString(R.string.share_as_photo)); - } - } else if ((mCurrentPhoto.getSupportedOperations() & MediaObject.SUPPORT_SHARE) != 0) { - MenuItem item = menu.findItem(R.id.action_share); - if (item != null) { - item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - item.setTitle(mActivity.getResources().getString(R.string.share)); - } - } - } - - @Override - public void onUndoBarVisibilityChanged(boolean visible) { - refreshBottomControlsWhenReady(); - } - - @Override - public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) { - final long timestampMillis = mCurrentPhoto.getDateInMs(); - final String mediaType = getMediaTypeString(mCurrentPhoto); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_GALLERY, - UsageStatistics.ACTION_SHARE, - mediaType, - timestampMillis > 0 - ? System.currentTimeMillis() - timestampMillis - : -1); - return false; - } - - private static String getMediaTypeString(MediaItem item) { - if (item.getMediaType() == MediaObject.MEDIA_TYPE_VIDEO) { - return "Video"; - } else if (item.getMediaType() == MediaObject.MEDIA_TYPE_IMAGE) { - return "Photo"; - } else { - return "Unknown:" + item.getMediaType(); - } - } - -} diff --git a/src/com/android/gallery3d/app/PhotoPageBottomControls.java b/src/com/android/gallery3d/app/PhotoPageBottomControls.java deleted file mode 100644 index 24b8ceb7e..000000000 --- a/src/com/android/gallery3d/app/PhotoPageBottomControls.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.view.animation.AlphaAnimation; -import android.view.animation.Animation; -import android.widget.RelativeLayout; - -import com.android.gallery3d.R; - -import java.util.HashMap; -import java.util.Map; - -public class PhotoPageBottomControls implements OnClickListener { - public interface Delegate { - public boolean canDisplayBottomControls(); - public boolean canDisplayBottomControl(int control); - public void onBottomControlClicked(int control); - public void refreshBottomControlsWhenReady(); - } - - private Delegate mDelegate; - private ViewGroup mParentLayout; - private ViewGroup mContainer; - - private boolean mContainerVisible = false; - private Map<View, Boolean> mControlsVisible = new HashMap<View, Boolean>(); - - private Animation mContainerAnimIn = new AlphaAnimation(0f, 1f); - private Animation mContainerAnimOut = new AlphaAnimation(1f, 0f); - private static final int CONTAINER_ANIM_DURATION_MS = 200; - - private static final int CONTROL_ANIM_DURATION_MS = 150; - private static Animation getControlAnimForVisibility(boolean visible) { - Animation anim = visible ? new AlphaAnimation(0f, 1f) - : new AlphaAnimation(1f, 0f); - anim.setDuration(CONTROL_ANIM_DURATION_MS); - return anim; - } - - public PhotoPageBottomControls(Delegate delegate, Context context, RelativeLayout layout) { - mDelegate = delegate; - mParentLayout = layout; - - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mContainer = (ViewGroup) inflater - .inflate(R.layout.photopage_bottom_controls, mParentLayout, false); - mParentLayout.addView(mContainer); - - for (int i = mContainer.getChildCount() - 1; i >= 0; i--) { - View child = mContainer.getChildAt(i); - child.setOnClickListener(this); - mControlsVisible.put(child, false); - } - - mContainerAnimIn.setDuration(CONTAINER_ANIM_DURATION_MS); - mContainerAnimOut.setDuration(CONTAINER_ANIM_DURATION_MS); - - mDelegate.refreshBottomControlsWhenReady(); - } - - private void hide() { - mContainer.clearAnimation(); - mContainerAnimOut.reset(); - mContainer.startAnimation(mContainerAnimOut); - mContainer.setVisibility(View.INVISIBLE); - } - - private void show() { - mContainer.clearAnimation(); - mContainerAnimIn.reset(); - mContainer.startAnimation(mContainerAnimIn); - mContainer.setVisibility(View.VISIBLE); - } - - public void refresh() { - boolean visible = mDelegate.canDisplayBottomControls(); - boolean containerVisibilityChanged = (visible != mContainerVisible); - if (containerVisibilityChanged) { - if (visible) { - show(); - } else { - hide(); - } - mContainerVisible = visible; - } - if (!mContainerVisible) { - return; - } - for (View control : mControlsVisible.keySet()) { - Boolean prevVisibility = mControlsVisible.get(control); - boolean curVisibility = mDelegate.canDisplayBottomControl(control.getId()); - if (prevVisibility.booleanValue() != curVisibility) { - if (!containerVisibilityChanged) { - control.clearAnimation(); - control.startAnimation(getControlAnimForVisibility(curVisibility)); - } - control.setVisibility(curVisibility ? View.VISIBLE : View.INVISIBLE); - mControlsVisible.put(control, curVisibility); - } - } - // Force a layout change - mContainer.requestLayout(); // Kick framework to draw the control. - } - - public void cleanup() { - mParentLayout.removeView(mContainer); - mControlsVisible.clear(); - } - - @Override - public void onClick(View view) { - if (mContainerVisible && mControlsVisible.get(view).booleanValue()) { - mDelegate.onBottomControlClicked(view.getId()); - } - } -} diff --git a/src/com/android/gallery3d/app/PhotoPageProgressBar.java b/src/com/android/gallery3d/app/PhotoPageProgressBar.java deleted file mode 100644 index 141fea698..000000000 --- a/src/com/android/gallery3d/app/PhotoPageProgressBar.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.app; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.widget.RelativeLayout; - -import com.android.gallery3d.R; - -public class PhotoPageProgressBar { - private ViewGroup mContainer; - private View mProgress; - - public PhotoPageProgressBar(Context context, RelativeLayout parentLayout) { - LayoutInflater inflater = (LayoutInflater) context - .getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mContainer = (ViewGroup) inflater.inflate(R.layout.photopage_progress_bar, parentLayout, - false); - parentLayout.addView(mContainer); - mProgress = mContainer.findViewById(R.id.photopage_progress_foreground); - } - - public void setProgress(int progressPercent) { - mContainer.setVisibility(View.VISIBLE); - LayoutParams layoutParams = mProgress.getLayoutParams(); - layoutParams.width = mContainer.getWidth() * progressPercent / 100; - mProgress.setLayoutParams(layoutParams); - } - - public void hideProgress() { - mContainer.setVisibility(View.INVISIBLE); - } -} diff --git a/src/com/android/gallery3d/app/PickerActivity.java b/src/com/android/gallery3d/app/PickerActivity.java deleted file mode 100644 index d5bb218ea..000000000 --- a/src/com/android/gallery3d/app/PickerActivity.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.os.Bundle; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.Window; - -import com.android.gallery3d.R; -import com.android.gallery3d.ui.GLRootView; - -public class PickerActivity extends AbstractGalleryActivity - implements OnClickListener { - - public static final String KEY_ALBUM_PATH = "album-path"; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - // We show the picker in two ways. One smaller screen we use a full - // screen window with an action bar. On larger screen we use a dialog. - boolean isDialog = getResources().getBoolean(R.bool.picker_is_dialog); - - if (!isDialog) { - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - } - - setContentView(R.layout.dialog_picker); - - if (isDialog) { - // In dialog mode, we don't have the action bar to show the - // "cancel" action, so we show an additional "cancel" button. - View view = findViewById(R.id.cancel); - view.setOnClickListener(this); - view.setVisibility(View.VISIBLE); - - // We need this, otherwise the view will be dimmed because it - // is "behind" the dialog. - ((GLRootView) findViewById(R.id.gl_root_view)).setZOrderOnTop(true); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.pickup, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - if (item.getItemId() == R.id.action_cancel) { - finish(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onClick(View v) { - if (v.getId() == R.id.cancel) finish(); - } -} diff --git a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java b/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java deleted file mode 100644 index 00f2fe78f..000000000 --- a/src/com/android/gallery3d/app/SinglePhotoDataAdapter.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Rect; -import android.os.Handler; -import android.os.Message; - -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.BitmapScreenNail; -import com.android.gallery3d.ui.PhotoView; -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.ui.TileImageViewAdapter; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; - -public class SinglePhotoDataAdapter extends TileImageViewAdapter - implements PhotoPage.Model { - - private static final String TAG = "SinglePhotoDataAdapter"; - private static final int SIZE_BACKUP = 1024; - private static final int MSG_UPDATE_IMAGE = 1; - - private MediaItem mItem; - private boolean mHasFullImage; - private Future<?> mTask; - private Handler mHandler; - - private PhotoView mPhotoView; - private ThreadPool mThreadPool; - private int mLoadingState = LOADING_INIT; - private BitmapScreenNail mBitmapScreenNail; - - public SinglePhotoDataAdapter( - AbstractGalleryActivity activity, PhotoView view, MediaItem item) { - mItem = Utils.checkNotNull(item); - mHasFullImage = (item.getSupportedOperations() & - MediaItem.SUPPORT_FULL_IMAGE) != 0; - mPhotoView = Utils.checkNotNull(view); - mHandler = new SynchronizedHandler(activity.getGLRoot()) { - @Override - @SuppressWarnings("unchecked") - public void handleMessage(Message message) { - Utils.assertTrue(message.what == MSG_UPDATE_IMAGE); - if (mHasFullImage) { - onDecodeLargeComplete((ImageBundle) message.obj); - } else { - onDecodeThumbComplete((Future<Bitmap>) message.obj); - } - } - }; - mThreadPool = activity.getThreadPool(); - } - - private static class ImageBundle { - public final BitmapRegionDecoder decoder; - public final Bitmap backupImage; - - public ImageBundle(BitmapRegionDecoder decoder, Bitmap backupImage) { - this.decoder = decoder; - this.backupImage = backupImage; - } - } - - private FutureListener<BitmapRegionDecoder> mLargeListener = - new FutureListener<BitmapRegionDecoder>() { - @Override - public void onFutureDone(Future<BitmapRegionDecoder> future) { - BitmapRegionDecoder decoder = future.get(); - if (decoder == null) return; - int width = decoder.getWidth(); - int height = decoder.getHeight(); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inSampleSize = BitmapUtils.computeSampleSize( - (float) SIZE_BACKUP / Math.max(width, height)); - Bitmap bitmap = decoder.decodeRegion(new Rect(0, 0, width, height), options); - mHandler.sendMessage(mHandler.obtainMessage( - MSG_UPDATE_IMAGE, new ImageBundle(decoder, bitmap))); - } - }; - - private FutureListener<Bitmap> mThumbListener = - new FutureListener<Bitmap>() { - @Override - public void onFutureDone(Future<Bitmap> future) { - mHandler.sendMessage( - mHandler.obtainMessage(MSG_UPDATE_IMAGE, future)); - } - }; - - @Override - public boolean isEmpty() { - return false; - } - - private void setScreenNail(Bitmap bitmap, int width, int height) { - mBitmapScreenNail = new BitmapScreenNail(bitmap); - setScreenNail(mBitmapScreenNail, width, height); - } - - private void onDecodeLargeComplete(ImageBundle bundle) { - try { - setScreenNail(bundle.backupImage, - bundle.decoder.getWidth(), bundle.decoder.getHeight()); - setRegionDecoder(bundle.decoder); - mPhotoView.notifyImageChange(0); - } catch (Throwable t) { - Log.w(TAG, "fail to decode large", t); - } - } - - private void onDecodeThumbComplete(Future<Bitmap> future) { - try { - Bitmap backup = future.get(); - if (backup == null) { - mLoadingState = LOADING_FAIL; - return; - } else { - mLoadingState = LOADING_COMPLETE; - } - setScreenNail(backup, backup.getWidth(), backup.getHeight()); - mPhotoView.notifyImageChange(0); - } catch (Throwable t) { - Log.w(TAG, "fail to decode thumb", t); - } - } - - @Override - public void resume() { - if (mTask == null) { - if (mHasFullImage) { - mTask = mThreadPool.submit( - mItem.requestLargeImage(), mLargeListener); - } else { - mTask = mThreadPool.submit( - mItem.requestImage(MediaItem.TYPE_THUMBNAIL), - mThumbListener); - } - } - } - - @Override - public void pause() { - Future<?> task = mTask; - task.cancel(); - task.waitDone(); - if (task.get() == null) { - mTask = null; - } - if (mBitmapScreenNail != null) { - mBitmapScreenNail.recycle(); - mBitmapScreenNail = null; - } - } - - @Override - public void moveTo(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public void getImageSize(int offset, PhotoView.Size size) { - if (offset == 0) { - size.width = mItem.getWidth(); - size.height = mItem.getHeight(); - } else { - size.width = 0; - size.height = 0; - } - } - - @Override - public int getImageRotation(int offset) { - return (offset == 0) ? mItem.getFullImageRotation() : 0; - } - - @Override - public ScreenNail getScreenNail(int offset) { - return (offset == 0) ? getScreenNail() : null; - } - - @Override - public void setNeedFullImage(boolean enabled) { - // currently not necessary. - } - - @Override - public boolean isCamera(int offset) { - return false; - } - - @Override - public boolean isPanorama(int offset) { - return false; - } - - @Override - public boolean isStaticCamera(int offset) { - return false; - } - - @Override - public boolean isVideo(int offset) { - return mItem.getMediaType() == MediaItem.MEDIA_TYPE_VIDEO; - } - - @Override - public boolean isDeletable(int offset) { - return (mItem.getSupportedOperations() & MediaItem.SUPPORT_DELETE) != 0; - } - - @Override - public MediaItem getMediaItem(int offset) { - return offset == 0 ? mItem : null; - } - - @Override - public int getCurrentIndex() { - return 0; - } - - @Override - public void setCurrentPhoto(Path path, int indexHint) { - // ignore - } - - @Override - public void setFocusHintDirection(int direction) { - // ignore - } - - @Override - public void setFocusHintPath(Path path) { - // ignore - } - - @Override - public int getLoadingState(int offset) { - return mLoadingState; - } -} diff --git a/src/com/android/gallery3d/app/SinglePhotoPage.java b/src/com/android/gallery3d/app/SinglePhotoPage.java deleted file mode 100644 index beb87d358..000000000 --- a/src/com/android/gallery3d/app/SinglePhotoPage.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -public class SinglePhotoPage extends PhotoPage { - -} diff --git a/src/com/android/gallery3d/app/SlideshowDataAdapter.java b/src/com/android/gallery3d/app/SlideshowDataAdapter.java deleted file mode 100644 index 7a0fba5fb..000000000 --- a/src/com/android/gallery3d/app/SlideshowDataAdapter.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.graphics.Bitmap; - -import com.android.gallery3d.app.SlideshowPage.Slide; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.LinkedList; -import java.util.concurrent.atomic.AtomicBoolean; - -public class SlideshowDataAdapter implements SlideshowPage.Model { - @SuppressWarnings("unused") - private static final String TAG = "SlideshowDataAdapter"; - - private static final int IMAGE_QUEUE_CAPACITY = 3; - - public interface SlideshowSource { - public void addContentListener(ContentListener listener); - public void removeContentListener(ContentListener listener); - public long reload(); - public MediaItem getMediaItem(int index); - public int findItemIndex(Path path, int hint); - } - - private final SlideshowSource mSource; - - private int mLoadIndex = 0; - private int mNextOutput = 0; - private boolean mIsActive = false; - private boolean mNeedReset; - private boolean mDataReady; - private Path mInitialPath; - - private final LinkedList<Slide> mImageQueue = new LinkedList<Slide>(); - - private Future<Void> mReloadTask; - private final ThreadPool mThreadPool; - - private long mDataVersion = MediaObject.INVALID_DATA_VERSION; - private final AtomicBoolean mNeedReload = new AtomicBoolean(false); - private final SourceListener mSourceListener = new SourceListener(); - - // The index is just a hint if initialPath is set - public SlideshowDataAdapter(GalleryContext context, SlideshowSource source, int index, - Path initialPath) { - mSource = source; - mInitialPath = initialPath; - mLoadIndex = index; - mNextOutput = index; - mThreadPool = context.getThreadPool(); - } - - private MediaItem loadItem() { - if (mNeedReload.compareAndSet(true, false)) { - long v = mSource.reload(); - if (v != mDataVersion) { - mDataVersion = v; - mNeedReset = true; - return null; - } - } - int index = mLoadIndex; - if (mInitialPath != null) { - index = mSource.findItemIndex(mInitialPath, index); - mInitialPath = null; - } - return mSource.getMediaItem(index); - } - - private class ReloadTask implements Job<Void> { - @Override - public Void run(JobContext jc) { - while (true) { - synchronized (SlideshowDataAdapter.this) { - while (mIsActive && (!mDataReady - || mImageQueue.size() >= IMAGE_QUEUE_CAPACITY)) { - try { - SlideshowDataAdapter.this.wait(); - } catch (InterruptedException ex) { - // ignored. - } - continue; - } - } - if (!mIsActive) return null; - mNeedReset = false; - - MediaItem item = loadItem(); - - if (mNeedReset) { - synchronized (SlideshowDataAdapter.this) { - mImageQueue.clear(); - mLoadIndex = mNextOutput; - } - continue; - } - - if (item == null) { - synchronized (SlideshowDataAdapter.this) { - if (!mNeedReload.get()) mDataReady = false; - SlideshowDataAdapter.this.notifyAll(); - } - continue; - } - - Bitmap bitmap = item - .requestImage(MediaItem.TYPE_THUMBNAIL) - .run(jc); - - if (bitmap != null) { - synchronized (SlideshowDataAdapter.this) { - mImageQueue.addLast( - new Slide(item, mLoadIndex, bitmap)); - if (mImageQueue.size() == 1) { - SlideshowDataAdapter.this.notifyAll(); - } - } - } - ++mLoadIndex; - } - } - } - - private class SourceListener implements ContentListener { - @Override - public void onContentDirty() { - synchronized (SlideshowDataAdapter.this) { - mNeedReload.set(true); - mDataReady = true; - SlideshowDataAdapter.this.notifyAll(); - } - } - } - - private synchronized Slide innerNextBitmap() { - while (mIsActive && mDataReady && mImageQueue.isEmpty()) { - try { - wait(); - } catch (InterruptedException t) { - throw new AssertionError(); - } - } - if (mImageQueue.isEmpty()) return null; - mNextOutput++; - this.notifyAll(); - return mImageQueue.removeFirst(); - } - - @Override - public Future<Slide> nextSlide(FutureListener<Slide> listener) { - return mThreadPool.submit(new Job<Slide>() { - @Override - public Slide run(JobContext jc) { - jc.setMode(ThreadPool.MODE_NONE); - return innerNextBitmap(); - } - }, listener); - } - - @Override - public void pause() { - synchronized (this) { - mIsActive = false; - notifyAll(); - } - mSource.removeContentListener(mSourceListener); - mReloadTask.cancel(); - mReloadTask.waitDone(); - mReloadTask = null; - } - - @Override - public synchronized void resume() { - mIsActive = true; - mSource.addContentListener(mSourceListener); - mNeedReload.set(true); - mDataReady = true; - mReloadTask = mThreadPool.submit(new ReloadTask()); - } -} diff --git a/src/com/android/gallery3d/app/SlideshowPage.java b/src/com/android/gallery3d/app/SlideshowPage.java deleted file mode 100644 index 174058dc8..000000000 --- a/src/com/android/gallery3d/app/SlideshowPage.java +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.content.Intent; -import android.graphics.Bitmap; -import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.view.MotionEvent; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.ui.GLView; -import com.android.gallery3d.ui.SlideshowView; -import com.android.gallery3d.ui.SynchronizedHandler; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; - -import java.util.ArrayList; -import java.util.Random; - -public class SlideshowPage extends ActivityState { - private static final String TAG = "SlideshowPage"; - - public static final String KEY_SET_PATH = "media-set-path"; - public static final String KEY_ITEM_PATH = "media-item-path"; - public static final String KEY_PHOTO_INDEX = "photo-index"; - public static final String KEY_RANDOM_ORDER = "random-order"; - public static final String KEY_REPEAT = "repeat"; - public static final String KEY_DREAM = "dream"; - - private static final long SLIDESHOW_DELAY = 3000; // 3 seconds - - private static final int MSG_LOAD_NEXT_BITMAP = 1; - private static final int MSG_SHOW_PENDING_BITMAP = 2; - - public static interface Model { - public void pause(); - - public void resume(); - - public Future<Slide> nextSlide(FutureListener<Slide> listener); - } - - public static class Slide { - public Bitmap bitmap; - public MediaItem item; - public int index; - - public Slide(MediaItem item, int index, Bitmap bitmap) { - this.bitmap = bitmap; - this.item = item; - this.index = index; - } - } - - private Handler mHandler; - private Model mModel; - private SlideshowView mSlideshowView; - - private Slide mPendingSlide = null; - private boolean mIsActive = false; - private final Intent mResultIntent = new Intent(); - - @Override - protected int getBackgroundColorId() { - return R.color.slideshow_background; - } - - private final GLView mRootPane = new GLView() { - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - mSlideshowView.layout(0, 0, right - left, bottom - top); - } - - @Override - protected boolean onTouch(MotionEvent event) { - if (event.getAction() == MotionEvent.ACTION_UP) { - onBackPressed(); - } - return true; - } - - @Override - protected void renderBackground(GLCanvas canvas) { - canvas.clearBuffer(getBackgroundColor()); - } - }; - - @Override - public void onCreate(Bundle data, Bundle restoreState) { - super.onCreate(data, restoreState); - mFlags |= (FLAG_HIDE_ACTION_BAR | FLAG_HIDE_STATUS_BAR); - if (data.getBoolean(KEY_DREAM)) { - // Dream screensaver only keeps screen on for plugged devices. - mFlags |= FLAG_SCREEN_ON_WHEN_PLUGGED | FLAG_SHOW_WHEN_LOCKED; - } else { - // User-initiated slideshow would always keep screen on. - mFlags |= FLAG_SCREEN_ON_ALWAYS; - } - - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_SHOW_PENDING_BITMAP: - showPendingBitmap(); - break; - case MSG_LOAD_NEXT_BITMAP: - loadNextBitmap(); - break; - default: throw new AssertionError(); - } - } - }; - initializeViews(); - initializeData(data); - } - - private void loadNextBitmap() { - mModel.nextSlide(new FutureListener<Slide>() { - @Override - public void onFutureDone(Future<Slide> future) { - mPendingSlide = future.get(); - mHandler.sendEmptyMessage(MSG_SHOW_PENDING_BITMAP); - } - }); - } - - private void showPendingBitmap() { - // mPendingBitmap could be null, if - // 1.) there is no more items - // 2.) mModel is paused - Slide slide = mPendingSlide; - if (slide == null) { - if (mIsActive) { - mActivity.getStateManager().finishState(SlideshowPage.this); - } - return; - } - - mSlideshowView.next(slide.bitmap, slide.item.getRotation()); - - setStateResult(Activity.RESULT_OK, mResultIntent - .putExtra(KEY_ITEM_PATH, slide.item.getPath().toString()) - .putExtra(KEY_PHOTO_INDEX, slide.index)); - mHandler.sendEmptyMessageDelayed(MSG_LOAD_NEXT_BITMAP, SLIDESHOW_DELAY); - } - - @Override - public void onPause() { - super.onPause(); - mIsActive = false; - mModel.pause(); - mSlideshowView.release(); - - mHandler.removeMessages(MSG_LOAD_NEXT_BITMAP); - mHandler.removeMessages(MSG_SHOW_PENDING_BITMAP); - } - - @Override - public void onResume() { - super.onResume(); - mIsActive = true; - mModel.resume(); - - if (mPendingSlide != null) { - showPendingBitmap(); - } else { - loadNextBitmap(); - } - } - - private void initializeData(Bundle data) { - boolean random = data.getBoolean(KEY_RANDOM_ORDER, false); - - // We only want to show slideshow for images only, not videos. - String mediaPath = data.getString(KEY_SET_PATH); - mediaPath = FilterUtils.newFilterPath(mediaPath, FilterUtils.FILTER_IMAGE_ONLY); - MediaSet mediaSet = mActivity.getDataManager().getMediaSet(mediaPath); - - if (random) { - boolean repeat = data.getBoolean(KEY_REPEAT); - mModel = new SlideshowDataAdapter(mActivity, - new ShuffleSource(mediaSet, repeat), 0, null); - setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, 0)); - } else { - int index = data.getInt(KEY_PHOTO_INDEX); - String itemPath = data.getString(KEY_ITEM_PATH); - Path path = itemPath != null ? Path.fromString(itemPath) : null; - boolean repeat = data.getBoolean(KEY_REPEAT); - mModel = new SlideshowDataAdapter(mActivity, new SequentialSource(mediaSet, repeat), - index, path); - setStateResult(Activity.RESULT_OK, mResultIntent.putExtra(KEY_PHOTO_INDEX, index)); - } - } - - private void initializeViews() { - mSlideshowView = new SlideshowView(); - mRootPane.addComponent(mSlideshowView); - setContentPane(mRootPane); - } - - private static MediaItem findMediaItem(MediaSet mediaSet, int index) { - for (int i = 0, n = mediaSet.getSubMediaSetCount(); i < n; ++i) { - MediaSet subset = mediaSet.getSubMediaSet(i); - int count = subset.getTotalMediaItemCount(); - if (index < count) { - return findMediaItem(subset, index); - } - index -= count; - } - ArrayList<MediaItem> list = mediaSet.getMediaItem(index, 1); - return list.isEmpty() ? null : list.get(0); - } - - private static class ShuffleSource implements SlideshowDataAdapter.SlideshowSource { - private static final int RETRY_COUNT = 5; - private final MediaSet mMediaSet; - private final Random mRandom = new Random(); - private int mOrder[] = new int[0]; - private final boolean mRepeat; - private long mSourceVersion = MediaSet.INVALID_DATA_VERSION; - private int mLastIndex = -1; - - public ShuffleSource(MediaSet mediaSet, boolean repeat) { - mMediaSet = Utils.checkNotNull(mediaSet); - mRepeat = repeat; - } - - @Override - public int findItemIndex(Path path, int hint) { - return hint; - } - - @Override - public MediaItem getMediaItem(int index) { - if (!mRepeat && index >= mOrder.length) return null; - if (mOrder.length == 0) return null; - mLastIndex = mOrder[index % mOrder.length]; - MediaItem item = findMediaItem(mMediaSet, mLastIndex); - for (int i = 0; i < RETRY_COUNT && item == null; ++i) { - Log.w(TAG, "fail to find image: " + mLastIndex); - mLastIndex = mRandom.nextInt(mOrder.length); - item = findMediaItem(mMediaSet, mLastIndex); - } - return item; - } - - @Override - public long reload() { - long version = mMediaSet.reload(); - if (version != mSourceVersion) { - mSourceVersion = version; - int count = mMediaSet.getTotalMediaItemCount(); - if (count != mOrder.length) generateOrderArray(count); - } - return version; - } - - private void generateOrderArray(int totalCount) { - if (mOrder.length != totalCount) { - mOrder = new int[totalCount]; - for (int i = 0; i < totalCount; ++i) { - mOrder[i] = i; - } - } - for (int i = totalCount - 1; i > 0; --i) { - Utils.swap(mOrder, i, mRandom.nextInt(i + 1)); - } - if (mOrder[0] == mLastIndex && totalCount > 1) { - Utils.swap(mOrder, 0, mRandom.nextInt(totalCount - 1) + 1); - } - } - - @Override - public void addContentListener(ContentListener listener) { - mMediaSet.addContentListener(listener); - } - - @Override - public void removeContentListener(ContentListener listener) { - mMediaSet.removeContentListener(listener); - } - } - - private static class SequentialSource implements SlideshowDataAdapter.SlideshowSource { - private static final int DATA_SIZE = 32; - - private ArrayList<MediaItem> mData = new ArrayList<MediaItem>(); - private int mDataStart = 0; - private long mDataVersion = MediaObject.INVALID_DATA_VERSION; - private final MediaSet mMediaSet; - private final boolean mRepeat; - - public SequentialSource(MediaSet mediaSet, boolean repeat) { - mMediaSet = mediaSet; - mRepeat = repeat; - } - - @Override - public int findItemIndex(Path path, int hint) { - return mMediaSet.getIndexOfItem(path, hint); - } - - @Override - public MediaItem getMediaItem(int index) { - int dataEnd = mDataStart + mData.size(); - - if (mRepeat) { - int count = mMediaSet.getMediaItemCount(); - if (count == 0) return null; - index = index % count; - } - if (index < mDataStart || index >= dataEnd) { - mData = mMediaSet.getMediaItem(index, DATA_SIZE); - mDataStart = index; - dataEnd = index + mData.size(); - } - - return (index < mDataStart || index >= dataEnd) ? null : mData.get(index - mDataStart); - } - - @Override - public long reload() { - long version = mMediaSet.reload(); - if (version != mDataVersion) { - mDataVersion = version; - mData.clear(); - } - return mDataVersion; - } - - @Override - public void addContentListener(ContentListener listener) { - mMediaSet.addContentListener(listener); - } - - @Override - public void removeContentListener(ContentListener listener) { - mMediaSet.removeContentListener(listener); - } - } -} diff --git a/src/com/android/gallery3d/app/StateManager.java b/src/com/android/gallery3d/app/StateManager.java deleted file mode 100644 index 53c3fc228..000000000 --- a/src/com/android/gallery3d/app/StateManager.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.Activity; -import android.content.Intent; -import android.content.res.Configuration; -import android.os.Bundle; -import android.os.Parcelable; -import android.view.Menu; -import android.view.MenuItem; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.anim.StateTransitionAnimation; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.UsageStatistics; - -import java.util.Stack; - -public class StateManager { - @SuppressWarnings("unused") - private static final String TAG = "StateManager"; - private boolean mIsResumed = false; - - private static final String KEY_MAIN = "activity-state"; - private static final String KEY_DATA = "data"; - private static final String KEY_STATE = "bundle"; - private static final String KEY_CLASS = "class"; - - private AbstractGalleryActivity mActivity; - private Stack<StateEntry> mStack = new Stack<StateEntry>(); - private ActivityState.ResultEntry mResult; - - public StateManager(AbstractGalleryActivity activity) { - mActivity = activity; - } - - public void startState(Class<? extends ActivityState> klass, - Bundle data) { - Log.v(TAG, "startState " + klass); - ActivityState state = null; - try { - state = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - if (!mStack.isEmpty()) { - ActivityState top = getTopState(); - top.transitionOnNextPause(top.getClass(), klass, - StateTransitionAnimation.Transition.Incoming); - if (mIsResumed) top.onPause(); - } - - UsageStatistics.onContentViewChanged( - UsageStatistics.COMPONENT_GALLERY, - klass.getSimpleName()); - state.initialize(mActivity, data); - - mStack.push(new StateEntry(data, state)); - state.onCreate(data, null); - if (mIsResumed) state.resume(); - } - - public void startStateForResult(Class<? extends ActivityState> klass, - int requestCode, Bundle data) { - Log.v(TAG, "startStateForResult " + klass + ", " + requestCode); - ActivityState state = null; - try { - state = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - state.initialize(mActivity, data); - state.mResult = new ActivityState.ResultEntry(); - state.mResult.requestCode = requestCode; - - if (!mStack.isEmpty()) { - ActivityState as = getTopState(); - as.transitionOnNextPause(as.getClass(), klass, - StateTransitionAnimation.Transition.Incoming); - as.mReceivedResults = state.mResult; - if (mIsResumed) as.onPause(); - } else { - mResult = state.mResult; - } - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - klass.getSimpleName()); - mStack.push(new StateEntry(data, state)); - state.onCreate(data, null); - if (mIsResumed) state.resume(); - } - - public boolean createOptionsMenu(Menu menu) { - if (mStack.isEmpty()) { - return false; - } else { - return getTopState().onCreateActionBar(menu); - } - } - - public void onConfigurationChange(Configuration config) { - for (StateEntry entry : mStack) { - entry.activityState.onConfigurationChanged(config); - } - } - - public void resume() { - if (mIsResumed) return; - mIsResumed = true; - if (!mStack.isEmpty()) getTopState().resume(); - } - - public void pause() { - if (!mIsResumed) return; - mIsResumed = false; - if (!mStack.isEmpty()) getTopState().onPause(); - } - - public void notifyActivityResult(int requestCode, int resultCode, Intent data) { - getTopState().onStateResult(requestCode, resultCode, data); - } - - public void clearActivityResult() { - if (!mStack.isEmpty()) { - getTopState().clearStateResult(); - } - } - - public int getStateCount() { - return mStack.size(); - } - - public boolean itemSelected(MenuItem item) { - if (!mStack.isEmpty()) { - if (getTopState().onItemSelected(item)) return true; - if (item.getItemId() == android.R.id.home) { - if (mStack.size() > 1) { - getTopState().onBackPressed(); - } - return true; - } - } - return false; - } - - public void onBackPressed() { - if (!mStack.isEmpty()) { - getTopState().onBackPressed(); - } - } - - void finishState(ActivityState state) { - finishState(state, true); - } - - public void clearTasks() { - // Remove all the states that are on top of the bottom PhotoPage state - while (mStack.size() > 1) { - mStack.pop().activityState.onDestroy(); - } - } - - void finishState(ActivityState state, boolean fireOnPause) { - // The finish() request could be rejected (only happens under Monkey), - // If it is rejected, we won't close the last page. - if (mStack.size() == 1) { - Activity activity = (Activity) mActivity.getAndroidContext(); - if (mResult != null) { - activity.setResult(mResult.resultCode, mResult.resultData); - } - activity.finish(); - if (!activity.isFinishing()) { - Log.w(TAG, "finish is rejected, keep the last state"); - return; - } - Log.v(TAG, "no more state, finish activity"); - } - - Log.v(TAG, "finishState " + state); - if (state != mStack.peek().activityState) { - if (state.isDestroyed()) { - Log.d(TAG, "The state is already destroyed"); - return; - } else { - throw new IllegalArgumentException("The stateview to be finished" - + " is not at the top of the stack: " + state + ", " - + mStack.peek().activityState); - } - } - - // Remove the top state. - mStack.pop(); - state.mIsFinishing = true; - ActivityState top = !mStack.isEmpty() ? mStack.peek().activityState : null; - if (mIsResumed && fireOnPause) { - if (top != null) { - state.transitionOnNextPause(state.getClass(), top.getClass(), - StateTransitionAnimation.Transition.Outgoing); - } - state.onPause(); - } - mActivity.getGLRoot().setContentPane(null); - state.onDestroy(); - - if (top != null && mIsResumed) top.resume(); - if (top != null) { - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - top.getClass().getSimpleName()); - } - } - - public void switchState(ActivityState oldState, - Class<? extends ActivityState> klass, Bundle data) { - Log.v(TAG, "switchState " + oldState + ", " + klass); - if (oldState != mStack.peek().activityState) { - throw new IllegalArgumentException("The stateview to be finished" - + " is not at the top of the stack: " + oldState + ", " - + mStack.peek().activityState); - } - // Remove the top state. - mStack.pop(); - if (!data.containsKey(PhotoPage.KEY_APP_BRIDGE)) { - // Do not do the fade out stuff when we are switching camera modes - oldState.transitionOnNextPause(oldState.getClass(), klass, - StateTransitionAnimation.Transition.Incoming); - } - if (mIsResumed) oldState.onPause(); - oldState.onDestroy(); - - // Create new state. - ActivityState state = null; - try { - state = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - state.initialize(mActivity, data); - mStack.push(new StateEntry(data, state)); - state.onCreate(data, null); - if (mIsResumed) state.resume(); - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - klass.getSimpleName()); - } - - public void destroy() { - Log.v(TAG, "destroy"); - while (!mStack.isEmpty()) { - mStack.pop().activityState.onDestroy(); - } - mStack.clear(); - } - - @SuppressWarnings("unchecked") - public void restoreFromState(Bundle inState) { - Log.v(TAG, "restoreFromState"); - Parcelable list[] = inState.getParcelableArray(KEY_MAIN); - ActivityState topState = null; - for (Parcelable parcelable : list) { - Bundle bundle = (Bundle) parcelable; - Class<? extends ActivityState> klass = - (Class<? extends ActivityState>) bundle.getSerializable(KEY_CLASS); - - Bundle data = bundle.getBundle(KEY_DATA); - Bundle state = bundle.getBundle(KEY_STATE); - - ActivityState activityState; - try { - Log.v(TAG, "restoreFromState " + klass); - activityState = klass.newInstance(); - } catch (Exception e) { - throw new AssertionError(e); - } - activityState.initialize(mActivity, data); - activityState.onCreate(data, state); - mStack.push(new StateEntry(data, activityState)); - topState = activityState; - } - if (topState != null) { - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_GALLERY, - topState.getClass().getSimpleName()); - } - } - - public void saveState(Bundle outState) { - Log.v(TAG, "saveState"); - - Parcelable list[] = new Parcelable[mStack.size()]; - int i = 0; - for (StateEntry entry : mStack) { - Bundle bundle = new Bundle(); - bundle.putSerializable(KEY_CLASS, entry.activityState.getClass()); - bundle.putBundle(KEY_DATA, entry.data); - Bundle state = new Bundle(); - entry.activityState.onSaveState(state); - bundle.putBundle(KEY_STATE, state); - Log.v(TAG, "saveState " + entry.activityState.getClass()); - list[i++] = bundle; - } - outState.putParcelableArray(KEY_MAIN, list); - } - - public boolean hasStateClass(Class<? extends ActivityState> klass) { - for (StateEntry entry : mStack) { - if (klass.isInstance(entry.activityState)) { - return true; - } - } - return false; - } - - public ActivityState getTopState() { - Utils.assertTrue(!mStack.isEmpty()); - return mStack.peek().activityState; - } - - private static class StateEntry { - public Bundle data; - public ActivityState activityState; - - public StateEntry(Bundle data, ActivityState state) { - this.data = data; - this.activityState = state; - } - } -} diff --git a/src/com/android/gallery3d/app/StitchingChangeListener.java b/src/com/android/gallery3d/app/StitchingChangeListener.java deleted file mode 100644 index 0b8c2d6d6..000000000 --- a/src/com/android/gallery3d/app/StitchingChangeListener.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.net.Uri; - -public interface StitchingChangeListener { - public void onStitchingQueued(Uri uri); - - public void onStitchingResult(Uri uri); - - public void onStitchingProgress(Uri uri, int progress); -} diff --git a/src/com/android/gallery3d/app/TimeBar.java b/src/com/android/gallery3d/app/TimeBar.java deleted file mode 100644 index 246346a56..000000000 --- a/src/com/android/gallery3d/app/TimeBar.java +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; - -/** - * The time bar view, which includes the current and total time, the progress - * bar, and the scrubber. - */ -public class TimeBar extends View { - - public interface Listener { - void onScrubbingStart(); - - void onScrubbingMove(int time); - - void onScrubbingEnd(int time, int start, int end); - } - - // Padding around the scrubber to increase its touch target - private static final int SCRUBBER_PADDING_IN_DP = 10; - - // The total padding, top plus bottom - private static final int V_PADDING_IN_DP = 30; - - private static final int TEXT_SIZE_IN_DP = 14; - - protected final Listener mListener; - - // the bars we use for displaying the progress - protected final Rect mProgressBar; - protected final Rect mPlayedBar; - - protected final Paint mProgressPaint; - protected final Paint mPlayedPaint; - protected final Paint mTimeTextPaint; - - protected final Bitmap mScrubber; - protected int mScrubberPadding; // adds some touch tolerance around the - // scrubber - - protected int mScrubberLeft; - protected int mScrubberTop; - protected int mScrubberCorrection; - protected boolean mScrubbing; - protected boolean mShowTimes; - protected boolean mShowScrubber; - - protected int mTotalTime; - protected int mCurrentTime; - - protected final Rect mTimeBounds; - - protected int mVPaddingInPx; - - public TimeBar(Context context, Listener listener) { - super(context); - mListener = Utils.checkNotNull(listener); - - mShowTimes = true; - mShowScrubber = true; - - mProgressBar = new Rect(); - mPlayedBar = new Rect(); - - mProgressPaint = new Paint(); - mProgressPaint.setColor(0xFF808080); - mPlayedPaint = new Paint(); - mPlayedPaint.setColor(0xFFFFFFFF); - - DisplayMetrics metrics = context.getResources().getDisplayMetrics(); - float textSizeInPx = metrics.density * TEXT_SIZE_IN_DP; - mTimeTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); - mTimeTextPaint.setColor(0xFFCECECE); - mTimeTextPaint.setTextSize(textSizeInPx); - mTimeTextPaint.setTextAlign(Paint.Align.CENTER); - - mTimeBounds = new Rect(); - mTimeTextPaint.getTextBounds("0:00:00", 0, 7, mTimeBounds); - - mScrubber = BitmapFactory.decodeResource(getResources(), R.drawable.scrubber_knob); - mScrubberPadding = (int) (metrics.density * SCRUBBER_PADDING_IN_DP); - - mVPaddingInPx = (int) (metrics.density * V_PADDING_IN_DP); - } - - private void update() { - mPlayedBar.set(mProgressBar); - - if (mTotalTime > 0) { - mPlayedBar.right = - mPlayedBar.left + (int) ((mProgressBar.width() * (long) mCurrentTime) / mTotalTime); - } else { - mPlayedBar.right = mProgressBar.left; - } - - if (!mScrubbing) { - mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2; - } - invalidate(); - } - - /** - * @return the preferred height of this view, including invisible padding - */ - public int getPreferredHeight() { - return mTimeBounds.height() + mVPaddingInPx + mScrubberPadding; - } - - /** - * @return the height of the time bar, excluding invisible padding - */ - public int getBarHeight() { - return mTimeBounds.height() + mVPaddingInPx; - } - - public void setTime(int currentTime, int totalTime, - int trimStartTime, int trimEndTime) { - if (mCurrentTime == currentTime && mTotalTime == totalTime) { - return; - } - mCurrentTime = currentTime; - mTotalTime = totalTime; - update(); - } - - private boolean inScrubber(float x, float y) { - int scrubberRight = mScrubberLeft + mScrubber.getWidth(); - int scrubberBottom = mScrubberTop + mScrubber.getHeight(); - return mScrubberLeft - mScrubberPadding < x && x < scrubberRight + mScrubberPadding - && mScrubberTop - mScrubberPadding < y && y < scrubberBottom + mScrubberPadding; - } - - private void clampScrubber() { - int half = mScrubber.getWidth() / 2; - int max = mProgressBar.right - half; - int min = mProgressBar.left - half; - mScrubberLeft = Math.min(max, Math.max(min, mScrubberLeft)); - } - - private int getScrubberTime() { - return (int) ((long) (mScrubberLeft + mScrubber.getWidth() / 2 - mProgressBar.left) - * mTotalTime / mProgressBar.width()); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int w = r - l; - int h = b - t; - if (!mShowTimes && !mShowScrubber) { - mProgressBar.set(0, 0, w, h); - } else { - int margin = mScrubber.getWidth() / 3; - if (mShowTimes) { - margin += mTimeBounds.width(); - } - int progressY = (h + mScrubberPadding) / 2; - mScrubberTop = progressY - mScrubber.getHeight() / 2 + 1; - mProgressBar.set( - getPaddingLeft() + margin, progressY, - w - getPaddingRight() - margin, progressY + 4); - } - update(); - } - - @Override - protected void onDraw(Canvas canvas) { - // draw progress bars - canvas.drawRect(mProgressBar, mProgressPaint); - canvas.drawRect(mPlayedBar, mPlayedPaint); - - // draw scrubber and timers - if (mShowScrubber) { - canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null); - } - if (mShowTimes) { - canvas.drawText( - stringForTime(mCurrentTime), - mTimeBounds.width() / 2 + getPaddingLeft(), - mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1, - mTimeTextPaint); - canvas.drawText( - stringForTime(mTotalTime), - getWidth() - getPaddingRight() - mTimeBounds.width() / 2, - mTimeBounds.height() + mVPaddingInPx / 2 + mScrubberPadding + 1, - mTimeTextPaint); - } - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mShowScrubber) { - int x = (int) event.getX(); - int y = (int) event.getY(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: { - mScrubberCorrection = inScrubber(x, y) - ? x - mScrubberLeft - : mScrubber.getWidth() / 2; - mScrubbing = true; - mListener.onScrubbingStart(); - } - // fall-through - case MotionEvent.ACTION_MOVE: { - mScrubberLeft = x - mScrubberCorrection; - clampScrubber(); - mCurrentTime = getScrubberTime(); - mListener.onScrubbingMove(mCurrentTime); - invalidate(); - return true; - } - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: { - mListener.onScrubbingEnd(getScrubberTime(), 0, 0); - mScrubbing = false; - return true; - } - } - } - return false; - } - - protected String stringForTime(long millis) { - int totalSeconds = (int) millis / 1000; - int seconds = totalSeconds % 60; - int minutes = (totalSeconds / 60) % 60; - int hours = totalSeconds / 3600; - if (hours > 0) { - return String.format("%d:%02d:%02d", hours, minutes, seconds).toString(); - } else { - return String.format("%02d:%02d", minutes, seconds).toString(); - } - } - - public void setSeekable(boolean canSeek) { - mShowScrubber = canSeek; - } - -} diff --git a/src/com/android/gallery3d/app/TransitionStore.java b/src/com/android/gallery3d/app/TransitionStore.java deleted file mode 100644 index aa38ed77e..000000000 --- a/src/com/android/gallery3d/app/TransitionStore.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import java.util.HashMap; - -public class TransitionStore { - private HashMap<Object, Object> mStorage = new HashMap<Object, Object>(); - - public void put(Object key, Object value) { - mStorage.put(key, value); - } - - public <T> void putIfNotPresent(Object key, T valueIfNull) { - mStorage.put(key, get(key, valueIfNull)); - } - - @SuppressWarnings("unchecked") - public <T> T get(Object key) { - return (T) mStorage.get(key); - } - - @SuppressWarnings("unchecked") - public <T> T get(Object key, T valueIfNull) { - T value = (T) mStorage.get(key); - return value == null ? valueIfNull : value; - } - - public void clear() { - mStorage.clear(); - } -} diff --git a/src/com/android/gallery3d/app/TrimControllerOverlay.java b/src/com/android/gallery3d/app/TrimControllerOverlay.java deleted file mode 100644 index cae016626..000000000 --- a/src/com/android/gallery3d/app/TrimControllerOverlay.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.animation.Animator; -import android.animation.Animator.AnimatorListener; -import android.animation.ObjectAnimator; -import android.content.Context; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.common.ApiHelper; - -/** - * The controller for the Trimming Video. - */ -public class TrimControllerOverlay extends CommonControllerOverlay { - - public TrimControllerOverlay(Context context) { - super(context); - } - - @Override - protected void createTimeBar(Context context) { - mTimeBar = new TrimTimeBar(context, this); - } - - private void hidePlayButtonIfPlaying() { - if (mState == State.PLAYING) { - mPlayPauseReplayView.setVisibility(View.INVISIBLE); - } - if (ApiHelper.HAS_OBJECT_ANIMATION) { - mPlayPauseReplayView.setAlpha(1f); - } - } - - @Override - public void showPlaying() { - super.showPlaying(); - if (ApiHelper.HAS_OBJECT_ANIMATION) { - // Add animation to hide the play button while playing. - ObjectAnimator anim = ObjectAnimator.ofFloat(mPlayPauseReplayView, "alpha", 1f, 0f); - anim.setDuration(200); - anim.start(); - anim.addListener(new AnimatorListener() { - @Override - public void onAnimationStart(Animator animation) { - } - - @Override - public void onAnimationEnd(Animator animation) { - hidePlayButtonIfPlaying(); - } - - @Override - public void onAnimationCancel(Animator animation) { - hidePlayButtonIfPlaying(); - } - - @Override - public void onAnimationRepeat(Animator animation) { - } - }); - } else { - hidePlayButtonIfPlaying(); - } - } - - @Override - public void setTimes(int currentTime, int totalTime, int trimStartTime, int trimEndTime) { - mTimeBar.setTime(currentTime, totalTime, trimStartTime, trimEndTime); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (super.onTouchEvent(event)) { - return true; - } - - // The special thing here is that the State.ENDED include both cases of - // the video completed and current == trimEnd. Both request a replay. - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - if (mState == State.PLAYING || mState == State.PAUSED) { - mListener.onPlayPause(); - } else if (mState == State.ENDED) { - if (mCanReplay) { - mListener.onReplay(); - } - } - break; - case MotionEvent.ACTION_UP: - break; - } - return true; - } -} diff --git a/src/com/android/gallery3d/app/TrimTimeBar.java b/src/com/android/gallery3d/app/TrimTimeBar.java deleted file mode 100644 index f8dbc749e..000000000 --- a/src/com/android/gallery3d/app/TrimTimeBar.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.view.MotionEvent; - -import com.android.gallery3d.R; - -/** - * The trim time bar view, which includes the current and total time, the progress - * bar, and the scrubbers for current time, start and end time for trimming. - */ -public class TrimTimeBar extends TimeBar { - - public static final int SCRUBBER_NONE = 0; - public static final int SCRUBBER_START = 1; - public static final int SCRUBBER_CURRENT = 2; - public static final int SCRUBBER_END = 3; - - private int mPressedThumb = SCRUBBER_NONE; - - // On touch event, the setting order is Scrubber Position -> Time -> - // PlayedBar. At the setTimes(), activity can update the Time directly, then - // PlayedBar will be updated too. - private int mTrimStartScrubberLeft; - private int mTrimEndScrubberLeft; - - private int mTrimStartScrubberTop; - private int mTrimEndScrubberTop; - - private int mTrimStartTime; - private int mTrimEndTime; - - private final Bitmap mTrimStartScrubber; - private final Bitmap mTrimEndScrubber; - public TrimTimeBar(Context context, Listener listener) { - super(context, listener); - - mTrimStartTime = 0; - mTrimEndTime = 0; - mTrimStartScrubberLeft = 0; - mTrimEndScrubberLeft = 0; - mTrimStartScrubberTop = 0; - mTrimEndScrubberTop = 0; - - mTrimStartScrubber = BitmapFactory.decodeResource(getResources(), - R.drawable.text_select_handle_left); - mTrimEndScrubber = BitmapFactory.decodeResource(getResources(), - R.drawable.text_select_handle_right); - // Increase the size of this trimTimeBar, but minimize the scrubber - // touch padding since we have 3 scrubbers now. - mScrubberPadding = 0; - mVPaddingInPx = mVPaddingInPx * 3 / 2; - } - - private int getBarPosFromTime(int time) { - return mProgressBar.left + - (int) ((mProgressBar.width() * (long) time) / mTotalTime); - } - - private int trimStartScrubberTipOffset() { - return mTrimStartScrubber.getWidth() * 3 / 4; - } - - private int trimEndScrubberTipOffset() { - return mTrimEndScrubber.getWidth() / 4; - } - - // Based on all the time info (current, total, trimStart, trimEnd), we - // decide the playedBar size. - private void updatePlayedBarAndScrubberFromTime() { - // According to the Time, update the Played Bar - mPlayedBar.set(mProgressBar); - if (mTotalTime > 0) { - // set playedBar according to the trim time. - mPlayedBar.left = getBarPosFromTime(mTrimStartTime); - mPlayedBar.right = getBarPosFromTime(mCurrentTime); - if (!mScrubbing) { - mScrubberLeft = mPlayedBar.right - mScrubber.getWidth() / 2; - mTrimStartScrubberLeft = mPlayedBar.left - trimStartScrubberTipOffset(); - mTrimEndScrubberLeft = getBarPosFromTime(mTrimEndTime) - - trimEndScrubberTipOffset(); - } - } else { - // If the video is not prepared, just show the scrubber at the end - // of progressBar - mPlayedBar.right = mProgressBar.left; - mScrubberLeft = mProgressBar.left - mScrubber.getWidth() / 2; - mTrimStartScrubberLeft = mProgressBar.left - trimStartScrubberTipOffset(); - mTrimEndScrubberLeft = mProgressBar.right - trimEndScrubberTipOffset(); - } - } - - private void initTrimTimeIfNeeded() { - if (mTotalTime > 0 && mTrimEndTime == 0) { - mTrimEndTime = mTotalTime; - } - } - - private void update() { - initTrimTimeIfNeeded(); - updatePlayedBarAndScrubberFromTime(); - invalidate(); - } - - @Override - public void setTime(int currentTime, int totalTime, - int trimStartTime, int trimEndTime) { - if (mCurrentTime == currentTime && mTotalTime == totalTime - && mTrimStartTime == trimStartTime && mTrimEndTime == trimEndTime) { - return; - } - mCurrentTime = currentTime; - mTotalTime = totalTime; - mTrimStartTime = trimStartTime; - mTrimEndTime = trimEndTime; - update(); - } - - private int whichScrubber(float x, float y) { - if (inScrubber(x, y, mTrimStartScrubberLeft, mTrimStartScrubberTop, mTrimStartScrubber)) { - return SCRUBBER_START; - } else if (inScrubber(x, y, mTrimEndScrubberLeft, mTrimEndScrubberTop, mTrimEndScrubber)) { - return SCRUBBER_END; - } else if (inScrubber(x, y, mScrubberLeft, mScrubberTop, mScrubber)) { - return SCRUBBER_CURRENT; - } - return SCRUBBER_NONE; - } - - private boolean inScrubber(float x, float y, int startX, int startY, Bitmap scrubber) { - int scrubberRight = startX + scrubber.getWidth(); - int scrubberBottom = startY + scrubber.getHeight(); - return startX < x && x < scrubberRight && startY < y && y < scrubberBottom; - } - - private int clampScrubber(int scrubberLeft, int offset, int lowerBound, int upperBound) { - int max = upperBound - offset; - int min = lowerBound - offset; - return Math.min(max, Math.max(min, scrubberLeft)); - } - - private int getScrubberTime(int scrubberLeft, int offset) { - return (int) ((long) (scrubberLeft + offset - mProgressBar.left) - * mTotalTime / mProgressBar.width()); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - int w = r - l; - int h = b - t; - if (!mShowTimes && !mShowScrubber) { - mProgressBar.set(0, 0, w, h); - } else { - int margin = mScrubber.getWidth() / 3; - if (mShowTimes) { - margin += mTimeBounds.width(); - } - int progressY = h / 4; - int scrubberY = progressY - mScrubber.getHeight() / 2 + 1; - mScrubberTop = scrubberY; - mTrimStartScrubberTop = progressY; - mTrimEndScrubberTop = progressY; - mProgressBar.set( - getPaddingLeft() + margin, progressY, - w - getPaddingRight() - margin, progressY + 4); - } - update(); - } - - @Override - protected void onDraw(Canvas canvas) { - // draw progress bars - canvas.drawRect(mProgressBar, mProgressPaint); - canvas.drawRect(mPlayedBar, mPlayedPaint); - - if (mShowTimes) { - canvas.drawText( - stringForTime(mCurrentTime), - mTimeBounds.width() / 2 + getPaddingLeft(), - mTimeBounds.height() / 2 + mTrimStartScrubberTop, - mTimeTextPaint); - canvas.drawText( - stringForTime(mTotalTime), - getWidth() - getPaddingRight() - mTimeBounds.width() / 2, - mTimeBounds.height() / 2 + mTrimStartScrubberTop, - mTimeTextPaint); - } - - // draw extra scrubbers - if (mShowScrubber) { - canvas.drawBitmap(mScrubber, mScrubberLeft, mScrubberTop, null); - canvas.drawBitmap(mTrimStartScrubber, mTrimStartScrubberLeft, - mTrimStartScrubberTop, null); - canvas.drawBitmap(mTrimEndScrubber, mTrimEndScrubberLeft, - mTrimEndScrubberTop, null); - } - } - - private void updateTimeFromPos() { - mCurrentTime = getScrubberTime(mScrubberLeft, mScrubber.getWidth() / 2); - mTrimStartTime = getScrubberTime(mTrimStartScrubberLeft, trimStartScrubberTipOffset()); - mTrimEndTime = getScrubberTime(mTrimEndScrubberLeft, trimEndScrubberTipOffset()); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mShowScrubber) { - int x = (int) event.getX(); - int y = (int) event.getY(); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mPressedThumb = whichScrubber(x, y); - switch (mPressedThumb) { - case SCRUBBER_NONE: - break; - case SCRUBBER_CURRENT: - mScrubbing = true; - mScrubberCorrection = x - mScrubberLeft; - break; - case SCRUBBER_START: - mScrubbing = true; - mScrubberCorrection = x - mTrimStartScrubberLeft; - break; - case SCRUBBER_END: - mScrubbing = true; - mScrubberCorrection = x - mTrimEndScrubberLeft; - break; - } - if (mScrubbing == true) { - mListener.onScrubbingStart(); - return true; - } - break; - case MotionEvent.ACTION_MOVE: - if (mScrubbing) { - int seekToTime = -1; - int lowerBound = mTrimStartScrubberLeft + trimStartScrubberTipOffset(); - int upperBound = mTrimEndScrubberLeft + trimEndScrubberTipOffset(); - switch (mPressedThumb) { - case SCRUBBER_CURRENT: - mScrubberLeft = x - mScrubberCorrection; - mScrubberLeft = - clampScrubber(mScrubberLeft, - mScrubber.getWidth() / 2, - lowerBound, upperBound); - seekToTime = getScrubberTime(mScrubberLeft, - mScrubber.getWidth() / 2); - break; - case SCRUBBER_START: - mTrimStartScrubberLeft = x - mScrubberCorrection; - // Limit start <= end - if (mTrimStartScrubberLeft > mTrimEndScrubberLeft) { - mTrimStartScrubberLeft = mTrimEndScrubberLeft; - } - lowerBound = mProgressBar.left; - mTrimStartScrubberLeft = - clampScrubber(mTrimStartScrubberLeft, - trimStartScrubberTipOffset(), - lowerBound, upperBound); - seekToTime = getScrubberTime(mTrimStartScrubberLeft, - trimStartScrubberTipOffset()); - break; - case SCRUBBER_END: - mTrimEndScrubberLeft = x - mScrubberCorrection; - upperBound = mProgressBar.right; - mTrimEndScrubberLeft = - clampScrubber(mTrimEndScrubberLeft, - trimEndScrubberTipOffset(), - lowerBound, upperBound); - seekToTime = getScrubberTime(mTrimEndScrubberLeft, - trimEndScrubberTipOffset()); - break; - } - updateTimeFromPos(); - updatePlayedBarAndScrubberFromTime(); - if (seekToTime != -1) { - mListener.onScrubbingMove(seekToTime); - } - invalidate(); - return true; - } - break; - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_UP: - if (mScrubbing) { - int seekToTime = 0; - switch (mPressedThumb) { - case SCRUBBER_CURRENT: - seekToTime = getScrubberTime(mScrubberLeft, - mScrubber.getWidth() / 2); - break; - case SCRUBBER_START: - seekToTime = getScrubberTime(mTrimStartScrubberLeft, - trimStartScrubberTipOffset()); - mScrubberLeft = mTrimStartScrubberLeft + - trimStartScrubberTipOffset() - mScrubber.getWidth() / 2; - break; - case SCRUBBER_END: - seekToTime = getScrubberTime(mTrimEndScrubberLeft, - trimEndScrubberTipOffset()); - mScrubberLeft = mTrimEndScrubberLeft + - trimEndScrubberTipOffset() - mScrubber.getWidth() / 2; - break; - } - updateTimeFromPos(); - mListener.onScrubbingEnd(seekToTime, - getScrubberTime(mTrimStartScrubberLeft, - trimStartScrubberTipOffset()), - getScrubberTime(mTrimEndScrubberLeft, trimEndScrubberTipOffset())); - mScrubbing = false; - mPressedThumb = SCRUBBER_NONE; - return true; - } - break; - } - } - return false; - } -} diff --git a/src/com/android/gallery3d/app/TrimVideo.java b/src/com/android/gallery3d/app/TrimVideo.java deleted file mode 100644 index 1e7728162..000000000 --- a/src/com/android/gallery3d/app/TrimVideo.java +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.app.ActionBar; -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.Intent; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.Bundle; -import android.os.Handler; -import android.provider.MediaStore; -import android.view.View; -import android.view.ViewGroup; -import android.view.Window; -import android.widget.TextView; -import android.widget.Toast; -import android.widget.VideoView; - -import com.android.gallery3d.R; -import com.android.gallery3d.util.SaveVideoFileInfo; -import com.android.gallery3d.util.SaveVideoFileUtils; - -import java.io.File; -import java.io.IOException; - -public class TrimVideo extends Activity implements - MediaPlayer.OnErrorListener, - MediaPlayer.OnCompletionListener, - ControllerOverlay.Listener { - - private VideoView mVideoView; - private TextView mSaveVideoTextView; - private TrimControllerOverlay mController; - private Context mContext; - private Uri mUri; - private final Handler mHandler = new Handler(); - public static final String TRIM_ACTION = "com.android.camera.action.TRIM"; - - public ProgressDialog mProgress; - - private int mTrimStartTime = 0; - private int mTrimEndTime = 0; - private int mVideoPosition = 0; - public static final String KEY_TRIM_START = "trim_start"; - public static final String KEY_TRIM_END = "trim_end"; - public static final String KEY_VIDEO_POSITION = "video_pos"; - private boolean mHasPaused = false; - - private String mSrcVideoPath = null; - private static final String TIME_STAMP_NAME = "'TRIM'_yyyyMMdd_HHmmss"; - private SaveVideoFileInfo mDstFileInfo = null; - - @Override - public void onCreate(Bundle savedInstanceState) { - mContext = getApplicationContext(); - super.onCreate(savedInstanceState); - - requestWindowFeature(Window.FEATURE_ACTION_BAR); - requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY); - - ActionBar actionBar = getActionBar(); - int displayOptions = ActionBar.DISPLAY_SHOW_HOME; - actionBar.setDisplayOptions(0, displayOptions); - displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM; - actionBar.setDisplayOptions(displayOptions, displayOptions); - actionBar.setCustomView(R.layout.trim_menu); - - mSaveVideoTextView = (TextView) findViewById(R.id.start_trim); - mSaveVideoTextView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View arg0) { - trimVideo(); - } - }); - mSaveVideoTextView.setEnabled(false); - - Intent intent = getIntent(); - mUri = intent.getData(); - mSrcVideoPath = intent.getStringExtra(PhotoPage.KEY_MEDIA_ITEM_PATH); - setContentView(R.layout.trim_view); - View rootView = findViewById(R.id.trim_view_root); - - mVideoView = (VideoView) rootView.findViewById(R.id.surface_view); - - mController = new TrimControllerOverlay(mContext); - ((ViewGroup) rootView).addView(mController.getView()); - mController.setListener(this); - mController.setCanReplay(true); - - mVideoView.setOnErrorListener(this); - mVideoView.setOnCompletionListener(this); - mVideoView.setVideoURI(mUri); - - playVideo(); - } - - @Override - public void onResume() { - super.onResume(); - if (mHasPaused) { - mVideoView.seekTo(mVideoPosition); - mVideoView.resume(); - mHasPaused = false; - } - mHandler.post(mProgressChecker); - } - - @Override - public void onPause() { - mHasPaused = true; - mHandler.removeCallbacksAndMessages(null); - mVideoPosition = mVideoView.getCurrentPosition(); - mVideoView.suspend(); - super.onPause(); - } - - @Override - public void onStop() { - if (mProgress != null) { - mProgress.dismiss(); - mProgress = null; - } - super.onStop(); - } - - @Override - public void onDestroy() { - mVideoView.stopPlayback(); - super.onDestroy(); - } - - private final Runnable mProgressChecker = new Runnable() { - @Override - public void run() { - int pos = setProgress(); - mHandler.postDelayed(mProgressChecker, 200 - (pos % 200)); - } - }; - - @Override - public void onSaveInstanceState(Bundle savedInstanceState) { - savedInstanceState.putInt(KEY_TRIM_START, mTrimStartTime); - savedInstanceState.putInt(KEY_TRIM_END, mTrimEndTime); - savedInstanceState.putInt(KEY_VIDEO_POSITION, mVideoPosition); - super.onSaveInstanceState(savedInstanceState); - } - - @Override - public void onRestoreInstanceState(Bundle savedInstanceState) { - super.onRestoreInstanceState(savedInstanceState); - mTrimStartTime = savedInstanceState.getInt(KEY_TRIM_START, 0); - mTrimEndTime = savedInstanceState.getInt(KEY_TRIM_END, 0); - mVideoPosition = savedInstanceState.getInt(KEY_VIDEO_POSITION, 0); - } - - // This updates the time bar display (if necessary). It is called by - // mProgressChecker and also from places where the time bar needs - // to be updated immediately. - private int setProgress() { - mVideoPosition = mVideoView.getCurrentPosition(); - // If the video position is smaller than the starting point of trimming, - // correct it. - if (mVideoPosition < mTrimStartTime) { - mVideoView.seekTo(mTrimStartTime); - mVideoPosition = mTrimStartTime; - } - // If the position is bigger than the end point of trimming, show the - // replay button and pause. - if (mVideoPosition >= mTrimEndTime && mTrimEndTime > 0) { - if (mVideoPosition > mTrimEndTime) { - mVideoView.seekTo(mTrimEndTime); - mVideoPosition = mTrimEndTime; - } - mController.showEnded(); - mVideoView.pause(); - } - - int duration = mVideoView.getDuration(); - if (duration > 0 && mTrimEndTime == 0) { - mTrimEndTime = duration; - } - mController.setTimes(mVideoPosition, duration, mTrimStartTime, mTrimEndTime); - return mVideoPosition; - } - - private void playVideo() { - mVideoView.start(); - mController.showPlaying(); - setProgress(); - } - - private void pauseVideo() { - mVideoView.pause(); - mController.showPaused(); - } - - - private boolean isModified() { - int delta = mTrimEndTime - mTrimStartTime; - - // Considering that we only trim at sync frame, we don't want to trim - // when the time interval is too short or too close to the origin. - if (delta < 100 || Math.abs(mVideoView.getDuration() - delta) < 100) { - return false; - } else { - return true; - } - } - - private void trimVideo() { - - mDstFileInfo = SaveVideoFileUtils.getDstMp4FileInfo(TIME_STAMP_NAME, - getContentResolver(), mUri, getString(R.string.folder_download)); - final File mSrcFile = new File(mSrcVideoPath); - - showProgressDialog(); - - new Thread(new Runnable() { - @Override - public void run() { - try { - VideoUtils.startTrim(mSrcFile, mDstFileInfo.mFile, - mTrimStartTime, mTrimEndTime); - // Update the database for adding a new video file. - SaveVideoFileUtils.insertContent(mDstFileInfo, - getContentResolver(), mUri); - } catch (IOException e) { - e.printStackTrace(); - } - // After trimming is done, trigger the UI changed. - mHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(getApplicationContext(), - getString(R.string.save_into, mDstFileInfo.mFolderName), - Toast.LENGTH_SHORT) - .show(); - // TODO: change trimming into a service to avoid - // this progressDialog and add notification properly. - if (mProgress != null) { - mProgress.dismiss(); - mProgress = null; - // Show the result only when the activity not stopped. - Intent intent = new Intent(android.content.Intent.ACTION_VIEW); - intent.setDataAndType(Uri.fromFile(mDstFileInfo.mFile), "video/*"); - intent.putExtra(MediaStore.EXTRA_FINISH_ON_COMPLETION, false); - startActivity(intent); - finish(); - } - } - }); - } - }).start(); - } - - private void showProgressDialog() { - // create a background thread to trim the video. - // and show the progress. - mProgress = new ProgressDialog(this); - mProgress.setTitle(getString(R.string.trimming)); - mProgress.setMessage(getString(R.string.please_wait)); - // TODO: make this cancelable. - mProgress.setCancelable(false); - mProgress.setCanceledOnTouchOutside(false); - mProgress.show(); - } - - @Override - public void onPlayPause() { - if (mVideoView.isPlaying()) { - pauseVideo(); - } else { - playVideo(); - } - } - - @Override - public void onSeekStart() { - pauseVideo(); - } - - @Override - public void onSeekMove(int time) { - mVideoView.seekTo(time); - } - - @Override - public void onSeekEnd(int time, int start, int end) { - mVideoView.seekTo(time); - mTrimStartTime = start; - mTrimEndTime = end; - setProgress(); - // Enable save if there's modifications - mSaveVideoTextView.setEnabled(isModified()); - } - - @Override - public void onShown() { - } - - @Override - public void onHidden() { - } - - @Override - public void onReplay() { - mVideoView.seekTo(mTrimStartTime); - playVideo(); - } - - @Override - public void onCompletion(MediaPlayer mp) { - mController.showEnded(); - } - - @Override - public boolean onError(MediaPlayer mp, int what, int extra) { - return false; - } -} diff --git a/src/com/android/gallery3d/app/VideoUtils.java b/src/com/android/gallery3d/app/VideoUtils.java deleted file mode 100644 index a3c3ef273..000000000 --- a/src/com/android/gallery3d/app/VideoUtils.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Modified example based on mp4parser google code open source project. -// http://code.google.com/p/mp4parser/source/browse/trunk/examples/src/main/java/com/googlecode/mp4parser/ShortenExample.java - -package com.android.gallery3d.app; - -import android.media.MediaCodec.BufferInfo; -import android.media.MediaExtractor; -import android.media.MediaFormat; -import android.media.MediaMetadataRetriever; -import android.media.MediaMuxer; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.util.SaveVideoFileInfo; -import com.coremedia.iso.IsoFile; -import com.coremedia.iso.boxes.TimeToSampleBox; -import com.googlecode.mp4parser.authoring.Movie; -import com.googlecode.mp4parser.authoring.Track; -import com.googlecode.mp4parser.authoring.builder.DefaultMp4Builder; -import com.googlecode.mp4parser.authoring.container.mp4.MovieCreator; -import com.googlecode.mp4parser.authoring.tracks.CroppedTrack; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; - -public class VideoUtils { - private static final String LOGTAG = "VideoUtils"; - private static final int DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024; - - /** - * Remove the sound track. - */ - public static void startMute(String filePath, SaveVideoFileInfo dstFileInfo) - throws IOException { - if (ApiHelper.HAS_MEDIA_MUXER) { - genVideoUsingMuxer(filePath, dstFileInfo.mFile.getPath(), -1, -1, - false, true); - } else { - startMuteUsingMp4Parser(filePath, dstFileInfo); - } - } - - /** - * Shortens/Crops tracks - */ - public static void startTrim(File src, File dst, int startMs, int endMs) - throws IOException { - if (ApiHelper.HAS_MEDIA_MUXER) { - genVideoUsingMuxer(src.getPath(), dst.getPath(), startMs, endMs, - true, true); - } else { - trimUsingMp4Parser(src, dst, startMs, endMs); - } - } - - private static void startMuteUsingMp4Parser(String filePath, - SaveVideoFileInfo dstFileInfo) throws FileNotFoundException, IOException { - File dst = dstFileInfo.mFile; - File src = new File(filePath); - RandomAccessFile randomAccessFile = new RandomAccessFile(src, "r"); - Movie movie = MovieCreator.build(randomAccessFile.getChannel()); - - // remove all tracks we will create new tracks from the old - List<Track> tracks = movie.getTracks(); - movie.setTracks(new LinkedList<Track>()); - - for (Track track : tracks) { - if (track.getHandler().equals("vide")) { - movie.addTrack(track); - } - } - writeMovieIntoFile(dst, movie); - randomAccessFile.close(); - } - - private static void writeMovieIntoFile(File dst, Movie movie) - throws IOException { - if (!dst.exists()) { - dst.createNewFile(); - } - - IsoFile out = new DefaultMp4Builder().build(movie); - FileOutputStream fos = new FileOutputStream(dst); - FileChannel fc = fos.getChannel(); - out.getBox(fc); // This one build up the memory. - - fc.close(); - fos.close(); - } - - /** - * @param srcPath the path of source video file. - * @param dstPath the path of destination video file. - * @param startMs starting time in milliseconds for trimming. Set to - * negative if starting from beginning. - * @param endMs end time for trimming in milliseconds. Set to negative if - * no trimming at the end. - * @param useAudio true if keep the audio track from the source. - * @param useVideo true if keep the video track from the source. - * @throws IOException - */ - private static void genVideoUsingMuxer(String srcPath, String dstPath, - int startMs, int endMs, boolean useAudio, boolean useVideo) - throws IOException { - // Set up MediaExtractor to read from the source. - MediaExtractor extractor = new MediaExtractor(); - extractor.setDataSource(srcPath); - - int trackCount = extractor.getTrackCount(); - - // Set up MediaMuxer for the destination. - MediaMuxer muxer; - muxer = new MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4); - - // Set up the tracks and retrieve the max buffer size for selected - // tracks. - HashMap<Integer, Integer> indexMap = new HashMap<Integer, - Integer>(trackCount); - int bufferSize = -1; - for (int i = 0; i < trackCount; i++) { - MediaFormat format = extractor.getTrackFormat(i); - String mime = format.getString(MediaFormat.KEY_MIME); - - boolean selectCurrentTrack = false; - - if (mime.startsWith("audio/") && useAudio) { - selectCurrentTrack = true; - } else if (mime.startsWith("video/") && useVideo) { - selectCurrentTrack = true; - } - - if (selectCurrentTrack) { - extractor.selectTrack(i); - int dstIndex = muxer.addTrack(format); - indexMap.put(i, dstIndex); - if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) { - int newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE); - bufferSize = newSize > bufferSize ? newSize : bufferSize; - } - } - } - - if (bufferSize < 0) { - bufferSize = DEFAULT_BUFFER_SIZE; - } - - // Set up the orientation and starting time for extractor. - MediaMetadataRetriever retrieverSrc = new MediaMetadataRetriever(); - retrieverSrc.setDataSource(srcPath); - String degreesString = retrieverSrc.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION); - if (degreesString != null) { - int degrees = Integer.parseInt(degreesString); - if (degrees >= 0) { - muxer.setOrientationHint(degrees); - } - } - - if (startMs > 0) { - extractor.seekTo(startMs * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC); - } - - // Copy the samples from MediaExtractor to MediaMuxer. We will loop - // for copying each sample and stop when we get to the end of the source - // file or exceed the end time of the trimming. - int offset = 0; - int trackIndex = -1; - ByteBuffer dstBuf = ByteBuffer.allocate(bufferSize); - BufferInfo bufferInfo = new BufferInfo(); - - muxer.start(); - while (true) { - bufferInfo.offset = offset; - bufferInfo.size = extractor.readSampleData(dstBuf, offset); - if (bufferInfo.size < 0) { - Log.d(LOGTAG, "Saw input EOS."); - bufferInfo.size = 0; - break; - } else { - bufferInfo.presentationTimeUs = extractor.getSampleTime(); - if (endMs > 0 && bufferInfo.presentationTimeUs > (endMs * 1000)) { - Log.d(LOGTAG, "The current sample is over the trim end time."); - break; - } else { - bufferInfo.flags = extractor.getSampleFlags(); - trackIndex = extractor.getSampleTrackIndex(); - - muxer.writeSampleData(indexMap.get(trackIndex), dstBuf, - bufferInfo); - extractor.advance(); - } - } - } - - muxer.stop(); - muxer.release(); - return; - } - - private static void trimUsingMp4Parser(File src, File dst, int startMs, int endMs) - throws FileNotFoundException, IOException { - RandomAccessFile randomAccessFile = new RandomAccessFile(src, "r"); - Movie movie = MovieCreator.build(randomAccessFile.getChannel()); - - // remove all tracks we will create new tracks from the old - List<Track> tracks = movie.getTracks(); - movie.setTracks(new LinkedList<Track>()); - - double startTime = startMs / 1000; - double endTime = endMs / 1000; - - boolean timeCorrected = false; - - // Here we try to find a track that has sync samples. Since we can only - // start decoding at such a sample we SHOULD make sure that the start of - // the new fragment is exactly such a frame. - for (Track track : tracks) { - if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) { - if (timeCorrected) { - // This exception here could be a false positive in case we - // have multiple tracks with sync samples at exactly the - // same positions. E.g. a single movie containing multiple - // qualities of the same video (Microsoft Smooth Streaming - // file) - throw new RuntimeException( - "The startTime has already been corrected by" + - " another track with SyncSample. Not Supported."); - } - startTime = correctTimeToSyncSample(track, startTime, false); - endTime = correctTimeToSyncSample(track, endTime, true); - timeCorrected = true; - } - } - - for (Track track : tracks) { - long currentSample = 0; - double currentTime = 0; - long startSample = -1; - long endSample = -1; - - for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { - TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); - for (int j = 0; j < entry.getCount(); j++) { - // entry.getDelta() is the amount of time the current sample - // covers. - - if (currentTime <= startTime) { - // current sample is still before the new starttime - startSample = currentSample; - } - if (currentTime <= endTime) { - // current sample is after the new start time and still - // before the new endtime - endSample = currentSample; - } else { - // current sample is after the end of the cropped video - break; - } - currentTime += (double) entry.getDelta() - / (double) track.getTrackMetaData().getTimescale(); - currentSample++; - } - } - movie.addTrack(new CroppedTrack(track, startSample, endSample)); - } - writeMovieIntoFile(dst, movie); - randomAccessFile.close(); - } - - private static double correctTimeToSyncSample(Track track, double cutHere, - boolean next) { - double[] timeOfSyncSamples = new double[track.getSyncSamples().length]; - long currentSample = 0; - double currentTime = 0; - for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) { - TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i); - for (int j = 0; j < entry.getCount(); j++) { - if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) { - // samples always start with 1 but we start with zero - // therefore +1 - timeOfSyncSamples[Arrays.binarySearch( - track.getSyncSamples(), currentSample + 1)] = currentTime; - } - currentTime += (double) entry.getDelta() - / (double) track.getTrackMetaData().getTimescale(); - currentSample++; - } - } - double previous = 0; - for (double timeOfSyncSample : timeOfSyncSamples) { - if (timeOfSyncSample > cutHere) { - if (next) { - return timeOfSyncSample; - } else { - return previous; - } - } - previous = timeOfSyncSample; - } - return timeOfSyncSamples[timeOfSyncSamples.length - 1]; - } - -} diff --git a/src/com/android/gallery3d/app/Wallpaper.java b/src/com/android/gallery3d/app/Wallpaper.java deleted file mode 100644 index b0a26c236..000000000 --- a/src/com/android/gallery3d/app/Wallpaper.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2007 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.app; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Intent; -import android.graphics.Point; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.view.Display; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.filtershow.crop.CropExtras; - -/** - * Wallpaper picker for the gallery application. This just redirects to the - * standard pick action. - */ -public class Wallpaper extends Activity { - @SuppressWarnings("unused") - private static final String TAG = "Wallpaper"; - - private static final String IMAGE_TYPE = "image/*"; - private static final String KEY_STATE = "activity-state"; - private static final String KEY_PICKED_ITEM = "picked-item"; - - private static final int STATE_INIT = 0; - private static final int STATE_PHOTO_PICKED = 1; - - private int mState = STATE_INIT; - private Uri mPickedItem; - - @Override - protected void onCreate(Bundle bundle) { - super.onCreate(bundle); - if (bundle != null) { - mState = bundle.getInt(KEY_STATE); - mPickedItem = (Uri) bundle.getParcelable(KEY_PICKED_ITEM); - } - } - - @Override - protected void onSaveInstanceState(Bundle saveState) { - saveState.putInt(KEY_STATE, mState); - if (mPickedItem != null) { - saveState.putParcelable(KEY_PICKED_ITEM, mPickedItem); - } - } - - @SuppressWarnings("deprecation") - @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR2) - private Point getDefaultDisplaySize(Point size) { - Display d = getWindowManager().getDefaultDisplay(); - if (Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.HONEYCOMB_MR2) { - d.getSize(size); - } else { - size.set(d.getWidth(), d.getHeight()); - } - return size; - } - - @SuppressWarnings("fallthrough") - @Override - protected void onResume() { - super.onResume(); - Intent intent = getIntent(); - switch (mState) { - case STATE_INIT: { - mPickedItem = intent.getData(); - if (mPickedItem == null) { - Intent request = new Intent(Intent.ACTION_GET_CONTENT) - .setClass(this, DialogPicker.class) - .setType(IMAGE_TYPE); - startActivityForResult(request, STATE_PHOTO_PICKED); - return; - } - mState = STATE_PHOTO_PICKED; - // fall-through - } - case STATE_PHOTO_PICKED: { - int width = getWallpaperDesiredMinimumWidth(); - int height = getWallpaperDesiredMinimumHeight(); - Point size = getDefaultDisplaySize(new Point()); - float spotlightX = (float) size.x / width; - float spotlightY = (float) size.y / height; - Intent request = new Intent(CropActivity.CROP_ACTION) - .setDataAndType(mPickedItem, IMAGE_TYPE) - .addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) - .putExtra(CropExtras.KEY_OUTPUT_X, width) - .putExtra(CropExtras.KEY_OUTPUT_Y, height) - .putExtra(CropExtras.KEY_ASPECT_X, width) - .putExtra(CropExtras.KEY_ASPECT_Y, height) - .putExtra(CropExtras.KEY_SPOTLIGHT_X, spotlightX) - .putExtra(CropExtras.KEY_SPOTLIGHT_Y, spotlightY) - .putExtra(CropExtras.KEY_SCALE, true) - .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true) - .putExtra(CropExtras.KEY_SET_AS_WALLPAPER, true); - startActivity(request); - finish(); - } - } - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode != RESULT_OK) { - setResult(resultCode); - finish(); - return; - } - mState = requestCode; - if (mState == STATE_PHOTO_PICKED) { - mPickedItem = data.getData(); - } - - // onResume() would be called next - } -} diff --git a/src/com/android/gallery3d/data/ActionImage.java b/src/com/android/gallery3d/data/ActionImage.java deleted file mode 100644 index 58e30b146..000000000 --- a/src/com/android/gallery3d/data/ActionImage.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -public class ActionImage extends MediaItem { - @SuppressWarnings("unused") - private static final String TAG = "ActionImage"; - private GalleryApp mApplication; - private int mResourceId; - - public ActionImage(Path path, GalleryApp application, int resourceId) { - super(path, nextVersionNumber()); - mApplication = Utils.checkNotNull(application); - mResourceId = resourceId; - } - - @Override - public Job<Bitmap> requestImage(int type) { - return new BitmapJob(type); - } - - @Override - public Job<BitmapRegionDecoder> requestLargeImage() { - return null; - } - - private class BitmapJob implements Job<Bitmap> { - private int mType; - - protected BitmapJob(int type) { - mType = type; - } - - @Override - public Bitmap run(JobContext jc) { - int targetSize = MediaItem.getTargetSize(mType); - Bitmap bitmap = BitmapFactory.decodeResource(mApplication.getResources(), - mResourceId); - - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = BitmapUtils.resizeAndCropCenter(bitmap, targetSize, true); - } else { - bitmap = BitmapUtils.resizeDownBySideLength(bitmap, targetSize, true); - } - return bitmap; - } - } - - @Override - public int getSupportedOperations() { - return SUPPORT_ACTION; - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_UNKNOWN; - } - - @Override - public Uri getContentUri() { - return null; - } - - @Override - public String getMimeType() { - return ""; - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } -} diff --git a/src/com/android/gallery3d/data/BucketHelper.java b/src/com/android/gallery3d/data/BucketHelper.java deleted file mode 100644 index 3418dafb7..000000000 --- a/src/com/android/gallery3d/data/BucketHelper.java +++ /dev/null @@ -1,241 +0,0 @@ -package com.android.gallery3d.data; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.database.Cursor; -import android.net.Uri; -import android.provider.MediaStore.Files; -import android.provider.MediaStore.Files.FileColumns; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.Video; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Comparator; -import java.util.HashMap; - -class BucketHelper { - - private static final String TAG = "BucketHelper"; - private static final String EXTERNAL_MEDIA = "external"; - - // BUCKET_DISPLAY_NAME is a string like "Camera" which is the directory - // name of where an image or video is in. BUCKET_ID is a hash of the path - // name of that directory (see computeBucketValues() in MediaProvider for - // details). MEDIA_TYPE is video, image, audio, etc. - // - // The "albums" are not explicitly recorded in the database, but each image - // or video has the two columns (BUCKET_ID, MEDIA_TYPE). We define an - // "album" to be the collection of images/videos which have the same value - // for the two columns. - // - // The goal of the query (used in loadSubMediaSetsFromFilesTable()) is to - // find all albums, that is, all unique values for (BUCKET_ID, MEDIA_TYPE). - // In the meantime sort them by the timestamp of the latest image/video in - // each of the album. - // - // The order of columns below is important: it must match to the index in - // MediaStore. - private static final String[] PROJECTION_BUCKET = { - ImageColumns.BUCKET_ID, - FileColumns.MEDIA_TYPE, - ImageColumns.BUCKET_DISPLAY_NAME}; - - // The indices should match the above projections. - private static final int INDEX_BUCKET_ID = 0; - private static final int INDEX_MEDIA_TYPE = 1; - private static final int INDEX_BUCKET_NAME = 2; - - // We want to order the albums by reverse chronological order. We abuse the - // "WHERE" parameter to insert a "GROUP BY" clause into the SQL statement. - // The template for "WHERE" parameter is like: - // SELECT ... FROM ... WHERE (%s) - // and we make it look like: - // SELECT ... FROM ... WHERE (1) GROUP BY 1,(2) - // The "(1)" means true. The "1,(2)" means the first two columns specified - // after SELECT. Note that because there is a ")" in the template, we use - // "(2" to match it. - private static final String BUCKET_GROUP_BY = "1) GROUP BY 1,(2"; - - private static final String BUCKET_ORDER_BY = "MAX(datetaken) DESC"; - - // Before HoneyComb there is no Files table. Thus, we need to query the - // bucket info from the Images and Video tables and then merge them - // together. - // - // A bucket can exist in both tables. In this case, we need to find the - // latest timestamp from the two tables and sort ourselves. So we add the - // MAX(date_taken) to the projection and remove the media_type since we - // already know the media type from the table we query from. - private static final String[] PROJECTION_BUCKET_IN_ONE_TABLE = { - ImageColumns.BUCKET_ID, - "MAX(datetaken)", - ImageColumns.BUCKET_DISPLAY_NAME}; - - // We keep the INDEX_BUCKET_ID and INDEX_BUCKET_NAME the same as - // PROJECTION_BUCKET so we can reuse the values defined before. - private static final int INDEX_DATE_TAKEN = 1; - - // When query from the Images or Video tables, we only need to group by BUCKET_ID. - private static final String BUCKET_GROUP_BY_IN_ONE_TABLE = "1) GROUP BY (1"; - - public static BucketEntry[] loadBucketEntries( - JobContext jc, ContentResolver resolver, int type) { - if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) { - return loadBucketEntriesFromFilesTable(jc, resolver, type); - } else { - return loadBucketEntriesFromImagesAndVideoTable(jc, resolver, type); - } - } - - private static void updateBucketEntriesFromTable(JobContext jc, - ContentResolver resolver, Uri tableUri, HashMap<Integer, BucketEntry> buckets) { - Cursor cursor = resolver.query(tableUri, PROJECTION_BUCKET_IN_ONE_TABLE, - BUCKET_GROUP_BY_IN_ONE_TABLE, null, null); - if (cursor == null) { - Log.w(TAG, "cannot open media database: " + tableUri); - return; - } - try { - while (cursor.moveToNext()) { - int bucketId = cursor.getInt(INDEX_BUCKET_ID); - int dateTaken = cursor.getInt(INDEX_DATE_TAKEN); - BucketEntry entry = buckets.get(bucketId); - if (entry == null) { - entry = new BucketEntry(bucketId, cursor.getString(INDEX_BUCKET_NAME)); - buckets.put(bucketId, entry); - entry.dateTaken = dateTaken; - } else { - entry.dateTaken = Math.max(entry.dateTaken, dateTaken); - } - } - } finally { - Utils.closeSilently(cursor); - } - } - - private static BucketEntry[] loadBucketEntriesFromImagesAndVideoTable( - JobContext jc, ContentResolver resolver, int type) { - HashMap<Integer, BucketEntry> buckets = new HashMap<Integer, BucketEntry>(64); - if ((type & MediaObject.MEDIA_TYPE_IMAGE) != 0) { - updateBucketEntriesFromTable( - jc, resolver, Images.Media.EXTERNAL_CONTENT_URI, buckets); - } - if ((type & MediaObject.MEDIA_TYPE_VIDEO) != 0) { - updateBucketEntriesFromTable( - jc, resolver, Video.Media.EXTERNAL_CONTENT_URI, buckets); - } - BucketEntry[] entries = buckets.values().toArray(new BucketEntry[buckets.size()]); - Arrays.sort(entries, new Comparator<BucketEntry>() { - @Override - public int compare(BucketEntry a, BucketEntry b) { - // sorted by dateTaken in descending order - return b.dateTaken - a.dateTaken; - } - }); - return entries; - } - - private static BucketEntry[] loadBucketEntriesFromFilesTable( - JobContext jc, ContentResolver resolver, int type) { - Uri uri = getFilesContentUri(); - - Cursor cursor = resolver.query(uri, - PROJECTION_BUCKET, BUCKET_GROUP_BY, - null, BUCKET_ORDER_BY); - if (cursor == null) { - Log.w(TAG, "cannot open local database: " + uri); - return new BucketEntry[0]; - } - ArrayList<BucketEntry> buffer = new ArrayList<BucketEntry>(); - int typeBits = 0; - if ((type & MediaObject.MEDIA_TYPE_IMAGE) != 0) { - typeBits |= (1 << FileColumns.MEDIA_TYPE_IMAGE); - } - if ((type & MediaObject.MEDIA_TYPE_VIDEO) != 0) { - typeBits |= (1 << FileColumns.MEDIA_TYPE_VIDEO); - } - try { - while (cursor.moveToNext()) { - if ((typeBits & (1 << cursor.getInt(INDEX_MEDIA_TYPE))) != 0) { - BucketEntry entry = new BucketEntry( - cursor.getInt(INDEX_BUCKET_ID), - cursor.getString(INDEX_BUCKET_NAME)); - if (!buffer.contains(entry)) { - buffer.add(entry); - } - } - if (jc.isCancelled()) return null; - } - } finally { - Utils.closeSilently(cursor); - } - return buffer.toArray(new BucketEntry[buffer.size()]); - } - - private static String getBucketNameInTable( - ContentResolver resolver, Uri tableUri, int bucketId) { - String selectionArgs[] = new String[] {String.valueOf(bucketId)}; - Uri uri = tableUri.buildUpon() - .appendQueryParameter("limit", "1") - .build(); - Cursor cursor = resolver.query(uri, PROJECTION_BUCKET_IN_ONE_TABLE, - "bucket_id = ?", selectionArgs, null); - try { - if (cursor != null && cursor.moveToNext()) { - return cursor.getString(INDEX_BUCKET_NAME); - } - } finally { - Utils.closeSilently(cursor); - } - return null; - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private static Uri getFilesContentUri() { - return Files.getContentUri(EXTERNAL_MEDIA); - } - - public static String getBucketName(ContentResolver resolver, int bucketId) { - if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) { - String result = getBucketNameInTable(resolver, getFilesContentUri(), bucketId); - return result == null ? "" : result; - } else { - String result = getBucketNameInTable( - resolver, Images.Media.EXTERNAL_CONTENT_URI, bucketId); - if (result != null) return result; - result = getBucketNameInTable( - resolver, Video.Media.EXTERNAL_CONTENT_URI, bucketId); - return result == null ? "" : result; - } - } - - public static class BucketEntry { - public String bucketName; - public int bucketId; - public int dateTaken; - - public BucketEntry(int id, String name) { - bucketId = id; - bucketName = Utils.ensureNotNull(name); - } - - @Override - public int hashCode() { - return bucketId; - } - - @Override - public boolean equals(Object object) { - if (!(object instanceof BucketEntry)) return false; - BucketEntry entry = (BucketEntry) object; - return bucketId == entry.bucketId; - } - } -} diff --git a/src/com/android/gallery3d/data/BytesBufferPool.java b/src/com/android/gallery3d/data/BytesBufferPool.java deleted file mode 100644 index d2da323fc..000000000 --- a/src/com/android/gallery3d/data/BytesBufferPool.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.ArrayList; - -public class BytesBufferPool { - - private static final int READ_STEP = 4096; - - public static class BytesBuffer { - public byte[] data; - public int offset; - public int length; - - private BytesBuffer(int capacity) { - this.data = new byte[capacity]; - } - - // an helper function to read content from FileDescriptor - public void readFrom(JobContext jc, FileDescriptor fd) throws IOException { - FileInputStream fis = new FileInputStream(fd); - length = 0; - try { - int capacity = data.length; - while (true) { - int step = Math.min(READ_STEP, capacity - length); - int rc = fis.read(data, length, step); - if (rc < 0 || jc.isCancelled()) return; - length += rc; - - if (length == capacity) { - byte[] newData = new byte[data.length * 2]; - System.arraycopy(data, 0, newData, 0, data.length); - data = newData; - capacity = data.length; - } - } - } finally { - fis.close(); - } - } - } - - private final int mPoolSize; - private final int mBufferSize; - private final ArrayList<BytesBuffer> mList; - - public BytesBufferPool(int poolSize, int bufferSize) { - mList = new ArrayList<BytesBuffer>(poolSize); - mPoolSize = poolSize; - mBufferSize = bufferSize; - } - - public synchronized BytesBuffer get() { - int n = mList.size(); - return n > 0 ? mList.remove(n - 1) : new BytesBuffer(mBufferSize); - } - - public synchronized void recycle(BytesBuffer buffer) { - if (buffer.data.length != mBufferSize) return; - if (mList.size() < mPoolSize) { - buffer.offset = 0; - buffer.length = 0; - mList.add(buffer); - } - } - - public synchronized void clear() { - mList.clear(); - } -} diff --git a/src/com/android/gallery3d/data/CameraShortcutImage.java b/src/com/android/gallery3d/data/CameraShortcutImage.java deleted file mode 100644 index 865270b4c..000000000 --- a/src/com/android/gallery3d/data/CameraShortcutImage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; - -public class CameraShortcutImage extends ActionImage { - @SuppressWarnings("unused") - private static final String TAG = "CameraShortcutImage"; - - public CameraShortcutImage(Path path, GalleryApp application) { - super(path, application, R.drawable.placeholder_camera); - } - - @Override - public int getSupportedOperations() { - return super.getSupportedOperations() | SUPPORT_CAMERA_SHORTCUT; - } -} diff --git a/src/com/android/gallery3d/data/ChangeNotifier.java b/src/com/android/gallery3d/data/ChangeNotifier.java deleted file mode 100644 index 558a8648e..000000000 --- a/src/com/android/gallery3d/data/ChangeNotifier.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.net.Uri; - -import com.android.gallery3d.app.GalleryApp; - -import java.util.concurrent.atomic.AtomicBoolean; - -// This handles change notification for media sets. -public class ChangeNotifier { - - private MediaSet mMediaSet; - private AtomicBoolean mContentDirty = new AtomicBoolean(true); - - public ChangeNotifier(MediaSet set, Uri uri, GalleryApp application) { - mMediaSet = set; - application.getDataManager().registerChangeNotifier(uri, this); - } - - public ChangeNotifier(MediaSet set, Uri[] uris, GalleryApp application) { - mMediaSet = set; - for (int i = 0; i < uris.length; i++) { - application.getDataManager().registerChangeNotifier(uris[i], this); - } - } - - // Returns the dirty flag and clear it. - public boolean isDirty() { - return mContentDirty.compareAndSet(true, false); - } - - public void fakeChange() { - onChange(false); - } - - protected void onChange(boolean selfChange) { - if (mContentDirty.compareAndSet(false, true)) { - mMediaSet.notifyContentChanged(); - } - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/data/ClusterAlbum.java b/src/com/android/gallery3d/data/ClusterAlbum.java deleted file mode 100644 index 8681952bf..000000000 --- a/src/com/android/gallery3d/data/ClusterAlbum.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -public class ClusterAlbum extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ClusterAlbum"; - private ArrayList<Path> mPaths = new ArrayList<Path>(); - private String mName = ""; - private DataManager mDataManager; - private MediaSet mClusterAlbumSet; - private MediaItem mCover; - - public ClusterAlbum(Path path, DataManager dataManager, - MediaSet clusterAlbumSet) { - super(path, nextVersionNumber()); - mDataManager = dataManager; - mClusterAlbumSet = clusterAlbumSet; - mClusterAlbumSet.addContentListener(this); - } - - public void setCoverMediaItem(MediaItem cover) { - mCover = cover; - } - - @Override - public MediaItem getCoverMediaItem() { - return mCover != null ? mCover : super.getCoverMediaItem(); - } - - void setMediaItems(ArrayList<Path> paths) { - mPaths = paths; - } - - ArrayList<Path> getMediaItems() { - return mPaths; - } - - public void setName(String name) { - mName = name; - } - - @Override - public String getName() { - return mName; - } - - @Override - public int getMediaItemCount() { - return mPaths.size(); - } - - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - return getMediaItemFromPath(mPaths, start, count, mDataManager); - } - - public static ArrayList<MediaItem> getMediaItemFromPath( - ArrayList<Path> paths, int start, int count, - DataManager dataManager) { - if (start >= paths.size()) { - return new ArrayList<MediaItem>(); - } - int end = Math.min(start + count, paths.size()); - ArrayList<Path> subset = new ArrayList<Path>(paths.subList(start, end)); - final MediaItem[] buf = new MediaItem[end - start]; - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - buf[index] = item; - } - }; - dataManager.mapMediaItems(subset, consumer, 0); - ArrayList<MediaItem> result = new ArrayList<MediaItem>(end - start); - for (int i = 0; i < buf.length; i++) { - result.add(buf[i]); - } - return result; - } - - @Override - protected int enumerateMediaItems(ItemConsumer consumer, int startIndex) { - mDataManager.mapMediaItems(mPaths, consumer, startIndex); - return mPaths.size(); - } - - @Override - public int getTotalMediaItemCount() { - return mPaths.size(); - } - - @Override - public long reload() { - if (mClusterAlbumSet.reload() > mDataVersion) { - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public int getSupportedOperations() { - return SUPPORT_SHARE | SUPPORT_DELETE | SUPPORT_INFO; - } - - @Override - public void delete() { - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if ((item.getSupportedOperations() & SUPPORT_DELETE) != 0) { - item.delete(); - } - } - }; - mDataManager.mapMediaItems(mPaths, consumer, 0); - } - - @Override - public boolean isLeafAlbum() { - return true; - } -} diff --git a/src/com/android/gallery3d/data/ClusterAlbumSet.java b/src/com/android/gallery3d/data/ClusterAlbumSet.java deleted file mode 100644 index cb212ba36..000000000 --- a/src/com/android/gallery3d/data/ClusterAlbumSet.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.net.Uri; - -import com.android.gallery3d.app.GalleryApp; - -import java.util.ArrayList; -import java.util.HashSet; - -public class ClusterAlbumSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ClusterAlbumSet"; - private GalleryApp mApplication; - private MediaSet mBaseSet; - private int mKind; - private ArrayList<ClusterAlbum> mAlbums = new ArrayList<ClusterAlbum>(); - private boolean mFirstReloadDone; - - public ClusterAlbumSet(Path path, GalleryApp application, - MediaSet baseSet, int kind) { - super(path, INVALID_DATA_VERSION); - mApplication = application; - mBaseSet = baseSet; - mKind = kind; - baseSet.addContentListener(this); - } - - @Override - public MediaSet getSubMediaSet(int index) { - return mAlbums.get(index); - } - - @Override - public int getSubMediaSetCount() { - return mAlbums.size(); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } - - @Override - public long reload() { - if (mBaseSet.reload() > mDataVersion) { - if (mFirstReloadDone) { - updateClustersContents(); - } else { - updateClusters(); - mFirstReloadDone = true; - } - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - private void updateClusters() { - mAlbums.clear(); - Clustering clustering; - Context context = mApplication.getAndroidContext(); - switch (mKind) { - case ClusterSource.CLUSTER_ALBUMSET_TIME: - clustering = new TimeClustering(context); - break; - case ClusterSource.CLUSTER_ALBUMSET_LOCATION: - clustering = new LocationClustering(context); - break; - case ClusterSource.CLUSTER_ALBUMSET_TAG: - clustering = new TagClustering(context); - break; - case ClusterSource.CLUSTER_ALBUMSET_FACE: - clustering = new FaceClustering(context); - break; - default: /* CLUSTER_ALBUMSET_SIZE */ - clustering = new SizeClustering(context); - break; - } - - clustering.run(mBaseSet); - int n = clustering.getNumberOfClusters(); - DataManager dataManager = mApplication.getDataManager(); - for (int i = 0; i < n; i++) { - Path childPath; - String childName = clustering.getClusterName(i); - if (mKind == ClusterSource.CLUSTER_ALBUMSET_TAG) { - childPath = mPath.getChild(Uri.encode(childName)); - } else if (mKind == ClusterSource.CLUSTER_ALBUMSET_SIZE) { - long minSize = ((SizeClustering) clustering).getMinSize(i); - childPath = mPath.getChild(minSize); - } else { - childPath = mPath.getChild(i); - } - - ClusterAlbum album; - synchronized (DataManager.LOCK) { - album = (ClusterAlbum) dataManager.peekMediaObject(childPath); - if (album == null) { - album = new ClusterAlbum(childPath, dataManager, this); - } - } - album.setMediaItems(clustering.getCluster(i)); - album.setName(childName); - album.setCoverMediaItem(clustering.getClusterCover(i)); - mAlbums.add(album); - } - } - - private void updateClustersContents() { - final HashSet<Path> existing = new HashSet<Path>(); - mBaseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - existing.add(item.getPath()); - } - }); - - int n = mAlbums.size(); - - // The loop goes backwards because we may remove empty albums from - // mAlbums. - for (int i = n - 1; i >= 0; i--) { - ArrayList<Path> oldPaths = mAlbums.get(i).getMediaItems(); - ArrayList<Path> newPaths = new ArrayList<Path>(); - int m = oldPaths.size(); - for (int j = 0; j < m; j++) { - Path p = oldPaths.get(j); - if (existing.contains(p)) { - newPaths.add(p); - } - } - mAlbums.get(i).setMediaItems(newPaths); - if (newPaths.isEmpty()) { - mAlbums.remove(i); - } - } - } -} diff --git a/src/com/android/gallery3d/data/ClusterSource.java b/src/com/android/gallery3d/data/ClusterSource.java deleted file mode 100644 index a1f22e57a..000000000 --- a/src/com/android/gallery3d/data/ClusterSource.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -class ClusterSource extends MediaSource { - static final int CLUSTER_ALBUMSET_TIME = 0; - static final int CLUSTER_ALBUMSET_LOCATION = 1; - static final int CLUSTER_ALBUMSET_TAG = 2; - static final int CLUSTER_ALBUMSET_SIZE = 3; - static final int CLUSTER_ALBUMSET_FACE = 4; - - static final int CLUSTER_ALBUM_TIME = 0x100; - static final int CLUSTER_ALBUM_LOCATION = 0x101; - static final int CLUSTER_ALBUM_TAG = 0x102; - static final int CLUSTER_ALBUM_SIZE = 0x103; - static final int CLUSTER_ALBUM_FACE = 0x104; - - GalleryApp mApplication; - PathMatcher mMatcher; - - public ClusterSource(GalleryApp application) { - super("cluster"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/cluster/*/time", CLUSTER_ALBUMSET_TIME); - mMatcher.add("/cluster/*/location", CLUSTER_ALBUMSET_LOCATION); - mMatcher.add("/cluster/*/tag", CLUSTER_ALBUMSET_TAG); - mMatcher.add("/cluster/*/size", CLUSTER_ALBUMSET_SIZE); - mMatcher.add("/cluster/*/face", CLUSTER_ALBUMSET_FACE); - - mMatcher.add("/cluster/*/time/*", CLUSTER_ALBUM_TIME); - mMatcher.add("/cluster/*/location/*", CLUSTER_ALBUM_LOCATION); - mMatcher.add("/cluster/*/tag/*", CLUSTER_ALBUM_TAG); - mMatcher.add("/cluster/*/size/*", CLUSTER_ALBUM_SIZE); - mMatcher.add("/cluster/*/face/*", CLUSTER_ALBUM_FACE); - } - - // The names we accept are: - // /cluster/{set}/time /cluster/{set}/time/k - // /cluster/{set}/location /cluster/{set}/location/k - // /cluster/{set}/tag /cluster/{set}/tag/encoded_tag - // /cluster/{set}/size /cluster/{set}/size/min_size - @Override - public MediaObject createMediaObject(Path path) { - int matchType = mMatcher.match(path); - String setsName = mMatcher.getVar(0); - DataManager dataManager = mApplication.getDataManager(); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - switch (matchType) { - case CLUSTER_ALBUMSET_TIME: - case CLUSTER_ALBUMSET_LOCATION: - case CLUSTER_ALBUMSET_TAG: - case CLUSTER_ALBUMSET_SIZE: - case CLUSTER_ALBUMSET_FACE: - return new ClusterAlbumSet(path, mApplication, sets[0], matchType); - case CLUSTER_ALBUM_TIME: - case CLUSTER_ALBUM_LOCATION: - case CLUSTER_ALBUM_TAG: - case CLUSTER_ALBUM_SIZE: - case CLUSTER_ALBUM_FACE: { - MediaSet parent = dataManager.getMediaSet(path.getParent()); - // The actual content in the ClusterAlbum will be filled later - // when the reload() method in the parent is run. - return new ClusterAlbum(path, dataManager, parent); - } - default: - throw new RuntimeException("bad path: " + path); - } - } -} diff --git a/src/com/android/gallery3d/data/Clustering.java b/src/com/android/gallery3d/data/Clustering.java deleted file mode 100644 index 4072bf57b..000000000 --- a/src/com/android/gallery3d/data/Clustering.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -public abstract class Clustering { - public abstract void run(MediaSet baseSet); - public abstract int getNumberOfClusters(); - public abstract ArrayList<Path> getCluster(int index); - public abstract String getClusterName(int index); - public MediaItem getClusterCover(int index) { - return null; - } -} diff --git a/src/com/android/gallery3d/data/ComboAlbum.java b/src/com/android/gallery3d/data/ComboAlbum.java deleted file mode 100644 index cadd9f8af..000000000 --- a/src/com/android/gallery3d/data/ComboAlbum.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.util.Future; - -import java.util.ArrayList; - -// ComboAlbum combines multiple media sets into one. It lists all media items -// from the input albums. -// This only handles SubMediaSets, not MediaItems. (That's all we need now) -public class ComboAlbum extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ComboAlbum"; - private final MediaSet[] mSets; - private String mName; - - public ComboAlbum(Path path, MediaSet[] mediaSets, String name) { - super(path, nextVersionNumber()); - mSets = mediaSets; - for (MediaSet set : mSets) { - set.addContentListener(this); - } - mName = name; - } - - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - ArrayList<MediaItem> items = new ArrayList<MediaItem>(); - for (MediaSet set : mSets) { - int size = set.getMediaItemCount(); - if (count < 1) break; - if (start < size) { - int fetchCount = (start + count <= size) ? count : size - start; - ArrayList<MediaItem> fetchItems = set.getMediaItem(start, fetchCount); - items.addAll(fetchItems); - count -= fetchItems.size(); - start = 0; - } else { - start -= size; - } - } - return items; - } - - @Override - public int getMediaItemCount() { - int count = 0; - for (MediaSet set : mSets) { - count += set.getMediaItemCount(); - } - return count; - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public String getName() { - return mName; - } - - public void useNameOfChild(int i) { - if (i < mSets.length) mName = mSets[i].getName(); - } - - @Override - public long reload() { - boolean changed = false; - for (int i = 0, n = mSets.length; i < n; ++i) { - long version = mSets[i].reload(); - if (version > mDataVersion) changed = true; - } - if (changed) mDataVersion = nextVersionNumber(); - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public Future<Integer> requestSync(SyncListener listener) { - return requestSyncOnMultipleSets(mSets, listener); - } -} diff --git a/src/com/android/gallery3d/data/ComboAlbumSet.java b/src/com/android/gallery3d/data/ComboAlbumSet.java deleted file mode 100644 index 3f3674500..000000000 --- a/src/com/android/gallery3d/data/ComboAlbumSet.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.util.Future; - -// ComboAlbumSet combines multiple media sets into one. It lists all sub -// media sets from the input album sets. -// This only handles SubMediaSets, not MediaItems. (That's all we need now) -public class ComboAlbumSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "ComboAlbumSet"; - private final MediaSet[] mSets; - private final String mName; - - public ComboAlbumSet(Path path, GalleryApp application, MediaSet[] mediaSets) { - super(path, nextVersionNumber()); - mSets = mediaSets; - for (MediaSet set : mSets) { - set.addContentListener(this); - } - mName = application.getResources().getString( - R.string.set_label_all_albums); - } - - @Override - public MediaSet getSubMediaSet(int index) { - for (MediaSet set : mSets) { - int size = set.getSubMediaSetCount(); - if (index < size) { - return set.getSubMediaSet(index); - } - index -= size; - } - return null; - } - - @Override - public int getSubMediaSetCount() { - int count = 0; - for (MediaSet set : mSets) { - count += set.getSubMediaSetCount(); - } - return count; - } - - @Override - public String getName() { - return mName; - } - - @Override - public boolean isLoading() { - for (int i = 0, n = mSets.length; i < n; ++i) { - if (mSets[i].isLoading()) return true; - } - return false; - } - - @Override - public long reload() { - boolean changed = false; - for (int i = 0, n = mSets.length; i < n; ++i) { - long version = mSets[i].reload(); - if (version > mDataVersion) changed = true; - } - if (changed) mDataVersion = nextVersionNumber(); - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public Future<Integer> requestSync(SyncListener listener) { - return requestSyncOnMultipleSets(mSets, listener); - } -} diff --git a/src/com/android/gallery3d/data/ComboSource.java b/src/com/android/gallery3d/data/ComboSource.java deleted file mode 100644 index 867d47e64..000000000 --- a/src/com/android/gallery3d/data/ComboSource.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -class ComboSource extends MediaSource { - private static final int COMBO_ALBUMSET = 0; - private static final int COMBO_ALBUM = 1; - private GalleryApp mApplication; - private PathMatcher mMatcher; - - public ComboSource(GalleryApp application) { - super("combo"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/combo/*", COMBO_ALBUMSET); - mMatcher.add("/combo/*/*", COMBO_ALBUM); - } - - // The only path we accept is "/combo/{set1, set2, ...} and /combo/item/{set1, set2, ...}" - @Override - public MediaObject createMediaObject(Path path) { - String[] segments = path.split(); - if (segments.length < 2) { - throw new RuntimeException("bad path: " + path); - } - - DataManager dataManager = mApplication.getDataManager(); - switch (mMatcher.match(path)) { - case COMBO_ALBUMSET: - return new ComboAlbumSet(path, mApplication, - dataManager.getMediaSetsFromString(segments[1])); - - case COMBO_ALBUM: - return new ComboAlbum(path, - dataManager.getMediaSetsFromString(segments[2]), segments[1]); - } - return null; - } -} diff --git a/src/com/android/gallery3d/data/ContentListener.java b/src/com/android/gallery3d/data/ContentListener.java deleted file mode 100644 index 5e2952685..000000000 --- a/src/com/android/gallery3d/data/ContentListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -public interface ContentListener { - public void onContentDirty(); -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/data/DataManager.java b/src/com/android/gallery3d/data/DataManager.java deleted file mode 100644 index 38865e9f1..000000000 --- a/src/com/android/gallery3d/data/DataManager.java +++ /dev/null @@ -1,371 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.database.ContentObserver; -import android.net.Uri; -import android.os.Handler; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.StitchingChangeListener; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.MediaSet.ItemConsumer; -import com.android.gallery3d.data.MediaSource.PathId; -import com.android.gallery3d.picasasource.PicasaSource; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Map.Entry; -import java.util.WeakHashMap; - -// DataManager manages all media sets and media items in the system. -// -// Each MediaSet and MediaItem has a unique 64 bits id. The most significant -// 32 bits represents its parent, and the least significant 32 bits represents -// the self id. For MediaSet the self id is is globally unique, but for -// MediaItem it's unique only relative to its parent. -// -// To make sure the id is the same when the MediaSet is re-created, a child key -// is provided to obtainSetId() to make sure the same self id will be used as -// when the parent and key are the same. A sequence of child keys is called a -// path. And it's used to identify a specific media set even if the process is -// killed and re-created, so child keys should be stable identifiers. - -public class DataManager implements StitchingChangeListener { - public static final int INCLUDE_IMAGE = 1; - public static final int INCLUDE_VIDEO = 2; - public static final int INCLUDE_ALL = INCLUDE_IMAGE | INCLUDE_VIDEO; - public static final int INCLUDE_LOCAL_ONLY = 4; - public static final int INCLUDE_LOCAL_IMAGE_ONLY = - INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE; - public static final int INCLUDE_LOCAL_VIDEO_ONLY = - INCLUDE_LOCAL_ONLY | INCLUDE_VIDEO; - public static final int INCLUDE_LOCAL_ALL_ONLY = - INCLUDE_LOCAL_ONLY | INCLUDE_IMAGE | INCLUDE_VIDEO; - - // Any one who would like to access data should require this lock - // to prevent concurrency issue. - public static final Object LOCK = new Object(); - - public static DataManager from(Context context) { - GalleryApp app = (GalleryApp) context.getApplicationContext(); - return app.getDataManager(); - } - - private static final String TAG = "DataManager"; - - // This is the path for the media set seen by the user at top level. - private static final String TOP_SET_PATH = "/combo/{/local/all,/picasa/all}"; - - private static final String TOP_IMAGE_SET_PATH = "/combo/{/local/image,/picasa/image}"; - - private static final String TOP_VIDEO_SET_PATH = - "/combo/{/local/video,/picasa/video}"; - - private static final String TOP_LOCAL_SET_PATH = "/local/all"; - - private static final String TOP_LOCAL_IMAGE_SET_PATH = "/local/image"; - - private static final String TOP_LOCAL_VIDEO_SET_PATH = "/local/video"; - - public static final Comparator<MediaItem> sDateTakenComparator = - new DateTakenComparator(); - - private static class DateTakenComparator implements Comparator<MediaItem> { - @Override - public int compare(MediaItem item1, MediaItem item2) { - return -Utils.compare(item1.getDateInMs(), item2.getDateInMs()); - } - } - - private final Handler mDefaultMainHandler; - - private GalleryApp mApplication; - private int mActiveCount = 0; - - private HashMap<Uri, NotifyBroker> mNotifierMap = - new HashMap<Uri, NotifyBroker>(); - - - private HashMap<String, MediaSource> mSourceMap = - new LinkedHashMap<String, MediaSource>(); - - public DataManager(GalleryApp application) { - mApplication = application; - mDefaultMainHandler = new Handler(application.getMainLooper()); - } - - public synchronized void initializeSourceMap() { - if (!mSourceMap.isEmpty()) return; - - // the order matters, the UriSource must come last - addSource(new LocalSource(mApplication)); - addSource(new PicasaSource(mApplication)); - addSource(new ComboSource(mApplication)); - addSource(new ClusterSource(mApplication)); - addSource(new FilterSource(mApplication)); - addSource(new SecureSource(mApplication)); - addSource(new UriSource(mApplication)); - addSource(new SnailSource(mApplication)); - - if (mActiveCount > 0) { - for (MediaSource source : mSourceMap.values()) { - source.resume(); - } - } - } - - public String getTopSetPath(int typeBits) { - - switch (typeBits) { - case INCLUDE_IMAGE: return TOP_IMAGE_SET_PATH; - case INCLUDE_VIDEO: return TOP_VIDEO_SET_PATH; - case INCLUDE_ALL: return TOP_SET_PATH; - case INCLUDE_LOCAL_IMAGE_ONLY: return TOP_LOCAL_IMAGE_SET_PATH; - case INCLUDE_LOCAL_VIDEO_ONLY: return TOP_LOCAL_VIDEO_SET_PATH; - case INCLUDE_LOCAL_ALL_ONLY: return TOP_LOCAL_SET_PATH; - default: throw new IllegalArgumentException(); - } - } - - // open for debug - void addSource(MediaSource source) { - if (source == null) return; - mSourceMap.put(source.getPrefix(), source); - } - - // A common usage of this method is: - // synchronized (DataManager.LOCK) { - // MediaObject object = peekMediaObject(path); - // if (object == null) { - // object = createMediaObject(...); - // } - // } - public MediaObject peekMediaObject(Path path) { - return path.getObject(); - } - - public MediaObject getMediaObject(Path path) { - synchronized (LOCK) { - MediaObject obj = path.getObject(); - if (obj != null) return obj; - - MediaSource source = mSourceMap.get(path.getPrefix()); - if (source == null) { - Log.w(TAG, "cannot find media source for path: " + path); - return null; - } - - try { - MediaObject object = source.createMediaObject(path); - if (object == null) { - Log.w(TAG, "cannot create media object: " + path); - } - return object; - } catch (Throwable t) { - Log.w(TAG, "exception in creating media object: " + path, t); - return null; - } - } - } - - public MediaObject getMediaObject(String s) { - return getMediaObject(Path.fromString(s)); - } - - public MediaSet getMediaSet(Path path) { - return (MediaSet) getMediaObject(path); - } - - public MediaSet getMediaSet(String s) { - return (MediaSet) getMediaObject(s); - } - - public MediaSet[] getMediaSetsFromString(String segment) { - String[] seq = Path.splitSequence(segment); - int n = seq.length; - MediaSet[] sets = new MediaSet[n]; - for (int i = 0; i < n; i++) { - sets[i] = getMediaSet(seq[i]); - } - return sets; - } - - // Maps a list of Paths to MediaItems, and invoke consumer.consume() - // for each MediaItem (may not be in the same order as the input list). - // An index number is also passed to consumer.consume() to identify - // the original position in the input list of the corresponding Path (plus - // startIndex). - public void mapMediaItems(ArrayList<Path> list, ItemConsumer consumer, - int startIndex) { - HashMap<String, ArrayList<PathId>> map = - new HashMap<String, ArrayList<PathId>>(); - - // Group the path by the prefix. - int n = list.size(); - for (int i = 0; i < n; i++) { - Path path = list.get(i); - String prefix = path.getPrefix(); - ArrayList<PathId> group = map.get(prefix); - if (group == null) { - group = new ArrayList<PathId>(); - map.put(prefix, group); - } - group.add(new PathId(path, i + startIndex)); - } - - // For each group, ask the corresponding media source to map it. - for (Entry<String, ArrayList<PathId>> entry : map.entrySet()) { - String prefix = entry.getKey(); - MediaSource source = mSourceMap.get(prefix); - source.mapMediaItems(entry.getValue(), consumer); - } - } - - // The following methods forward the request to the proper object. - public int getSupportedOperations(Path path) { - return getMediaObject(path).getSupportedOperations(); - } - - public void getPanoramaSupport(Path path, PanoramaSupportCallback callback) { - getMediaObject(path).getPanoramaSupport(callback); - } - - public void delete(Path path) { - getMediaObject(path).delete(); - } - - public void rotate(Path path, int degrees) { - getMediaObject(path).rotate(degrees); - } - - public Uri getContentUri(Path path) { - return getMediaObject(path).getContentUri(); - } - - public int getMediaType(Path path) { - return getMediaObject(path).getMediaType(); - } - - public Path findPathByUri(Uri uri, String type) { - if (uri == null) return null; - for (MediaSource source : mSourceMap.values()) { - Path path = source.findPathByUri(uri, type); - if (path != null) return path; - } - return null; - } - - public Path getDefaultSetOf(Path item) { - MediaSource source = mSourceMap.get(item.getPrefix()); - return source == null ? null : source.getDefaultSetOf(item); - } - - // Returns number of bytes used by cached pictures currently downloaded. - public long getTotalUsedCacheSize() { - long sum = 0; - for (MediaSource source : mSourceMap.values()) { - sum += source.getTotalUsedCacheSize(); - } - return sum; - } - - // Returns number of bytes used by cached pictures if all pending - // downloads and removals are completed. - public long getTotalTargetCacheSize() { - long sum = 0; - for (MediaSource source : mSourceMap.values()) { - sum += source.getTotalTargetCacheSize(); - } - return sum; - } - - public void registerChangeNotifier(Uri uri, ChangeNotifier notifier) { - NotifyBroker broker = null; - synchronized (mNotifierMap) { - broker = mNotifierMap.get(uri); - if (broker == null) { - broker = new NotifyBroker(mDefaultMainHandler); - mApplication.getContentResolver() - .registerContentObserver(uri, true, broker); - mNotifierMap.put(uri, broker); - } - } - broker.registerNotifier(notifier); - } - - public void resume() { - if (++mActiveCount == 1) { - for (MediaSource source : mSourceMap.values()) { - source.resume(); - } - } - } - - public void pause() { - if (--mActiveCount == 0) { - for (MediaSource source : mSourceMap.values()) { - source.pause(); - } - } - } - - private static class NotifyBroker extends ContentObserver { - private WeakHashMap<ChangeNotifier, Object> mNotifiers = - new WeakHashMap<ChangeNotifier, Object>(); - - public NotifyBroker(Handler handler) { - super(handler); - } - - public synchronized void registerNotifier(ChangeNotifier notifier) { - mNotifiers.put(notifier, null); - } - - @Override - public synchronized void onChange(boolean selfChange) { - for(ChangeNotifier notifier : mNotifiers.keySet()) { - notifier.onChange(selfChange); - } - } - } - - @Override - public void onStitchingQueued(Uri uri) { - // Do nothing. - } - - @Override - public void onStitchingResult(Uri uri) { - Path path = findPathByUri(uri, null); - if (path != null) { - MediaObject mediaObject = getMediaObject(path); - if (mediaObject != null) { - mediaObject.clearCachedPanoramaSupport(); - } - } - } - - @Override - public void onStitchingProgress(Uri uri, int progress) { - // Do nothing. - } -} diff --git a/src/com/android/gallery3d/data/DataSourceType.java b/src/com/android/gallery3d/data/DataSourceType.java deleted file mode 100644 index ab534d0c3..000000000 --- a/src/com/android/gallery3d/data/DataSourceType.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.util.MediaSetUtils; - -public final class DataSourceType { - public static final int TYPE_NOT_CATEGORIZED = 0; - public static final int TYPE_LOCAL = 1; - public static final int TYPE_PICASA = 2; - public static final int TYPE_CAMERA = 3; - - private static final Path PICASA_ROOT = Path.fromString("/picasa"); - private static final Path LOCAL_ROOT = Path.fromString("/local"); - - public static int identifySourceType(MediaSet set) { - if (set == null) { - return TYPE_NOT_CATEGORIZED; - } - - Path path = set.getPath(); - if (MediaSetUtils.isCameraSource(path)) return TYPE_CAMERA; - - Path prefix = path.getPrefixPath(); - - if (prefix == PICASA_ROOT) return TYPE_PICASA; - if (prefix == LOCAL_ROOT) return TYPE_LOCAL; - - return TYPE_NOT_CATEGORIZED; - } -} diff --git a/src/com/android/gallery3d/data/DecodeUtils.java b/src/com/android/gallery3d/data/DecodeUtils.java deleted file mode 100644 index fa709157d..000000000 --- a/src/com/android/gallery3d/data/DecodeUtils.java +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.annotation.TargetApi; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.graphics.BitmapFactory.Options; -import android.graphics.BitmapRegionDecoder; -import android.os.Build; -import android.util.FloatMath; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.photos.data.GalleryBitmapPool; -import com.android.gallery3d.ui.Log; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.FileDescriptor; -import java.io.FileInputStream; -import java.io.InputStream; - -public class DecodeUtils { - private static final String TAG = "DecodeUtils"; - - private static class DecodeCanceller implements CancelListener { - Options mOptions; - - public DecodeCanceller(Options options) { - mOptions = options; - } - - @Override - public void onCancel() { - mOptions.requestCancelDecode(); - } - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - public static void setOptionsMutable(Options options) { - if (ApiHelper.HAS_OPTIONS_IN_MUTABLE) options.inMutable = true; - } - - public static Bitmap decode(JobContext jc, FileDescriptor fd, Options options) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - setOptionsMutable(options); - return ensureGLCompatibleBitmap( - BitmapFactory.decodeFileDescriptor(fd, null, options)); - } - - public static void decodeBounds(JobContext jc, FileDescriptor fd, - Options options) { - Utils.assertTrue(options != null); - options.inJustDecodeBounds = true; - jc.setCancelListener(new DecodeCanceller(options)); - BitmapFactory.decodeFileDescriptor(fd, null, options); - options.inJustDecodeBounds = false; - } - - public static Bitmap decode(JobContext jc, byte[] bytes, Options options) { - return decode(jc, bytes, 0, bytes.length, options); - } - - public static Bitmap decode(JobContext jc, byte[] bytes, int offset, - int length, Options options) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - setOptionsMutable(options); - return ensureGLCompatibleBitmap( - BitmapFactory.decodeByteArray(bytes, offset, length, options)); - } - - public static void decodeBounds(JobContext jc, byte[] bytes, int offset, - int length, Options options) { - Utils.assertTrue(options != null); - options.inJustDecodeBounds = true; - jc.setCancelListener(new DecodeCanceller(options)); - BitmapFactory.decodeByteArray(bytes, offset, length, options); - options.inJustDecodeBounds = false; - } - - public static Bitmap decodeThumbnail( - JobContext jc, String filePath, Options options, int targetSize, int type) { - FileInputStream fis = null; - try { - fis = new FileInputStream(filePath); - FileDescriptor fd = fis.getFD(); - return decodeThumbnail(jc, fd, options, targetSize, type); - } catch (Exception ex) { - Log.w(TAG, ex); - return null; - } finally { - Utils.closeSilently(fis); - } - } - - public static Bitmap decodeThumbnail( - JobContext jc, FileDescriptor fd, Options options, int targetSize, int type) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - - options.inJustDecodeBounds = true; - BitmapFactory.decodeFileDescriptor(fd, null, options); - if (jc.isCancelled()) return null; - - int w = options.outWidth; - int h = options.outHeight; - - if (type == MediaItem.TYPE_MICROTHUMBNAIL) { - // We center-crop the original image as it's micro thumbnail. In this case, - // we want to make sure the shorter side >= "targetSize". - float scale = (float) targetSize / Math.min(w, h); - options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); - - // For an extremely wide image, e.g. 300x30000, we may got OOM when decoding - // it for TYPE_MICROTHUMBNAIL. So we add a max number of pixels limit here. - final int MAX_PIXEL_COUNT = 640000; // 400 x 1600 - if ((w / options.inSampleSize) * (h / options.inSampleSize) > MAX_PIXEL_COUNT) { - options.inSampleSize = BitmapUtils.computeSampleSize( - FloatMath.sqrt((float) MAX_PIXEL_COUNT / (w * h))); - } - } else { - // For screen nail, we only want to keep the longer side >= targetSize. - float scale = (float) targetSize / Math.max(w, h); - options.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale); - } - - options.inJustDecodeBounds = false; - setOptionsMutable(options); - - Bitmap result = BitmapFactory.decodeFileDescriptor(fd, null, options); - if (result == null) return null; - - // We need to resize down if the decoder does not support inSampleSize - // (For example, GIF images) - float scale = (float) targetSize / (type == MediaItem.TYPE_MICROTHUMBNAIL - ? Math.min(result.getWidth(), result.getHeight()) - : Math.max(result.getWidth(), result.getHeight())); - - if (scale <= 0.5) result = BitmapUtils.resizeBitmapByScale(result, scale, true); - return ensureGLCompatibleBitmap(result); - } - - /** - * Decodes the bitmap from the given byte array if the image size is larger than the given - * requirement. - * - * Note: The returned image may be resized down. However, both width and height must be - * larger than the <code>targetSize</code>. - */ - public static Bitmap decodeIfBigEnough(JobContext jc, byte[] data, - Options options, int targetSize) { - if (options == null) options = new Options(); - jc.setCancelListener(new DecodeCanceller(options)); - - options.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(data, 0, data.length, options); - if (jc.isCancelled()) return null; - if (options.outWidth < targetSize || options.outHeight < targetSize) { - return null; - } - options.inSampleSize = BitmapUtils.computeSampleSizeLarger( - options.outWidth, options.outHeight, targetSize); - options.inJustDecodeBounds = false; - setOptionsMutable(options); - - return ensureGLCompatibleBitmap( - BitmapFactory.decodeByteArray(data, 0, data.length, options)); - } - - // TODO: This function should not be called directly from - // DecodeUtils.requestDecode(...), since we don't have the knowledge - // if the bitmap will be uploaded to GL. - public static Bitmap ensureGLCompatibleBitmap(Bitmap bitmap) { - if (bitmap == null || bitmap.getConfig() != null) return bitmap; - Bitmap newBitmap = bitmap.copy(Config.ARGB_8888, false); - bitmap.recycle(); - return newBitmap; - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, byte[] bytes, int offset, int length, - boolean shareable) { - if (offset < 0 || length <= 0 || offset + length > bytes.length) { - throw new IllegalArgumentException(String.format( - "offset = %s, length = %s, bytes = %s", - offset, length, bytes.length)); - } - - try { - return BitmapRegionDecoder.newInstance( - bytes, offset, length, shareable); - } catch (Throwable t) { - Log.w(TAG, t); - return null; - } - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, String filePath, boolean shareable) { - try { - return BitmapRegionDecoder.newInstance(filePath, shareable); - } catch (Throwable t) { - Log.w(TAG, t); - return null; - } - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, FileDescriptor fd, boolean shareable) { - try { - return BitmapRegionDecoder.newInstance(fd, shareable); - } catch (Throwable t) { - Log.w(TAG, t); - return null; - } - } - - public static BitmapRegionDecoder createBitmapRegionDecoder( - JobContext jc, InputStream is, boolean shareable) { - try { - return BitmapRegionDecoder.newInstance(is, shareable); - } catch (Throwable t) { - // We often cancel the creating of bitmap region decoder, - // so just log one line. - Log.w(TAG, "requestCreateBitmapRegionDecoder: " + t); - return null; - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static Bitmap decodeUsingPool(JobContext jc, byte[] data, int offset, - int length, BitmapFactory.Options options) { - if (options == null) options = new BitmapFactory.Options(); - if (options.inSampleSize < 1) options.inSampleSize = 1; - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - options.inBitmap = (options.inSampleSize == 1) - ? findCachedBitmap(jc, data, offset, length, options) : null; - try { - Bitmap bitmap = decode(jc, data, offset, length, options); - if (options.inBitmap != null && options.inBitmap != bitmap) { - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - } - return bitmap; - } catch (IllegalArgumentException e) { - if (options.inBitmap == null) throw e; - - Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - return decode(jc, data, offset, length, options); - } - } - - // This is the same as the method above except the source data comes - // from a file descriptor instead of a byte array. - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public static Bitmap decodeUsingPool(JobContext jc, - FileDescriptor fileDescriptor, Options options) { - if (options == null) options = new BitmapFactory.Options(); - if (options.inSampleSize < 1) options.inSampleSize = 1; - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - options.inBitmap = (options.inSampleSize == 1) - ? findCachedBitmap(jc, fileDescriptor, options) : null; - try { - Bitmap bitmap = DecodeUtils.decode(jc, fileDescriptor, options); - if (options.inBitmap != null && options.inBitmap != bitmap) { - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - } - return bitmap; - } catch (IllegalArgumentException e) { - if (options.inBitmap == null) throw e; - - Log.w(TAG, "decode fail with a given bitmap, try decode to a new bitmap"); - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - return decode(jc, fileDescriptor, options); - } - } - - private static Bitmap findCachedBitmap(JobContext jc, byte[] data, - int offset, int length, Options options) { - decodeBounds(jc, data, offset, length, options); - return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); - } - - private static Bitmap findCachedBitmap(JobContext jc, FileDescriptor fileDescriptor, - Options options) { - decodeBounds(jc, fileDescriptor, options); - return GalleryBitmapPool.getInstance().get(options.outWidth, options.outHeight); - } -} diff --git a/src/com/android/gallery3d/data/DownloadCache.java b/src/com/android/gallery3d/data/DownloadCache.java deleted file mode 100644 index be7820b01..000000000 --- a/src/com/android/gallery3d/data/DownloadCache.java +++ /dev/null @@ -1,370 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.LruCache; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DownloadEntry.Columns; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.File; -import java.net.URL; -import java.util.HashMap; -import java.util.HashSet; - -public class DownloadCache { - private static final String TAG = "DownloadCache"; - private static final int MAX_DELETE_COUNT = 16; - private static final int LRU_CAPACITY = 4; - - private static final String TABLE_NAME = DownloadEntry.SCHEMA.getTableName(); - - private static final String QUERY_PROJECTION[] = {Columns.ID, Columns.DATA}; - private static final String WHERE_HASH_AND_URL = String.format( - "%s = ? AND %s = ?", Columns.HASH_CODE, Columns.CONTENT_URL); - private static final int QUERY_INDEX_ID = 0; - private static final int QUERY_INDEX_DATA = 1; - - private static final String FREESPACE_PROJECTION[] = { - Columns.ID, Columns.DATA, Columns.CONTENT_URL, Columns.CONTENT_SIZE}; - private static final String FREESPACE_ORDER_BY = - String.format("%s ASC", Columns.LAST_ACCESS); - private static final int FREESPACE_IDNEX_ID = 0; - private static final int FREESPACE_IDNEX_DATA = 1; - private static final int FREESPACE_INDEX_CONTENT_URL = 2; - private static final int FREESPACE_INDEX_CONTENT_SIZE = 3; - - private static final String ID_WHERE = Columns.ID + " = ?"; - - private static final String SUM_PROJECTION[] = - {String.format("sum(%s)", Columns.CONTENT_SIZE)}; - private static final int SUM_INDEX_SUM = 0; - - private final LruCache<String, Entry> mEntryMap = - new LruCache<String, Entry>(LRU_CAPACITY); - private final HashMap<String, DownloadTask> mTaskMap = - new HashMap<String, DownloadTask>(); - private final File mRoot; - private final GalleryApp mApplication; - private final SQLiteDatabase mDatabase; - private final long mCapacity; - - private long mTotalBytes = 0; - private boolean mInitialized = false; - - public DownloadCache(GalleryApp application, File root, long capacity) { - mRoot = Utils.checkNotNull(root); - mApplication = Utils.checkNotNull(application); - mCapacity = capacity; - mDatabase = new DatabaseHelper(application.getAndroidContext()) - .getWritableDatabase(); - } - - private Entry findEntryInDatabase(String stringUrl) { - long hash = Utils.crc64Long(stringUrl); - String whereArgs[] = {String.valueOf(hash), stringUrl}; - Cursor cursor = mDatabase.query(TABLE_NAME, QUERY_PROJECTION, - WHERE_HASH_AND_URL, whereArgs, null, null, null); - try { - if (cursor.moveToNext()) { - File file = new File(cursor.getString(QUERY_INDEX_DATA)); - long id = cursor.getInt(QUERY_INDEX_ID); - Entry entry = null; - synchronized (mEntryMap) { - entry = mEntryMap.get(stringUrl); - if (entry == null) { - entry = new Entry(id, file); - mEntryMap.put(stringUrl, entry); - } - } - return entry; - } - } finally { - cursor.close(); - } - return null; - } - - public Entry download(JobContext jc, URL url) { - if (!mInitialized) initialize(); - - String stringUrl = url.toString(); - - // First find in the entry-pool - synchronized (mEntryMap) { - Entry entry = mEntryMap.get(stringUrl); - if (entry != null) { - updateLastAccess(entry.mId); - return entry; - } - } - - // Then, find it in database - TaskProxy proxy = new TaskProxy(); - synchronized (mTaskMap) { - Entry entry = findEntryInDatabase(stringUrl); - if (entry != null) { - updateLastAccess(entry.mId); - return entry; - } - - // Finally, we need to download the file .... - // First check if we are downloading it now ... - DownloadTask task = mTaskMap.get(stringUrl); - if (task == null) { // if not, start the download task now - task = new DownloadTask(stringUrl); - mTaskMap.put(stringUrl, task); - task.mFuture = mApplication.getThreadPool().submit(task, task); - } - task.addProxy(proxy); - } - - return proxy.get(jc); - } - - private void updateLastAccess(long id) { - ContentValues values = new ContentValues(); - values.put(Columns.LAST_ACCESS, System.currentTimeMillis()); - mDatabase.update(TABLE_NAME, values, - ID_WHERE, new String[] {String.valueOf(id)}); - } - - private synchronized void freeSomeSpaceIfNeed(int maxDeleteFileCount) { - if (mTotalBytes <= mCapacity) return; - Cursor cursor = mDatabase.query(TABLE_NAME, - FREESPACE_PROJECTION, null, null, null, null, FREESPACE_ORDER_BY); - try { - while (maxDeleteFileCount > 0 - && mTotalBytes > mCapacity && cursor.moveToNext()) { - long id = cursor.getLong(FREESPACE_IDNEX_ID); - String url = cursor.getString(FREESPACE_INDEX_CONTENT_URL); - long size = cursor.getLong(FREESPACE_INDEX_CONTENT_SIZE); - String path = cursor.getString(FREESPACE_IDNEX_DATA); - boolean containsKey; - synchronized (mEntryMap) { - containsKey = mEntryMap.containsKey(url); - } - if (!containsKey) { - --maxDeleteFileCount; - mTotalBytes -= size; - new File(path).delete(); - mDatabase.delete(TABLE_NAME, - ID_WHERE, new String[]{String.valueOf(id)}); - } else { - // skip delete, since it is being used - } - } - } finally { - cursor.close(); - } - } - - private synchronized long insertEntry(String url, File file) { - long size = file.length(); - mTotalBytes += size; - - ContentValues values = new ContentValues(); - String hashCode = String.valueOf(Utils.crc64Long(url)); - values.put(Columns.DATA, file.getAbsolutePath()); - values.put(Columns.HASH_CODE, hashCode); - values.put(Columns.CONTENT_URL, url); - values.put(Columns.CONTENT_SIZE, size); - values.put(Columns.LAST_UPDATED, System.currentTimeMillis()); - return mDatabase.insert(TABLE_NAME, "", values); - } - - private synchronized void initialize() { - if (mInitialized) return; - mInitialized = true; - if (!mRoot.isDirectory()) mRoot.mkdirs(); - if (!mRoot.isDirectory()) { - throw new RuntimeException("cannot create " + mRoot.getAbsolutePath()); - } - - Cursor cursor = mDatabase.query( - TABLE_NAME, SUM_PROJECTION, null, null, null, null, null); - mTotalBytes = 0; - try { - if (cursor.moveToNext()) { - mTotalBytes = cursor.getLong(SUM_INDEX_SUM); - } - } finally { - cursor.close(); - } - if (mTotalBytes > mCapacity) freeSomeSpaceIfNeed(MAX_DELETE_COUNT); - } - - private final class DatabaseHelper extends SQLiteOpenHelper { - public static final String DATABASE_NAME = "download.db"; - public static final int DATABASE_VERSION = 2; - - public DatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - DownloadEntry.SCHEMA.createTables(db); - // Delete old files - for (File file : mRoot.listFiles()) { - if (!file.delete()) { - Log.w(TAG, "fail to remove: " + file.getAbsolutePath()); - } - } - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - //reset everything - DownloadEntry.SCHEMA.dropTables(db); - onCreate(db); - } - } - - public class Entry { - public File cacheFile; - protected long mId; - - Entry(long id, File cacheFile) { - mId = id; - this.cacheFile = Utils.checkNotNull(cacheFile); - } - } - - private class DownloadTask implements Job<File>, FutureListener<File> { - private HashSet<TaskProxy> mProxySet = new HashSet<TaskProxy>(); - private Future<File> mFuture; - private final String mUrl; - - public DownloadTask(String url) { - mUrl = Utils.checkNotNull(url); - } - - public void removeProxy(TaskProxy proxy) { - synchronized (mTaskMap) { - Utils.assertTrue(mProxySet.remove(proxy)); - if (mProxySet.isEmpty()) { - mFuture.cancel(); - mTaskMap.remove(mUrl); - } - } - } - - // should be used in synchronized block of mDatabase - public void addProxy(TaskProxy proxy) { - proxy.mTask = this; - mProxySet.add(proxy); - } - - @Override - public void onFutureDone(Future<File> future) { - File file = future.get(); - long id = 0; - if (file != null) { // insert to database - id = insertEntry(mUrl, file); - } - - if (future.isCancelled()) { - Utils.assertTrue(mProxySet.isEmpty()); - return; - } - - synchronized (mTaskMap) { - Entry entry = null; - synchronized (mEntryMap) { - if (file != null) { - entry = new Entry(id, file); - Utils.assertTrue(mEntryMap.put(mUrl, entry) == null); - } - } - for (TaskProxy proxy : mProxySet) { - proxy.setResult(entry); - } - mTaskMap.remove(mUrl); - freeSomeSpaceIfNeed(MAX_DELETE_COUNT); - } - } - - @Override - public File run(JobContext jc) { - // TODO: utilize etag - jc.setMode(ThreadPool.MODE_NETWORK); - File tempFile = null; - try { - URL url = new URL(mUrl); - tempFile = File.createTempFile("cache", ".tmp", mRoot); - // download from url to tempFile - jc.setMode(ThreadPool.MODE_NETWORK); - boolean downloaded = DownloadUtils.requestDownload(jc, url, tempFile); - jc.setMode(ThreadPool.MODE_NONE); - if (downloaded) return tempFile; - } catch (Exception e) { - Log.e(TAG, String.format("fail to download %s", mUrl), e); - } finally { - jc.setMode(ThreadPool.MODE_NONE); - } - if (tempFile != null) tempFile.delete(); - return null; - } - } - - public static class TaskProxy { - private DownloadTask mTask; - private boolean mIsCancelled = false; - private Entry mEntry; - - synchronized void setResult(Entry entry) { - if (mIsCancelled) return; - mEntry = entry; - notifyAll(); - } - - public synchronized Entry get(JobContext jc) { - jc.setCancelListener(new CancelListener() { - @Override - public void onCancel() { - mTask.removeProxy(TaskProxy.this); - synchronized (TaskProxy.this) { - mIsCancelled = true; - TaskProxy.this.notifyAll(); - } - } - }); - while (!mIsCancelled && mEntry == null) { - try { - wait(); - } catch (InterruptedException e) { - Log.w(TAG, "ignore interrupt", e); - } - } - jc.setCancelListener(null); - return mEntry; - } - } -} diff --git a/src/com/android/gallery3d/data/DownloadEntry.java b/src/com/android/gallery3d/data/DownloadEntry.java deleted file mode 100644 index 578523f73..000000000 --- a/src/com/android/gallery3d/data/DownloadEntry.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.data; - -import com.android.gallery3d.common.Entry; -import com.android.gallery3d.common.EntrySchema; - - -@Entry.Table("download") -public class DownloadEntry extends Entry { - public static final EntrySchema SCHEMA = new EntrySchema(DownloadEntry.class); - - public static interface Columns extends Entry.Columns { - public static final String HASH_CODE = "hash_code"; - public static final String CONTENT_URL = "content_url"; - public static final String CONTENT_SIZE = "_size"; - public static final String ETAG = "etag"; - public static final String LAST_ACCESS = "last_access"; - public static final String LAST_UPDATED = "last_updated"; - public static final String DATA = "_data"; - } - - @Column(value = "hash_code", indexed = true) - public long hashCode; - - @Column("content_url") - public String contentUrl; - - @Column("_size") - public long contentSize; - - @Column("etag") - public String eTag; - - @Column(value = "last_access", indexed = true) - public long lastAccessTime; - - @Column(value = "last_updated") - public long lastUpdatedTime; - - @Column("_data") - public String path; - - @Override - public String toString() { - // Note: THIS IS REQUIRED. We used all the fields here. Otherwise, - // ProGuard will remove these UNUSED fields. However, these - // fields are needed to generate database. - return new StringBuilder() - .append("hash_code: ").append(hashCode).append(", ") - .append("content_url").append(contentUrl).append(", ") - .append("_size").append(contentSize).append(", ") - .append("etag").append(eTag).append(", ") - .append("last_access").append(lastAccessTime).append(", ") - .append("last_updated").append(lastUpdatedTime).append(",") - .append("_data").append(path) - .toString(); - } -} diff --git a/src/com/android/gallery3d/data/DownloadUtils.java b/src/com/android/gallery3d/data/DownloadUtils.java deleted file mode 100644 index 137898e91..000000000 --- a/src/com/android/gallery3d/data/DownloadUtils.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.io.OutputStream; -import java.net.URL; - -public class DownloadUtils { - private static final String TAG = "DownloadService"; - - public static boolean requestDownload(JobContext jc, URL url, File file) { - FileOutputStream fos = null; - try { - fos = new FileOutputStream(file); - return download(jc, url, fos); - } catch (Throwable t) { - return false; - } finally { - Utils.closeSilently(fos); - } - } - - public static void dump(JobContext jc, InputStream is, OutputStream os) - throws IOException { - byte buffer[] = new byte[4096]; - int rc = is.read(buffer, 0, buffer.length); - final Thread thread = Thread.currentThread(); - jc.setCancelListener(new CancelListener() { - @Override - public void onCancel() { - thread.interrupt(); - } - }); - while (rc > 0) { - if (jc.isCancelled()) throw new InterruptedIOException(); - os.write(buffer, 0, rc); - rc = is.read(buffer, 0, buffer.length); - } - jc.setCancelListener(null); - Thread.interrupted(); // consume the interrupt signal - } - - public static boolean download(JobContext jc, URL url, OutputStream output) { - InputStream input = null; - try { - input = url.openStream(); - dump(jc, input, output); - return true; - } catch (Throwable t) { - Log.w(TAG, "fail to download", t); - return false; - } finally { - Utils.closeSilently(input); - } - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/data/EmptyAlbumImage.java b/src/com/android/gallery3d/data/EmptyAlbumImage.java deleted file mode 100644 index 6f8c37c6b..000000000 --- a/src/com/android/gallery3d/data/EmptyAlbumImage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; - -public class EmptyAlbumImage extends ActionImage { - @SuppressWarnings("unused") - private static final String TAG = "EmptyAlbumImage"; - - public EmptyAlbumImage(Path path, GalleryApp application) { - super(path, application, R.drawable.placeholder_empty); - } - - @Override - public int getSupportedOperations() { - return super.getSupportedOperations() | SUPPORT_BACK; - } -} diff --git a/src/com/android/gallery3d/data/Exif.java b/src/com/android/gallery3d/data/Exif.java deleted file mode 100644 index 950e7de18..000000000 --- a/src/com/android/gallery3d/data/Exif.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.util.Log; - -import com.android.gallery3d.exif.ExifInterface; - -import java.io.IOException; -import java.io.InputStream; - -public class Exif { - private static final String TAG = "CameraExif"; - - // Returns the degrees in clockwise. Values are 0, 90, 180, or 270. - public static int getOrientation(InputStream is) { - if (is == null) { - return 0; - } - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(is); - Integer val = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION); - if (val == null) { - return 0; - } else { - return ExifInterface.getRotationForOrientationValue(val.shortValue()); - } - } catch (IOException e) { - Log.w(TAG, "Failed to read EXIF orientation", e); - return 0; - } - } -} diff --git a/src/com/android/gallery3d/data/Face.java b/src/com/android/gallery3d/data/Face.java deleted file mode 100644 index d2dc22bfc..000000000 --- a/src/com/android/gallery3d/data/Face.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.graphics.Rect; - -import com.android.gallery3d.common.Utils; - -import java.util.StringTokenizer; - -public class Face implements Comparable<Face> { - private String mName; - private String mPersonId; - private Rect mPosition; - - public Face(String name, String personId, String rect) { - mName = name; - mPersonId = personId; - Utils.assertTrue(mName != null && mPersonId != null && rect != null); - StringTokenizer tokenizer = new StringTokenizer(rect); - mPosition = new Rect(); - while (tokenizer.hasMoreElements()) { - mPosition.left = Integer.parseInt(tokenizer.nextToken()); - mPosition.top = Integer.parseInt(tokenizer.nextToken()); - mPosition.right = Integer.parseInt(tokenizer.nextToken()); - mPosition.bottom = Integer.parseInt(tokenizer.nextToken()); - } - } - - public Rect getPosition() { - return mPosition; - } - - public String getName() { - return mName; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Face) { - Face face = (Face) obj; - return mPersonId.equals(face.mPersonId); - } - return false; - } - - @Override - public int compareTo(Face another) { - return mName.compareTo(another.mName); - } -} diff --git a/src/com/android/gallery3d/data/FaceClustering.java b/src/com/android/gallery3d/data/FaceClustering.java deleted file mode 100644 index 819915edb..000000000 --- a/src/com/android/gallery3d/data/FaceClustering.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.graphics.Rect; - -import com.android.gallery3d.R; -import com.android.gallery3d.picasasource.PicasaSource; - -import java.util.ArrayList; -import java.util.TreeMap; - -public class FaceClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "FaceClustering"; - - private FaceCluster[] mClusters; - private String mUntaggedString; - private Context mContext; - - private class FaceCluster { - ArrayList<Path> mPaths = new ArrayList<Path>(); - String mName; - MediaItem mCoverItem; - Rect mCoverRegion; - int mCoverFaceIndex; - - public FaceCluster(String name) { - mName = name; - } - - public void add(MediaItem item, int faceIndex) { - Path path = item.getPath(); - mPaths.add(path); - Face[] faces = item.getFaces(); - if (faces != null) { - Face face = faces[faceIndex]; - if (mCoverItem == null) { - mCoverItem = item; - mCoverRegion = face.getPosition(); - mCoverFaceIndex = faceIndex; - } else { - Rect region = face.getPosition(); - if (mCoverRegion.width() < region.width() && - mCoverRegion.height() < region.height()) { - mCoverItem = item; - mCoverRegion = face.getPosition(); - mCoverFaceIndex = faceIndex; - } - } - } - } - - public int size() { - return mPaths.size(); - } - - public MediaItem getCover() { - if (mCoverItem != null) { - if (PicasaSource.isPicasaImage(mCoverItem)) { - return PicasaSource.getFaceItem(mContext, mCoverItem, mCoverFaceIndex); - } else { - return mCoverItem; - } - } - return null; - } - } - - public FaceClustering(Context context) { - mUntaggedString = context.getResources().getString(R.string.untagged); - mContext = context; - } - - @Override - public void run(MediaSet baseSet) { - final TreeMap<Face, FaceCluster> map = - new TreeMap<Face, FaceCluster>(); - final FaceCluster untagged = new FaceCluster(mUntaggedString); - - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - Face[] faces = item.getFaces(); - if (faces == null || faces.length == 0) { - untagged.add(item, -1); - return; - } - for (int j = 0; j < faces.length; j++) { - Face face = faces[j]; - FaceCluster cluster = map.get(face); - if (cluster == null) { - cluster = new FaceCluster(face.getName()); - map.put(face, cluster); - } - cluster.add(item, j); - } - } - }); - - int m = map.size(); - mClusters = map.values().toArray(new FaceCluster[m + ((untagged.size() > 0) ? 1 : 0)]); - if (untagged.size() > 0) { - mClusters[m] = untagged; - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.length; - } - - @Override - public ArrayList<Path> getCluster(int index) { - return mClusters[index].mPaths; - } - - @Override - public String getClusterName(int index) { - return mClusters[index].mName; - } - - @Override - public MediaItem getClusterCover(int index) { - return mClusters[index].getCover(); - } -} diff --git a/src/com/android/gallery3d/data/FilterDeleteSet.java b/src/com/android/gallery3d/data/FilterDeleteSet.java deleted file mode 100644 index c76412ff8..000000000 --- a/src/com/android/gallery3d/data/FilterDeleteSet.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -// FilterDeleteSet filters a base MediaSet to remove some deletion items (we -// expect the number to be small). The user can use the following methods to -// add/remove deletion items: -// -// void addDeletion(Path path, int index); -// void removeDelection(Path path); -// void clearDeletion(); -// int getNumberOfDeletions(); -// -public class FilterDeleteSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "FilterDeleteSet"; - - private static final int REQUEST_ADD = 1; - private static final int REQUEST_REMOVE = 2; - private static final int REQUEST_CLEAR = 3; - - private static class Request { - int type; // one of the REQUEST_* constants - Path path; - int indexHint; - public Request(int type, Path path, int indexHint) { - this.type = type; - this.path = path; - this.indexHint = indexHint; - } - } - - private static class Deletion { - Path path; - int index; - public Deletion(Path path, int index) { - this.path = path; - this.index = index; - } - } - - // The underlying MediaSet - private final MediaSet mBaseSet; - - // Pending Requests - private ArrayList<Request> mRequests = new ArrayList<Request>(); - - // Deletions currently in effect, ordered by index - private ArrayList<Deletion> mCurrent = new ArrayList<Deletion>(); - - public FilterDeleteSet(Path path, MediaSet baseSet) { - super(path, INVALID_DATA_VERSION); - mBaseSet = baseSet; - mBaseSet.addContentListener(this); - } - - @Override - public boolean isCameraRoll() { - return mBaseSet.isCameraRoll(); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } - - @Override - public int getMediaItemCount() { - return mBaseSet.getMediaItemCount() - mCurrent.size(); - } - - // Gets the MediaItems whose (post-deletion) index are in the range [start, - // start + count). Because we remove some of the MediaItems, the index need - // to be adjusted. - // - // For example, if there are 12 items in total. The deleted items are 3, 5, - // 10, and the the requested range is [3, 7]: - // - // The original index: 0 1 2 3 4 5 6 7 8 9 A B C - // The deleted items: X X X - // The new index: 0 1 2 3 4 5 6 7 8 9 - // Requested: * * * * * - // - // We need to figure out the [3, 7] actually maps to the original index 4, - // 6, 7, 8, 9. - // - // We can break the MediaItems into segments, each segment other than the - // last one ends in a deleted item. The difference between the new index and - // the original index increases with each segment: - // - // 0 1 2 X (new index = old index) - // 4 X (new index = old index - 1) - // 6 7 8 9 X (new index = old index - 2) - // B C (new index = old index - 3) - // - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - if (count <= 0) return new ArrayList<MediaItem>(); - - int end = start + count - 1; - int n = mCurrent.size(); - // Find the segment that "start" falls into. Count the number of items - // not yet deleted until it reaches "start". - int i = 0; - for (i = 0; i < n; i++) { - Deletion d = mCurrent.get(i); - if (d.index - i > start) break; - } - // Find the segment that "end" falls into. - int j = i; - for (; j < n; j++) { - Deletion d = mCurrent.get(j); - if (d.index - j > end) break; - } - - // Now get enough to cover deleted items in [start, end] - ArrayList<MediaItem> base = mBaseSet.getMediaItem(start + i, count + (j - i)); - - // Remove the deleted items. - for (int m = j - 1; m >= i; m--) { - Deletion d = mCurrent.get(m); - int k = d.index - (start + i); - base.remove(k); - } - return base; - } - - // We apply the pending requests in the mRequests to construct mCurrent in reload(). - @Override - public long reload() { - boolean newData = mBaseSet.reload() > mDataVersion; - synchronized (mRequests) { - if (!newData && mRequests.isEmpty()) { - return mDataVersion; - } - for (int i = 0; i < mRequests.size(); i++) { - Request r = mRequests.get(i); - switch (r.type) { - case REQUEST_ADD: { - // Add the path into mCurrent if there is no duplicate. - int n = mCurrent.size(); - int j; - for (j = 0; j < n; j++) { - if (mCurrent.get(j).path == r.path) break; - } - if (j == n) { - mCurrent.add(new Deletion(r.path, r.indexHint)); - } - break; - } - case REQUEST_REMOVE: { - // Remove the path from mCurrent. - int n = mCurrent.size(); - for (int j = 0; j < n; j++) { - if (mCurrent.get(j).path == r.path) { - mCurrent.remove(j); - break; - } - } - break; - } - case REQUEST_CLEAR: { - mCurrent.clear(); - break; - } - } - } - mRequests.clear(); - } - - if (!mCurrent.isEmpty()) { - // See if the elements in mCurrent can be found in the MediaSet. We - // don't want to search the whole mBaseSet, so we just search a - // small window that contains the index hints (plus some margin). - int minIndex = mCurrent.get(0).index; - int maxIndex = minIndex; - for (int i = 1; i < mCurrent.size(); i++) { - Deletion d = mCurrent.get(i); - minIndex = Math.min(d.index, minIndex); - maxIndex = Math.max(d.index, maxIndex); - } - - int n = mBaseSet.getMediaItemCount(); - int from = Math.max(minIndex - 5, 0); - int to = Math.min(maxIndex + 5, n); - ArrayList<MediaItem> items = mBaseSet.getMediaItem(from, to - from); - ArrayList<Deletion> result = new ArrayList<Deletion>(); - for (int i = 0; i < items.size(); i++) { - MediaItem item = items.get(i); - if (item == null) continue; - Path p = item.getPath(); - // Find the matching path in mCurrent, if found move it to result - for (int j = 0; j < mCurrent.size(); j++) { - Deletion d = mCurrent.get(j); - if (d.path == p) { - d.index = from + i; - result.add(d); - mCurrent.remove(j); - break; - } - } - } - mCurrent = result; - } - - mDataVersion = nextVersionNumber(); - return mDataVersion; - } - - private void sendRequest(int type, Path path, int indexHint) { - Request r = new Request(type, path, indexHint); - synchronized (mRequests) { - mRequests.add(r); - } - notifyContentChanged(); - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - public void addDeletion(Path path, int indexHint) { - sendRequest(REQUEST_ADD, path, indexHint); - } - - public void removeDeletion(Path path) { - sendRequest(REQUEST_REMOVE, path, 0 /* unused */); - } - - public void clearDeletion() { - sendRequest(REQUEST_CLEAR, null /* unused */ , 0 /* unused */); - } - - // Returns number of deletions _in effect_ (the number will only gets - // updated after a reload()). - public int getNumberOfDeletions() { - return mCurrent.size(); - } -} diff --git a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java b/src/com/android/gallery3d/data/FilterEmptyPromptSet.java deleted file mode 100644 index b576e06d4..000000000 --- a/src/com/android/gallery3d/data/FilterEmptyPromptSet.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -public class FilterEmptyPromptSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "FilterEmptyPromptSet"; - - private ArrayList<MediaItem> mEmptyItem; - private MediaSet mBaseSet; - - public FilterEmptyPromptSet(Path path, MediaSet baseSet, MediaItem emptyItem) { - super(path, INVALID_DATA_VERSION); - mEmptyItem = new ArrayList<MediaItem>(1); - mEmptyItem.add(emptyItem); - mBaseSet = baseSet; - mBaseSet.addContentListener(this); - } - - @Override - public int getMediaItemCount() { - int itemCount = mBaseSet.getMediaItemCount(); - if (itemCount > 0) { - return itemCount; - } else { - return 1; - } - } - - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - int itemCount = mBaseSet.getMediaItemCount(); - if (itemCount > 0) { - return mBaseSet.getMediaItem(start, count); - } else if (start == 0 && count == 1) { - return mEmptyItem; - } else { - throw new ArrayIndexOutOfBoundsException(); - } - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public boolean isCameraRoll() { - return mBaseSet.isCameraRoll(); - } - - @Override - public long reload() { - return mBaseSet.reload(); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } -} diff --git a/src/com/android/gallery3d/data/FilterSource.java b/src/com/android/gallery3d/data/FilterSource.java deleted file mode 100644 index d689fe336..000000000 --- a/src/com/android/gallery3d/data/FilterSource.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -public class FilterSource extends MediaSource { - @SuppressWarnings("unused") - private static final String TAG = "FilterSource"; - private static final int FILTER_BY_MEDIATYPE = 0; - private static final int FILTER_BY_DELETE = 1; - private static final int FILTER_BY_EMPTY = 2; - private static final int FILTER_BY_EMPTY_ITEM = 3; - private static final int FILTER_BY_CAMERA_SHORTCUT = 4; - private static final int FILTER_BY_CAMERA_SHORTCUT_ITEM = 5; - - public static final String FILTER_EMPTY_ITEM = "/filter/empty_prompt"; - public static final String FILTER_CAMERA_SHORTCUT = "/filter/camera_shortcut"; - private static final String FILTER_CAMERA_SHORTCUT_ITEM = "/filter/camera_shortcut_item"; - - private GalleryApp mApplication; - private PathMatcher mMatcher; - private MediaItem mEmptyItem; - private MediaItem mCameraShortcutItem; - - public FilterSource(GalleryApp application) { - super("filter"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/filter/mediatype/*/*", FILTER_BY_MEDIATYPE); - mMatcher.add("/filter/delete/*", FILTER_BY_DELETE); - mMatcher.add("/filter/empty/*", FILTER_BY_EMPTY); - mMatcher.add(FILTER_EMPTY_ITEM, FILTER_BY_EMPTY_ITEM); - mMatcher.add(FILTER_CAMERA_SHORTCUT, FILTER_BY_CAMERA_SHORTCUT); - mMatcher.add(FILTER_CAMERA_SHORTCUT_ITEM, FILTER_BY_CAMERA_SHORTCUT_ITEM); - - mEmptyItem = new EmptyAlbumImage(Path.fromString(FILTER_EMPTY_ITEM), - mApplication); - mCameraShortcutItem = new CameraShortcutImage( - Path.fromString(FILTER_CAMERA_SHORTCUT_ITEM), mApplication); - } - - // The name we accept are: - // /filter/mediatype/k/{set} where k is the media type we want. - // /filter/delete/{set} - @Override - public MediaObject createMediaObject(Path path) { - int matchType = mMatcher.match(path); - DataManager dataManager = mApplication.getDataManager(); - switch (matchType) { - case FILTER_BY_MEDIATYPE: { - int mediaType = mMatcher.getIntVar(0); - String setsName = mMatcher.getVar(1); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - return new FilterTypeSet(path, dataManager, sets[0], mediaType); - } - case FILTER_BY_DELETE: { - String setsName = mMatcher.getVar(0); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - return new FilterDeleteSet(path, sets[0]); - } - case FILTER_BY_EMPTY: { - String setsName = mMatcher.getVar(0); - MediaSet[] sets = dataManager.getMediaSetsFromString(setsName); - return new FilterEmptyPromptSet(path, sets[0], mEmptyItem); - } - case FILTER_BY_EMPTY_ITEM: { - return mEmptyItem; - } - case FILTER_BY_CAMERA_SHORTCUT: { - return new SingleItemAlbum(path, mCameraShortcutItem); - } - case FILTER_BY_CAMERA_SHORTCUT_ITEM: { - return mCameraShortcutItem; - } - default: - throw new RuntimeException("bad path: " + path); - } - } -} diff --git a/src/com/android/gallery3d/data/FilterTypeSet.java b/src/com/android/gallery3d/data/FilterTypeSet.java deleted file mode 100644 index 477ef73ad..000000000 --- a/src/com/android/gallery3d/data/FilterTypeSet.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -// FilterTypeSet filters a base MediaSet according to a matching media type. -public class FilterTypeSet extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "FilterTypeSet"; - - private final DataManager mDataManager; - private final MediaSet mBaseSet; - private final int mMediaType; - private final ArrayList<Path> mPaths = new ArrayList<Path>(); - private final ArrayList<MediaSet> mAlbums = new ArrayList<MediaSet>(); - - public FilterTypeSet(Path path, DataManager dataManager, MediaSet baseSet, - int mediaType) { - super(path, INVALID_DATA_VERSION); - mDataManager = dataManager; - mBaseSet = baseSet; - mMediaType = mediaType; - mBaseSet.addContentListener(this); - } - - @Override - public String getName() { - return mBaseSet.getName(); - } - - @Override - public MediaSet getSubMediaSet(int index) { - return mAlbums.get(index); - } - - @Override - public int getSubMediaSetCount() { - return mAlbums.size(); - } - - @Override - public int getMediaItemCount() { - return mPaths.size(); - } - - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - return ClusterAlbum.getMediaItemFromPath( - mPaths, start, count, mDataManager); - } - - @Override - public long reload() { - if (mBaseSet.reload() > mDataVersion) { - updateData(); - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - private void updateData() { - // Albums - mAlbums.clear(); - String basePath = "/filter/mediatype/" + mMediaType; - - for (int i = 0, n = mBaseSet.getSubMediaSetCount(); i < n; i++) { - MediaSet set = mBaseSet.getSubMediaSet(i); - String filteredPath = basePath + "/{" + set.getPath().toString() + "}"; - MediaSet filteredSet = mDataManager.getMediaSet(filteredPath); - filteredSet.reload(); - if (filteredSet.getMediaItemCount() > 0 - || filteredSet.getSubMediaSetCount() > 0) { - mAlbums.add(filteredSet); - } - } - - // Items - mPaths.clear(); - final int total = mBaseSet.getMediaItemCount(); - final Path[] buf = new Path[total]; - - mBaseSet.enumerateMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if (item.getMediaType() == mMediaType) { - if (index < 0 || index >= total) return; - Path path = item.getPath(); - buf[index] = path; - } - } - }); - - for (int i = 0; i < total; i++) { - if (buf[i] != null) { - mPaths.add(buf[i]); - } - } - } - - @Override - public int getSupportedOperations() { - return SUPPORT_SHARE | SUPPORT_DELETE; - } - - @Override - public void delete() { - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if ((item.getSupportedOperations() & SUPPORT_DELETE) != 0) { - item.delete(); - } - } - }; - mDataManager.mapMediaItems(mPaths, consumer, 0); - } -} diff --git a/src/com/android/gallery3d/data/ImageCacheRequest.java b/src/com/android/gallery3d/data/ImageCacheRequest.java deleted file mode 100644 index 6cbc5c5ea..000000000 --- a/src/com/android/gallery3d/data/ImageCacheRequest.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.data.BytesBufferPool.BytesBuffer; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -abstract class ImageCacheRequest implements Job<Bitmap> { - private static final String TAG = "ImageCacheRequest"; - - protected GalleryApp mApplication; - private Path mPath; - private int mType; - private int mTargetSize; - private long mTimeModified; - - public ImageCacheRequest(GalleryApp application, - Path path, long timeModified, int type, int targetSize) { - mApplication = application; - mPath = path; - mType = type; - mTargetSize = targetSize; - mTimeModified = timeModified; - } - - private String debugTag() { - return mPath + "," + mTimeModified + "," + - ((mType == MediaItem.TYPE_THUMBNAIL) ? "THUMB" : - (mType == MediaItem.TYPE_MICROTHUMBNAIL) ? "MICROTHUMB" : "?"); - } - - @Override - public Bitmap run(JobContext jc) { - ImageCacheService cacheService = mApplication.getImageCacheService(); - - BytesBuffer buffer = MediaItem.getBytesBufferPool().get(); - try { - boolean found = cacheService.getImageData(mPath, mTimeModified, mType, buffer); - if (jc.isCancelled()) return null; - if (found) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - Bitmap bitmap; - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = DecodeUtils.decodeUsingPool(jc, - buffer.data, buffer.offset, buffer.length, options); - } else { - bitmap = DecodeUtils.decodeUsingPool(jc, - buffer.data, buffer.offset, buffer.length, options); - } - if (bitmap == null && !jc.isCancelled()) { - Log.w(TAG, "decode cached failed " + debugTag()); - } - return bitmap; - } - } finally { - MediaItem.getBytesBufferPool().recycle(buffer); - } - Bitmap bitmap = onDecodeOriginal(jc, mType); - if (jc.isCancelled()) return null; - - if (bitmap == null) { - Log.w(TAG, "decode orig failed " + debugTag()); - return null; - } - - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = BitmapUtils.resizeAndCropCenter(bitmap, mTargetSize, true); - } else { - bitmap = BitmapUtils.resizeDownBySideLength(bitmap, mTargetSize, true); - } - if (jc.isCancelled()) return null; - - byte[] array = BitmapUtils.compressToBytes(bitmap); - if (jc.isCancelled()) return null; - - cacheService.putImageData(mPath, mTimeModified, mType, array); - return bitmap; - } - - public abstract Bitmap onDecodeOriginal(JobContext jc, int targetSize); -} diff --git a/src/com/android/gallery3d/data/ImageCacheService.java b/src/com/android/gallery3d/data/ImageCacheService.java deleted file mode 100644 index 1c7cb8c5e..000000000 --- a/src/com/android/gallery3d/data/ImageCacheService.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; - -import com.android.gallery3d.common.BlobCache; -import com.android.gallery3d.common.BlobCache.LookupRequest; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.BytesBufferPool.BytesBuffer; -import com.android.gallery3d.util.CacheManager; -import com.android.gallery3d.util.GalleryUtils; - -import java.io.IOException; -import java.nio.ByteBuffer; - -public class ImageCacheService { - @SuppressWarnings("unused") - private static final String TAG = "ImageCacheService"; - - private static final String IMAGE_CACHE_FILE = "imgcache"; - private static final int IMAGE_CACHE_MAX_ENTRIES = 5000; - private static final int IMAGE_CACHE_MAX_BYTES = 200 * 1024 * 1024; - private static final int IMAGE_CACHE_VERSION = 7; - - private BlobCache mCache; - - public ImageCacheService(Context context) { - mCache = CacheManager.getCache(context, IMAGE_CACHE_FILE, - IMAGE_CACHE_MAX_ENTRIES, IMAGE_CACHE_MAX_BYTES, - IMAGE_CACHE_VERSION); - } - - /** - * Gets the cached image data for the given <code>path</code>, - * <code>timeModified</code> and <code>type</code>. - * - * The image data will be stored in <code>buffer.data</code>, started from - * <code>buffer.offset</code> for <code>buffer.length</code> bytes. If the - * buffer.data is not big enough, a new byte array will be allocated and returned. - * - * @return true if the image data is found; false if not found. - */ - public boolean getImageData(Path path, long timeModified, int type, BytesBuffer buffer) { - byte[] key = makeKey(path, timeModified, type); - long cacheKey = Utils.crc64Long(key); - try { - LookupRequest request = new LookupRequest(); - request.key = cacheKey; - request.buffer = buffer.data; - synchronized (mCache) { - if (!mCache.lookup(request)) return false; - } - if (isSameKey(key, request.buffer)) { - buffer.data = request.buffer; - buffer.offset = key.length; - buffer.length = request.length - buffer.offset; - return true; - } - } catch (IOException ex) { - // ignore. - } - return false; - } - - public void putImageData(Path path, long timeModified, int type, byte[] value) { - byte[] key = makeKey(path, timeModified, type); - long cacheKey = Utils.crc64Long(key); - ByteBuffer buffer = ByteBuffer.allocate(key.length + value.length); - buffer.put(key); - buffer.put(value); - synchronized (mCache) { - try { - mCache.insert(cacheKey, buffer.array()); - } catch (IOException ex) { - // ignore. - } - } - } - - public void clearImageData(Path path, long timeModified, int type) { - byte[] key = makeKey(path, timeModified, type); - long cacheKey = Utils.crc64Long(key); - synchronized (mCache) { - try { - mCache.clearEntry(cacheKey); - } catch (IOException ex) { - // ignore. - } - } - } - - private static byte[] makeKey(Path path, long timeModified, int type) { - return GalleryUtils.getBytes(path.toString() + "+" + timeModified + "+" + type); - } - - private static boolean isSameKey(byte[] key, byte[] buffer) { - int n = key.length; - if (buffer.length < n) { - return false; - } - for (int i = 0; i < n; ++i) { - if (key[i] != buffer[i]) { - return false; - } - } - return true; - } -} diff --git a/src/com/android/gallery3d/data/LocalAlbum.java b/src/com/android/gallery3d/data/LocalAlbum.java deleted file mode 100644 index 7b7015af6..000000000 --- a/src/com/android/gallery3d/data/LocalAlbum.java +++ /dev/null @@ -1,325 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.ContentResolver; -import android.content.res.Resources; -import android.database.Cursor; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.Video; -import android.provider.MediaStore.Video.VideoColumns; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.BucketNames; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.MediaSetUtils; - -import java.io.File; -import java.util.ArrayList; - -// LocalAlbumSet lists all media items in one bucket on local storage. -// The media items need to be all images or all videos, but not both. -public class LocalAlbum extends MediaSet { - private static final String TAG = "LocalAlbum"; - private static final String[] COUNT_PROJECTION = { "count(*)" }; - - private static final int INVALID_COUNT = -1; - private final String mWhereClause; - private final String mOrderClause; - private final Uri mBaseUri; - private final String[] mProjection; - - private final GalleryApp mApplication; - private final ContentResolver mResolver; - private final int mBucketId; - private final String mName; - private final boolean mIsImage; - private final ChangeNotifier mNotifier; - private final Path mItemPath; - private int mCachedCount = INVALID_COUNT; - - public LocalAlbum(Path path, GalleryApp application, int bucketId, - boolean isImage, String name) { - super(path, nextVersionNumber()); - mApplication = application; - mResolver = application.getContentResolver(); - mBucketId = bucketId; - mName = name; - mIsImage = isImage; - - if (isImage) { - mWhereClause = ImageColumns.BUCKET_ID + " = ?"; - mOrderClause = ImageColumns.DATE_TAKEN + " DESC, " - + ImageColumns._ID + " DESC"; - mBaseUri = Images.Media.EXTERNAL_CONTENT_URI; - mProjection = LocalImage.PROJECTION; - mItemPath = LocalImage.ITEM_PATH; - } else { - mWhereClause = VideoColumns.BUCKET_ID + " = ?"; - mOrderClause = VideoColumns.DATE_TAKEN + " DESC, " - + VideoColumns._ID + " DESC"; - mBaseUri = Video.Media.EXTERNAL_CONTENT_URI; - mProjection = LocalVideo.PROJECTION; - mItemPath = LocalVideo.ITEM_PATH; - } - - mNotifier = new ChangeNotifier(this, mBaseUri, application); - } - - public LocalAlbum(Path path, GalleryApp application, int bucketId, - boolean isImage) { - this(path, application, bucketId, isImage, - BucketHelper.getBucketName( - application.getContentResolver(), bucketId)); - } - - @Override - public boolean isCameraRoll() { - return mBucketId == MediaSetUtils.CAMERA_BUCKET_ID; - } - - @Override - public Uri getContentUri() { - if (mIsImage) { - return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, - String.valueOf(mBucketId)).build(); - } else { - return MediaStore.Video.Media.EXTERNAL_CONTENT_URI.buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, - String.valueOf(mBucketId)).build(); - } - } - - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - DataManager dataManager = mApplication.getDataManager(); - Uri uri = mBaseUri.buildUpon() - .appendQueryParameter("limit", start + "," + count).build(); - ArrayList<MediaItem> list = new ArrayList<MediaItem>(); - GalleryUtils.assertNotInRenderThread(); - Cursor cursor = mResolver.query( - uri, mProjection, mWhereClause, - new String[]{String.valueOf(mBucketId)}, - mOrderClause); - if (cursor == null) { - Log.w(TAG, "query fail: " + uri); - return list; - } - - try { - while (cursor.moveToNext()) { - int id = cursor.getInt(0); // _id must be in the first column - Path childPath = mItemPath.getChild(id); - MediaItem item = loadOrUpdateItem(childPath, cursor, - dataManager, mApplication, mIsImage); - list.add(item); - } - } finally { - cursor.close(); - } - return list; - } - - private static MediaItem loadOrUpdateItem(Path path, Cursor cursor, - DataManager dataManager, GalleryApp app, boolean isImage) { - synchronized (DataManager.LOCK) { - LocalMediaItem item = (LocalMediaItem) dataManager.peekMediaObject(path); - if (item == null) { - if (isImage) { - item = new LocalImage(path, app, cursor); - } else { - item = new LocalVideo(path, app, cursor); - } - } else { - item.updateContent(cursor); - } - return item; - } - } - - // The pids array are sorted by the (path) id. - public static MediaItem[] getMediaItemById( - GalleryApp application, boolean isImage, ArrayList<Integer> ids) { - // get the lower and upper bound of (path) id - MediaItem[] result = new MediaItem[ids.size()]; - if (ids.isEmpty()) return result; - int idLow = ids.get(0); - int idHigh = ids.get(ids.size() - 1); - - // prepare the query parameters - Uri baseUri; - String[] projection; - Path itemPath; - if (isImage) { - baseUri = Images.Media.EXTERNAL_CONTENT_URI; - projection = LocalImage.PROJECTION; - itemPath = LocalImage.ITEM_PATH; - } else { - baseUri = Video.Media.EXTERNAL_CONTENT_URI; - projection = LocalVideo.PROJECTION; - itemPath = LocalVideo.ITEM_PATH; - } - - ContentResolver resolver = application.getContentResolver(); - DataManager dataManager = application.getDataManager(); - Cursor cursor = resolver.query(baseUri, projection, "_id BETWEEN ? AND ?", - new String[]{String.valueOf(idLow), String.valueOf(idHigh)}, - "_id"); - if (cursor == null) { - Log.w(TAG, "query fail" + baseUri); - return result; - } - try { - int n = ids.size(); - int i = 0; - - while (i < n && cursor.moveToNext()) { - int id = cursor.getInt(0); // _id must be in the first column - - // Match id with the one on the ids list. - if (ids.get(i) > id) { - continue; - } - - while (ids.get(i) < id) { - if (++i >= n) { - return result; - } - } - - Path childPath = itemPath.getChild(id); - MediaItem item = loadOrUpdateItem(childPath, cursor, dataManager, - application, isImage); - result[i] = item; - ++i; - } - return result; - } finally { - cursor.close(); - } - } - - public static Cursor getItemCursor(ContentResolver resolver, Uri uri, - String[] projection, int id) { - return resolver.query(uri, projection, "_id=?", - new String[]{String.valueOf(id)}, null); - } - - @Override - public int getMediaItemCount() { - if (mCachedCount == INVALID_COUNT) { - Cursor cursor = mResolver.query( - mBaseUri, COUNT_PROJECTION, mWhereClause, - new String[]{String.valueOf(mBucketId)}, null); - if (cursor == null) { - Log.w(TAG, "query fail"); - return 0; - } - try { - Utils.assertTrue(cursor.moveToNext()); - mCachedCount = cursor.getInt(0); - } finally { - cursor.close(); - } - } - return mCachedCount; - } - - @Override - public String getName() { - return getLocalizedName(mApplication.getResources(), mBucketId, mName); - } - - @Override - public long reload() { - if (mNotifier.isDirty()) { - mDataVersion = nextVersionNumber(); - mCachedCount = INVALID_COUNT; - } - return mDataVersion; - } - - @Override - public int getSupportedOperations() { - return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_INFO; - } - - @Override - public void delete() { - GalleryUtils.assertNotInRenderThread(); - mResolver.delete(mBaseUri, mWhereClause, - new String[]{String.valueOf(mBucketId)}); - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - public static String getLocalizedName(Resources res, int bucketId, - String name) { - if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) { - return res.getString(R.string.folder_camera); - } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) { - return res.getString(R.string.folder_download); - } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) { - return res.getString(R.string.folder_imported); - } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) { - return res.getString(R.string.folder_screenshot); - } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) { - return res.getString(R.string.folder_edited_online_photos); - } else { - return name; - } - } - - // Relative path is the absolute path minus external storage path - public static String getRelativePath(int bucketId) { - String relativePath = "/"; - if (bucketId == MediaSetUtils.CAMERA_BUCKET_ID) { - relativePath += BucketNames.CAMERA; - } else if (bucketId == MediaSetUtils.DOWNLOAD_BUCKET_ID) { - relativePath += BucketNames.DOWNLOAD; - } else if (bucketId == MediaSetUtils.IMPORTED_BUCKET_ID) { - relativePath += BucketNames.IMPORTED; - } else if (bucketId == MediaSetUtils.SNAPSHOT_BUCKET_ID) { - relativePath += BucketNames.SCREENSHOTS; - } else if (bucketId == MediaSetUtils.EDITED_ONLINE_PHOTOS_BUCKET_ID) { - relativePath += BucketNames.EDITED_ONLINE_PHOTOS; - } else { - // If the first few cases didn't hit the matching path, do a - // thorough search in the local directories. - File extStorage = Environment.getExternalStorageDirectory(); - String path = GalleryUtils.searchDirForPath(extStorage, bucketId); - if (path == null) { - Log.w(TAG, "Relative path for bucket id: " + bucketId + " is not found."); - relativePath = null; - } else { - relativePath = path.substring(extStorage.getAbsolutePath().length()); - } - } - return relativePath; - } - -} diff --git a/src/com/android/gallery3d/data/LocalAlbumSet.java b/src/com/android/gallery3d/data/LocalAlbumSet.java deleted file mode 100644 index b2b4b8c5d..000000000 --- a/src/com/android/gallery3d/data/LocalAlbumSet.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.net.Uri; -import android.os.Handler; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Video; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.data.BucketHelper.BucketEntry; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.MediaSetUtils; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; -import java.util.Comparator; - -// LocalAlbumSet lists all image or video albums in the local storage. -// The path should be "/local/image", "local/video" or "/local/all" -public class LocalAlbumSet extends MediaSet - implements FutureListener<ArrayList<MediaSet>> { - @SuppressWarnings("unused") - private static final String TAG = "LocalAlbumSet"; - - public static final Path PATH_ALL = Path.fromString("/local/all"); - public static final Path PATH_IMAGE = Path.fromString("/local/image"); - public static final Path PATH_VIDEO = Path.fromString("/local/video"); - - private static final Uri[] mWatchUris = - {Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI}; - - private final GalleryApp mApplication; - private final int mType; - private ArrayList<MediaSet> mAlbums = new ArrayList<MediaSet>(); - private final ChangeNotifier mNotifier; - private final String mName; - private final Handler mHandler; - private boolean mIsLoading; - - private Future<ArrayList<MediaSet>> mLoadTask; - private ArrayList<MediaSet> mLoadBuffer; - - public LocalAlbumSet(Path path, GalleryApp application) { - super(path, nextVersionNumber()); - mApplication = application; - mHandler = new Handler(application.getMainLooper()); - mType = getTypeFromPath(path); - mNotifier = new ChangeNotifier(this, mWatchUris, application); - mName = application.getResources().getString( - R.string.set_label_local_albums); - } - - private static int getTypeFromPath(Path path) { - String name[] = path.split(); - if (name.length < 2) { - throw new IllegalArgumentException(path.toString()); - } - return getTypeFromString(name[1]); - } - - @Override - public MediaSet getSubMediaSet(int index) { - return mAlbums.get(index); - } - - @Override - public int getSubMediaSetCount() { - return mAlbums.size(); - } - - @Override - public String getName() { - return mName; - } - - private static int findBucket(BucketEntry entries[], int bucketId) { - for (int i = 0, n = entries.length; i < n; ++i) { - if (entries[i].bucketId == bucketId) return i; - } - return -1; - } - - private class AlbumsLoader implements ThreadPool.Job<ArrayList<MediaSet>> { - - @Override - @SuppressWarnings("unchecked") - public ArrayList<MediaSet> run(JobContext jc) { - // Note: it will be faster if we only select media_type and bucket_id. - // need to test the performance if that is worth - BucketEntry[] entries = BucketHelper.loadBucketEntries( - jc, mApplication.getContentResolver(), mType); - - if (jc.isCancelled()) return null; - - int offset = 0; - // Move camera and download bucket to the front, while keeping the - // order of others. - int index = findBucket(entries, MediaSetUtils.CAMERA_BUCKET_ID); - if (index != -1) { - circularShiftRight(entries, offset++, index); - } - index = findBucket(entries, MediaSetUtils.DOWNLOAD_BUCKET_ID); - if (index != -1) { - circularShiftRight(entries, offset++, index); - } - - ArrayList<MediaSet> albums = new ArrayList<MediaSet>(); - DataManager dataManager = mApplication.getDataManager(); - for (BucketEntry entry : entries) { - MediaSet album = getLocalAlbum(dataManager, - mType, mPath, entry.bucketId, entry.bucketName); - albums.add(album); - } - return albums; - } - } - - private MediaSet getLocalAlbum( - DataManager manager, int type, Path parent, int id, String name) { - synchronized (DataManager.LOCK) { - Path path = parent.getChild(id); - MediaObject object = manager.peekMediaObject(path); - if (object != null) return (MediaSet) object; - switch (type) { - case MEDIA_TYPE_IMAGE: - return new LocalAlbum(path, mApplication, id, true, name); - case MEDIA_TYPE_VIDEO: - return new LocalAlbum(path, mApplication, id, false, name); - case MEDIA_TYPE_ALL: - Comparator<MediaItem> comp = DataManager.sDateTakenComparator; - return new LocalMergeAlbum(path, comp, new MediaSet[] { - getLocalAlbum(manager, MEDIA_TYPE_IMAGE, PATH_IMAGE, id, name), - getLocalAlbum(manager, MEDIA_TYPE_VIDEO, PATH_VIDEO, id, name)}, id); - } - throw new IllegalArgumentException(String.valueOf(type)); - } - } - - @Override - public synchronized boolean isLoading() { - return mIsLoading; - } - - @Override - // synchronized on this function for - // 1. Prevent calling reload() concurrently. - // 2. Prevent calling onFutureDone() and reload() concurrently - public synchronized long reload() { - if (mNotifier.isDirty()) { - if (mLoadTask != null) mLoadTask.cancel(); - mIsLoading = true; - mLoadTask = mApplication.getThreadPool().submit(new AlbumsLoader(), this); - } - if (mLoadBuffer != null) { - mAlbums = mLoadBuffer; - mLoadBuffer = null; - for (MediaSet album : mAlbums) { - album.reload(); - } - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - @Override - public synchronized void onFutureDone(Future<ArrayList<MediaSet>> future) { - if (mLoadTask != future) return; // ignore, wait for the latest task - mLoadBuffer = future.get(); - mIsLoading = false; - if (mLoadBuffer == null) mLoadBuffer = new ArrayList<MediaSet>(); - mHandler.post(new Runnable() { - @Override - public void run() { - notifyContentChanged(); - } - }); - } - - // For debug only. Fake there is a ContentObserver.onChange() event. - void fakeChange() { - mNotifier.fakeChange(); - } - - // Circular shift the array range from a[i] to a[j] (inclusive). That is, - // a[i] -> a[i+1] -> a[i+2] -> ... -> a[j], and a[j] -> a[i] - private static <T> void circularShiftRight(T[] array, int i, int j) { - T temp = array[j]; - for (int k = j; k > i; k--) { - array[k] = array[k - 1]; - } - array[i] = temp; - } -} diff --git a/src/com/android/gallery3d/data/LocalImage.java b/src/com/android/gallery3d/data/LocalImage.java deleted file mode 100644 index cc70dd457..000000000 --- a/src/com/android/gallery3d/data/LocalImage.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.annotation.TargetApi; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; -import android.os.Build; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.provider.MediaStore.MediaColumns; -import android.util.Log; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.PanoramaMetadataSupport; -import com.android.gallery3d.app.StitchingProgressManager; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.exif.ExifTag; -import com.android.gallery3d.filtershow.tools.SaveImage; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; -import com.android.gallery3d.util.UpdateHelper; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.IOException; - -// LocalImage represents an image in the local storage. -public class LocalImage extends LocalMediaItem { - private static final String TAG = "LocalImage"; - - static final Path ITEM_PATH = Path.fromString("/local/image/item"); - - // Must preserve order between these indices and the order of the terms in - // the following PROJECTION array. - private static final int INDEX_ID = 0; - private static final int INDEX_CAPTION = 1; - private static final int INDEX_MIME_TYPE = 2; - private static final int INDEX_LATITUDE = 3; - private static final int INDEX_LONGITUDE = 4; - private static final int INDEX_DATE_TAKEN = 5; - private static final int INDEX_DATE_ADDED = 6; - private static final int INDEX_DATE_MODIFIED = 7; - private static final int INDEX_DATA = 8; - private static final int INDEX_ORIENTATION = 9; - private static final int INDEX_BUCKET_ID = 10; - private static final int INDEX_SIZE = 11; - private static final int INDEX_WIDTH = 12; - private static final int INDEX_HEIGHT = 13; - - static final String[] PROJECTION = { - ImageColumns._ID, // 0 - ImageColumns.TITLE, // 1 - ImageColumns.MIME_TYPE, // 2 - ImageColumns.LATITUDE, // 3 - ImageColumns.LONGITUDE, // 4 - ImageColumns.DATE_TAKEN, // 5 - ImageColumns.DATE_ADDED, // 6 - ImageColumns.DATE_MODIFIED, // 7 - ImageColumns.DATA, // 8 - ImageColumns.ORIENTATION, // 9 - ImageColumns.BUCKET_ID, // 10 - ImageColumns.SIZE, // 11 - "0", // 12 - "0" // 13 - }; - - static { - updateWidthAndHeightProjection(); - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private static void updateWidthAndHeightProjection() { - if (ApiHelper.HAS_MEDIA_COLUMNS_WIDTH_AND_HEIGHT) { - PROJECTION[INDEX_WIDTH] = MediaColumns.WIDTH; - PROJECTION[INDEX_HEIGHT] = MediaColumns.HEIGHT; - } - } - - private final GalleryApp mApplication; - - public int rotation; - - private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this); - - public LocalImage(Path path, GalleryApp application, Cursor cursor) { - super(path, nextVersionNumber()); - mApplication = application; - loadFromCursor(cursor); - } - - public LocalImage(Path path, GalleryApp application, int id) { - super(path, nextVersionNumber()); - mApplication = application; - ContentResolver resolver = mApplication.getContentResolver(); - Uri uri = Images.Media.EXTERNAL_CONTENT_URI; - Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id); - if (cursor == null) { - throw new RuntimeException("cannot get cursor for: " + path); - } - try { - if (cursor.moveToNext()) { - loadFromCursor(cursor); - } else { - throw new RuntimeException("cannot find data for: " + path); - } - } finally { - cursor.close(); - } - } - - private void loadFromCursor(Cursor cursor) { - id = cursor.getInt(INDEX_ID); - caption = cursor.getString(INDEX_CAPTION); - mimeType = cursor.getString(INDEX_MIME_TYPE); - latitude = cursor.getDouble(INDEX_LATITUDE); - longitude = cursor.getDouble(INDEX_LONGITUDE); - dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN); - dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED); - dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED); - filePath = cursor.getString(INDEX_DATA); - rotation = cursor.getInt(INDEX_ORIENTATION); - bucketId = cursor.getInt(INDEX_BUCKET_ID); - fileSize = cursor.getLong(INDEX_SIZE); - width = cursor.getInt(INDEX_WIDTH); - height = cursor.getInt(INDEX_HEIGHT); - } - - @Override - protected boolean updateFromCursor(Cursor cursor) { - UpdateHelper uh = new UpdateHelper(); - id = uh.update(id, cursor.getInt(INDEX_ID)); - caption = uh.update(caption, cursor.getString(INDEX_CAPTION)); - mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE)); - latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE)); - longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE)); - dateTakenInMs = uh.update( - dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN)); - dateAddedInSec = uh.update( - dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED)); - dateModifiedInSec = uh.update( - dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED)); - filePath = uh.update(filePath, cursor.getString(INDEX_DATA)); - rotation = uh.update(rotation, cursor.getInt(INDEX_ORIENTATION)); - bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID)); - fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE)); - width = uh.update(width, cursor.getInt(INDEX_WIDTH)); - height = uh.update(height, cursor.getInt(INDEX_HEIGHT)); - return uh.isUpdated(); - } - - @Override - public Job<Bitmap> requestImage(int type) { - return new LocalImageRequest(mApplication, mPath, dateModifiedInSec, - type, filePath); - } - - public static class LocalImageRequest extends ImageCacheRequest { - private String mLocalFilePath; - - LocalImageRequest(GalleryApp application, Path path, long timeModified, - int type, String localFilePath) { - super(application, path, timeModified, type, - MediaItem.getTargetSize(type)); - mLocalFilePath = localFilePath; - } - - @Override - public Bitmap onDecodeOriginal(JobContext jc, final int type) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - int targetSize = MediaItem.getTargetSize(type); - - // try to decode from JPEG EXIF - if (type == MediaItem.TYPE_MICROTHUMBNAIL) { - ExifInterface exif = new ExifInterface(); - byte[] thumbData = null; - try { - exif.readExif(mLocalFilePath); - thumbData = exif.getThumbnail(); - } catch (FileNotFoundException e) { - Log.w(TAG, "failed to find file to read thumbnail: " + mLocalFilePath); - } catch (IOException e) { - Log.w(TAG, "failed to get thumbnail from: " + mLocalFilePath); - } - if (thumbData != null) { - Bitmap bitmap = DecodeUtils.decodeIfBigEnough( - jc, thumbData, options, targetSize); - if (bitmap != null) return bitmap; - } - } - - return DecodeUtils.decodeThumbnail(jc, mLocalFilePath, options, targetSize, type); - } - } - - @Override - public Job<BitmapRegionDecoder> requestLargeImage() { - return new LocalLargeImageRequest(filePath); - } - - public static class LocalLargeImageRequest - implements Job<BitmapRegionDecoder> { - String mLocalFilePath; - - public LocalLargeImageRequest(String localFilePath) { - mLocalFilePath = localFilePath; - } - - @Override - public BitmapRegionDecoder run(JobContext jc) { - return DecodeUtils.createBitmapRegionDecoder(jc, mLocalFilePath, false); - } - } - - @Override - public int getSupportedOperations() { - StitchingProgressManager progressManager = mApplication.getStitchingProgressManager(); - if (progressManager != null && progressManager.getProgress(getContentUri()) != null) { - return 0; // doesn't support anything while stitching! - } - int operation = SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_CROP - | SUPPORT_SETAS | SUPPORT_EDIT | SUPPORT_INFO; - if (BitmapUtils.isSupportedByRegionDecoder(mimeType)) { - operation |= SUPPORT_FULL_IMAGE; - } - - if (BitmapUtils.isRotationSupported(mimeType)) { - operation |= SUPPORT_ROTATE; - } - - if (GalleryUtils.isValidLocation(latitude, longitude)) { - operation |= SUPPORT_SHOW_ON_MAP; - } - return operation; - } - - @Override - public void getPanoramaSupport(PanoramaSupportCallback callback) { - mPanoramaMetadata.getPanoramaSupport(mApplication, callback); - } - - @Override - public void clearCachedPanoramaSupport() { - mPanoramaMetadata.clearCachedValues(); - } - - @Override - public void delete() { - GalleryUtils.assertNotInRenderThread(); - Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; - ContentResolver contentResolver = mApplication.getContentResolver(); - SaveImage.deleteAuxFiles(contentResolver, getContentUri()); - contentResolver.delete(baseUri, "_id=?", - new String[]{String.valueOf(id)}); - } - - @Override - public void rotate(int degrees) { - GalleryUtils.assertNotInRenderThread(); - Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; - ContentValues values = new ContentValues(); - int rotation = (this.rotation + degrees) % 360; - if (rotation < 0) rotation += 360; - - if (mimeType.equalsIgnoreCase("image/jpeg")) { - ExifInterface exifInterface = new ExifInterface(); - ExifTag tag = exifInterface.buildTag(ExifInterface.TAG_ORIENTATION, - ExifInterface.getOrientationValueForRotation(rotation)); - if(tag != null) { - exifInterface.setTag(tag); - try { - exifInterface.forceRewriteExif(filePath); - fileSize = new File(filePath).length(); - values.put(Images.Media.SIZE, fileSize); - } catch (FileNotFoundException e) { - Log.w(TAG, "cannot find file to set exif: " + filePath); - } catch (IOException e) { - Log.w(TAG, "cannot set exif data: " + filePath); - } - } else { - Log.w(TAG, "Could not build tag: " + ExifInterface.TAG_ORIENTATION); - } - } - - values.put(Images.Media.ORIENTATION, rotation); - mApplication.getContentResolver().update(baseUri, values, "_id=?", - new String[]{String.valueOf(id)}); - } - - @Override - public Uri getContentUri() { - Uri baseUri = Images.Media.EXTERNAL_CONTENT_URI; - return baseUri.buildUpon().appendPath(String.valueOf(id)).build(); - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_IMAGE; - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - details.addDetail(MediaDetails.INDEX_ORIENTATION, Integer.valueOf(rotation)); - if (MIME_TYPE_JPEG.equals(mimeType)) { - // ExifInterface returns incorrect values for photos in other format. - // For example, the width and height of an webp images is always '0'. - MediaDetails.extractExifInfo(details, filePath); - } - return details; - } - - @Override - public int getRotation() { - return rotation; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public String getFilePath() { - return filePath; - } -} diff --git a/src/com/android/gallery3d/data/LocalMediaItem.java b/src/com/android/gallery3d/data/LocalMediaItem.java deleted file mode 100644 index 7e003cd3a..000000000 --- a/src/com/android/gallery3d/data/LocalMediaItem.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.database.Cursor; - -import com.android.gallery3d.util.GalleryUtils; - -import java.text.DateFormat; -import java.util.Date; - -// -// LocalMediaItem is an abstract class captures those common fields -// in LocalImage and LocalVideo. -// -public abstract class LocalMediaItem extends MediaItem { - - @SuppressWarnings("unused") - private static final String TAG = "LocalMediaItem"; - - // database fields - public int id; - public String caption; - public String mimeType; - public long fileSize; - public double latitude = INVALID_LATLNG; - public double longitude = INVALID_LATLNG; - public long dateTakenInMs; - public long dateAddedInSec; - public long dateModifiedInSec; - public String filePath; - public int bucketId; - public int width; - public int height; - - public LocalMediaItem(Path path, long version) { - super(path, version); - } - - @Override - public long getDateInMs() { - return dateTakenInMs; - } - - @Override - public String getName() { - return caption; - } - - @Override - public void getLatLong(double[] latLong) { - latLong[0] = latitude; - latLong[1] = longitude; - } - - abstract protected boolean updateFromCursor(Cursor cursor); - - public int getBucketId() { - return bucketId; - } - - protected void updateContent(Cursor cursor) { - if (updateFromCursor(cursor)) { - mDataVersion = nextVersionNumber(); - } - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - details.addDetail(MediaDetails.INDEX_PATH, filePath); - details.addDetail(MediaDetails.INDEX_TITLE, caption); - DateFormat formater = DateFormat.getDateTimeInstance(); - details.addDetail(MediaDetails.INDEX_DATETIME, - formater.format(new Date(dateModifiedInSec * 1000))); - details.addDetail(MediaDetails.INDEX_WIDTH, width); - details.addDetail(MediaDetails.INDEX_HEIGHT, height); - - if (GalleryUtils.isValidLocation(latitude, longitude)) { - details.addDetail(MediaDetails.INDEX_LOCATION, new double[] {latitude, longitude}); - } - if (fileSize > 0) details.addDetail(MediaDetails.INDEX_SIZE, fileSize); - return details; - } - - @Override - public String getMimeType() { - return mimeType; - } - - @Override - public long getSize() { - return fileSize; - } -} diff --git a/src/com/android/gallery3d/data/LocalMergeAlbum.java b/src/com/android/gallery3d/data/LocalMergeAlbum.java deleted file mode 100644 index f0b5e5726..000000000 --- a/src/com/android/gallery3d/data/LocalMergeAlbum.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.net.Uri; -import android.provider.MediaStore; - -import com.android.gallery3d.common.ApiHelper; - -import java.lang.ref.SoftReference; -import java.util.ArrayList; -import java.util.Comparator; -import java.util.NoSuchElementException; -import java.util.SortedMap; -import java.util.TreeMap; - -// MergeAlbum merges items from two or more MediaSets. It uses a Comparator to -// determine the order of items. The items are assumed to be sorted in the input -// media sets (with the same order that the Comparator uses). -// -// This only handles MediaItems, not SubMediaSets. -public class LocalMergeAlbum extends MediaSet implements ContentListener { - @SuppressWarnings("unused") - private static final String TAG = "LocalMergeAlbum"; - private static final int PAGE_SIZE = 64; - - private final Comparator<MediaItem> mComparator; - private final MediaSet[] mSources; - - private FetchCache[] mFetcher; - private int mSupportedOperation; - private int mBucketId; - - // mIndex maps global position to the position of each underlying media sets. - private TreeMap<Integer, int[]> mIndex = new TreeMap<Integer, int[]>(); - - public LocalMergeAlbum( - Path path, Comparator<MediaItem> comparator, MediaSet[] sources, int bucketId) { - super(path, INVALID_DATA_VERSION); - mComparator = comparator; - mSources = sources; - mBucketId = bucketId; - for (MediaSet set : mSources) { - set.addContentListener(this); - } - reload(); - } - - @Override - public boolean isCameraRoll() { - if (mSources.length == 0) return false; - for(MediaSet set : mSources) { - if (!set.isCameraRoll()) return false; - } - return true; - } - - private void updateData() { - ArrayList<MediaSet> matches = new ArrayList<MediaSet>(); - int supported = mSources.length == 0 ? 0 : MediaItem.SUPPORT_ALL; - mFetcher = new FetchCache[mSources.length]; - for (int i = 0, n = mSources.length; i < n; ++i) { - mFetcher[i] = new FetchCache(mSources[i]); - supported &= mSources[i].getSupportedOperations(); - } - mSupportedOperation = supported; - mIndex.clear(); - mIndex.put(0, new int[mSources.length]); - } - - private void invalidateCache() { - for (int i = 0, n = mSources.length; i < n; i++) { - mFetcher[i].invalidate(); - } - mIndex.clear(); - mIndex.put(0, new int[mSources.length]); - } - - @Override - public Uri getContentUri() { - String bucketId = String.valueOf(mBucketId); - if (ApiHelper.HAS_MEDIA_PROVIDER_FILES_TABLE) { - return MediaStore.Files.getContentUri("external").buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId) - .build(); - } else { - // We don't have a single URL for a merged image before ICS - // So we used the image's URL as a substitute. - return MediaStore.Images.Media.EXTERNAL_CONTENT_URI.buildUpon() - .appendQueryParameter(LocalSource.KEY_BUCKET_ID, bucketId) - .build(); - } - } - - @Override - public String getName() { - return mSources.length == 0 ? "" : mSources[0].getName(); - } - - @Override - public int getMediaItemCount() { - return getTotalMediaItemCount(); - } - - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - - // First find the nearest mark position <= start. - SortedMap<Integer, int[]> head = mIndex.headMap(start + 1); - int markPos = head.lastKey(); - int[] subPos = head.get(markPos).clone(); - MediaItem[] slot = new MediaItem[mSources.length]; - - int size = mSources.length; - - // fill all slots - for (int i = 0; i < size; i++) { - slot[i] = mFetcher[i].getItem(subPos[i]); - } - - ArrayList<MediaItem> result = new ArrayList<MediaItem>(); - - for (int i = markPos; i < start + count; i++) { - int k = -1; // k points to the best slot up to now. - for (int j = 0; j < size; j++) { - if (slot[j] != null) { - if (k == -1 || mComparator.compare(slot[j], slot[k]) < 0) { - k = j; - } - } - } - - // If we don't have anything, all streams are exhausted. - if (k == -1) break; - - // Pick the best slot and refill it. - subPos[k]++; - if (i >= start) { - result.add(slot[k]); - } - slot[k] = mFetcher[k].getItem(subPos[k]); - - // Periodically leave a mark in the index, so we can come back later. - if ((i + 1) % PAGE_SIZE == 0) { - mIndex.put(i + 1, subPos.clone()); - } - } - - return result; - } - - @Override - public int getTotalMediaItemCount() { - int count = 0; - for (MediaSet set : mSources) { - count += set.getTotalMediaItemCount(); - } - return count; - } - - @Override - public long reload() { - boolean changed = false; - for (int i = 0, n = mSources.length; i < n; ++i) { - if (mSources[i].reload() > mDataVersion) changed = true; - } - if (changed) { - mDataVersion = nextVersionNumber(); - updateData(); - invalidateCache(); - } - return mDataVersion; - } - - @Override - public void onContentDirty() { - notifyContentChanged(); - } - - @Override - public int getSupportedOperations() { - return mSupportedOperation; - } - - @Override - public void delete() { - for (MediaSet set : mSources) { - set.delete(); - } - } - - @Override - public void rotate(int degrees) { - for (MediaSet set : mSources) { - set.rotate(degrees); - } - } - - private static class FetchCache { - private MediaSet mBaseSet; - private SoftReference<ArrayList<MediaItem>> mCacheRef; - private int mStartPos; - - public FetchCache(MediaSet baseSet) { - mBaseSet = baseSet; - } - - public void invalidate() { - mCacheRef = null; - } - - public MediaItem getItem(int index) { - boolean needLoading = false; - ArrayList<MediaItem> cache = null; - if (mCacheRef == null - || index < mStartPos || index >= mStartPos + PAGE_SIZE) { - needLoading = true; - } else { - cache = mCacheRef.get(); - if (cache == null) { - needLoading = true; - } - } - - if (needLoading) { - cache = mBaseSet.getMediaItem(index, PAGE_SIZE); - mCacheRef = new SoftReference<ArrayList<MediaItem>>(cache); - mStartPos = index; - } - - if (index < mStartPos || index >= mStartPos + cache.size()) { - return null; - } - - return cache.get(index - mStartPos); - } - } - - @Override - public boolean isLeafAlbum() { - return true; - } -} diff --git a/src/com/android/gallery3d/data/LocalSource.java b/src/com/android/gallery3d/data/LocalSource.java deleted file mode 100644 index a2e3d1443..000000000 --- a/src/com/android/gallery3d/data/LocalSource.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.ContentProviderClient; -import android.content.ContentUris; -import android.content.UriMatcher; -import android.net.Uri; -import android.provider.MediaStore; - -import com.android.gallery3d.app.Gallery; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.data.MediaSet.ItemConsumer; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -class LocalSource extends MediaSource { - - public static final String KEY_BUCKET_ID = "bucketId"; - - private GalleryApp mApplication; - private PathMatcher mMatcher; - private static final int NO_MATCH = -1; - private final UriMatcher mUriMatcher = new UriMatcher(NO_MATCH); - public static final Comparator<PathId> sIdComparator = new IdComparator(); - - private static final int LOCAL_IMAGE_ALBUMSET = 0; - private static final int LOCAL_VIDEO_ALBUMSET = 1; - private static final int LOCAL_IMAGE_ALBUM = 2; - private static final int LOCAL_VIDEO_ALBUM = 3; - private static final int LOCAL_IMAGE_ITEM = 4; - private static final int LOCAL_VIDEO_ITEM = 5; - private static final int LOCAL_ALL_ALBUMSET = 6; - private static final int LOCAL_ALL_ALBUM = 7; - - private static final String TAG = "LocalSource"; - - private ContentProviderClient mClient; - - public LocalSource(GalleryApp context) { - super("local"); - mApplication = context; - mMatcher = new PathMatcher(); - mMatcher.add("/local/image", LOCAL_IMAGE_ALBUMSET); - mMatcher.add("/local/video", LOCAL_VIDEO_ALBUMSET); - mMatcher.add("/local/all", LOCAL_ALL_ALBUMSET); - - mMatcher.add("/local/image/*", LOCAL_IMAGE_ALBUM); - mMatcher.add("/local/video/*", LOCAL_VIDEO_ALBUM); - mMatcher.add("/local/all/*", LOCAL_ALL_ALBUM); - mMatcher.add("/local/image/item/*", LOCAL_IMAGE_ITEM); - mMatcher.add("/local/video/item/*", LOCAL_VIDEO_ITEM); - - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/images/media/#", LOCAL_IMAGE_ITEM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/video/media/#", LOCAL_VIDEO_ITEM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/images/media", LOCAL_IMAGE_ALBUM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/video/media", LOCAL_VIDEO_ALBUM); - mUriMatcher.addURI(MediaStore.AUTHORITY, - "external/file", LOCAL_ALL_ALBUM); - } - - @Override - public MediaObject createMediaObject(Path path) { - GalleryApp app = mApplication; - switch (mMatcher.match(path)) { - case LOCAL_ALL_ALBUMSET: - case LOCAL_IMAGE_ALBUMSET: - case LOCAL_VIDEO_ALBUMSET: - return new LocalAlbumSet(path, mApplication); - case LOCAL_IMAGE_ALBUM: - return new LocalAlbum(path, app, mMatcher.getIntVar(0), true); - case LOCAL_VIDEO_ALBUM: - return new LocalAlbum(path, app, mMatcher.getIntVar(0), false); - case LOCAL_ALL_ALBUM: { - int bucketId = mMatcher.getIntVar(0); - DataManager dataManager = app.getDataManager(); - MediaSet imageSet = (MediaSet) dataManager.getMediaObject( - LocalAlbumSet.PATH_IMAGE.getChild(bucketId)); - MediaSet videoSet = (MediaSet) dataManager.getMediaObject( - LocalAlbumSet.PATH_VIDEO.getChild(bucketId)); - Comparator<MediaItem> comp = DataManager.sDateTakenComparator; - return new LocalMergeAlbum( - path, comp, new MediaSet[] {imageSet, videoSet}, bucketId); - } - case LOCAL_IMAGE_ITEM: - return new LocalImage(path, mApplication, mMatcher.getIntVar(0)); - case LOCAL_VIDEO_ITEM: - return new LocalVideo(path, mApplication, mMatcher.getIntVar(0)); - default: - throw new RuntimeException("bad path: " + path); - } - } - - private static int getMediaType(String type, int defaultType) { - if (type == null) return defaultType; - try { - int value = Integer.parseInt(type); - if ((value & (MEDIA_TYPE_IMAGE - | MEDIA_TYPE_VIDEO)) != 0) return value; - } catch (NumberFormatException e) { - Log.w(TAG, "invalid type: " + type, e); - } - return defaultType; - } - - // The media type bit passed by the intent - private static final int MEDIA_TYPE_ALL = 0; - private static final int MEDIA_TYPE_IMAGE = 1; - private static final int MEDIA_TYPE_VIDEO = 4; - - private Path getAlbumPath(Uri uri, int defaultType) { - int mediaType = getMediaType( - uri.getQueryParameter(Gallery.KEY_MEDIA_TYPES), - defaultType); - String bucketId = uri.getQueryParameter(KEY_BUCKET_ID); - int id = 0; - try { - id = Integer.parseInt(bucketId); - } catch (NumberFormatException e) { - Log.w(TAG, "invalid bucket id: " + bucketId, e); - return null; - } - switch (mediaType) { - case MEDIA_TYPE_IMAGE: - return Path.fromString("/local/image").getChild(id); - case MEDIA_TYPE_VIDEO: - return Path.fromString("/local/video").getChild(id); - default: - return Path.fromString("/local/all").getChild(id); - } - } - - @Override - public Path findPathByUri(Uri uri, String type) { - try { - switch (mUriMatcher.match(uri)) { - case LOCAL_IMAGE_ITEM: { - long id = ContentUris.parseId(uri); - return id >= 0 ? LocalImage.ITEM_PATH.getChild(id) : null; - } - case LOCAL_VIDEO_ITEM: { - long id = ContentUris.parseId(uri); - return id >= 0 ? LocalVideo.ITEM_PATH.getChild(id) : null; - } - case LOCAL_IMAGE_ALBUM: { - return getAlbumPath(uri, MEDIA_TYPE_IMAGE); - } - case LOCAL_VIDEO_ALBUM: { - return getAlbumPath(uri, MEDIA_TYPE_VIDEO); - } - case LOCAL_ALL_ALBUM: { - return getAlbumPath(uri, MEDIA_TYPE_ALL); - } - } - } catch (NumberFormatException e) { - Log.w(TAG, "uri: " + uri.toString(), e); - } - return null; - } - - @Override - public Path getDefaultSetOf(Path item) { - MediaObject object = mApplication.getDataManager().getMediaObject(item); - if (object instanceof LocalMediaItem) { - return Path.fromString("/local/all").getChild( - String.valueOf(((LocalMediaItem) object).getBucketId())); - } - return null; - } - - @Override - public void mapMediaItems(ArrayList<PathId> list, ItemConsumer consumer) { - ArrayList<PathId> imageList = new ArrayList<PathId>(); - ArrayList<PathId> videoList = new ArrayList<PathId>(); - int n = list.size(); - for (int i = 0; i < n; i++) { - PathId pid = list.get(i); - // We assume the form is: "/local/{image,video}/item/#" - // We don't use mMatcher for efficiency's reason. - Path parent = pid.path.getParent(); - if (parent == LocalImage.ITEM_PATH) { - imageList.add(pid); - } else if (parent == LocalVideo.ITEM_PATH) { - videoList.add(pid); - } - } - // TODO: use "files" table so we can merge the two cases. - processMapMediaItems(imageList, consumer, true); - processMapMediaItems(videoList, consumer, false); - } - - private void processMapMediaItems(ArrayList<PathId> list, - ItemConsumer consumer, boolean isImage) { - // Sort path by path id - Collections.sort(list, sIdComparator); - int n = list.size(); - for (int i = 0; i < n; ) { - PathId pid = list.get(i); - - // Find a range of items. - ArrayList<Integer> ids = new ArrayList<Integer>(); - int startId = Integer.parseInt(pid.path.getSuffix()); - ids.add(startId); - - int j; - for (j = i + 1; j < n; j++) { - PathId pid2 = list.get(j); - int curId = Integer.parseInt(pid2.path.getSuffix()); - if (curId - startId >= MediaSet.MEDIAITEM_BATCH_FETCH_COUNT) { - break; - } - ids.add(curId); - } - - MediaItem[] items = LocalAlbum.getMediaItemById( - mApplication, isImage, ids); - for(int k = i ; k < j; k++) { - PathId pid2 = list.get(k); - consumer.consume(pid2.id, items[k - i]); - } - - i = j; - } - } - - // This is a comparator which compares the suffix number in two Paths. - private static class IdComparator implements Comparator<PathId> { - @Override - public int compare(PathId p1, PathId p2) { - String s1 = p1.path.getSuffix(); - String s2 = p2.path.getSuffix(); - int len1 = s1.length(); - int len2 = s2.length(); - if (len1 < len2) { - return -1; - } else if (len1 > len2) { - return 1; - } else { - return s1.compareTo(s2); - } - } - } - - @Override - public void resume() { - mClient = mApplication.getContentResolver() - .acquireContentProviderClient(MediaStore.AUTHORITY); - } - - @Override - public void pause() { - mClient.release(); - mClient = null; - } -} diff --git a/src/com/android/gallery3d/data/LocalVideo.java b/src/com/android/gallery3d/data/LocalVideo.java deleted file mode 100644 index 4b8774ca4..000000000 --- a/src/com/android/gallery3d/data/LocalVideo.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.ContentResolver; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; -import android.provider.MediaStore.Video; -import android.provider.MediaStore.Video.VideoColumns; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; -import com.android.gallery3d.util.UpdateHelper; - -// LocalVideo represents a video in the local storage. -public class LocalVideo extends LocalMediaItem { - private static final String TAG = "LocalVideo"; - static final Path ITEM_PATH = Path.fromString("/local/video/item"); - - // Must preserve order between these indices and the order of the terms in - // the following PROJECTION array. - private static final int INDEX_ID = 0; - private static final int INDEX_CAPTION = 1; - private static final int INDEX_MIME_TYPE = 2; - private static final int INDEX_LATITUDE = 3; - private static final int INDEX_LONGITUDE = 4; - private static final int INDEX_DATE_TAKEN = 5; - private static final int INDEX_DATE_ADDED = 6; - private static final int INDEX_DATE_MODIFIED = 7; - private static final int INDEX_DATA = 8; - private static final int INDEX_DURATION = 9; - private static final int INDEX_BUCKET_ID = 10; - private static final int INDEX_SIZE = 11; - private static final int INDEX_RESOLUTION = 12; - - static final String[] PROJECTION = new String[] { - VideoColumns._ID, - VideoColumns.TITLE, - VideoColumns.MIME_TYPE, - VideoColumns.LATITUDE, - VideoColumns.LONGITUDE, - VideoColumns.DATE_TAKEN, - VideoColumns.DATE_ADDED, - VideoColumns.DATE_MODIFIED, - VideoColumns.DATA, - VideoColumns.DURATION, - VideoColumns.BUCKET_ID, - VideoColumns.SIZE, - VideoColumns.RESOLUTION, - }; - - private final GalleryApp mApplication; - - public int durationInSec; - - public LocalVideo(Path path, GalleryApp application, Cursor cursor) { - super(path, nextVersionNumber()); - mApplication = application; - loadFromCursor(cursor); - } - - public LocalVideo(Path path, GalleryApp context, int id) { - super(path, nextVersionNumber()); - mApplication = context; - ContentResolver resolver = mApplication.getContentResolver(); - Uri uri = Video.Media.EXTERNAL_CONTENT_URI; - Cursor cursor = LocalAlbum.getItemCursor(resolver, uri, PROJECTION, id); - if (cursor == null) { - throw new RuntimeException("cannot get cursor for: " + path); - } - try { - if (cursor.moveToNext()) { - loadFromCursor(cursor); - } else { - throw new RuntimeException("cannot find data for: " + path); - } - } finally { - cursor.close(); - } - } - - private void loadFromCursor(Cursor cursor) { - id = cursor.getInt(INDEX_ID); - caption = cursor.getString(INDEX_CAPTION); - mimeType = cursor.getString(INDEX_MIME_TYPE); - latitude = cursor.getDouble(INDEX_LATITUDE); - longitude = cursor.getDouble(INDEX_LONGITUDE); - dateTakenInMs = cursor.getLong(INDEX_DATE_TAKEN); - dateAddedInSec = cursor.getLong(INDEX_DATE_ADDED); - dateModifiedInSec = cursor.getLong(INDEX_DATE_MODIFIED); - filePath = cursor.getString(INDEX_DATA); - durationInSec = cursor.getInt(INDEX_DURATION) / 1000; - bucketId = cursor.getInt(INDEX_BUCKET_ID); - fileSize = cursor.getLong(INDEX_SIZE); - parseResolution(cursor.getString(INDEX_RESOLUTION)); - } - - private void parseResolution(String resolution) { - if (resolution == null) return; - int m = resolution.indexOf('x'); - if (m == -1) return; - try { - int w = Integer.parseInt(resolution.substring(0, m)); - int h = Integer.parseInt(resolution.substring(m + 1)); - width = w; - height = h; - } catch (Throwable t) { - Log.w(TAG, t); - } - } - - @Override - protected boolean updateFromCursor(Cursor cursor) { - UpdateHelper uh = new UpdateHelper(); - id = uh.update(id, cursor.getInt(INDEX_ID)); - caption = uh.update(caption, cursor.getString(INDEX_CAPTION)); - mimeType = uh.update(mimeType, cursor.getString(INDEX_MIME_TYPE)); - latitude = uh.update(latitude, cursor.getDouble(INDEX_LATITUDE)); - longitude = uh.update(longitude, cursor.getDouble(INDEX_LONGITUDE)); - dateTakenInMs = uh.update( - dateTakenInMs, cursor.getLong(INDEX_DATE_TAKEN)); - dateAddedInSec = uh.update( - dateAddedInSec, cursor.getLong(INDEX_DATE_ADDED)); - dateModifiedInSec = uh.update( - dateModifiedInSec, cursor.getLong(INDEX_DATE_MODIFIED)); - filePath = uh.update(filePath, cursor.getString(INDEX_DATA)); - durationInSec = uh.update( - durationInSec, cursor.getInt(INDEX_DURATION) / 1000); - bucketId = uh.update(bucketId, cursor.getInt(INDEX_BUCKET_ID)); - fileSize = uh.update(fileSize, cursor.getLong(INDEX_SIZE)); - return uh.isUpdated(); - } - - @Override - public Job<Bitmap> requestImage(int type) { - return new LocalVideoRequest(mApplication, getPath(), dateModifiedInSec, - type, filePath); - } - - public static class LocalVideoRequest extends ImageCacheRequest { - private String mLocalFilePath; - - LocalVideoRequest(GalleryApp application, Path path, long timeModified, - int type, String localFilePath) { - super(application, path, timeModified, type, - MediaItem.getTargetSize(type)); - mLocalFilePath = localFilePath; - } - - @Override - public Bitmap onDecodeOriginal(JobContext jc, int type) { - Bitmap bitmap = BitmapUtils.createVideoThumbnail(mLocalFilePath); - if (bitmap == null || jc.isCancelled()) return null; - return bitmap; - } - } - - @Override - public Job<BitmapRegionDecoder> requestLargeImage() { - throw new UnsupportedOperationException("Cannot regquest a large image" - + " to a local video!"); - } - - @Override - public int getSupportedOperations() { - return SUPPORT_DELETE | SUPPORT_SHARE | SUPPORT_PLAY | SUPPORT_INFO | SUPPORT_TRIM | SUPPORT_MUTE; - } - - @Override - public void delete() { - GalleryUtils.assertNotInRenderThread(); - Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI; - mApplication.getContentResolver().delete(baseUri, "_id=?", - new String[]{String.valueOf(id)}); - } - - @Override - public void rotate(int degrees) { - // TODO - } - - @Override - public Uri getContentUri() { - Uri baseUri = Video.Media.EXTERNAL_CONTENT_URI; - return baseUri.buildUpon().appendPath(String.valueOf(id)).build(); - } - - @Override - public Uri getPlayUri() { - return getContentUri(); - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_VIDEO; - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - int s = durationInSec; - if (s > 0) { - details.addDetail(MediaDetails.INDEX_DURATION, GalleryUtils.formatDuration( - mApplication.getAndroidContext(), durationInSec)); - } - return details; - } - - @Override - public int getWidth() { - return width; - } - - @Override - public int getHeight() { - return height; - } - - @Override - public String getFilePath() { - return filePath; - } -} diff --git a/src/com/android/gallery3d/data/LocationClustering.java b/src/com/android/gallery3d/data/LocationClustering.java deleted file mode 100644 index 540322a33..000000000 --- a/src/com/android/gallery3d/data/LocationClustering.java +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.os.Handler; -import android.os.Looper; -import android.util.FloatMath; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ReverseGeocoder; - -import java.util.ArrayList; - -class LocationClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "LocationClustering"; - - private static final int MIN_GROUPS = 1; - private static final int MAX_GROUPS = 20; - private static final int MAX_ITERATIONS = 30; - - // If the total distance change is less than this ratio, stop iterating. - private static final float STOP_CHANGE_RATIO = 0.01f; - private Context mContext; - private ArrayList<ArrayList<SmallItem>> mClusters; - private ArrayList<String> mNames; - private String mNoLocationString; - private Handler mHandler; - - private static class Point { - public Point(double lat, double lng) { - latRad = Math.toRadians(lat); - lngRad = Math.toRadians(lng); - } - public Point() {} - public double latRad, lngRad; - } - - private static class SmallItem { - Path path; - double lat, lng; - } - - public LocationClustering(Context context) { - mContext = context; - mNoLocationString = mContext.getResources().getString(R.string.no_location); - mHandler = new Handler(Looper.getMainLooper()); - } - - @Override - public void run(MediaSet baseSet) { - final int total = baseSet.getTotalMediaItemCount(); - final SmallItem[] buf = new SmallItem[total]; - // Separate items to two sets: with or without lat-long. - final double[] latLong = new double[2]; - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if (index < 0 || index >= total) return; - SmallItem s = new SmallItem(); - s.path = item.getPath(); - item.getLatLong(latLong); - s.lat = latLong[0]; - s.lng = latLong[1]; - buf[index] = s; - } - }); - - final ArrayList<SmallItem> withLatLong = new ArrayList<SmallItem>(); - final ArrayList<SmallItem> withoutLatLong = new ArrayList<SmallItem>(); - final ArrayList<Point> points = new ArrayList<Point>(); - for (int i = 0; i < total; i++) { - SmallItem s = buf[i]; - if (s == null) continue; - if (GalleryUtils.isValidLocation(s.lat, s.lng)) { - withLatLong.add(s); - points.add(new Point(s.lat, s.lng)); - } else { - withoutLatLong.add(s); - } - } - - ArrayList<ArrayList<SmallItem>> clusters = new ArrayList<ArrayList<SmallItem>>(); - - int m = withLatLong.size(); - if (m > 0) { - // cluster the items with lat-long - Point[] pointsArray = new Point[m]; - pointsArray = points.toArray(pointsArray); - int[] bestK = new int[1]; - int[] index = kMeans(pointsArray, bestK); - - for (int i = 0; i < bestK[0]; i++) { - clusters.add(new ArrayList<SmallItem>()); - } - - for (int i = 0; i < m; i++) { - clusters.get(index[i]).add(withLatLong.get(i)); - } - } - - ReverseGeocoder geocoder = new ReverseGeocoder(mContext); - mNames = new ArrayList<String>(); - boolean hasUnresolvedAddress = false; - mClusters = new ArrayList<ArrayList<SmallItem>>(); - for (ArrayList<SmallItem> cluster : clusters) { - String name = generateName(cluster, geocoder); - if (name != null) { - mNames.add(name); - mClusters.add(cluster); - } else { - // move cluster-i to no location cluster - withoutLatLong.addAll(cluster); - hasUnresolvedAddress = true; - } - } - - if (withoutLatLong.size() > 0) { - mNames.add(mNoLocationString); - mClusters.add(withoutLatLong); - } - - if (hasUnresolvedAddress) { - mHandler.post(new Runnable() { - @Override - public void run() { - Toast.makeText(mContext, R.string.no_connectivity, - Toast.LENGTH_LONG).show(); - } - }); - } - } - - private static String generateName(ArrayList<SmallItem> items, - ReverseGeocoder geocoder) { - ReverseGeocoder.SetLatLong set = new ReverseGeocoder.SetLatLong(); - - int n = items.size(); - for (int i = 0; i < n; i++) { - SmallItem item = items.get(i); - double itemLatitude = item.lat; - double itemLongitude = item.lng; - - if (set.mMinLatLatitude > itemLatitude) { - set.mMinLatLatitude = itemLatitude; - set.mMinLatLongitude = itemLongitude; - } - if (set.mMaxLatLatitude < itemLatitude) { - set.mMaxLatLatitude = itemLatitude; - set.mMaxLatLongitude = itemLongitude; - } - if (set.mMinLonLongitude > itemLongitude) { - set.mMinLonLatitude = itemLatitude; - set.mMinLonLongitude = itemLongitude; - } - if (set.mMaxLonLongitude < itemLongitude) { - set.mMaxLonLatitude = itemLatitude; - set.mMaxLonLongitude = itemLongitude; - } - } - - return geocoder.computeAddress(set); - } - - @Override - public int getNumberOfClusters() { - return mClusters.size(); - } - - @Override - public ArrayList<Path> getCluster(int index) { - ArrayList<SmallItem> items = mClusters.get(index); - ArrayList<Path> result = new ArrayList<Path>(items.size()); - for (int i = 0, n = items.size(); i < n; i++) { - result.add(items.get(i).path); - } - return result; - } - - @Override - public String getClusterName(int index) { - return mNames.get(index); - } - - // Input: n points - // Output: the best k is stored in bestK[0], and the return value is the - // an array which specifies the group that each point belongs (0 to k - 1). - private static int[] kMeans(Point points[], int[] bestK) { - int n = points.length; - - // min and max number of groups wanted - int minK = Math.min(n, MIN_GROUPS); - int maxK = Math.min(n, MAX_GROUPS); - - Point[] center = new Point[maxK]; // center of each group. - Point[] groupSum = new Point[maxK]; // sum of points in each group. - int[] groupCount = new int[maxK]; // number of points in each group. - int[] grouping = new int[n]; // The group assignment for each point. - - for (int i = 0; i < maxK; i++) { - center[i] = new Point(); - groupSum[i] = new Point(); - } - - // The score we want to minimize is: - // (sum of distance from each point to its group center) * sqrt(k). - float bestScore = Float.MAX_VALUE; - // The best group assignment up to now. - int[] bestGrouping = new int[n]; - // The best K up to now. - bestK[0] = 1; - - float lastDistance = 0; - float totalDistance = 0; - - for (int k = minK; k <= maxK; k++) { - // step 1: (arbitrarily) pick k points as the initial centers. - int delta = n / k; - for (int i = 0; i < k; i++) { - Point p = points[i * delta]; - center[i].latRad = p.latRad; - center[i].lngRad = p.lngRad; - } - - for (int iter = 0; iter < MAX_ITERATIONS; iter++) { - // step 2: assign each point to the nearest center. - for (int i = 0; i < k; i++) { - groupSum[i].latRad = 0; - groupSum[i].lngRad = 0; - groupCount[i] = 0; - } - totalDistance = 0; - - for (int i = 0; i < n; i++) { - Point p = points[i]; - float bestDistance = Float.MAX_VALUE; - int bestIndex = 0; - for (int j = 0; j < k; j++) { - float distance = (float) GalleryUtils.fastDistanceMeters( - p.latRad, p.lngRad, center[j].latRad, center[j].lngRad); - // We may have small non-zero distance introduced by - // floating point calculation, so zero out small - // distances less than 1 meter. - if (distance < 1) { - distance = 0; - } - if (distance < bestDistance) { - bestDistance = distance; - bestIndex = j; - } - } - grouping[i] = bestIndex; - groupCount[bestIndex]++; - groupSum[bestIndex].latRad += p.latRad; - groupSum[bestIndex].lngRad += p.lngRad; - totalDistance += bestDistance; - } - - // step 3: calculate new centers - for (int i = 0; i < k; i++) { - if (groupCount[i] > 0) { - center[i].latRad = groupSum[i].latRad / groupCount[i]; - center[i].lngRad = groupSum[i].lngRad / groupCount[i]; - } - } - - if (totalDistance == 0 || (Math.abs(lastDistance - totalDistance) - / totalDistance) < STOP_CHANGE_RATIO) { - break; - } - lastDistance = totalDistance; - } - - // step 4: remove empty groups and reassign group number - int reassign[] = new int[k]; - int realK = 0; - for (int i = 0; i < k; i++) { - if (groupCount[i] > 0) { - reassign[i] = realK++; - } - } - - // step 5: calculate the final score - float score = totalDistance * FloatMath.sqrt(realK); - - if (score < bestScore) { - bestScore = score; - bestK[0] = realK; - for (int i = 0; i < n; i++) { - bestGrouping[i] = reassign[grouping[i]]; - } - if (score == 0) { - break; - } - } - } - return bestGrouping; - } -} diff --git a/src/com/android/gallery3d/data/Log.java b/src/com/android/gallery3d/data/Log.java deleted file mode 100644 index 3384eb66c..000000000 --- a/src/com/android/gallery3d/data/Log.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -public class Log { - public static int v(String tag, String msg) { - return android.util.Log.v(tag, msg); - } - public static int v(String tag, String msg, Throwable tr) { - return android.util.Log.v(tag, msg, tr); - } - public static int d(String tag, String msg) { - return android.util.Log.d(tag, msg); - } - public static int d(String tag, String msg, Throwable tr) { - return android.util.Log.d(tag, msg, tr); - } - public static int i(String tag, String msg) { - return android.util.Log.i(tag, msg); - } - public static int i(String tag, String msg, Throwable tr) { - return android.util.Log.i(tag, msg, tr); - } - public static int w(String tag, String msg) { - return android.util.Log.w(tag, msg); - } - public static int w(String tag, String msg, Throwable tr) { - return android.util.Log.w(tag, msg, tr); - } - public static int w(String tag, Throwable tr) { - return android.util.Log.w(tag, tr); - } - public static int e(String tag, String msg) { - return android.util.Log.e(tag, msg); - } - public static int e(String tag, String msg, Throwable tr) { - return android.util.Log.e(tag, msg, tr); - } -} diff --git a/src/com/android/gallery3d/data/MediaDetails.java b/src/com/android/gallery3d/data/MediaDetails.java deleted file mode 100644 index cac524b88..000000000 --- a/src/com/android/gallery3d/data/MediaDetails.java +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.exif.ExifTag; -import com.android.gallery3d.exif.Rational; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map.Entry; -import java.util.TreeMap; - -public class MediaDetails implements Iterable<Entry<Integer, Object>> { - @SuppressWarnings("unused") - private static final String TAG = "MediaDetails"; - - private TreeMap<Integer, Object> mDetails = new TreeMap<Integer, Object>(); - private HashMap<Integer, Integer> mUnits = new HashMap<Integer, Integer>(); - - public static final int INDEX_TITLE = 1; - public static final int INDEX_DESCRIPTION = 2; - public static final int INDEX_DATETIME = 3; - public static final int INDEX_LOCATION = 4; - public static final int INDEX_WIDTH = 5; - public static final int INDEX_HEIGHT = 6; - public static final int INDEX_ORIENTATION = 7; - public static final int INDEX_DURATION = 8; - public static final int INDEX_MIMETYPE = 9; - public static final int INDEX_SIZE = 10; - - // for EXIF - public static final int INDEX_MAKE = 100; - public static final int INDEX_MODEL = 101; - public static final int INDEX_FLASH = 102; - public static final int INDEX_FOCAL_LENGTH = 103; - public static final int INDEX_WHITE_BALANCE = 104; - public static final int INDEX_APERTURE = 105; - public static final int INDEX_SHUTTER_SPEED = 106; - public static final int INDEX_EXPOSURE_TIME = 107; - public static final int INDEX_ISO = 108; - - // Put this last because it may be long. - public static final int INDEX_PATH = 200; - - public static class FlashState { - private static int FLASH_FIRED_MASK = 1; - private static int FLASH_RETURN_MASK = 2 | 4; - private static int FLASH_MODE_MASK = 8 | 16; - private static int FLASH_FUNCTION_MASK = 32; - private static int FLASH_RED_EYE_MASK = 64; - private int mState; - - public FlashState(int state) { - mState = state; - } - - public boolean isFlashFired() { - return (mState & FLASH_FIRED_MASK) != 0; - } - } - - public void addDetail(int index, Object value) { - mDetails.put(index, value); - } - - public Object getDetail(int index) { - return mDetails.get(index); - } - - public int size() { - return mDetails.size(); - } - - @Override - public Iterator<Entry<Integer, Object>> iterator() { - return mDetails.entrySet().iterator(); - } - - public void setUnit(int index, int unit) { - mUnits.put(index, unit); - } - - public boolean hasUnit(int index) { - return mUnits.containsKey(index); - } - - public int getUnit(int index) { - return mUnits.get(index); - } - - private static void setExifData(MediaDetails details, ExifTag tag, - int key) { - if (tag != null) { - String value = null; - int type = tag.getDataType(); - if (type == ExifTag.TYPE_UNSIGNED_RATIONAL || type == ExifTag.TYPE_RATIONAL) { - value = String.valueOf(tag.getValueAsRational(0).toDouble()); - } else if (type == ExifTag.TYPE_ASCII) { - value = tag.getValueAsString(); - } else { - value = String.valueOf(tag.forceGetValueAsLong(0)); - } - if (key == MediaDetails.INDEX_FLASH) { - MediaDetails.FlashState state = new MediaDetails.FlashState( - Integer.valueOf(value.toString())); - details.addDetail(key, state); - } else { - details.addDetail(key, value); - } - } - } - - public static void extractExifInfo(MediaDetails details, String filePath) { - - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(filePath); - } catch (FileNotFoundException e) { - Log.w(TAG, "Could not find file to read exif: " + filePath, e); - } catch (IOException e) { - Log.w(TAG, "Could not read exif from file: " + filePath, e); - } - - setExifData(details, exif.getTag(ExifInterface.TAG_FLASH), - MediaDetails.INDEX_FLASH); - setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_WIDTH), - MediaDetails.INDEX_WIDTH); - setExifData(details, exif.getTag(ExifInterface.TAG_IMAGE_LENGTH), - MediaDetails.INDEX_HEIGHT); - setExifData(details, exif.getTag(ExifInterface.TAG_MAKE), - MediaDetails.INDEX_MAKE); - setExifData(details, exif.getTag(ExifInterface.TAG_MODEL), - MediaDetails.INDEX_MODEL); - setExifData(details, exif.getTag(ExifInterface.TAG_APERTURE_VALUE), - MediaDetails.INDEX_APERTURE); - setExifData(details, exif.getTag(ExifInterface.TAG_ISO_SPEED_RATINGS), - MediaDetails.INDEX_ISO); - setExifData(details, exif.getTag(ExifInterface.TAG_WHITE_BALANCE), - MediaDetails.INDEX_WHITE_BALANCE); - setExifData(details, exif.getTag(ExifInterface.TAG_EXPOSURE_TIME), - MediaDetails.INDEX_EXPOSURE_TIME); - ExifTag focalTag = exif.getTag(ExifInterface.TAG_FOCAL_LENGTH); - if (focalTag != null) { - details.addDetail(MediaDetails.INDEX_FOCAL_LENGTH, - focalTag.getValueAsRational(0).toDouble()); - details.setUnit(MediaDetails.INDEX_FOCAL_LENGTH, R.string.unit_mm); - } - } -} diff --git a/src/com/android/gallery3d/data/MediaItem.java b/src/com/android/gallery3d/data/MediaItem.java deleted file mode 100644 index 59ea86551..000000000 --- a/src/com/android/gallery3d/data/MediaItem.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.util.ThreadPool.Job; - -// MediaItem represents an image or a video item. -public abstract class MediaItem extends MediaObject { - // NOTE: These type numbers are stored in the image cache, so it should not - // not be changed without resetting the cache. - public static final int TYPE_THUMBNAIL = 1; - public static final int TYPE_MICROTHUMBNAIL = 2; - - public static final int CACHED_IMAGE_QUALITY = 95; - - public static final int IMAGE_READY = 0; - public static final int IMAGE_WAIT = 1; - public static final int IMAGE_ERROR = -1; - - public static final String MIME_TYPE_JPEG = "image/jpeg"; - - private static final int BYTESBUFFE_POOL_SIZE = 4; - private static final int BYTESBUFFER_SIZE = 200 * 1024; - - private static int sMicrothumbnailTargetSize = 200; - private static final BytesBufferPool sMicroThumbBufferPool = - new BytesBufferPool(BYTESBUFFE_POOL_SIZE, BYTESBUFFER_SIZE); - - private static int sThumbnailTargetSize = 640; - - // TODO: fix default value for latlng and change this. - public static final double INVALID_LATLNG = 0f; - - public abstract Job<Bitmap> requestImage(int type); - public abstract Job<BitmapRegionDecoder> requestLargeImage(); - - public MediaItem(Path path, long version) { - super(path, version); - } - - public long getDateInMs() { - return 0; - } - - public String getName() { - return null; - } - - public void getLatLong(double[] latLong) { - latLong[0] = INVALID_LATLNG; - latLong[1] = INVALID_LATLNG; - } - - public String[] getTags() { - return null; - } - - public Face[] getFaces() { - return null; - } - - // The rotation of the full-resolution image. By default, it returns the value of - // getRotation(). - public int getFullImageRotation() { - return getRotation(); - } - - public int getRotation() { - return 0; - } - - public long getSize() { - return 0; - } - - public abstract String getMimeType(); - - public String getFilePath() { - return ""; - } - - // Returns width and height of the media item. - // Returns 0, 0 if the information is not available. - public abstract int getWidth(); - public abstract int getHeight(); - - // This is an alternative for requestImage() in PhotoPage. If this - // is implemented, you don't need to implement requestImage(). - public ScreenNail getScreenNail() { - return null; - } - - public static int getTargetSize(int type) { - switch (type) { - case TYPE_THUMBNAIL: - return sThumbnailTargetSize; - case TYPE_MICROTHUMBNAIL: - return sMicrothumbnailTargetSize; - default: - throw new RuntimeException( - "should only request thumb/microthumb from cache"); - } - } - - public static BytesBufferPool getBytesBufferPool() { - return sMicroThumbBufferPool; - } - - public static void setThumbnailSizes(int size, int microSize) { - sThumbnailTargetSize = size; - if (sMicrothumbnailTargetSize != microSize) { - sMicrothumbnailTargetSize = microSize; - } - } -} diff --git a/src/com/android/gallery3d/data/MediaObject.java b/src/com/android/gallery3d/data/MediaObject.java deleted file mode 100644 index 270d4cf0b..000000000 --- a/src/com/android/gallery3d/data/MediaObject.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.net.Uri; - -public abstract class MediaObject { - @SuppressWarnings("unused") - private static final String TAG = "MediaObject"; - public static final long INVALID_DATA_VERSION = -1; - - // These are the bits returned from getSupportedOperations(): - public static final int SUPPORT_DELETE = 1 << 0; - public static final int SUPPORT_ROTATE = 1 << 1; - public static final int SUPPORT_SHARE = 1 << 2; - public static final int SUPPORT_CROP = 1 << 3; - public static final int SUPPORT_SHOW_ON_MAP = 1 << 4; - public static final int SUPPORT_SETAS = 1 << 5; - public static final int SUPPORT_FULL_IMAGE = 1 << 6; - public static final int SUPPORT_PLAY = 1 << 7; - public static final int SUPPORT_CACHE = 1 << 8; - public static final int SUPPORT_EDIT = 1 << 9; - public static final int SUPPORT_INFO = 1 << 10; - public static final int SUPPORT_TRIM = 1 << 11; - public static final int SUPPORT_UNLOCK = 1 << 12; - public static final int SUPPORT_BACK = 1 << 13; - public static final int SUPPORT_ACTION = 1 << 14; - public static final int SUPPORT_CAMERA_SHORTCUT = 1 << 15; - public static final int SUPPORT_MUTE = 1 << 16; - public static final int SUPPORT_ALL = 0xffffffff; - - // These are the bits returned from getMediaType(): - public static final int MEDIA_TYPE_UNKNOWN = 1; - public static final int MEDIA_TYPE_IMAGE = 2; - public static final int MEDIA_TYPE_VIDEO = 4; - public static final int MEDIA_TYPE_ALL = MEDIA_TYPE_IMAGE | MEDIA_TYPE_VIDEO; - - public static final String MEDIA_TYPE_IMAGE_STRING = "image"; - public static final String MEDIA_TYPE_VIDEO_STRING = "video"; - public static final String MEDIA_TYPE_ALL_STRING = "all"; - - // These are flags for cache() and return values for getCacheFlag(): - public static final int CACHE_FLAG_NO = 0; - public static final int CACHE_FLAG_SCREENNAIL = 1; - public static final int CACHE_FLAG_FULL = 2; - - // These are return values for getCacheStatus(): - public static final int CACHE_STATUS_NOT_CACHED = 0; - public static final int CACHE_STATUS_CACHING = 1; - public static final int CACHE_STATUS_CACHED_SCREENNAIL = 2; - public static final int CACHE_STATUS_CACHED_FULL = 3; - - private static long sVersionSerial = 0; - - protected long mDataVersion; - - protected final Path mPath; - - public interface PanoramaSupportCallback { - void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360); - } - - public MediaObject(Path path, long version) { - path.setObject(this); - mPath = path; - mDataVersion = version; - } - - public Path getPath() { - return mPath; - } - - public int getSupportedOperations() { - return 0; - } - - public void getPanoramaSupport(PanoramaSupportCallback callback) { - callback.panoramaInfoAvailable(this, false, false); - } - - public void clearCachedPanoramaSupport() { - } - - public void delete() { - throw new UnsupportedOperationException(); - } - - public void rotate(int degrees) { - throw new UnsupportedOperationException(); - } - - public Uri getContentUri() { - String className = getClass().getName(); - Log.e(TAG, "Class " + className + "should implement getContentUri."); - Log.e(TAG, "The object was created from path: " + getPath()); - throw new UnsupportedOperationException(); - } - - public Uri getPlayUri() { - throw new UnsupportedOperationException(); - } - - public int getMediaType() { - return MEDIA_TYPE_UNKNOWN; - } - - public MediaDetails getDetails() { - MediaDetails details = new MediaDetails(); - return details; - } - - public long getDataVersion() { - return mDataVersion; - } - - public int getCacheFlag() { - return CACHE_FLAG_NO; - } - - public int getCacheStatus() { - throw new UnsupportedOperationException(); - } - - public long getCacheSize() { - throw new UnsupportedOperationException(); - } - - public void cache(int flag) { - throw new UnsupportedOperationException(); - } - - public static synchronized long nextVersionNumber() { - return ++MediaObject.sVersionSerial; - } - - public static int getTypeFromString(String s) { - if (MEDIA_TYPE_ALL_STRING.equals(s)) return MediaObject.MEDIA_TYPE_ALL; - if (MEDIA_TYPE_IMAGE_STRING.equals(s)) return MediaObject.MEDIA_TYPE_IMAGE; - if (MEDIA_TYPE_VIDEO_STRING.equals(s)) return MediaObject.MEDIA_TYPE_VIDEO; - throw new IllegalArgumentException(s); - } - - public static String getTypeString(int type) { - switch (type) { - case MEDIA_TYPE_IMAGE: return MEDIA_TYPE_IMAGE_STRING; - case MEDIA_TYPE_VIDEO: return MEDIA_TYPE_VIDEO_STRING; - case MEDIA_TYPE_ALL: return MEDIA_TYPE_ALL_STRING; - } - throw new IllegalArgumentException(); - } -} diff --git a/src/com/android/gallery3d/data/MediaSet.java b/src/com/android/gallery3d/data/MediaSet.java deleted file mode 100644 index 683aa6b32..000000000 --- a/src/com/android/gallery3d/data/MediaSet.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.Future; - -import java.util.ArrayList; -import java.util.WeakHashMap; - -// MediaSet is a directory-like data structure. -// It contains MediaItems and sub-MediaSets. -// -// The primary interface are: -// getMediaItemCount(), getMediaItem() and -// getSubMediaSetCount(), getSubMediaSet(). -// -// getTotalMediaItemCount() returns the number of all MediaItems, including -// those in sub-MediaSets. -public abstract class MediaSet extends MediaObject { - @SuppressWarnings("unused") - private static final String TAG = "MediaSet"; - - public static final int MEDIAITEM_BATCH_FETCH_COUNT = 500; - public static final int INDEX_NOT_FOUND = -1; - - public static final int SYNC_RESULT_SUCCESS = 0; - public static final int SYNC_RESULT_CANCELLED = 1; - public static final int SYNC_RESULT_ERROR = 2; - - /** Listener to be used with requestSync(SyncListener). */ - public static interface SyncListener { - /** - * Called when the sync task completed. Completion may be due to normal termination, - * an exception, or cancellation. - * - * @param mediaSet the MediaSet that's done with sync - * @param resultCode one of the SYNC_RESULT_* constants - */ - void onSyncDone(MediaSet mediaSet, int resultCode); - } - - public MediaSet(Path path, long version) { - super(path, version); - } - - public int getMediaItemCount() { - return 0; - } - - // Returns the media items in the range [start, start + count). - // - // The number of media items returned may be less than the specified count - // if there are not enough media items available. The number of - // media items available may not be consistent with the return value of - // getMediaItemCount() because the contents of database may have already - // changed. - public ArrayList<MediaItem> getMediaItem(int start, int count) { - return new ArrayList<MediaItem>(); - } - - public MediaItem getCoverMediaItem() { - ArrayList<MediaItem> items = getMediaItem(0, 1); - if (items.size() > 0) return items.get(0); - for (int i = 0, n = getSubMediaSetCount(); i < n; i++) { - MediaItem cover = getSubMediaSet(i).getCoverMediaItem(); - if (cover != null) return cover; - } - return null; - } - - public int getSubMediaSetCount() { - return 0; - } - - public MediaSet getSubMediaSet(int index) { - throw new IndexOutOfBoundsException(); - } - - public boolean isLeafAlbum() { - return false; - } - - public boolean isCameraRoll() { - return false; - } - - /** - * Method {@link #reload()} may process the loading task in background, this method tells - * its client whether the loading is still in process or not. - */ - public boolean isLoading() { - return false; - } - - public int getTotalMediaItemCount() { - int total = getMediaItemCount(); - for (int i = 0, n = getSubMediaSetCount(); i < n; i++) { - total += getSubMediaSet(i).getTotalMediaItemCount(); - } - return total; - } - - // TODO: we should have better implementation of sub classes - public int getIndexOfItem(Path path, int hint) { - // hint < 0 is handled below - // first, try to find it around the hint - int start = Math.max(0, - hint - MEDIAITEM_BATCH_FETCH_COUNT / 2); - ArrayList<MediaItem> list = getMediaItem( - start, MEDIAITEM_BATCH_FETCH_COUNT); - int index = getIndexOf(path, list); - if (index != INDEX_NOT_FOUND) return start + index; - - // try to find it globally - start = start == 0 ? MEDIAITEM_BATCH_FETCH_COUNT : 0; - list = getMediaItem(start, MEDIAITEM_BATCH_FETCH_COUNT); - while (true) { - index = getIndexOf(path, list); - if (index != INDEX_NOT_FOUND) return start + index; - if (list.size() < MEDIAITEM_BATCH_FETCH_COUNT) return INDEX_NOT_FOUND; - start += MEDIAITEM_BATCH_FETCH_COUNT; - list = getMediaItem(start, MEDIAITEM_BATCH_FETCH_COUNT); - } - } - - protected int getIndexOf(Path path, ArrayList<MediaItem> list) { - for (int i = 0, n = list.size(); i < n; ++i) { - // item could be null only in ClusterAlbum - MediaObject item = list.get(i); - if (item != null && item.mPath == path) return i; - } - return INDEX_NOT_FOUND; - } - - public abstract String getName(); - - private WeakHashMap<ContentListener, Object> mListeners = - new WeakHashMap<ContentListener, Object>(); - - // NOTE: The MediaSet only keeps a weak reference to the listener. The - // listener is automatically removed when there is no other reference to - // the listener. - public void addContentListener(ContentListener listener) { - mListeners.put(listener, null); - } - - public void removeContentListener(ContentListener listener) { - mListeners.remove(listener); - } - - // This should be called by subclasses when the content is changed. - public void notifyContentChanged() { - for (ContentListener listener : mListeners.keySet()) { - listener.onContentDirty(); - } - } - - // Reload the content. Return the current data version. reload() should be called - // in the same thread as getMediaItem(int, int) and getSubMediaSet(int). - public abstract long reload(); - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - details.addDetail(MediaDetails.INDEX_TITLE, getName()); - return details; - } - - // Enumerate all media items in this media set (including the ones in sub - // media sets), in an efficient order. ItemConsumer.consumer() will be - // called for each media item with its index. - public void enumerateMediaItems(ItemConsumer consumer) { - enumerateMediaItems(consumer, 0); - } - - public void enumerateTotalMediaItems(ItemConsumer consumer) { - enumerateTotalMediaItems(consumer, 0); - } - - public static interface ItemConsumer { - void consume(int index, MediaItem item); - } - - // The default implementation uses getMediaItem() for enumerateMediaItems(). - // Subclasses may override this and use more efficient implementations. - // Returns the number of items enumerated. - protected int enumerateMediaItems(ItemConsumer consumer, int startIndex) { - int total = getMediaItemCount(); - int start = 0; - while (start < total) { - int count = Math.min(MEDIAITEM_BATCH_FETCH_COUNT, total - start); - ArrayList<MediaItem> items = getMediaItem(start, count); - for (int i = 0, n = items.size(); i < n; i++) { - MediaItem item = items.get(i); - consumer.consume(startIndex + start + i, item); - } - start += count; - } - return total; - } - - // Recursively enumerate all media items under this set. - // Returns the number of items enumerated. - protected int enumerateTotalMediaItems( - ItemConsumer consumer, int startIndex) { - int start = 0; - start += enumerateMediaItems(consumer, startIndex); - int m = getSubMediaSetCount(); - for (int i = 0; i < m; i++) { - start += getSubMediaSet(i).enumerateTotalMediaItems( - consumer, startIndex + start); - } - return start; - } - - /** - * Requests sync on this MediaSet. It returns a Future object that can be used by the caller - * to query the status of the sync. The sync result code is one of the SYNC_RESULT_* constants - * defined in this class and can be obtained by Future.get(). - * - * Subclasses should perform sync on a different thread. - * - * The default implementation here returns a Future stub that does nothing and returns - * SYNC_RESULT_SUCCESS by get(). - */ - public Future<Integer> requestSync(SyncListener listener) { - listener.onSyncDone(this, SYNC_RESULT_SUCCESS); - return FUTURE_STUB; - } - - private static final Future<Integer> FUTURE_STUB = new Future<Integer>() { - @Override - public void cancel() {} - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public boolean isDone() { - return true; - } - - @Override - public Integer get() { - return SYNC_RESULT_SUCCESS; - } - - @Override - public void waitDone() {} - }; - - protected Future<Integer> requestSyncOnMultipleSets(MediaSet[] sets, SyncListener listener) { - return new MultiSetSyncFuture(sets, listener); - } - - private class MultiSetSyncFuture implements Future<Integer>, SyncListener { - @SuppressWarnings("hiding") - private static final String TAG = "Gallery.MultiSetSync"; - - private final SyncListener mListener; - private final Future<Integer> mFutures[]; - - private boolean mIsCancelled = false; - private int mResult = -1; - private int mPendingCount; - - @SuppressWarnings("unchecked") - MultiSetSyncFuture(MediaSet[] sets, SyncListener listener) { - mListener = listener; - mPendingCount = sets.length; - mFutures = new Future[sets.length]; - - synchronized (this) { - for (int i = 0, n = sets.length; i < n; ++i) { - mFutures[i] = sets[i].requestSync(this); - Log.d(TAG, " request sync: " + Utils.maskDebugInfo(sets[i].getName())); - } - } - } - - @Override - public synchronized void cancel() { - if (mIsCancelled) return; - mIsCancelled = true; - for (Future<Integer> future : mFutures) future.cancel(); - if (mResult < 0) mResult = SYNC_RESULT_CANCELLED; - } - - @Override - public synchronized boolean isCancelled() { - return mIsCancelled; - } - - @Override - public synchronized boolean isDone() { - return mPendingCount == 0; - } - - @Override - public synchronized Integer get() { - waitDone(); - return mResult; - } - - @Override - public synchronized void waitDone() { - try { - while (!isDone()) wait(); - } catch (InterruptedException e) { - Log.d(TAG, "waitDone() interrupted"); - } - } - - // SyncListener callback - @Override - public void onSyncDone(MediaSet mediaSet, int resultCode) { - SyncListener listener = null; - synchronized (this) { - if (resultCode == SYNC_RESULT_ERROR) mResult = SYNC_RESULT_ERROR; - --mPendingCount; - if (mPendingCount == 0) { - listener = mListener; - notifyAll(); - } - Log.d(TAG, "onSyncDone: " + Utils.maskDebugInfo(mediaSet.getName()) - + " #pending=" + mPendingCount); - } - if (listener != null) listener.onSyncDone(MediaSet.this, mResult); - } - } -} diff --git a/src/com/android/gallery3d/data/MediaSource.java b/src/com/android/gallery3d/data/MediaSource.java deleted file mode 100644 index 95901283b..000000000 --- a/src/com/android/gallery3d/data/MediaSource.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.net.Uri; - -import com.android.gallery3d.data.MediaSet.ItemConsumer; - -import java.util.ArrayList; - -public abstract class MediaSource { - private static final String TAG = "MediaSource"; - private String mPrefix; - - protected MediaSource(String prefix) { - mPrefix = prefix; - } - - public String getPrefix() { - return mPrefix; - } - - public Path findPathByUri(Uri uri, String type) { - return null; - } - - public abstract MediaObject createMediaObject(Path path); - - public void pause() { - } - - public void resume() { - } - - public Path getDefaultSetOf(Path item) { - return null; - } - - public long getTotalUsedCacheSize() { - return 0; - } - - public long getTotalTargetCacheSize() { - return 0; - } - - public static class PathId { - public PathId(Path path, int id) { - this.path = path; - this.id = id; - } - public Path path; - public int id; - } - - // Maps a list of Paths (all belong to this MediaSource) to MediaItems, - // and invoke consumer.consume() for each MediaItem with the given id. - // - // This default implementation uses getMediaObject for each Path. Subclasses - // may override this and provide more efficient implementation (like - // batching the database query). - public void mapMediaItems(ArrayList<PathId> list, ItemConsumer consumer) { - int n = list.size(); - for (int i = 0; i < n; i++) { - PathId pid = list.get(i); - MediaObject obj; - synchronized (DataManager.LOCK) { - obj = pid.path.getObject(); - if (obj == null) { - try { - obj = createMediaObject(pid.path); - } catch (Throwable th) { - Log.w(TAG, "cannot create media object: " + pid.path, th); - } - } - } - if (obj != null) { - consumer.consume(pid.id, (MediaItem) obj); - } - } - } -} diff --git a/src/com/android/gallery3d/data/MtpClient.java b/src/com/android/gallery3d/data/MtpClient.java deleted file mode 100644 index 737b5b60d..000000000 --- a/src/com/android/gallery3d/data/MtpClient.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.annotation.TargetApi; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.hardware.usb.UsbConstants; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbDeviceConnection; -import android.hardware.usb.UsbInterface; -import android.hardware.usb.UsbManager; -import android.mtp.MtpDevice; -import android.mtp.MtpObjectInfo; -import android.mtp.MtpStorageInfo; -import android.util.Log; - -import com.android.gallery3d.common.ApiHelper; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; - -/** - * This class helps an application manage a list of connected MTP or PTP devices. - * It listens for MTP devices being attached and removed from the USB host bus - * and notifies the application when the MTP device list changes. - */ -@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB_MR1) -public class MtpClient { - - private static final String TAG = "MtpClient"; - - private static final String ACTION_USB_PERMISSION = - "android.mtp.MtpClient.action.USB_PERMISSION"; - - private final Context mContext; - private final UsbManager mUsbManager; - private final ArrayList<Listener> mListeners = new ArrayList<Listener>(); - // mDevices contains all MtpDevices that have been seen by our client, - // so we can inform when the device has been detached. - // mDevices is also used for synchronization in this class. - private final HashMap<String, MtpDevice> mDevices = new HashMap<String, MtpDevice>(); - // List of MTP devices we should not try to open for which we are currently - // asking for permission to open. - private final ArrayList<String> mRequestPermissionDevices = new ArrayList<String>(); - // List of MTP devices we should not try to open. - // We add devices to this list if the user canceled a permission request or we were - // unable to open the device. - private final ArrayList<String> mIgnoredDevices = new ArrayList<String>(); - - private final PendingIntent mPermissionIntent; - - private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - UsbDevice usbDevice = (UsbDevice)intent.getParcelableExtra(UsbManager.EXTRA_DEVICE); - String deviceName = usbDevice.getDeviceName(); - - synchronized (mDevices) { - MtpDevice mtpDevice = mDevices.get(deviceName); - - if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) { - if (mtpDevice == null) { - mtpDevice = openDeviceLocked(usbDevice); - } - if (mtpDevice != null) { - for (Listener listener : mListeners) { - listener.deviceAdded(mtpDevice); - } - } - } else if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) { - if (mtpDevice != null) { - mDevices.remove(deviceName); - mRequestPermissionDevices.remove(deviceName); - mIgnoredDevices.remove(deviceName); - for (Listener listener : mListeners) { - listener.deviceRemoved(mtpDevice); - } - } - } else if (ACTION_USB_PERMISSION.equals(action)) { - mRequestPermissionDevices.remove(deviceName); - boolean permission = intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, - false); - Log.d(TAG, "ACTION_USB_PERMISSION: " + permission); - if (permission) { - if (mtpDevice == null) { - mtpDevice = openDeviceLocked(usbDevice); - } - if (mtpDevice != null) { - for (Listener listener : mListeners) { - listener.deviceAdded(mtpDevice); - } - } - } else { - // so we don't ask for permission again - mIgnoredDevices.add(deviceName); - } - } - } - } - }; - - /** - * An interface for being notified when MTP or PTP devices are attached - * or removed. In the current implementation, only PTP devices are supported. - */ - public interface Listener { - /** - * Called when a new device has been added - * - * @param device the new device that was added - */ - public void deviceAdded(MtpDevice device); - - /** - * Called when a new device has been removed - * - * @param device the device that was removed - */ - public void deviceRemoved(MtpDevice device); - } - - /** - * Tests to see if a {@link android.hardware.usb.UsbDevice} - * supports the PTP protocol (typically used by digital cameras) - * - * @param device the device to test - * @return true if the device is a PTP device. - */ - static public boolean isCamera(UsbDevice device) { - int count = device.getInterfaceCount(); - for (int i = 0; i < count; i++) { - UsbInterface intf = device.getInterface(i); - if (intf.getInterfaceClass() == UsbConstants.USB_CLASS_STILL_IMAGE && - intf.getInterfaceSubclass() == 1 && - intf.getInterfaceProtocol() == 1) { - return true; - } - } - return false; - } - - /** - * MtpClient constructor - * - * @param context the {@link android.content.Context} to use for the MtpClient - */ - public MtpClient(Context context) { - mContext = context; - mUsbManager = (UsbManager)context.getSystemService(Context.USB_SERVICE); - mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0); - IntentFilter filter = new IntentFilter(); - filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED); - filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED); - filter.addAction(ACTION_USB_PERMISSION); - context.registerReceiver(mUsbReceiver, filter); - } - - /** - * Opens the {@link android.hardware.usb.UsbDevice} for an MTP or PTP - * device and return an {@link android.mtp.MtpDevice} for it. - * - * @param usbDevice the device to open - * @return an MtpDevice for the device. - */ - private MtpDevice openDeviceLocked(UsbDevice usbDevice) { - String deviceName = usbDevice.getDeviceName(); - - // don't try to open devices that we have decided to ignore - // or are currently asking permission for - if (isCamera(usbDevice) && !mIgnoredDevices.contains(deviceName) - && !mRequestPermissionDevices.contains(deviceName)) { - if (!mUsbManager.hasPermission(usbDevice)) { - mUsbManager.requestPermission(usbDevice, mPermissionIntent); - mRequestPermissionDevices.add(deviceName); - } else { - UsbDeviceConnection connection = mUsbManager.openDevice(usbDevice); - if (connection != null) { - MtpDevice mtpDevice = new MtpDevice(usbDevice); - if (mtpDevice.open(connection)) { - mDevices.put(usbDevice.getDeviceName(), mtpDevice); - return mtpDevice; - } else { - // so we don't try to open it again - mIgnoredDevices.add(deviceName); - } - } else { - // so we don't try to open it again - mIgnoredDevices.add(deviceName); - } - } - } - return null; - } - - /** - * Closes all resources related to the MtpClient object - */ - public void close() { - mContext.unregisterReceiver(mUsbReceiver); - } - - /** - * Registers a {@link com.android.gallery3d.data.MtpClient.Listener} interface to receive - * notifications when MTP or PTP devices are added or removed. - * - * @param listener the listener to register - */ - public void addListener(Listener listener) { - synchronized (mDevices) { - if (!mListeners.contains(listener)) { - mListeners.add(listener); - } - } - } - - /** - * Unregisters a {@link com.android.gallery3d.data.MtpClient.Listener} interface. - * - * @param listener the listener to unregister - */ - public void removeListener(Listener listener) { - synchronized (mDevices) { - mListeners.remove(listener); - } - } - - /** - * Retrieves an {@link android.mtp.MtpDevice} object for the USB device - * with the given name. - * - * @param deviceName the name of the USB device - * @return the MtpDevice, or null if it does not exist - */ - public MtpDevice getDevice(String deviceName) { - synchronized (mDevices) { - return mDevices.get(deviceName); - } - } - - /** - * Retrieves an {@link android.mtp.MtpDevice} object for the USB device - * with the given ID. - * - * @param id the ID of the USB device - * @return the MtpDevice, or null if it does not exist - */ - public MtpDevice getDevice(int id) { - synchronized (mDevices) { - return mDevices.get(UsbDevice.getDeviceName(id)); - } - } - - /** - * Retrieves a list of all currently connected {@link android.mtp.MtpDevice}. - * - * @return the list of MtpDevices - */ - public List<MtpDevice> getDeviceList() { - synchronized (mDevices) { - // Query the USB manager since devices might have attached - // before we added our listener. - for (UsbDevice usbDevice : mUsbManager.getDeviceList().values()) { - if (mDevices.get(usbDevice.getDeviceName()) == null) { - openDeviceLocked(usbDevice); - } - } - - return new ArrayList<MtpDevice>(mDevices.values()); - } - } - - /** - * Retrieves a list of all {@link android.mtp.MtpStorageInfo} - * for the MTP or PTP device with the given USB device name - * - * @param deviceName the name of the USB device - * @return the list of MtpStorageInfo - */ - public List<MtpStorageInfo> getStorageList(String deviceName) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - int[] storageIds = device.getStorageIds(); - if (storageIds == null) { - return null; - } - - int length = storageIds.length; - ArrayList<MtpStorageInfo> storageList = new ArrayList<MtpStorageInfo>(length); - for (int i = 0; i < length; i++) { - MtpStorageInfo info = device.getStorageInfo(storageIds[i]); - if (info == null) { - Log.w(TAG, "getStorageInfo failed"); - } else { - storageList.add(info); - } - } - return storageList; - } - - /** - * Retrieves the {@link android.mtp.MtpObjectInfo} for an object on - * the MTP or PTP device with the given USB device name with the given - * object handle - * - * @param deviceName the name of the USB device - * @param objectHandle handle of the object to query - * @return the MtpObjectInfo - */ - public MtpObjectInfo getObjectInfo(String deviceName, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - return device.getObjectInfo(objectHandle); - } - - /** - * Deletes an object on the MTP or PTP device with the given USB device name. - * - * @param deviceName the name of the USB device - * @param objectHandle handle of the object to delete - * @return true if the deletion succeeds - */ - public boolean deleteObject(String deviceName, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return false; - } - return device.deleteObject(objectHandle); - } - - /** - * Retrieves a list of {@link android.mtp.MtpObjectInfo} for all objects - * on the MTP or PTP device with the given USB device name and given storage ID - * and/or object handle. - * If the object handle is zero, then all objects in the root of the storage unit - * will be returned. Otherwise, all immediate children of the object will be returned. - * If the storage ID is also zero, then all objects on all storage units will be returned. - * - * @param deviceName the name of the USB device - * @param storageId the ID of the storage unit to query, or zero for all - * @param objectHandle the handle of the parent object to query, or zero for the storage root - * @return the list of MtpObjectInfo - */ - public List<MtpObjectInfo> getObjectList(String deviceName, int storageId, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - if (objectHandle == 0) { - // all objects in root of storage - objectHandle = 0xFFFFFFFF; - } - int[] handles = device.getObjectHandles(storageId, 0, objectHandle); - if (handles == null) { - return null; - } - - int length = handles.length; - ArrayList<MtpObjectInfo> objectList = new ArrayList<MtpObjectInfo>(length); - for (int i = 0; i < length; i++) { - MtpObjectInfo info = device.getObjectInfo(handles[i]); - if (info == null) { - Log.w(TAG, "getObjectInfo failed"); - } else { - objectList.add(info); - } - } - return objectList; - } - - /** - * Returns the data for an object as a byte array. - * - * @param deviceName the name of the USB device containing the object - * @param objectHandle handle of the object to read - * @param objectSize the size of the object (this should match - * {@link android.mtp.MtpObjectInfo#getCompressedSize} - * @return the object's data, or null if reading fails - */ - public byte[] getObject(String deviceName, int objectHandle, int objectSize) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - return device.getObject(objectHandle, objectSize); - } - - /** - * Returns the thumbnail data for an object as a byte array. - * - * @param deviceName the name of the USB device containing the object - * @param objectHandle handle of the object to read - * @return the object's thumbnail, or null if reading fails - */ - public byte[] getThumbnail(String deviceName, int objectHandle) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return null; - } - return device.getThumbnail(objectHandle); - } - - /** - * Copies the data for an object to a file in external storage. - * - * @param deviceName the name of the USB device containing the object - * @param objectHandle handle of the object to read - * @param destPath path to destination for the file transfer. - * This path should be in the external storage as defined by - * {@link android.os.Environment#getExternalStorageDirectory} - * @return true if the file transfer succeeds - */ - public boolean importFile(String deviceName, int objectHandle, String destPath) { - MtpDevice device = getDevice(deviceName); - if (device == null) { - return false; - } - return device.importFile(objectHandle, destPath); - } -} diff --git a/src/com/android/gallery3d/data/PanoramaMetadataJob.java b/src/com/android/gallery3d/data/PanoramaMetadataJob.java deleted file mode 100644 index ab99d6a81..000000000 --- a/src/com/android/gallery3d/data/PanoramaMetadataJob.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.net.Uri; - -import com.android.gallery3d.util.LightCycleHelper; -import com.android.gallery3d.util.LightCycleHelper.PanoramaMetadata; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -public class PanoramaMetadataJob implements Job<PanoramaMetadata> { - Context mContext; - Uri mUri; - - public PanoramaMetadataJob(Context context, Uri uri) { - mContext = context; - mUri = uri; - } - - @Override - public PanoramaMetadata run(JobContext jc) { - return LightCycleHelper.getPanoramaMetadata(mContext, mUri); - } -} diff --git a/src/com/android/gallery3d/data/Path.java b/src/com/android/gallery3d/data/Path.java deleted file mode 100644 index fcae65e66..000000000 --- a/src/com/android/gallery3d/data/Path.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.IdentityCache; - -import java.lang.ref.WeakReference; -import java.util.ArrayList; - -public class Path { - private static final String TAG = "Path"; - private static Path sRoot = new Path(null, "ROOT"); - - private final Path mParent; - private final String mSegment; - private WeakReference<MediaObject> mObject; - private IdentityCache<String, Path> mChildren; - - private Path(Path parent, String segment) { - mParent = parent; - mSegment = segment; - } - - public Path getChild(String segment) { - synchronized (Path.class) { - if (mChildren == null) { - mChildren = new IdentityCache<String, Path>(); - } else { - Path p = mChildren.get(segment); - if (p != null) return p; - } - - Path p = new Path(this, segment); - mChildren.put(segment, p); - return p; - } - } - - public Path getParent() { - synchronized (Path.class) { - return mParent; - } - } - - public Path getChild(int segment) { - return getChild(String.valueOf(segment)); - } - - public Path getChild(long segment) { - return getChild(String.valueOf(segment)); - } - - public void setObject(MediaObject object) { - synchronized (Path.class) { - Utils.assertTrue(mObject == null || mObject.get() == null); - mObject = new WeakReference<MediaObject>(object); - } - } - - MediaObject getObject() { - synchronized (Path.class) { - return (mObject == null) ? null : mObject.get(); - } - } - - @Override - // TODO: toString() should be more efficient, will fix it later - public String toString() { - synchronized (Path.class) { - StringBuilder sb = new StringBuilder(); - String[] segments = split(); - for (int i = 0; i < segments.length; i++) { - sb.append("/"); - sb.append(segments[i]); - } - return sb.toString(); - } - } - - public boolean equalsIgnoreCase (String p) { - String path = toString(); - return path.equalsIgnoreCase(p); - } - - public static Path fromString(String s) { - synchronized (Path.class) { - String[] segments = split(s); - Path current = sRoot; - for (int i = 0; i < segments.length; i++) { - current = current.getChild(segments[i]); - } - return current; - } - } - - public String[] split() { - synchronized (Path.class) { - int n = 0; - for (Path p = this; p != sRoot; p = p.mParent) { - n++; - } - String[] segments = new String[n]; - int i = n - 1; - for (Path p = this; p != sRoot; p = p.mParent) { - segments[i--] = p.mSegment; - } - return segments; - } - } - - public static String[] split(String s) { - int n = s.length(); - if (n == 0) return new String[0]; - if (s.charAt(0) != '/') { - throw new RuntimeException("malformed path:" + s); - } - ArrayList<String> segments = new ArrayList<String>(); - int i = 1; - while (i < n) { - int brace = 0; - int j; - for (j = i; j < n; j++) { - char c = s.charAt(j); - if (c == '{') ++brace; - else if (c == '}') --brace; - else if (brace == 0 && c == '/') break; - } - if (brace != 0) { - throw new RuntimeException("unbalanced brace in path:" + s); - } - segments.add(s.substring(i, j)); - i = j + 1; - } - String[] result = new String[segments.size()]; - segments.toArray(result); - return result; - } - - // Splits a string to an array of strings. - // For example, "{foo,bar,baz}" -> {"foo","bar","baz"}. - public static String[] splitSequence(String s) { - int n = s.length(); - if (s.charAt(0) != '{' || s.charAt(n-1) != '}') { - throw new RuntimeException("bad sequence: " + s); - } - ArrayList<String> segments = new ArrayList<String>(); - int i = 1; - while (i < n - 1) { - int brace = 0; - int j; - for (j = i; j < n - 1; j++) { - char c = s.charAt(j); - if (c == '{') ++brace; - else if (c == '}') --brace; - else if (brace == 0 && c == ',') break; - } - if (brace != 0) { - throw new RuntimeException("unbalanced brace in path:" + s); - } - segments.add(s.substring(i, j)); - i = j + 1; - } - String[] result = new String[segments.size()]; - segments.toArray(result); - return result; - } - - public String getPrefix() { - if (this == sRoot) return ""; - return getPrefixPath().mSegment; - } - - public Path getPrefixPath() { - synchronized (Path.class) { - Path current = this; - if (current == sRoot) { - throw new IllegalStateException(); - } - while (current.mParent != sRoot) { - current = current.mParent; - } - return current; - } - } - - public String getSuffix() { - // We don't need lock because mSegment is final. - return mSegment; - } - - // Below are for testing/debugging only - static void clearAll() { - synchronized (Path.class) { - sRoot = new Path(null, ""); - } - } - - static void dumpAll() { - dumpAll(sRoot, "", ""); - } - - static void dumpAll(Path p, String prefix1, String prefix2) { - synchronized (Path.class) { - MediaObject obj = p.getObject(); - Log.d(TAG, prefix1 + p.mSegment + ":" - + (obj == null ? "null" : obj.getClass().getSimpleName())); - if (p.mChildren != null) { - ArrayList<String> childrenKeys = p.mChildren.keys(); - int i = 0, n = childrenKeys.size(); - for (String key : childrenKeys) { - Path child = p.mChildren.get(key); - if (child == null) { - ++i; - continue; - } - Log.d(TAG, prefix2 + "|"); - if (++i < n) { - dumpAll(child, prefix2 + "+-- ", prefix2 + "| "); - } else { - dumpAll(child, prefix2 + "+-- ", prefix2 + " "); - } - } - } - } - } -} diff --git a/src/com/android/gallery3d/data/PathMatcher.java b/src/com/android/gallery3d/data/PathMatcher.java deleted file mode 100644 index 9c6b840d5..000000000 --- a/src/com/android/gallery3d/data/PathMatcher.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; -import java.util.HashMap; - -public class PathMatcher { - public static final int NOT_FOUND = -1; - - private ArrayList<String> mVariables = new ArrayList<String>(); - private Node mRoot = new Node(); - - public PathMatcher() { - mRoot = new Node(); - } - - public void add(String pattern, int kind) { - String[] segments = Path.split(pattern); - Node current = mRoot; - for (int i = 0; i < segments.length; i++) { - current = current.addChild(segments[i]); - } - current.setKind(kind); - } - - public int match(Path path) { - String[] segments = path.split(); - mVariables.clear(); - Node current = mRoot; - for (int i = 0; i < segments.length; i++) { - Node next = current.getChild(segments[i]); - if (next == null) { - next = current.getChild("*"); - if (next != null) { - mVariables.add(segments[i]); - } else { - return NOT_FOUND; - } - } - current = next; - } - return current.getKind(); - } - - public String getVar(int index) { - return mVariables.get(index); - } - - public int getIntVar(int index) { - return Integer.parseInt(mVariables.get(index)); - } - - public long getLongVar(int index) { - return Long.parseLong(mVariables.get(index)); - } - - private static class Node { - private HashMap<String, Node> mMap; - private int mKind = NOT_FOUND; - - Node addChild(String segment) { - if (mMap == null) { - mMap = new HashMap<String, Node>(); - } else { - Node node = mMap.get(segment); - if (node != null) return node; - } - - Node n = new Node(); - mMap.put(segment, n); - return n; - } - - Node getChild(String segment) { - if (mMap == null) return null; - return mMap.get(segment); - } - - void setKind(int kind) { - mKind = kind; - } - - int getKind() { - return mKind; - } - } -} diff --git a/src/com/android/gallery3d/data/SecureAlbum.java b/src/com/android/gallery3d/data/SecureAlbum.java deleted file mode 100644 index 204f848f8..000000000 --- a/src/com/android/gallery3d/data/SecureAlbum.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.database.Cursor; -import android.net.Uri; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.MediaColumns; -import android.provider.MediaStore.Video; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.StitchingChangeListener; -import com.android.gallery3d.util.MediaSetUtils; - -import java.util.ArrayList; - -// This class lists all media items added by the client. -public class SecureAlbum extends MediaSet implements StitchingChangeListener { - @SuppressWarnings("unused") - private static final String TAG = "SecureAlbum"; - private static final String[] PROJECTION = {MediaColumns._ID}; - private int mMinImageId = Integer.MAX_VALUE; // the smallest id of images - private int mMaxImageId = Integer.MIN_VALUE; // the biggest id in images - private int mMinVideoId = Integer.MAX_VALUE; // the smallest id of videos - private int mMaxVideoId = Integer.MIN_VALUE; // the biggest id of videos - // All the media items added by the client. - private ArrayList<Path> mAllItems = new ArrayList<Path>(); - // The types of items in mAllItems. True is video and false is image. - private ArrayList<Boolean> mAllItemTypes = new ArrayList<Boolean>(); - private ArrayList<Path> mExistingItems = new ArrayList<Path>(); - private Context mContext; - private DataManager mDataManager; - private static final Uri[] mWatchUris = - {Images.Media.EXTERNAL_CONTENT_URI, Video.Media.EXTERNAL_CONTENT_URI}; - private final ChangeNotifier mNotifier; - // A placeholder image in the end of secure album. When it is tapped, it - // will take the user to the lock screen. - private MediaItem mUnlockItem; - private boolean mShowUnlockItem; - - public SecureAlbum(Path path, GalleryApp application, MediaItem unlock) { - super(path, nextVersionNumber()); - mContext = application.getAndroidContext(); - mDataManager = application.getDataManager(); - mNotifier = new ChangeNotifier(this, mWatchUris, application); - mUnlockItem = unlock; - mShowUnlockItem = (!isCameraBucketEmpty(Images.Media.EXTERNAL_CONTENT_URI) - || !isCameraBucketEmpty(Video.Media.EXTERNAL_CONTENT_URI)); - } - - public void addMediaItem(boolean isVideo, int id) { - Path pathBase; - if (isVideo) { - pathBase = LocalVideo.ITEM_PATH; - mMinVideoId = Math.min(mMinVideoId, id); - mMaxVideoId = Math.max(mMaxVideoId, id); - } else { - pathBase = LocalImage.ITEM_PATH; - mMinImageId = Math.min(mMinImageId, id); - mMaxImageId = Math.max(mMaxImageId, id); - } - Path path = pathBase.getChild(id); - if (!mAllItems.contains(path)) { - mAllItems.add(path); - mAllItemTypes.add(isVideo); - mNotifier.fakeChange(); - } - } - - // The sequence is stitching items, local media items, and unlock image. - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - int existingCount = mExistingItems.size(); - if (start >= existingCount + 1) { - return new ArrayList<MediaItem>(); - } - - // Add paths of requested stitching items. - int end = Math.min(start + count, existingCount); - ArrayList<Path> subset = new ArrayList<Path>(mExistingItems.subList(start, end)); - - // Convert paths to media items. - final MediaItem[] buf = new MediaItem[end - start]; - ItemConsumer consumer = new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - buf[index] = item; - } - }; - mDataManager.mapMediaItems(subset, consumer, 0); - ArrayList<MediaItem> result = new ArrayList<MediaItem>(end - start); - for (int i = 0; i < buf.length; i++) { - result.add(buf[i]); - } - if (mShowUnlockItem) result.add(mUnlockItem); - return result; - } - - @Override - public int getMediaItemCount() { - return (mExistingItems.size() + (mShowUnlockItem ? 1 : 0)); - } - - @Override - public String getName() { - return "secure"; - } - - @Override - public long reload() { - if (mNotifier.isDirty()) { - mDataVersion = nextVersionNumber(); - updateExistingItems(); - } - return mDataVersion; - } - - private ArrayList<Integer> queryExistingIds(Uri uri, int minId, int maxId) { - ArrayList<Integer> ids = new ArrayList<Integer>(); - if (minId == Integer.MAX_VALUE || maxId == Integer.MIN_VALUE) return ids; - - String[] selectionArgs = {String.valueOf(minId), String.valueOf(maxId)}; - Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION, - "_id BETWEEN ? AND ?", selectionArgs, null); - if (cursor == null) return ids; - try { - while (cursor.moveToNext()) { - ids.add(cursor.getInt(0)); - } - } finally { - cursor.close(); - } - return ids; - } - - private boolean isCameraBucketEmpty(Uri baseUri) { - Uri uri = baseUri.buildUpon() - .appendQueryParameter("limit", "1").build(); - String[] selection = {String.valueOf(MediaSetUtils.CAMERA_BUCKET_ID)}; - Cursor cursor = mContext.getContentResolver().query(uri, PROJECTION, - "bucket_id = ?", selection, null); - if (cursor == null) return true; - try { - return (cursor.getCount() == 0); - } finally { - cursor.close(); - } - } - - private void updateExistingItems() { - if (mAllItems.size() == 0) return; - - // Query existing ids. - ArrayList<Integer> imageIds = queryExistingIds( - Images.Media.EXTERNAL_CONTENT_URI, mMinImageId, mMaxImageId); - ArrayList<Integer> videoIds = queryExistingIds( - Video.Media.EXTERNAL_CONTENT_URI, mMinVideoId, mMaxVideoId); - - // Construct the existing items list. - mExistingItems.clear(); - for (int i = mAllItems.size() - 1; i >= 0; i--) { - Path path = mAllItems.get(i); - boolean isVideo = mAllItemTypes.get(i); - int id = Integer.parseInt(path.getSuffix()); - if (isVideo) { - if (videoIds.contains(id)) mExistingItems.add(path); - } else { - if (imageIds.contains(id)) mExistingItems.add(path); - } - } - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public void onStitchingQueued(Uri uri) { - int id = Integer.parseInt(uri.getLastPathSegment()); - addMediaItem(false, id); - } - - @Override - public void onStitchingResult(Uri uri) { - } - - @Override - public void onStitchingProgress(Uri uri, final int progress) { - } -} diff --git a/src/com/android/gallery3d/data/SecureSource.java b/src/com/android/gallery3d/data/SecureSource.java deleted file mode 100644 index 6bc8cc295..000000000 --- a/src/com/android/gallery3d/data/SecureSource.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -public class SecureSource extends MediaSource { - private GalleryApp mApplication; - private static PathMatcher mMatcher = new PathMatcher(); - private static final int SECURE_ALBUM = 0; - private static final int SECURE_UNLOCK = 1; - - static { - mMatcher.add("/secure/all/*", SECURE_ALBUM); - mMatcher.add("/secure/unlock", SECURE_UNLOCK); - } - - public SecureSource(GalleryApp context) { - super("secure"); - mApplication = context; - } - - public static boolean isSecurePath(String path) { - return (SECURE_ALBUM == mMatcher.match(Path.fromString(path))); - } - - @Override - public MediaObject createMediaObject(Path path) { - switch (mMatcher.match(path)) { - case SECURE_ALBUM: { - DataManager dataManager = mApplication.getDataManager(); - MediaItem unlock = (MediaItem) dataManager.getMediaObject( - "/secure/unlock"); - return new SecureAlbum(path, mApplication, unlock); - } - case SECURE_UNLOCK: - return new UnlockImage(path, mApplication); - default: - throw new RuntimeException("bad path: " + path); - } - } -} diff --git a/src/com/android/gallery3d/data/SingleItemAlbum.java b/src/com/android/gallery3d/data/SingleItemAlbum.java deleted file mode 100644 index a0093e0c3..000000000 --- a/src/com/android/gallery3d/data/SingleItemAlbum.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.ArrayList; - -public class SingleItemAlbum extends MediaSet { - @SuppressWarnings("unused") - private static final String TAG = "SingleItemAlbum"; - private final MediaItem mItem; - private final String mName; - - public SingleItemAlbum(Path path, MediaItem item) { - super(path, nextVersionNumber()); - mItem = item; - mName = "SingleItemAlbum("+mItem.getClass().getSimpleName()+")"; - } - - @Override - public int getMediaItemCount() { - return 1; - } - - @Override - public ArrayList<MediaItem> getMediaItem(int start, int count) { - ArrayList<MediaItem> result = new ArrayList<MediaItem>(); - - // If [start, start+count) contains the index 0, return the item. - if (start <= 0 && start + count > 0) { - result.add(mItem); - } - - return result; - } - - public MediaItem getItem() { - return mItem; - } - - @Override - public boolean isLeafAlbum() { - return true; - } - - @Override - public String getName() { - return mName; - } - - @Override - public long reload() { - return mDataVersion; - } -} diff --git a/src/com/android/gallery3d/data/SizeClustering.java b/src/com/android/gallery3d/data/SizeClustering.java deleted file mode 100644 index b809c841b..000000000 --- a/src/com/android/gallery3d/data/SizeClustering.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.content.res.Resources; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class SizeClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "SizeClustering"; - - private Context mContext; - private ArrayList<Path>[] mClusters; - private String[] mNames; - private long mMinSizes[]; - - private static final long MEGA_BYTES = 1024L*1024; - private static final long GIGA_BYTES = 1024L*1024*1024; - - private static final long[] SIZE_LEVELS = { - 0, - 1 * MEGA_BYTES, - 10 * MEGA_BYTES, - 100 * MEGA_BYTES, - 1 * GIGA_BYTES, - 2 * GIGA_BYTES, - 4 * GIGA_BYTES, - }; - - public SizeClustering(Context context) { - mContext = context; - } - - @SuppressWarnings("unchecked") - @Override - public void run(MediaSet baseSet) { - @SuppressWarnings("unchecked") - final ArrayList<Path>[] group = new ArrayList[SIZE_LEVELS.length]; - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - // Find the cluster this item belongs to. - long size = item.getSize(); - int i; - for (i = 0; i < SIZE_LEVELS.length - 1; i++) { - if (size < SIZE_LEVELS[i + 1]) { - break; - } - } - - ArrayList<Path> list = group[i]; - if (list == null) { - list = new ArrayList<Path>(); - group[i] = list; - } - list.add(item.getPath()); - } - }); - - int count = 0; - for (int i = 0; i < group.length; i++) { - if (group[i] != null) { - count++; - } - } - - mClusters = new ArrayList[count]; - mNames = new String[count]; - mMinSizes = new long[count]; - - Resources res = mContext.getResources(); - int k = 0; - // Go through group in the reverse order, so the group with the largest - // size will show first. - for (int i = group.length - 1; i >= 0; i--) { - if (group[i] == null) continue; - - mClusters[k] = group[i]; - if (i == 0) { - mNames[k] = String.format( - res.getString(R.string.size_below), getSizeString(i + 1)); - } else if (i == group.length - 1) { - mNames[k] = String.format( - res.getString(R.string.size_above), getSizeString(i)); - } else { - String minSize = getSizeString(i); - String maxSize = getSizeString(i + 1); - mNames[k] = String.format( - res.getString(R.string.size_between), minSize, maxSize); - } - mMinSizes[k] = SIZE_LEVELS[i]; - k++; - } - } - - private String getSizeString(int index) { - long bytes = SIZE_LEVELS[index]; - if (bytes >= GIGA_BYTES) { - return (bytes / GIGA_BYTES) + "GB"; - } else { - return (bytes / MEGA_BYTES) + "MB"; - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.length; - } - - @Override - public ArrayList<Path> getCluster(int index) { - return mClusters[index]; - } - - @Override - public String getClusterName(int index) { - return mNames[index]; - } - - public long getMinSize(int index) { - return mMinSizes[index]; - } -} diff --git a/src/com/android/gallery3d/data/SnailAlbum.java b/src/com/android/gallery3d/data/SnailAlbum.java deleted file mode 100644 index 7bce7a695..000000000 --- a/src/com/android/gallery3d/data/SnailAlbum.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import java.util.concurrent.atomic.AtomicBoolean; - -// This is a simple MediaSet which contains only one MediaItem -- a SnailItem. -public class SnailAlbum extends SingleItemAlbum { - @SuppressWarnings("unused") - private static final String TAG = "SnailAlbum"; - private AtomicBoolean mDirty = new AtomicBoolean(false); - - public SnailAlbum(Path path, SnailItem item) { - super(path, item); - } - - @Override - public long reload() { - if (mDirty.compareAndSet(true, false)) { - ((SnailItem) getItem()).updateVersion(); - mDataVersion = nextVersionNumber(); - } - return mDataVersion; - } - - public void notifyChange() { - mDirty.set(true); - notifyContentChanged(); - } -} diff --git a/src/com/android/gallery3d/data/SnailItem.java b/src/com/android/gallery3d/data/SnailItem.java deleted file mode 100644 index 3586d2cab..000000000 --- a/src/com/android/gallery3d/data/SnailItem.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.graphics.Bitmap; -import android.graphics.BitmapRegionDecoder; - -import com.android.gallery3d.ui.ScreenNail; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -// SnailItem is a MediaItem which can provide a ScreenNail. This is -// used so we can show an foreign component (like an -// android.view.View) instead of a Bitmap. -public class SnailItem extends MediaItem { - @SuppressWarnings("unused") - private static final String TAG = "SnailItem"; - private ScreenNail mScreenNail; - - public SnailItem(Path path) { - super(path, nextVersionNumber()); - } - - @Override - public Job<Bitmap> requestImage(int type) { - // nothing to return - return new Job<Bitmap>() { - @Override - public Bitmap run(JobContext jc) { - return null; - } - }; - } - - @Override - public Job<BitmapRegionDecoder> requestLargeImage() { - // nothing to return - return new Job<BitmapRegionDecoder>() { - @Override - public BitmapRegionDecoder run(JobContext jc) { - return null; - } - }; - } - - // We do not provide requestImage or requestLargeImage, instead we - // provide a ScreenNail. - @Override - public ScreenNail getScreenNail() { - return mScreenNail; - } - - @Override - public String getMimeType() { - return ""; - } - - // Returns width and height of the media item. - // Returns 0, 0 if the information is not available. - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - ////////////////////////////////////////////////////////////////////////// - // Extra methods for SnailItem - ////////////////////////////////////////////////////////////////////////// - - public void setScreenNail(ScreenNail screenNail) { - mScreenNail = screenNail; - } - - public void updateVersion() { - mDataVersion = nextVersionNumber(); - } -} diff --git a/src/com/android/gallery3d/data/SnailSource.java b/src/com/android/gallery3d/data/SnailSource.java deleted file mode 100644 index 5c690ccdb..000000000 --- a/src/com/android/gallery3d/data/SnailSource.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.data; - -import com.android.gallery3d.app.GalleryApp; - -public class SnailSource extends MediaSource { - @SuppressWarnings("unused") - private static final String TAG = "SnailSource"; - private static final int SNAIL_ALBUM = 0; - private static final int SNAIL_ITEM = 1; - - private GalleryApp mApplication; - private PathMatcher mMatcher; - private static int sNextId; - - public SnailSource(GalleryApp application) { - super("snail"); - mApplication = application; - mMatcher = new PathMatcher(); - mMatcher.add("/snail/set/*", SNAIL_ALBUM); - mMatcher.add("/snail/item/*", SNAIL_ITEM); - } - - // The only path we accept is "/snail/set/id" and "/snail/item/id" - @Override - public MediaObject createMediaObject(Path path) { - DataManager dataManager = mApplication.getDataManager(); - switch (mMatcher.match(path)) { - case SNAIL_ALBUM: - String itemPath = "/snail/item/" + mMatcher.getVar(0); - SnailItem item = - (SnailItem) dataManager.getMediaObject(itemPath); - return new SnailAlbum(path, item); - case SNAIL_ITEM: { - int id = mMatcher.getIntVar(0); - return new SnailItem(path); - } - } - return null; - } - - // Registers a new SnailAlbum containing a SnailItem and returns the id of - // them. You can obtain the Path of the SnailAlbum and SnailItem associated - // with the id by getSetPath and getItemPath(). - public static synchronized int newId() { - return sNextId++; - } - - public static Path getSetPath(int id) { - return Path.fromString("/snail/set").getChild(id); - } - - public static Path getItemPath(int id) { - return Path.fromString("/snail/item").getChild(id); - } -} diff --git a/src/com/android/gallery3d/data/TagClustering.java b/src/com/android/gallery3d/data/TagClustering.java deleted file mode 100644 index 407ca84c4..000000000 --- a/src/com/android/gallery3d/data/TagClustering.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; - -import com.android.gallery3d.R; - -import java.util.ArrayList; -import java.util.Map; -import java.util.TreeMap; - -public class TagClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "TagClustering"; - - private ArrayList<ArrayList<Path>> mClusters; - private String[] mNames; - private String mUntaggedString; - - public TagClustering(Context context) { - mUntaggedString = context.getResources().getString(R.string.untagged); - } - - @Override - public void run(MediaSet baseSet) { - final TreeMap<String, ArrayList<Path>> map = - new TreeMap<String, ArrayList<Path>>(); - final ArrayList<Path> untagged = new ArrayList<Path>(); - - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - Path path = item.getPath(); - - String[] tags = item.getTags(); - if (tags == null || tags.length == 0) { - untagged.add(path); - return; - } - for (int j = 0; j < tags.length; j++) { - String key = tags[j]; - ArrayList<Path> list = map.get(key); - if (list == null) { - list = new ArrayList<Path>(); - map.put(key, list); - } - list.add(path); - } - } - }); - - int m = map.size(); - mClusters = new ArrayList<ArrayList<Path>>(); - mNames = new String[m + ((untagged.size() > 0) ? 1 : 0)]; - int i = 0; - for (Map.Entry<String, ArrayList<Path>> entry : map.entrySet()) { - mNames[i++] = entry.getKey(); - mClusters.add(entry.getValue()); - } - if (untagged.size() > 0) { - mNames[i++] = mUntaggedString; - mClusters.add(untagged); - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.size(); - } - - @Override - public ArrayList<Path> getCluster(int index) { - return mClusters.get(index); - } - - @Override - public String getClusterName(int index) { - return mNames[index]; - } -} diff --git a/src/com/android/gallery3d/data/TimeClustering.java b/src/com/android/gallery3d/data/TimeClustering.java deleted file mode 100644 index 35cbab1ee..000000000 --- a/src/com/android/gallery3d/data/TimeClustering.java +++ /dev/null @@ -1,439 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.Context; -import android.text.format.DateFormat; -import android.text.format.DateUtils; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.GalleryUtils; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; - -public class TimeClustering extends Clustering { - @SuppressWarnings("unused") - private static final String TAG = "TimeClustering"; - - // If 2 items are greater than 25 miles apart, they will be in different - // clusters. - private static final int GEOGRAPHIC_DISTANCE_CUTOFF_IN_MILES = 20; - - // Do not want to split based on anything under 1 min. - private static final long MIN_CLUSTER_SPLIT_TIME_IN_MS = 60000L; - - // Disregard a cluster split time of anything over 2 hours. - private static final long MAX_CLUSTER_SPLIT_TIME_IN_MS = 7200000L; - - // Try and get around 9 clusters (best-effort for the common case). - private static final int NUM_CLUSTERS_TARGETED = 9; - - // Try and merge 2 clusters if they are both smaller than min cluster size. - // The min cluster size can range from 8 to 15. - private static final int MIN_MIN_CLUSTER_SIZE = 8; - private static final int MAX_MIN_CLUSTER_SIZE = 15; - - // Try and split a cluster if it is bigger than max cluster size. - // The max cluster size can range from 20 to 50. - private static final int MIN_MAX_CLUSTER_SIZE = 20; - private static final int MAX_MAX_CLUSTER_SIZE = 50; - - // Initially put 2 items in the same cluster as long as they are within - // 3 cluster frequencies of each other. - private static int CLUSTER_SPLIT_MULTIPLIER = 3; - - // The minimum change factor in the time between items to consider a - // partition. - // Example: (Item 3 - Item 2) / (Item 2 - Item 1). - private static final int MIN_PARTITION_CHANGE_FACTOR = 2; - - // Make the cluster split time of a large cluster half that of a regular - // cluster. - private static final int PARTITION_CLUSTER_SPLIT_TIME_FACTOR = 2; - - private Context mContext; - private ArrayList<Cluster> mClusters; - private String[] mNames; - private Cluster mCurrCluster; - - private long mClusterSplitTime = - (MIN_CLUSTER_SPLIT_TIME_IN_MS + MAX_CLUSTER_SPLIT_TIME_IN_MS) / 2; - private long mLargeClusterSplitTime = - mClusterSplitTime / PARTITION_CLUSTER_SPLIT_TIME_FACTOR; - private int mMinClusterSize = (MIN_MIN_CLUSTER_SIZE + MAX_MIN_CLUSTER_SIZE) / 2; - private int mMaxClusterSize = (MIN_MAX_CLUSTER_SIZE + MAX_MAX_CLUSTER_SIZE) / 2; - - - private static final Comparator<SmallItem> sDateComparator = - new DateComparator(); - - private static class DateComparator implements Comparator<SmallItem> { - @Override - public int compare(SmallItem item1, SmallItem item2) { - return -Utils.compare(item1.dateInMs, item2.dateInMs); - } - } - - public TimeClustering(Context context) { - mContext = context; - mClusters = new ArrayList<Cluster>(); - mCurrCluster = new Cluster(); - } - - @Override - public void run(MediaSet baseSet) { - final int total = baseSet.getTotalMediaItemCount(); - final SmallItem[] buf = new SmallItem[total]; - final double[] latLng = new double[2]; - - baseSet.enumerateTotalMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if (index < 0 || index >= total) return; - SmallItem s = new SmallItem(); - s.path = item.getPath(); - s.dateInMs = item.getDateInMs(); - item.getLatLong(latLng); - s.lat = latLng[0]; - s.lng = latLng[1]; - buf[index] = s; - } - }); - - ArrayList<SmallItem> items = new ArrayList<SmallItem>(total); - for (int i = 0; i < total; i++) { - if (buf[i] != null) { - items.add(buf[i]); - } - } - - Collections.sort(items, sDateComparator); - - int n = items.size(); - long minTime = 0; - long maxTime = 0; - for (int i = 0; i < n; i++) { - long t = items.get(i).dateInMs; - if (t == 0) continue; - if (minTime == 0) { - minTime = maxTime = t; - } else { - minTime = Math.min(minTime, t); - maxTime = Math.max(maxTime, t); - } - } - - setTimeRange(maxTime - minTime, n); - - for (int i = 0; i < n; i++) { - compute(items.get(i)); - } - - compute(null); - - int m = mClusters.size(); - mNames = new String[m]; - for (int i = 0; i < m; i++) { - mNames[i] = mClusters.get(i).generateCaption(mContext); - } - } - - @Override - public int getNumberOfClusters() { - return mClusters.size(); - } - - @Override - public ArrayList<Path> getCluster(int index) { - ArrayList<SmallItem> items = mClusters.get(index).getItems(); - ArrayList<Path> result = new ArrayList<Path>(items.size()); - for (int i = 0, n = items.size(); i < n; i++) { - result.add(items.get(i).path); - } - return result; - } - - @Override - public String getClusterName(int index) { - return mNames[index]; - } - - private void setTimeRange(long timeRange, int numItems) { - if (numItems != 0) { - int meanItemsPerCluster = numItems / NUM_CLUSTERS_TARGETED; - // Heuristic to get min and max cluster size - half and double the - // desired items per cluster. - mMinClusterSize = meanItemsPerCluster / 2; - mMaxClusterSize = meanItemsPerCluster * 2; - mClusterSplitTime = timeRange / numItems * CLUSTER_SPLIT_MULTIPLIER; - } - mClusterSplitTime = Utils.clamp(mClusterSplitTime, MIN_CLUSTER_SPLIT_TIME_IN_MS, MAX_CLUSTER_SPLIT_TIME_IN_MS); - mLargeClusterSplitTime = mClusterSplitTime / PARTITION_CLUSTER_SPLIT_TIME_FACTOR; - mMinClusterSize = Utils.clamp(mMinClusterSize, MIN_MIN_CLUSTER_SIZE, MAX_MIN_CLUSTER_SIZE); - mMaxClusterSize = Utils.clamp(mMaxClusterSize, MIN_MAX_CLUSTER_SIZE, MAX_MAX_CLUSTER_SIZE); - } - - private void compute(SmallItem currentItem) { - if (currentItem != null) { - int numClusters = mClusters.size(); - int numCurrClusterItems = mCurrCluster.size(); - boolean geographicallySeparateItem = false; - boolean itemAddedToCurrentCluster = false; - - // Determine if this item should go in the current cluster or be the - // start of a new cluster. - if (numCurrClusterItems == 0) { - mCurrCluster.addItem(currentItem); - } else { - SmallItem prevItem = mCurrCluster.getLastItem(); - if (isGeographicallySeparated(prevItem, currentItem)) { - mClusters.add(mCurrCluster); - geographicallySeparateItem = true; - } else if (numCurrClusterItems > mMaxClusterSize) { - splitAndAddCurrentCluster(); - } else if (timeDistance(prevItem, currentItem) < mClusterSplitTime) { - mCurrCluster.addItem(currentItem); - itemAddedToCurrentCluster = true; - } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize - && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) { - mergeAndAddCurrentCluster(); - } else { - mClusters.add(mCurrCluster); - } - - // Creating a new cluster and adding the current item to it. - if (!itemAddedToCurrentCluster) { - mCurrCluster = new Cluster(); - if (geographicallySeparateItem) { - mCurrCluster.mGeographicallySeparatedFromPrevCluster = true; - } - mCurrCluster.addItem(currentItem); - } - } - } else { - if (mCurrCluster.size() > 0) { - int numClusters = mClusters.size(); - int numCurrClusterItems = mCurrCluster.size(); - - // The last cluster may potentially be too big or too small. - if (numCurrClusterItems > mMaxClusterSize) { - splitAndAddCurrentCluster(); - } else if (numClusters > 0 && numCurrClusterItems < mMinClusterSize - && !mCurrCluster.mGeographicallySeparatedFromPrevCluster) { - mergeAndAddCurrentCluster(); - } else { - mClusters.add(mCurrCluster); - } - mCurrCluster = new Cluster(); - } - } - } - - private void splitAndAddCurrentCluster() { - ArrayList<SmallItem> currClusterItems = mCurrCluster.getItems(); - int numCurrClusterItems = mCurrCluster.size(); - int secondPartitionStartIndex = getPartitionIndexForCurrentCluster(); - if (secondPartitionStartIndex != -1) { - Cluster partitionedCluster = new Cluster(); - for (int j = 0; j < secondPartitionStartIndex; j++) { - partitionedCluster.addItem(currClusterItems.get(j)); - } - mClusters.add(partitionedCluster); - partitionedCluster = new Cluster(); - for (int j = secondPartitionStartIndex; j < numCurrClusterItems; j++) { - partitionedCluster.addItem(currClusterItems.get(j)); - } - mClusters.add(partitionedCluster); - } else { - mClusters.add(mCurrCluster); - } - } - - private int getPartitionIndexForCurrentCluster() { - int partitionIndex = -1; - float largestChange = MIN_PARTITION_CHANGE_FACTOR; - ArrayList<SmallItem> currClusterItems = mCurrCluster.getItems(); - int numCurrClusterItems = mCurrCluster.size(); - int minClusterSize = mMinClusterSize; - - // Could be slightly more efficient here but this code seems cleaner. - if (numCurrClusterItems > minClusterSize + 1) { - for (int i = minClusterSize; i < numCurrClusterItems - minClusterSize; i++) { - SmallItem prevItem = currClusterItems.get(i - 1); - SmallItem currItem = currClusterItems.get(i); - SmallItem nextItem = currClusterItems.get(i + 1); - - long timeNext = nextItem.dateInMs; - long timeCurr = currItem.dateInMs; - long timePrev = prevItem.dateInMs; - - if (timeNext == 0 || timeCurr == 0 || timePrev == 0) continue; - - long diff1 = Math.abs(timeNext - timeCurr); - long diff2 = Math.abs(timeCurr - timePrev); - - float change = Math.max(diff1 / (diff2 + 0.01f), diff2 / (diff1 + 0.01f)); - if (change > largestChange) { - if (timeDistance(currItem, prevItem) > mLargeClusterSplitTime) { - partitionIndex = i; - largestChange = change; - } else if (timeDistance(nextItem, currItem) > mLargeClusterSplitTime) { - partitionIndex = i + 1; - largestChange = change; - } - } - } - } - return partitionIndex; - } - - private void mergeAndAddCurrentCluster() { - int numClusters = mClusters.size(); - Cluster prevCluster = mClusters.get(numClusters - 1); - ArrayList<SmallItem> currClusterItems = mCurrCluster.getItems(); - int numCurrClusterItems = mCurrCluster.size(); - if (prevCluster.size() < mMinClusterSize) { - for (int i = 0; i < numCurrClusterItems; i++) { - prevCluster.addItem(currClusterItems.get(i)); - } - mClusters.set(numClusters - 1, prevCluster); - } else { - mClusters.add(mCurrCluster); - } - } - - // Returns true if a, b are sufficiently geographically separated. - private static boolean isGeographicallySeparated(SmallItem itemA, SmallItem itemB) { - if (!GalleryUtils.isValidLocation(itemA.lat, itemA.lng) - || !GalleryUtils.isValidLocation(itemB.lat, itemB.lng)) { - return false; - } - - double distance = GalleryUtils.fastDistanceMeters( - Math.toRadians(itemA.lat), - Math.toRadians(itemA.lng), - Math.toRadians(itemB.lat), - Math.toRadians(itemB.lng)); - return (GalleryUtils.toMile(distance) > GEOGRAPHIC_DISTANCE_CUTOFF_IN_MILES); - } - - // Returns the time interval between the two items in milliseconds. - private static long timeDistance(SmallItem a, SmallItem b) { - return Math.abs(a.dateInMs - b.dateInMs); - } -} - -class SmallItem { - Path path; - long dateInMs; - double lat, lng; -} - -class Cluster { - @SuppressWarnings("unused") - private static final String TAG = "Cluster"; - private static final String MMDDYY_FORMAT = "MMddyy"; - - // This is for TimeClustering only. - public boolean mGeographicallySeparatedFromPrevCluster = false; - - private ArrayList<SmallItem> mItems = new ArrayList<SmallItem>(); - - public Cluster() { - } - - public void addItem(SmallItem item) { - mItems.add(item); - } - - public int size() { - return mItems.size(); - } - - public SmallItem getLastItem() { - int n = mItems.size(); - return (n == 0) ? null : mItems.get(n - 1); - } - - public ArrayList<SmallItem> getItems() { - return mItems; - } - - public String generateCaption(Context context) { - int n = mItems.size(); - long minTimestamp = 0; - long maxTimestamp = 0; - - for (int i = 0; i < n; i++) { - long t = mItems.get(i).dateInMs; - if (t == 0) continue; - if (minTimestamp == 0) { - minTimestamp = maxTimestamp = t; - } else { - minTimestamp = Math.min(minTimestamp, t); - maxTimestamp = Math.max(maxTimestamp, t); - } - } - if (minTimestamp == 0) return ""; - - String caption; - String minDay = DateFormat.format(MMDDYY_FORMAT, minTimestamp) - .toString(); - String maxDay = DateFormat.format(MMDDYY_FORMAT, maxTimestamp) - .toString(); - - if (minDay.substring(4).equals(maxDay.substring(4))) { - // The items are from the same year - show at least as - // much granularity as abbrev_all allows. - caption = DateUtils.formatDateRange(context, minTimestamp, - maxTimestamp, DateUtils.FORMAT_ABBREV_ALL); - - // Get a more granular date range string if the min and - // max timestamp are on the same day and from the - // current year. - if (minDay.equals(maxDay)) { - int flags = DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE; - // Contains the year only if the date does not - // correspond to the current year. - String dateRangeWithOptionalYear = DateUtils.formatDateTime( - context, minTimestamp, flags); - String dateRangeWithYear = DateUtils.formatDateTime( - context, minTimestamp, flags | DateUtils.FORMAT_SHOW_YEAR); - if (!dateRangeWithOptionalYear.equals(dateRangeWithYear)) { - // This means both dates are from the same year - // - show the time. - // Not enough room to display the time range. - // Pick the mid-point. - long midTimestamp = (minTimestamp + maxTimestamp) / 2; - caption = DateUtils.formatDateRange(context, midTimestamp, - midTimestamp, DateUtils.FORMAT_SHOW_TIME | flags); - } - } - } else { - // The items are not from the same year - only show - // month and year. - int flags = DateUtils.FORMAT_NO_MONTH_DAY - | DateUtils.FORMAT_ABBREV_MONTH | DateUtils.FORMAT_SHOW_DATE; - caption = DateUtils.formatDateRange(context, minTimestamp, - maxTimestamp, flags); - } - - return caption; - } -} diff --git a/src/com/android/gallery3d/data/UnlockImage.java b/src/com/android/gallery3d/data/UnlockImage.java deleted file mode 100644 index ed3b485c4..000000000 --- a/src/com/android/gallery3d/data/UnlockImage.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; - -public class UnlockImage extends ActionImage { - @SuppressWarnings("unused") - private static final String TAG = "UnlockImage"; - - public UnlockImage(Path path, GalleryApp application) { - super(path, application, R.drawable.placeholder_locked); - } - - @Override - public int getSupportedOperations() { - return super.getSupportedOperations() | SUPPORT_UNLOCK; - } -} diff --git a/src/com/android/gallery3d/data/UriImage.java b/src/com/android/gallery3d/data/UriImage.java deleted file mode 100644 index e8875b572..000000000 --- a/src/com/android/gallery3d/data/UriImage.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.ContentResolver; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory.Options; -import android.graphics.BitmapRegionDecoder; -import android.net.Uri; -import android.os.ParcelFileDescriptor; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.app.PanoramaMetadataSupport; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; - -public class UriImage extends MediaItem { - private static final String TAG = "UriImage"; - - private static final int STATE_INIT = 0; - private static final int STATE_DOWNLOADING = 1; - private static final int STATE_DOWNLOADED = 2; - private static final int STATE_ERROR = -1; - - private final Uri mUri; - private final String mContentType; - - private DownloadCache.Entry mCacheEntry; - private ParcelFileDescriptor mFileDescriptor; - private int mState = STATE_INIT; - private int mWidth; - private int mHeight; - private int mRotation; - private PanoramaMetadataSupport mPanoramaMetadata = new PanoramaMetadataSupport(this); - - private GalleryApp mApplication; - - public UriImage(GalleryApp application, Path path, Uri uri, String contentType) { - super(path, nextVersionNumber()); - mUri = uri; - mApplication = Utils.checkNotNull(application); - mContentType = contentType; - } - - @Override - public Job<Bitmap> requestImage(int type) { - return new BitmapJob(type); - } - - @Override - public Job<BitmapRegionDecoder> requestLargeImage() { - return new RegionDecoderJob(); - } - - private void openFileOrDownloadTempFile(JobContext jc) { - int state = openOrDownloadInner(jc); - synchronized (this) { - mState = state; - if (mState != STATE_DOWNLOADED) { - if (mFileDescriptor != null) { - Utils.closeSilently(mFileDescriptor); - mFileDescriptor = null; - } - } - notifyAll(); - } - } - - private int openOrDownloadInner(JobContext jc) { - String scheme = mUri.getScheme(); - if (ContentResolver.SCHEME_CONTENT.equals(scheme) - || ContentResolver.SCHEME_ANDROID_RESOURCE.equals(scheme) - || ContentResolver.SCHEME_FILE.equals(scheme)) { - try { - if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) { - InputStream is = mApplication.getContentResolver() - .openInputStream(mUri); - mRotation = Exif.getOrientation(is); - Utils.closeSilently(is); - } - mFileDescriptor = mApplication.getContentResolver() - .openFileDescriptor(mUri, "r"); - if (jc.isCancelled()) return STATE_INIT; - return STATE_DOWNLOADED; - } catch (FileNotFoundException e) { - Log.w(TAG, "fail to open: " + mUri, e); - return STATE_ERROR; - } - } else { - try { - URL url = new URI(mUri.toString()).toURL(); - mCacheEntry = mApplication.getDownloadCache().download(jc, url); - if (jc.isCancelled()) return STATE_INIT; - if (mCacheEntry == null) { - Log.w(TAG, "download failed " + url); - return STATE_ERROR; - } - if (MIME_TYPE_JPEG.equalsIgnoreCase(mContentType)) { - InputStream is = new FileInputStream(mCacheEntry.cacheFile); - mRotation = Exif.getOrientation(is); - Utils.closeSilently(is); - } - mFileDescriptor = ParcelFileDescriptor.open( - mCacheEntry.cacheFile, ParcelFileDescriptor.MODE_READ_ONLY); - return STATE_DOWNLOADED; - } catch (Throwable t) { - Log.w(TAG, "download error", t); - return STATE_ERROR; - } - } - } - - private boolean prepareInputFile(JobContext jc) { - jc.setCancelListener(new CancelListener() { - @Override - public void onCancel() { - synchronized (this) { - notifyAll(); - } - } - }); - - while (true) { - synchronized (this) { - if (jc.isCancelled()) return false; - if (mState == STATE_INIT) { - mState = STATE_DOWNLOADING; - // Then leave the synchronized block and continue. - } else if (mState == STATE_ERROR) { - return false; - } else if (mState == STATE_DOWNLOADED) { - return true; - } else /* if (mState == STATE_DOWNLOADING) */ { - try { - wait(); - } catch (InterruptedException ex) { - // ignored. - } - continue; - } - } - // This is only reached for STATE_INIT->STATE_DOWNLOADING - openFileOrDownloadTempFile(jc); - } - } - - private class RegionDecoderJob implements Job<BitmapRegionDecoder> { - @Override - public BitmapRegionDecoder run(JobContext jc) { - if (!prepareInputFile(jc)) return null; - BitmapRegionDecoder decoder = DecodeUtils.createBitmapRegionDecoder( - jc, mFileDescriptor.getFileDescriptor(), false); - mWidth = decoder.getWidth(); - mHeight = decoder.getHeight(); - return decoder; - } - } - - private class BitmapJob implements Job<Bitmap> { - private int mType; - - protected BitmapJob(int type) { - mType = type; - } - - @Override - public Bitmap run(JobContext jc) { - if (!prepareInputFile(jc)) return null; - int targetSize = MediaItem.getTargetSize(mType); - Options options = new Options(); - options.inPreferredConfig = Config.ARGB_8888; - Bitmap bitmap = DecodeUtils.decodeThumbnail(jc, - mFileDescriptor.getFileDescriptor(), options, targetSize, mType); - - if (jc.isCancelled() || bitmap == null) { - return null; - } - - if (mType == MediaItem.TYPE_MICROTHUMBNAIL) { - bitmap = BitmapUtils.resizeAndCropCenter(bitmap, targetSize, true); - } else { - bitmap = BitmapUtils.resizeDownBySideLength(bitmap, targetSize, true); - } - return bitmap; - } - } - - @Override - public int getSupportedOperations() { - int supported = SUPPORT_EDIT | SUPPORT_SETAS; - if (isSharable()) supported |= SUPPORT_SHARE; - if (BitmapUtils.isSupportedByRegionDecoder(mContentType)) { - supported |= SUPPORT_FULL_IMAGE; - } - return supported; - } - - @Override - public void getPanoramaSupport(PanoramaSupportCallback callback) { - mPanoramaMetadata.getPanoramaSupport(mApplication, callback); - } - - @Override - public void clearCachedPanoramaSupport() { - mPanoramaMetadata.clearCachedValues(); - } - - private boolean isSharable() { - // We cannot grant read permission to the receiver since we put - // the data URI in EXTRA_STREAM instead of the data part of an intent - // And there are issues in MediaUploader and Bluetooth file sender to - // share a general image data. So, we only share for local file. - return ContentResolver.SCHEME_FILE.equals(mUri.getScheme()); - } - - @Override - public int getMediaType() { - return MEDIA_TYPE_IMAGE; - } - - @Override - public Uri getContentUri() { - return mUri; - } - - @Override - public MediaDetails getDetails() { - MediaDetails details = super.getDetails(); - if (mWidth != 0 && mHeight != 0) { - details.addDetail(MediaDetails.INDEX_WIDTH, mWidth); - details.addDetail(MediaDetails.INDEX_HEIGHT, mHeight); - } - if (mContentType != null) { - details.addDetail(MediaDetails.INDEX_MIMETYPE, mContentType); - } - if (ContentResolver.SCHEME_FILE.equals(mUri.getScheme())) { - String filePath = mUri.getPath(); - details.addDetail(MediaDetails.INDEX_PATH, filePath); - MediaDetails.extractExifInfo(details, filePath); - } - return details; - } - - @Override - public String getMimeType() { - return mContentType; - } - - @Override - protected void finalize() throws Throwable { - try { - if (mFileDescriptor != null) { - Utils.closeSilently(mFileDescriptor); - } - } finally { - super.finalize(); - } - } - - @Override - public int getWidth() { - return 0; - } - - @Override - public int getHeight() { - return 0; - } - - @Override - public int getRotation() { - return mRotation; - } -} diff --git a/src/com/android/gallery3d/data/UriSource.java b/src/com/android/gallery3d/data/UriSource.java deleted file mode 100644 index f66bacd7b..000000000 --- a/src/com/android/gallery3d/data/UriSource.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.data; - -import android.content.ContentResolver; -import android.net.Uri; -import android.webkit.MimeTypeMap; - -import com.android.gallery3d.app.GalleryApp; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.net.URLEncoder; - -class UriSource extends MediaSource { - @SuppressWarnings("unused") - private static final String TAG = "UriSource"; - private static final String IMAGE_TYPE_PREFIX = "image/"; - private static final String IMAGE_TYPE_ANY = "image/*"; - private static final String CHARSET_UTF_8 = "utf-8"; - - private GalleryApp mApplication; - - public UriSource(GalleryApp context) { - super("uri"); - mApplication = context; - } - - @Override - public MediaObject createMediaObject(Path path) { - String segment[] = path.split(); - if (segment.length != 3) { - throw new RuntimeException("bad path: " + path); - } - try { - String uri = URLDecoder.decode(segment[1], CHARSET_UTF_8); - String type = URLDecoder.decode(segment[2], CHARSET_UTF_8); - return new UriImage(mApplication, path, Uri.parse(uri), type); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } - } - - private String getMimeType(Uri uri) { - if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - String extension = - MimeTypeMap.getFileExtensionFromUrl(uri.toString()); - String type = MimeTypeMap.getSingleton() - .getMimeTypeFromExtension(extension.toLowerCase()); - if (type != null) return type; - } - // Assume the type is image if the type cannot be resolved - // This could happen for "http" URI. - String type = mApplication.getContentResolver().getType(uri); - if (type == null) type = "image/*"; - return type; - } - - @Override - public Path findPathByUri(Uri uri, String type) { - String mimeType = getMimeType(uri); - - // Try to find a most specific type but it has to be started with "image/" - if ((type == null) || (IMAGE_TYPE_ANY.equals(type) - && mimeType.startsWith(IMAGE_TYPE_PREFIX))) { - type = mimeType; - } - - if (type.startsWith(IMAGE_TYPE_PREFIX)) { - try { - return Path.fromString("/uri/" - + URLEncoder.encode(uri.toString(), CHARSET_UTF_8) - + "/" +URLEncoder.encode(type, CHARSET_UTF_8)); - } catch (UnsupportedEncodingException e) { - throw new AssertionError(e); - } - } - // We have no clues that it is an image - return null; - } -} diff --git a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java b/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java deleted file mode 100644 index bc9342d6f..000000000 --- a/src/com/android/gallery3d/filtershow/CenteredLinearLayout.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow; - -import android.content.Context; -import android.content.res.Resources; -import android.content.res.TypedArray; -import android.util.AttributeSet; -import android.util.TypedValue; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; - -public class CenteredLinearLayout extends LinearLayout { - private final int mMaxWidth; - - public CenteredLinearLayout(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CenteredLinearLayout); - mMaxWidth = a.getDimensionPixelSize(R.styleable.CenteredLinearLayout_max_width, 0); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int parentWidth = MeasureSpec.getSize(widthMeasureSpec); - int parentHeight = MeasureSpec.getSize(heightMeasureSpec); - Resources r = getContext().getResources(); - float value = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, parentWidth, - r.getDisplayMetrics()); - if (mMaxWidth > 0 && parentWidth > mMaxWidth) { - int measureMode = MeasureSpec.getMode(widthMeasureSpec); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxWidth, measureMode); - } - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - -} diff --git a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java b/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java deleted file mode 100644 index 95abce114..000000000 --- a/src/com/android/gallery3d/filtershow/EditorPlaceHolder.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.android.gallery3d.filtershow; - -import android.view.View; -import android.view.ViewParent; -import android.widget.FrameLayout; - -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.editors.Editor; -import com.android.gallery3d.filtershow.imageshow.ImageShow; - -import java.util.HashMap; -import java.util.Vector; - -public class EditorPlaceHolder { - private static final String LOGTAG = "EditorPlaceHolder"; - - private FilterShowActivity mActivity = null; - private FrameLayout mContainer = null; - private HashMap<Integer, Editor> mEditors = new HashMap<Integer, Editor>(); - private Vector<ImageShow> mOldViews = new Vector<ImageShow>(); - - public EditorPlaceHolder(FilterShowActivity activity) { - mActivity = activity; - } - - public void setContainer(FrameLayout container) { - mContainer = container; - } - - public void addEditor(Editor c) { - mEditors.put(c.getID(), c); - } - - public boolean contains(int type) { - if (mEditors.get(type) != null) { - return true; - } - return false; - } - - public Editor showEditor(int type) { - Editor editor = mEditors.get(type); - if (editor == null) { - return null; - } - - editor.createEditor(mActivity, mContainer); - editor.getImageShow().bindAsImageLoadListener(); - mContainer.setVisibility(View.VISIBLE); - mContainer.removeAllViews(); - View eview = editor.getTopLevelView(); - ViewParent parent = eview.getParent(); - - if (parent != null && parent instanceof FrameLayout) { - ((FrameLayout) parent).removeAllViews(); - } - - mContainer.addView(eview); - hideOldViews(); - editor.setVisibility(View.VISIBLE); - return editor; - } - - public void setOldViews(Vector<ImageShow> views) { - mOldViews = views; - } - - public void hide() { - mContainer.setVisibility(View.GONE); - } - - public void hideOldViews() { - for (View view : mOldViews) { - view.setVisibility(View.GONE); - } - } - - public Editor getEditor(int editorId) { - return mEditors.get(editorId); - } - -} diff --git a/src/com/android/gallery3d/filtershow/FilterShowActivity.java b/src/com/android/gallery3d/filtershow/FilterShowActivity.java deleted file mode 100644 index 4700fccfe..000000000 --- a/src/com/android/gallery3d/filtershow/FilterShowActivity.java +++ /dev/null @@ -1,1121 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow; - -import android.app.ActionBar; -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.ComponentName; -import android.content.ContentValues; -import android.content.Context; -import android.content.DialogInterface; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.pm.ActivityInfo; -import android.content.res.Configuration; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.support.v4.app.DialogFragment; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentTransaction; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.TypedValue; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewPropertyAnimator; -import android.view.WindowManager; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.FrameLayout; -import android.widget.ShareActionProvider; -import android.widget.ShareActionProvider.OnShareTargetSelectedListener; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.PhotoPage; -import com.android.gallery3d.data.LocalAlbum; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.category.Action; -import com.android.gallery3d.filtershow.category.CategoryAdapter; -import com.android.gallery3d.filtershow.category.MainPanel; -import com.android.gallery3d.filtershow.data.UserPresetsManager; -import com.android.gallery3d.filtershow.editors.BasicEditor; -import com.android.gallery3d.filtershow.editors.Editor; -import com.android.gallery3d.filtershow.editors.EditorChanSat; -import com.android.gallery3d.filtershow.editors.EditorCrop; -import com.android.gallery3d.filtershow.editors.EditorDraw; -import com.android.gallery3d.filtershow.editors.EditorGrad; -import com.android.gallery3d.filtershow.editors.EditorManager; -import com.android.gallery3d.filtershow.editors.EditorMirror; -import com.android.gallery3d.filtershow.editors.EditorPanel; -import com.android.gallery3d.filtershow.editors.EditorRedEye; -import com.android.gallery3d.filtershow.editors.EditorRotate; -import com.android.gallery3d.filtershow.editors.EditorStraighten; -import com.android.gallery3d.filtershow.editors.EditorTinyPlanet; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.filters.ImageFilter; -import com.android.gallery3d.filtershow.history.HistoryItem; -import com.android.gallery3d.filtershow.history.HistoryManager; -import com.android.gallery3d.filtershow.imageshow.ImageShow; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.imageshow.Spline; -import com.android.gallery3d.filtershow.pipeline.CachingPipeline; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.filtershow.pipeline.ProcessingService; -import com.android.gallery3d.filtershow.presets.PresetManagementDialog; -import com.android.gallery3d.filtershow.presets.UserPresetsAdapter; -import com.android.gallery3d.filtershow.provider.SharedImageProvider; -import com.android.gallery3d.filtershow.state.StateAdapter; -import com.android.gallery3d.filtershow.tools.SaveImage; -import com.android.gallery3d.filtershow.tools.XmpPresets; -import com.android.gallery3d.filtershow.tools.XmpPresets.XMresults; -import com.android.gallery3d.filtershow.ui.ExportDialog; -import com.android.gallery3d.filtershow.ui.FramedTextButton; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.UsageStatistics; -import com.android.photos.data.GalleryBitmapPool; - -import java.io.File; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Vector; - -public class FilterShowActivity extends FragmentActivity implements OnItemClickListener, - OnShareTargetSelectedListener { - - private String mAction = ""; - MasterImage mMasterImage = null; - - private static final long LIMIT_SUPPORTS_HIGHRES = 134217728; // 128Mb - - public static final String TINY_PLANET_ACTION = "com.android.camera.action.TINY_PLANET"; - public static final String LAUNCH_FULLSCREEN = "launch-fullscreen"; - private ImageShow mImageShow = null; - - private View mSaveButton = null; - - private EditorPlaceHolder mEditorPlaceHolder = new EditorPlaceHolder(this); - - private static final int SELECT_PICTURE = 1; - private static final String LOGTAG = "FilterShowActivity"; - - private boolean mShowingTinyPlanet = false; - private boolean mShowingImageStatePanel = false; - - private final Vector<ImageShow> mImageViews = new Vector<ImageShow>(); - - private ShareActionProvider mShareActionProvider; - private File mSharedOutputFile = null; - - private boolean mSharingImage = false; - - private WeakReference<ProgressDialog> mSavingProgressDialog; - - private LoadBitmapTask mLoadBitmapTask; - - private Uri mOriginalImageUri = null; - private ImagePreset mOriginalPreset = null; - - private Uri mSelectedImageUri = null; - - private UserPresetsManager mUserPresetsManager = null; - private UserPresetsAdapter mUserPresetsAdapter = null; - private CategoryAdapter mCategoryLooksAdapter = null; - private CategoryAdapter mCategoryBordersAdapter = null; - private CategoryAdapter mCategoryGeometryAdapter = null; - private CategoryAdapter mCategoryFiltersAdapter = null; - private int mCurrentPanel = MainPanel.LOOKS; - - private ProcessingService mBoundService; - private boolean mIsBound = false; - - public ProcessingService getProcessingService() { - return mBoundService; - } - - public boolean isSimpleEditAction() { - return !PhotoPage.ACTION_NEXTGEN_EDIT.equalsIgnoreCase(mAction); - } - - private ServiceConnection mConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - /* - * This is called when the connection with the service has been - * established, giving us the service object we can use to - * interact with the service. Because we have bound to a explicit - * service that we know is running in our own process, we can - * cast its IBinder to a concrete class and directly access it. - */ - mBoundService = ((ProcessingService.LocalBinder)service).getService(); - mBoundService.setFiltershowActivity(FilterShowActivity.this); - mBoundService.onStart(); - } - - public void onServiceDisconnected(ComponentName className) { - /* - * This is called when the connection with the service has been - * unexpectedly disconnected -- that is, its process crashed. - * Because it is running in our same process, we should never - * see this happen. - */ - mBoundService = null; - } - }; - - void doBindService() { - /* - * Establish a connection with the service. We use an explicit - * class name because we want a specific service implementation that - * we know will be running in our own process (and thus won't be - * supporting component replacement by other applications). - */ - bindService(new Intent(FilterShowActivity.this, ProcessingService.class), - mConnection, Context.BIND_AUTO_CREATE); - mIsBound = true; - } - - void doUnbindService() { - if (mIsBound) { - // Detach our existing connection. - unbindService(mConnection); - mIsBound = false; - } - } - - private void setupPipeline() { - doBindService(); - ImageFilter.setActivityForMemoryToasts(this); - mUserPresetsManager = new UserPresetsManager(this); - mUserPresetsAdapter = new UserPresetsAdapter(this); - mCategoryLooksAdapter = new CategoryAdapter(this); - } - - public void updateUIAfterServiceStarted() { - fillCategories(); - loadMainPanel(); - setDefaultPreset(); - extractXMPData(); - processIntent(); - } - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - boolean onlyUsePortrait = getResources().getBoolean(R.bool.only_use_portrait); - if (onlyUsePortrait) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); - } - MasterImage.setMaster(mMasterImage); - - clearGalleryBitmapPool(); - setupPipeline(); - - setupMasterImage(); - setDefaultValues(); - fillEditors(); - - loadXML(); - UsageStatistics.onContentViewChanged(UsageStatistics.COMPONENT_EDITOR, "Main"); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_LIFECYCLE, UsageStatistics.LIFECYCLE_START); - } - - public boolean isShowingImageStatePanel() { - return mShowingImageStatePanel; - } - - public void loadMainPanel() { - if (findViewById(R.id.main_panel_container) == null) { - return; - } - MainPanel panel = new MainPanel(); - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG); - transaction.commit(); - } - - public void loadEditorPanel(FilterRepresentation representation, - final Editor currentEditor) { - if (representation.getEditorId() == ImageOnlyEditor.ID) { - currentEditor.reflectCurrentFilter(); - return; - } - final int currentId = currentEditor.getID(); - Runnable showEditor = new Runnable() { - @Override - public void run() { - EditorPanel panel = new EditorPanel(); - panel.setEditor(currentId); - FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); - transaction.remove(getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG)); - transaction.replace(R.id.main_panel_container, panel, MainPanel.FRAGMENT_TAG); - transaction.commit(); - } - }; - Fragment main = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - boolean doAnimation = false; - if (mShowingImageStatePanel - && getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { - doAnimation = true; - } - if (doAnimation && main != null && main instanceof MainPanel) { - MainPanel mainPanel = (MainPanel) main; - View container = mainPanel.getView().findViewById(R.id.category_panel_container); - View bottom = mainPanel.getView().findViewById(R.id.bottom_panel); - int panelHeight = container.getHeight() + bottom.getHeight(); - ViewPropertyAnimator anim = mainPanel.getView().animate(); - anim.translationY(panelHeight).start(); - final Handler handler = new Handler(); - handler.postDelayed(showEditor, anim.getDuration()); - } else { - showEditor.run(); - } - } - - private void loadXML() { - setContentView(R.layout.filtershow_activity); - - ActionBar actionBar = getActionBar(); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - actionBar.setCustomView(R.layout.filtershow_actionbar); - - mSaveButton = actionBar.getCustomView(); - mSaveButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - saveImage(); - } - }); - - mImageShow = (ImageShow) findViewById(R.id.imageShow); - mImageViews.add(mImageShow); - - setupEditors(); - - mEditorPlaceHolder.hide(); - mImageShow.bindAsImageLoadListener(); - - setupStatePanel(); - } - - public void fillCategories() { - fillLooks(); - loadUserPresets(); - fillBorders(); - fillTools(); - fillEffects(); - } - - public void setupStatePanel() { - MasterImage.getImage().setHistoryManager(mMasterImage.getHistory()); - } - - private void fillEffects() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getEffects(); - mCategoryFiltersAdapter = new CategoryAdapter(this); - for (FilterRepresentation representation : filtersRepresentations) { - if (representation.getTextId() != 0) { - representation.setName(getString(representation.getTextId())); - } - mCategoryFiltersAdapter.add(new Action(this, representation)); - } - } - - private void fillTools() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getTools(); - mCategoryGeometryAdapter = new CategoryAdapter(this); - for (FilterRepresentation representation : filtersRepresentations) { - mCategoryGeometryAdapter.add(new Action(this, representation)); - } - } - - private void processIntent() { - Intent intent = getIntent(); - if (intent.getBooleanExtra(LAUNCH_FULLSCREEN, false)) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); - } - - mAction = intent.getAction(); - mSelectedImageUri = intent.getData(); - Uri loadUri = mSelectedImageUri; - if (mOriginalImageUri != null) { - loadUri = mOriginalImageUri; - } - if (loadUri != null) { - startLoadBitmap(loadUri); - } else { - pickImage(); - } - } - - private void setupEditors() { - mEditorPlaceHolder.setContainer((FrameLayout) findViewById(R.id.editorContainer)); - EditorManager.addEditors(mEditorPlaceHolder); - mEditorPlaceHolder.setOldViews(mImageViews); - } - - private void fillEditors() { - mEditorPlaceHolder.addEditor(new EditorChanSat()); - mEditorPlaceHolder.addEditor(new EditorGrad()); - mEditorPlaceHolder.addEditor(new EditorDraw()); - mEditorPlaceHolder.addEditor(new BasicEditor()); - mEditorPlaceHolder.addEditor(new ImageOnlyEditor()); - mEditorPlaceHolder.addEditor(new EditorTinyPlanet()); - mEditorPlaceHolder.addEditor(new EditorRedEye()); - mEditorPlaceHolder.addEditor(new EditorCrop()); - mEditorPlaceHolder.addEditor(new EditorMirror()); - mEditorPlaceHolder.addEditor(new EditorRotate()); - mEditorPlaceHolder.addEditor(new EditorStraighten()); - } - - private void setDefaultValues() { - Resources res = getResources(); - - // TODO: get those values from XML. - FramedTextButton.setTextSize((int) getPixelsFromDip(14)); - FramedTextButton.setTrianglePadding((int) getPixelsFromDip(4)); - FramedTextButton.setTriangleSize((int) getPixelsFromDip(10)); - - Drawable curveHandle = res.getDrawable(R.drawable.camera_crop); - int curveHandleSize = (int) res.getDimension(R.dimen.crop_indicator_size); - Spline.setCurveHandle(curveHandle, curveHandleSize); - Spline.setCurveWidth((int) getPixelsFromDip(3)); - } - - private void startLoadBitmap(Uri uri) { - final View loading = findViewById(R.id.loading); - final View imageShow = findViewById(R.id.imageShow); - imageShow.setVisibility(View.INVISIBLE); - loading.setVisibility(View.VISIBLE); - mShowingTinyPlanet = false; - mLoadBitmapTask = new LoadBitmapTask(); - mLoadBitmapTask.execute(uri); - } - - private void fillBorders() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList<FilterRepresentation> borders = filtersManager.getBorders(); - - for (int i = 0; i < borders.size(); i++) { - FilterRepresentation filter = borders.get(i); - filter.setName(getString(R.string.borders)); - if (i == 0) { - filter.setName(getString(R.string.none)); - } - } - - mCategoryBordersAdapter = new CategoryAdapter(this); - for (FilterRepresentation representation : borders) { - if (representation.getTextId() != 0) { - representation.setName(getString(representation.getTextId())); - } - mCategoryBordersAdapter.add(new Action(this, representation, Action.FULL_VIEW)); - } - } - - public UserPresetsAdapter getUserPresetsAdapter() { - return mUserPresetsAdapter; - } - - public CategoryAdapter getCategoryLooksAdapter() { - return mCategoryLooksAdapter; - } - - public CategoryAdapter getCategoryBordersAdapter() { - return mCategoryBordersAdapter; - } - - public CategoryAdapter getCategoryGeometryAdapter() { - return mCategoryGeometryAdapter; - } - - public CategoryAdapter getCategoryFiltersAdapter() { - return mCategoryFiltersAdapter; - } - - public void removeFilterRepresentation(FilterRepresentation filterRepresentation) { - if (filterRepresentation == null) { - return; - } - ImagePreset oldPreset = MasterImage.getImage().getPreset(); - ImagePreset copy = new ImagePreset(oldPreset); - copy.removeFilter(filterRepresentation); - MasterImage.getImage().setPreset(copy, copy.getLastRepresentation(), true); - if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) { - FilterRepresentation lastRepresentation = copy.getLastRepresentation(); - MasterImage.getImage().setCurrentFilterRepresentation(lastRepresentation); - } - } - - public void useFilterRepresentation(FilterRepresentation filterRepresentation) { - if (filterRepresentation == null) { - return; - } - if (MasterImage.getImage().getCurrentFilterRepresentation() == filterRepresentation) { - return; - } - ImagePreset oldPreset = MasterImage.getImage().getPreset(); - ImagePreset copy = new ImagePreset(oldPreset); - FilterRepresentation representation = copy.getRepresentation(filterRepresentation); - if (representation == null) { - copy.addFilter(filterRepresentation); - } else if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) { - filterRepresentation = representation; - } else { - if (filterRepresentation.allowsSingleInstanceOnly()) { - // Don't just update the filter representation. Centralize the - // logic in the addFilter(), such that we can keep "None" as - // null. - copy.removeFilter(representation); - copy.addFilter(filterRepresentation); - } - } - MasterImage.getImage().setPreset(copy, filterRepresentation, true); - MasterImage.getImage().setCurrentFilterRepresentation(filterRepresentation); - } - - public void showRepresentation(FilterRepresentation representation) { - if (representation == null) { - return; - } - - useFilterRepresentation(representation); - - // show representation - Editor mCurrentEditor = mEditorPlaceHolder.showEditor(representation.getEditorId()); - loadEditorPanel(representation, mCurrentEditor); - } - - public Editor getEditor(int editorID) { - return mEditorPlaceHolder.getEditor(editorID); - } - - public void setCurrentPanel(int currentPanel) { - mCurrentPanel = currentPanel; - } - - public int getCurrentPanel() { - return mCurrentPanel; - } - - public void updateCategories() { - ImagePreset preset = mMasterImage.getPreset(); - mCategoryLooksAdapter.reflectImagePreset(preset); - mCategoryBordersAdapter.reflectImagePreset(preset); - } - - private class LoadHighresBitmapTask extends AsyncTask<Void, Void, Boolean> { - @Override - protected Boolean doInBackground(Void... params) { - MasterImage master = MasterImage.getImage(); - Rect originalBounds = master.getOriginalBounds(); - if (master.supportsHighRes()) { - int highresPreviewSize = master.getOriginalBitmapLarge().getWidth() * 2; - if (highresPreviewSize > originalBounds.width()) { - highresPreviewSize = originalBounds.width(); - } - Rect bounds = new Rect(); - Bitmap originalHires = ImageLoader.loadOrientedConstrainedBitmap(master.getUri(), - master.getActivity(), highresPreviewSize, - master.getOrientation(), bounds); - master.setOriginalBounds(bounds); - master.setOriginalBitmapHighres(originalHires); - mBoundService.setOriginalBitmapHighres(originalHires); - master.warnListeners(); - } - return true; - } - - @Override - protected void onPostExecute(Boolean result) { - Bitmap highresBitmap = MasterImage.getImage().getOriginalBitmapHighres(); - if (highresBitmap != null) { - float highResPreviewScale = (float) highresBitmap.getWidth() - / (float) MasterImage.getImage().getOriginalBounds().width(); - mBoundService.setHighresPreviewScaleFactor(highResPreviewScale); - } - } - } - - private class LoadBitmapTask extends AsyncTask<Uri, Boolean, Boolean> { - int mBitmapSize; - - public LoadBitmapTask() { - mBitmapSize = getScreenImageSize(); - } - - @Override - protected Boolean doInBackground(Uri... params) { - if (!MasterImage.getImage().loadBitmap(params[0], mBitmapSize)) { - return false; - } - publishProgress(ImageLoader.queryLightCycle360(MasterImage.getImage().getActivity())); - return true; - } - - @Override - protected void onProgressUpdate(Boolean... values) { - super.onProgressUpdate(values); - if (isCancelled()) { - return; - } - if (values[0]) { - mShowingTinyPlanet = true; - } - } - - @Override - protected void onPostExecute(Boolean result) { - MasterImage.setMaster(mMasterImage); - if (isCancelled()) { - return; - } - - if (!result) { - cannotLoadImage(); - } - - if (null == CachingPipeline.getRenderScriptContext()){ - Log.v(LOGTAG,"RenderScript context destroyed during load"); - return; - } - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - final View imageShow = findViewById(R.id.imageShow); - imageShow.setVisibility(View.VISIBLE); - - Bitmap largeBitmap = MasterImage.getImage().getOriginalBitmapLarge(); - mBoundService.setOriginalBitmap(largeBitmap); - - float previewScale = (float) largeBitmap.getWidth() - / (float) MasterImage.getImage().getOriginalBounds().width(); - mBoundService.setPreviewScaleFactor(previewScale); - if (!mShowingTinyPlanet) { - mCategoryFiltersAdapter.removeTinyPlanet(); - } - mCategoryLooksAdapter.imageLoaded(); - mCategoryBordersAdapter.imageLoaded(); - mCategoryGeometryAdapter.imageLoaded(); - mCategoryFiltersAdapter.imageLoaded(); - mLoadBitmapTask = null; - - if (mOriginalPreset != null) { - MasterImage.getImage().setLoadedPreset(mOriginalPreset); - MasterImage.getImage().setPreset(mOriginalPreset, - mOriginalPreset.getLastRepresentation(), true); - mOriginalPreset = null; - } - - if (mAction == TINY_PLANET_ACTION) { - showRepresentation(mCategoryFiltersAdapter.getTinyPlanet()); - } - LoadHighresBitmapTask highresLoad = new LoadHighresBitmapTask(); - highresLoad.execute(); - super.onPostExecute(result); - } - - } - - private void clearGalleryBitmapPool() { - (new AsyncTask<Void, Void, Void>() { - @Override - protected Void doInBackground(Void... params) { - // Free memory held in Gallery's Bitmap pool. May be O(n) for n bitmaps. - GalleryBitmapPool.getInstance().clear(); - return null; - } - }).execute(); - } - - @Override - protected void onDestroy() { - if (mLoadBitmapTask != null) { - mLoadBitmapTask.cancel(false); - } - mUserPresetsManager.close(); - doUnbindService(); - super.onDestroy(); - } - - // TODO: find a more robust way of handling image size selection - // for high screen densities. - private int getScreenImageSize() { - DisplayMetrics outMetrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(outMetrics); - return (int) Math.max(outMetrics.heightPixels, outMetrics.widthPixels); - } - - private void showSavingProgress(String albumName) { - ProgressDialog progress; - if (mSavingProgressDialog != null) { - progress = mSavingProgressDialog.get(); - if (progress != null) { - progress.show(); - return; - } - } - // TODO: Allow cancellation of the saving process - String progressText; - if (albumName == null) { - progressText = getString(R.string.saving_image); - } else { - progressText = getString(R.string.filtershow_saving_image, albumName); - } - progress = ProgressDialog.show(this, "", progressText, true, false); - mSavingProgressDialog = new WeakReference<ProgressDialog>(progress); - } - - private void hideSavingProgress() { - if (mSavingProgressDialog != null) { - ProgressDialog progress = mSavingProgressDialog.get(); - if (progress != null) - progress.dismiss(); - } - } - - public void completeSaveImage(Uri saveUri) { - if (mSharingImage && mSharedOutputFile != null) { - // Image saved, we unblock the content provider - Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, - Uri.encode(mSharedOutputFile.getAbsolutePath())); - ContentValues values = new ContentValues(); - values.put(SharedImageProvider.PREPARE, false); - getContentResolver().insert(uri, values); - } - setResult(RESULT_OK, new Intent().setData(saveUri)); - hideSavingProgress(); - finish(); - } - - @Override - public boolean onShareTargetSelected(ShareActionProvider arg0, Intent arg1) { - // First, let's tell the SharedImageProvider that it will need to wait - // for the image - Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, - Uri.encode(mSharedOutputFile.getAbsolutePath())); - ContentValues values = new ContentValues(); - values.put(SharedImageProvider.PREPARE, true); - getContentResolver().insert(uri, values); - mSharingImage = true; - - // Process and save the image in the background. - showSavingProgress(null); - mImageShow.saveImage(this, mSharedOutputFile); - return true; - } - - private Intent getDefaultShareIntent() { - Intent intent = new Intent(Intent.ACTION_SEND); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.setType(SharedImageProvider.MIME_TYPE); - mSharedOutputFile = SaveImage.getNewFile(this, MasterImage.getImage().getUri()); - Uri uri = Uri.withAppendedPath(SharedImageProvider.CONTENT_URI, - Uri.encode(mSharedOutputFile.getAbsolutePath())); - intent.putExtra(Intent.EXTRA_STREAM, uri); - return intent; - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.filtershow_activity_menu, menu); - MenuItem showState = menu.findItem(R.id.showImageStateButton); - if (mShowingImageStatePanel) { - showState.setTitle(R.string.hide_imagestate_panel); - } else { - showState.setTitle(R.string.show_imagestate_panel); - } - mShareActionProvider = (ShareActionProvider) menu.findItem(R.id.menu_share) - .getActionProvider(); - mShareActionProvider.setShareIntent(getDefaultShareIntent()); - mShareActionProvider.setOnShareTargetSelectedListener(this); - - MenuItem undoItem = menu.findItem(R.id.undoButton); - MenuItem redoItem = menu.findItem(R.id.redoButton); - MenuItem resetItem = menu.findItem(R.id.resetHistoryButton); - mMasterImage.getHistory().setMenuItems(undoItem, redoItem, resetItem); - return true; - } - - @Override - public void onPause() { - super.onPause(); - if (mShareActionProvider != null) { - mShareActionProvider.setOnShareTargetSelectedListener(null); - } - } - - @Override - public void onResume() { - super.onResume(); - if (mShareActionProvider != null) { - mShareActionProvider.setOnShareTargetSelectedListener(this); - } - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.undoButton: { - HistoryManager adapter = mMasterImage.getHistory(); - int position = adapter.undo(); - mMasterImage.onHistoryItemClick(position); - backToMain(); - invalidateViews(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, "Undo"); - return true; - } - case R.id.redoButton: { - HistoryManager adapter = mMasterImage.getHistory(); - int position = adapter.redo(); - mMasterImage.onHistoryItemClick(position); - invalidateViews(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, "Redo"); - return true; - } - case R.id.resetHistoryButton: { - resetHistory(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, "ResetHistory"); - return true; - } - case R.id.showImageStateButton: { - toggleImageStatePanel(); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - UsageStatistics.CATEGORY_BUTTON_PRESS, - mShowingImageStatePanel ? "ShowPanel" : "HidePanel"); - return true; - } - case R.id.exportFlattenButton: { - showExportOptionsDialog(); - return true; - } - case android.R.id.home: { - saveImage(); - return true; - } - case R.id.manageUserPresets: { - manageUserPresets(); - return true; - } - } - return false; - } - - private void manageUserPresets() { - DialogFragment dialog = new PresetManagementDialog(); - dialog.show(getSupportFragmentManager(), "NoticeDialogFragment"); - } - - private void showExportOptionsDialog() { - DialogFragment dialog = new ExportDialog(); - dialog.show(getSupportFragmentManager(), "ExportDialogFragment"); - } - - public void updateUserPresetsFromAdapter(UserPresetsAdapter adapter) { - ArrayList<FilterUserPresetRepresentation> representations = - adapter.getDeletedRepresentations(); - for (FilterUserPresetRepresentation representation : representations) { - deletePreset(representation.getId()); - } - ArrayList<FilterUserPresetRepresentation> changedRepresentations = - adapter.getChangedRepresentations(); - for (FilterUserPresetRepresentation representation : changedRepresentations) { - updatePreset(representation); - } - adapter.clearDeletedRepresentations(); - adapter.clearChangedRepresentations(); - loadUserPresets(); - } - - public void loadUserPresets() { - mUserPresetsManager.load(); - } - - public void updateUserPresetsFromManager() { - ArrayList<FilterUserPresetRepresentation> presets = mUserPresetsManager.getRepresentations(); - if (presets == null) { - return; - } - if (mCategoryLooksAdapter != null) { - fillLooks(); - } - mUserPresetsAdapter.clear(); - for (int i = 0; i < presets.size(); i++) { - FilterUserPresetRepresentation representation = presets.get(i); - mCategoryLooksAdapter.add( - new Action(this, representation, Action.FULL_VIEW)); - mUserPresetsAdapter.add(new Action(this, representation, Action.FULL_VIEW)); - } - mCategoryLooksAdapter.notifyDataSetInvalidated(); - - } - - public void saveCurrentImagePreset() { - mUserPresetsManager.save(MasterImage.getImage().getPreset()); - } - - private void deletePreset(int id) { - mUserPresetsManager.delete(id); - } - - private void updatePreset(FilterUserPresetRepresentation representation) { - mUserPresetsManager.update(representation); - } - - public void enableSave(boolean enable) { - if (mSaveButton != null) { - mSaveButton.setEnabled(enable); - } - } - - private void fillLooks() { - FiltersManager filtersManager = FiltersManager.getManager(); - ArrayList<FilterRepresentation> filtersRepresentations = filtersManager.getLooks(); - - mCategoryLooksAdapter.clear(); - int verticalItemHeight = (int) getResources().getDimension(R.dimen.action_item_height); - mCategoryLooksAdapter.setItemHeight(verticalItemHeight); - for (FilterRepresentation representation : filtersRepresentations) { - mCategoryLooksAdapter.add(new Action(this, representation, Action.FULL_VIEW)); - } - } - - public void setDefaultPreset() { - // Default preset (original) - ImagePreset preset = new ImagePreset(); // empty - mMasterImage.setPreset(preset, preset.getLastRepresentation(), true); - } - - // ////////////////////////////////////////////////////////////////////////////// - // Some utility functions - // TODO: finish the cleanup. - - public void invalidateViews() { - for (ImageShow views : mImageViews) { - views.updateImage(); - } - } - - public void hideImageViews() { - for (View view : mImageViews) { - view.setVisibility(View.GONE); - } - mEditorPlaceHolder.hide(); - } - - // ////////////////////////////////////////////////////////////////////////////// - // imageState panel... - - public void toggleImageStatePanel() { - invalidateOptionsMenu(); - mShowingImageStatePanel = !mShowingImageStatePanel; - Fragment panel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - if (panel != null) { - if (panel instanceof EditorPanel) { - EditorPanel editorPanel = (EditorPanel) panel; - editorPanel.showImageStatePanel(mShowingImageStatePanel); - } else if (panel instanceof MainPanel) { - MainPanel mainPanel = (MainPanel) panel; - mainPanel.showImageStatePanel(mShowingImageStatePanel); - } - } - } - - @Override - public void onConfigurationChanged(Configuration newConfig) - { - super.onConfigurationChanged(newConfig); - setDefaultValues(); - loadXML(); - fillCategories(); - loadMainPanel(); - - // mLoadBitmapTask==null implies you have looked at the intent - if (!mShowingTinyPlanet && (mLoadBitmapTask == null)) { - mCategoryFiltersAdapter.removeTinyPlanet(); - } - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - } - - public void setupMasterImage() { - - HistoryManager historyManager = new HistoryManager(); - StateAdapter imageStateAdapter = new StateAdapter(this, 0); - MasterImage.reset(); - mMasterImage = MasterImage.getImage(); - mMasterImage.setHistoryManager(historyManager); - mMasterImage.setStateAdapter(imageStateAdapter); - mMasterImage.setActivity(this); - - if (Runtime.getRuntime().maxMemory() > LIMIT_SUPPORTS_HIGHRES) { - mMasterImage.setSupportsHighRes(true); - } else { - mMasterImage.setSupportsHighRes(false); - } - } - - void resetHistory() { - HistoryManager adapter = mMasterImage.getHistory(); - adapter.reset(); - HistoryItem historyItem = adapter.getItem(0); - ImagePreset original = new ImagePreset(historyItem.getImagePreset()); - mMasterImage.setPreset(original, historyItem.getFilterRepresentation(), true); - invalidateViews(); - backToMain(); - } - - public void showDefaultImageView() { - mEditorPlaceHolder.hide(); - mImageShow.setVisibility(View.VISIBLE); - MasterImage.getImage().setCurrentFilter(null); - MasterImage.getImage().setCurrentFilterRepresentation(null); - } - - public void backToMain() { - Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - if (currentPanel instanceof MainPanel) { - return; - } - loadMainPanel(); - showDefaultImageView(); - } - - @Override - public void onBackPressed() { - Fragment currentPanel = getSupportFragmentManager().findFragmentByTag(MainPanel.FRAGMENT_TAG); - if (currentPanel instanceof MainPanel) { - if (!mImageShow.hasModifications()) { - done(); - } else { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setMessage(R.string.unsaved).setTitle(R.string.save_before_exit); - builder.setPositiveButton(R.string.save_and_exit, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - saveImage(); - } - }); - builder.setNegativeButton(R.string.exit, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int id) { - done(); - } - }); - builder.show(); - } - } else { - backToMain(); - } - } - - public void cannotLoadImage() { - Toast.makeText(this, R.string.cannot_load_image, Toast.LENGTH_SHORT).show(); - finish(); - } - - // ////////////////////////////////////////////////////////////////////////////// - - public float getPixelsFromDip(float value) { - Resources r = getResources(); - return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, - r.getDisplayMetrics()); - } - - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, - long id) { - mMasterImage.onHistoryItemClick(position); - invalidateViews(); - } - - public void pickImage() { - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)), - SELECT_PICTURE); - } - - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK) { - if (requestCode == SELECT_PICTURE) { - Uri selectedImageUri = data.getData(); - startLoadBitmap(selectedImageUri); - } - } - } - - - public void saveImage() { - if (mImageShow.hasModifications()) { - // Get the name of the album, to which the image will be saved - File saveDir = SaveImage.getFinalSaveDirectory(this, mSelectedImageUri); - int bucketId = GalleryUtils.getBucketId(saveDir.getPath()); - String albumName = LocalAlbum.getLocalizedName(getResources(), bucketId, null); - showSavingProgress(albumName); - mImageShow.saveImage(this, null); - } else { - done(); - } - } - - - public void done() { - hideSavingProgress(); - if (mLoadBitmapTask != null) { - mLoadBitmapTask.cancel(false); - } - finish(); - } - - private void extractXMPData() { - XMresults res = XmpPresets.extractXMPData( - getBaseContext(), mMasterImage, getIntent().getData()); - if (res == null) - return; - - mOriginalImageUri = res.originalimage; - mOriginalPreset = res.preset; - } - - public Uri getSelectedImageUri() { - return mSelectedImageUri; - } - -} diff --git a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java b/src/com/android/gallery3d/filtershow/cache/ImageLoader.java deleted file mode 100644 index b6c72fd9d..000000000 --- a/src/com/android/gallery3d/filtershow/cache/ImageLoader.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.cache; - -import android.content.ContentResolver; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.database.Cursor; -import android.database.sqlite.SQLiteException; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.net.Uri; -import android.provider.MediaStore; -import android.util.Log; -import android.webkit.MimeTypeMap; - -import com.adobe.xmp.XMPException; -import com.adobe.xmp.XMPMeta; -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.util.XmpUtilHelper; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -public final class ImageLoader { - - private static final String LOGTAG = "ImageLoader"; - - public static final String JPEG_MIME_TYPE = "image/jpeg"; - public static final int DEFAULT_COMPRESS_QUALITY = 95; - - public static final int ORI_NORMAL = ExifInterface.Orientation.TOP_LEFT; - public static final int ORI_ROTATE_90 = ExifInterface.Orientation.RIGHT_TOP; - public static final int ORI_ROTATE_180 = ExifInterface.Orientation.BOTTOM_LEFT; - public static final int ORI_ROTATE_270 = ExifInterface.Orientation.RIGHT_BOTTOM; - public static final int ORI_FLIP_HOR = ExifInterface.Orientation.TOP_RIGHT; - public static final int ORI_FLIP_VERT = ExifInterface.Orientation.BOTTOM_RIGHT; - public static final int ORI_TRANSPOSE = ExifInterface.Orientation.LEFT_TOP; - public static final int ORI_TRANSVERSE = ExifInterface.Orientation.LEFT_BOTTOM; - - private static final int BITMAP_LOAD_BACKOUT_ATTEMPTS = 5; - - private ImageLoader() {} - - /** - * Returns the Mime type for a Url. Safe to use with Urls that do not - * come from Gallery's content provider. - */ - public static String getMimeType(Uri src) { - String postfix = MimeTypeMap.getFileExtensionFromUrl(src.toString()); - String ret = null; - if (postfix != null) { - ret = MimeTypeMap.getSingleton().getMimeTypeFromExtension(postfix); - } - return ret; - } - - /** - * Returns the image's orientation flag. Defaults to ORI_NORMAL if no valid - * orientation was found. - */ - public static int getMetadataOrientation(Context context, Uri uri) { - if (uri == null || context == null) { - throw new IllegalArgumentException("bad argument to getOrientation"); - } - - // First try to find orientation data in Gallery's ContentProvider. - Cursor cursor = null; - try { - cursor = context.getContentResolver().query(uri, - new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, - null, null, null); - if (cursor != null && cursor.moveToNext()) { - int ori = cursor.getInt(0); - switch (ori) { - case 90: - return ORI_ROTATE_90; - case 270: - return ORI_ROTATE_270; - case 180: - return ORI_ROTATE_180; - default: - return ORI_NORMAL; - } - } - } catch (SQLiteException e) { - // Do nothing - } catch (IllegalArgumentException e) { - // Do nothing - } finally { - Utils.closeSilently(cursor); - } - - // Fall back to checking EXIF tags in file. - if (ContentResolver.SCHEME_FILE.equals(uri.getScheme())) { - String mimeType = getMimeType(uri); - if (!JPEG_MIME_TYPE.equals(mimeType)) { - return ORI_NORMAL; - } - String path = uri.getPath(); - ExifInterface exif = new ExifInterface(); - try { - exif.readExif(path); - Integer tagval = exif.getTagIntValue(ExifInterface.TAG_ORIENTATION); - if (tagval != null) { - int orientation = tagval; - switch(orientation) { - case ORI_NORMAL: - case ORI_ROTATE_90: - case ORI_ROTATE_180: - case ORI_ROTATE_270: - case ORI_FLIP_HOR: - case ORI_FLIP_VERT: - case ORI_TRANSPOSE: - case ORI_TRANSVERSE: - return orientation; - default: - return ORI_NORMAL; - } - } - } catch (IOException e) { - Log.w(LOGTAG, "Failed to read EXIF orientation", e); - } - } - return ORI_NORMAL; - } - - /** - * Returns the rotation of image at the given URI as one of 0, 90, 180, - * 270. Defaults to 0. - */ - public static int getMetadataRotation(Context context, Uri uri) { - int orientation = getMetadataOrientation(context, uri); - switch(orientation) { - case ORI_ROTATE_90: - return 90; - case ORI_ROTATE_180: - return 180; - case ORI_ROTATE_270: - return 270; - default: - return 0; - } - } - - /** - * Takes an orientation and a bitmap, and returns the bitmap transformed - * to that orientation. - */ - public static Bitmap orientBitmap(Bitmap bitmap, int ori) { - Matrix matrix = new Matrix(); - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - if (ori == ORI_ROTATE_90 || - ori == ORI_ROTATE_270 || - ori == ORI_TRANSPOSE || - ori == ORI_TRANSVERSE) { - int tmp = w; - w = h; - h = tmp; - } - switch (ori) { - case ORI_ROTATE_90: - matrix.setRotate(90, w / 2f, h / 2f); - break; - case ORI_ROTATE_180: - matrix.setRotate(180, w / 2f, h / 2f); - break; - case ORI_ROTATE_270: - matrix.setRotate(270, w / 2f, h / 2f); - break; - case ORI_FLIP_HOR: - matrix.preScale(-1, 1); - break; - case ORI_FLIP_VERT: - matrix.preScale(1, -1); - break; - case ORI_TRANSPOSE: - matrix.setRotate(90, w / 2f, h / 2f); - matrix.preScale(1, -1); - break; - case ORI_TRANSVERSE: - matrix.setRotate(270, w / 2f, h / 2f); - matrix.preScale(1, -1); - break; - case ORI_NORMAL: - default: - return bitmap; - } - return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), - bitmap.getHeight(), matrix, true); - } - - /** - * Returns the bitmap for the rectangular region given by "bounds" - * if it is a subset of the bitmap stored at uri. Otherwise returns - * null. - */ - public static Bitmap loadRegionBitmap(Context context, Uri uri, BitmapFactory.Options options, - Rect bounds) { - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(uri); - BitmapRegionDecoder decoder = BitmapRegionDecoder.newInstance(is, false); - Rect r = new Rect(0, 0, decoder.getWidth(), decoder.getHeight()); - // return null if bounds are not entirely within the bitmap - if (!r.contains(bounds)) { - return null; - } - return decoder.decodeRegion(bounds, options); - } catch (FileNotFoundException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } catch (IOException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } finally { - Utils.closeSilently(is); - } - return null; - } - - /** - * Returns the bounds of the bitmap stored at a given Url. - */ - public static Rect loadBitmapBounds(Context context, Uri uri) { - BitmapFactory.Options o = new BitmapFactory.Options(); - loadBitmap(context, uri, o); - return new Rect(0, 0, o.outWidth, o.outHeight); - } - - /** - * Loads a bitmap that has been downsampled using sampleSize from a given url. - */ - public static Bitmap loadDownsampledBitmap(Context context, Uri uri, int sampleSize) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - options.inSampleSize = sampleSize; - return loadBitmap(context, uri, options); - } - - - /** - * Returns the bitmap from the given uri loaded using the given options. - * Returns null on failure. - */ - public static Bitmap loadBitmap(Context context, Uri uri, BitmapFactory.Options o) { - if (uri == null || context == null) { - throw new IllegalArgumentException("bad argument to loadBitmap"); - } - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(uri); - return BitmapFactory.decodeStream(is, null, o); - } catch (FileNotFoundException e) { - Log.e(LOGTAG, "FileNotFoundException for " + uri, e); - } finally { - Utils.closeSilently(is); - } - return null; - } - - /** - * Loads a bitmap at a given URI that is downsampled so that both sides are - * smaller than maxSideLength. The Bitmap's original dimensions are stored - * in the rect originalBounds. - * - * @param uri URI of image to open. - * @param context context whose ContentResolver to use. - * @param maxSideLength max side length of returned bitmap. - * @param originalBounds If not null, set to the actual bounds of the stored bitmap. - * @param useMin use min or max side of the original image - * @return downsampled bitmap or null if this operation failed. - */ - public static Bitmap loadConstrainedBitmap(Uri uri, Context context, int maxSideLength, - Rect originalBounds, boolean useMin) { - if (maxSideLength <= 0 || uri == null || context == null) { - throw new IllegalArgumentException("bad argument to getScaledBitmap"); - } - // Get width and height of stored bitmap - Rect storedBounds = loadBitmapBounds(context, uri); - if (originalBounds != null) { - originalBounds.set(storedBounds); - } - int w = storedBounds.width(); - int h = storedBounds.height(); - - // If bitmap cannot be decoded, return null - if (w <= 0 || h <= 0) { - return null; - } - - // Find best downsampling size - int imageSide = 0; - if (useMin) { - imageSide = Math.min(w, h); - } else { - imageSide = Math.max(w, h); - } - int sampleSize = 1; - while (imageSide > maxSideLength) { - imageSide >>>= 1; - sampleSize <<= 1; - } - - // Make sure sample size is reasonable - if (sampleSize <= 0 || - 0 >= (int) (Math.min(w, h) / sampleSize)) { - return null; - } - return loadDownsampledBitmap(context, uri, sampleSize); - } - - /** - * Loads a bitmap at a given URI that is downsampled so that both sides are - * smaller than maxSideLength. The Bitmap's original dimensions are stored - * in the rect originalBounds. The output is also transformed to the given - * orientation. - * - * @param uri URI of image to open. - * @param context context whose ContentResolver to use. - * @param maxSideLength max side length of returned bitmap. - * @param orientation the orientation to transform the bitmap to. - * @param originalBounds set to the actual bounds of the stored bitmap. - * @return downsampled bitmap or null if this operation failed. - */ - public static Bitmap loadOrientedConstrainedBitmap(Uri uri, Context context, int maxSideLength, - int orientation, Rect originalBounds) { - Bitmap bmap = loadConstrainedBitmap(uri, context, maxSideLength, originalBounds, false); - if (bmap != null) { - bmap = orientBitmap(bmap, orientation); - } - return bmap; - } - - public static Bitmap getScaleOneImageForPreset(Context context, Uri uri, Rect bounds, - Rect destination) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - if (destination != null) { - if (bounds.width() > destination.width()) { - int sampleSize = 1; - int w = bounds.width(); - while (w > destination.width()) { - sampleSize *= 2; - w /= sampleSize; - } - options.inSampleSize = sampleSize; - } - } - Bitmap bmp = loadRegionBitmap(context, uri, options, bounds); - return bmp; - } - - /** - * Loads a bitmap that is downsampled by at least the input sample size. In - * low-memory situations, the bitmap may be downsampled further. - */ - public static Bitmap loadBitmapWithBackouts(Context context, Uri sourceUri, int sampleSize) { - boolean noBitmap = true; - int num_tries = 0; - if (sampleSize <= 0) { - sampleSize = 1; - } - Bitmap bmap = null; - while (noBitmap) { - try { - // Try to decode, downsample if low-memory. - bmap = loadDownsampledBitmap(context, sourceUri, sampleSize); - noBitmap = false; - } catch (java.lang.OutOfMemoryError e) { - // Try with more downsampling before failing for good. - if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { - throw e; - } - bmap = null; - System.gc(); - sampleSize *= 2; - } - } - return bmap; - } - - /** - * Loads an oriented bitmap that is downsampled by at least the input sample - * size. In low-memory situations, the bitmap may be downsampled further. - */ - public static Bitmap loadOrientedBitmapWithBackouts(Context context, Uri sourceUri, - int sampleSize) { - Bitmap bitmap = loadBitmapWithBackouts(context, sourceUri, sampleSize); - if (bitmap == null) { - return null; - } - int orientation = getMetadataOrientation(context, sourceUri); - bitmap = orientBitmap(bitmap, orientation); - return bitmap; - } - - /** - * Loads bitmap from a resource that may be downsampled in low-memory situations. - */ - public static Bitmap decodeResourceWithBackouts(Resources res, BitmapFactory.Options options, - int id) { - boolean noBitmap = true; - int num_tries = 0; - if (options.inSampleSize < 1) { - options.inSampleSize = 1; - } - // Stopgap fix for low-memory devices. - Bitmap bmap = null; - while (noBitmap) { - try { - // Try to decode, downsample if low-memory. - bmap = BitmapFactory.decodeResource( - res, id, options); - noBitmap = false; - } catch (java.lang.OutOfMemoryError e) { - // Retry before failing for good. - if (++num_tries >= BITMAP_LOAD_BACKOUT_ATTEMPTS) { - throw e; - } - bmap = null; - System.gc(); - options.inSampleSize *= 2; - } - } - return bmap; - } - - public static XMPMeta getXmpObject(Context context) { - try { - InputStream is = context.getContentResolver().openInputStream( - MasterImage.getImage().getUri()); - return XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - return null; - } - } - - /** - * Determine if this is a light cycle 360 image - * - * @return true if it is a light Cycle image that is full 360 - */ - public static boolean queryLightCycle360(Context context) { - InputStream is = null; - try { - is = context.getContentResolver().openInputStream(MasterImage.getImage().getUri()); - XMPMeta meta = XmpUtilHelper.extractXMPMeta(is); - if (meta == null) { - return false; - } - String namespace = "http://ns.google.com/photos/1.0/panorama/"; - String cropWidthName = "GPano:CroppedAreaImageWidthPixels"; - String fullWidthName = "GPano:FullPanoWidthPixels"; - - if (!meta.doesPropertyExist(namespace, cropWidthName)) { - return false; - } - if (!meta.doesPropertyExist(namespace, fullWidthName)) { - return false; - } - - Integer cropValue = meta.getPropertyInteger(namespace, cropWidthName); - Integer fullValue = meta.getPropertyInteger(namespace, fullWidthName); - - // Definition of a 360: - // GFullPanoWidthPixels == CroppedAreaImageWidthPixels - if (cropValue != null && fullValue != null) { - return cropValue.equals(fullValue); - } - - return false; - } catch (FileNotFoundException e) { - return false; - } catch (XMPException e) { - return false; - } finally { - Utils.closeSilently(is); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/category/Action.java b/src/com/android/gallery3d/filtershow/category/Action.java deleted file mode 100644 index 332ca18b0..000000000 --- a/src/com/android/gallery3d/filtershow/category/Action.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.category; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; -import android.widget.ArrayAdapter; -import android.widget.ListAdapter; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.pipeline.RenderingRequest; -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -public class Action implements RenderingRequestCaller { - - private static final String LOGTAG = "Action"; - private FilterRepresentation mRepresentation; - private String mName; - private Rect mImageFrame; - private Bitmap mImage; - private ArrayAdapter mAdapter; - public static final int FULL_VIEW = 0; - public static final int CROP_VIEW = 1; - private int mType = CROP_VIEW; - private Bitmap mPortraitImage; - private Bitmap mOverlayBitmap; - private Context mContext; - - public Action(Context context, FilterRepresentation representation, int type) { - mContext = context; - setRepresentation(representation); - setType(type); - } - - public Action(Context context, FilterRepresentation representation) { - this(context, representation, CROP_VIEW); - } - - public FilterRepresentation getRepresentation() { - return mRepresentation; - } - - public void setRepresentation(FilterRepresentation representation) { - mRepresentation = representation; - mName = representation.getName(); - } - - public String getName() { - return mName; - } - - public void setName(String name) { - mName = name; - } - - public void setImageFrame(Rect imageFrame, int orientation) { - if (mImageFrame != null && mImageFrame.equals(imageFrame)) { - return; - } - Bitmap bitmap = MasterImage.getImage().getLargeThumbnailBitmap(); - if (bitmap != null) { - mImageFrame = imageFrame; - int w = mImageFrame.width(); - int h = mImageFrame.height(); - if (orientation == CategoryView.VERTICAL - && mType == CROP_VIEW) { - w /= 2; - } - Bitmap bitmapCrop = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); - drawCenteredImage(bitmap, bitmapCrop, true); - - postNewIconRenderRequest(bitmapCrop); - } - } - - public Bitmap getImage() { - return mImage; - } - - public void setImage(Bitmap image) { - mImage = image; - } - - public void setAdapter(ArrayAdapter adapter) { - mAdapter = adapter; - } - - public void setType(int type) { - mType = type; - } - - private void postNewIconRenderRequest(Bitmap bitmap) { - if (bitmap != null && mRepresentation != null) { - ImagePreset preset = new ImagePreset(); - preset.addFilter(mRepresentation); - RenderingRequest.post(mContext, bitmap, - preset, RenderingRequest.ICON_RENDERING, this); - } - } - - private void drawCenteredImage(Bitmap source, Bitmap destination, boolean scale) { - RectF image = new RectF(0, 0, source.getWidth(), source.getHeight()); - int border = 0; - if (!scale) { - border = destination.getWidth() - destination.getHeight(); - if (border < 0) { - border = 0; - } - } - RectF frame = new RectF(border, 0, - destination.getWidth() - border, - destination.getHeight()); - Matrix m = new Matrix(); - m.setRectToRect(frame, image, Matrix.ScaleToFit.CENTER); - image.set(frame); - m.mapRect(image); - m.setRectToRect(image, frame, Matrix.ScaleToFit.FILL); - Canvas canvas = new Canvas(destination); - canvas.drawBitmap(source, m, new Paint(Paint.FILTER_BITMAP_FLAG)); - } - - @Override - public void available(RenderingRequest request) { - mImage = request.getBitmap(); - if (mImage == null) { - return; - } - if (mRepresentation.getOverlayId() != 0 && mOverlayBitmap == null) { - mOverlayBitmap = BitmapFactory.decodeResource( - mContext.getResources(), - mRepresentation.getOverlayId()); - } - if (mOverlayBitmap != null) { - if (getRepresentation().getFilterType() == FilterRepresentation.TYPE_BORDER) { - Canvas canvas = new Canvas(mImage); - canvas.drawBitmap(mOverlayBitmap, new Rect(0, 0, mOverlayBitmap.getWidth(), mOverlayBitmap.getHeight()), - new Rect(0, 0, mImage.getWidth(), mImage.getHeight()), new Paint()); - } else { - Canvas canvas = new Canvas(mImage); - canvas.drawARGB(128, 0, 0, 0); - drawCenteredImage(mOverlayBitmap, mImage, false); - } - } - if (mAdapter != null) { - mAdapter.notifyDataSetChanged(); - } - } - - public void setPortraitImage(Bitmap portraitImage) { - mPortraitImage = portraitImage; - } - - public Bitmap getPortraitImage() { - return mPortraitImage; - } - - public Bitmap getOverlayBitmap() { - return mOverlayBitmap; - } - - public void setOverlayBitmap(Bitmap overlayBitmap) { - mOverlayBitmap = overlayBitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java b/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java deleted file mode 100644 index 6451c39df..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryAdapter.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.category; - -import android.content.Context; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.ListView; - -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -public class CategoryAdapter extends ArrayAdapter<Action> { - - private static final String LOGTAG = "CategoryAdapter"; - private int mItemHeight; - private View mContainer; - private int mItemWidth = ListView.LayoutParams.MATCH_PARENT; - private int mSelectedPosition; - int mCategory; - private int mOrientation; - - public CategoryAdapter(Context context, int textViewResourceId) { - super(context, textViewResourceId); - mItemHeight = (int) (context.getResources().getDisplayMetrics().density * 100); - } - - public CategoryAdapter(Context context) { - this(context, 0); - } - - public void setItemHeight(int height) { - mItemHeight = height; - } - - public void setItemWidth(int width) { - mItemWidth = width; - } - - @Override - public void add(Action action) { - super.add(action); - action.setAdapter(this); - } - - public void initializeSelection(int category) { - mCategory = category; - mSelectedPosition = -1; - if (category == MainPanel.LOOKS) { - mSelectedPosition = 0; - } - if (category == MainPanel.BORDERS) { - mSelectedPosition = 0; - } - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = new CategoryView(getContext()); - } - CategoryView view = (CategoryView) convertView; - view.setOrientation(mOrientation); - view.setAction(getItem(position), this); - view.setLayoutParams( - new ListView.LayoutParams(mItemWidth, mItemHeight)); - view.setTag(position); - view.invalidate(); - return view; - } - - public void setSelected(View v) { - int old = mSelectedPosition; - mSelectedPosition = (Integer) v.getTag(); - if (old != -1) { - invalidateView(old); - } - invalidateView(mSelectedPosition); - } - - public boolean isSelected(View v) { - return (Integer) v.getTag() == mSelectedPosition; - } - - private void invalidateView(int position) { - View child = null; - if (mContainer instanceof ListView) { - ListView lv = (ListView) mContainer; - child = lv.getChildAt(position - lv.getFirstVisiblePosition()); - } else { - CategoryTrack ct = (CategoryTrack) mContainer; - child = ct.getChildAt(position); - } - if (child != null) { - child.invalidate(); - } - } - - public void setContainer(View container) { - mContainer = container; - } - - public void imageLoaded() { - notifyDataSetChanged(); - } - - public FilterRepresentation getTinyPlanet() { - for (int i = 0; i < getCount(); i++) { - Action action = getItem(i); - if (action.getRepresentation() != null - && action.getRepresentation() - instanceof FilterTinyPlanetRepresentation) { - return action.getRepresentation(); - } - } - return null; - } - - public void removeTinyPlanet() { - for (int i = 0; i < getCount(); i++) { - Action action = getItem(i); - if (action.getRepresentation() != null - && action.getRepresentation() - instanceof FilterTinyPlanetRepresentation) { - remove(action); - return; - } - } - } - - public void setOrientation(int orientation) { - mOrientation = orientation; - } - - public void reflectImagePreset(ImagePreset preset) { - if (preset == null) { - return; - } - int selected = 0; // if nothing found, select "none" (first element) - FilterRepresentation rep = null; - if (mCategory == MainPanel.LOOKS) { - int pos = preset.getPositionForType(FilterRepresentation.TYPE_FX); - if (pos != -1) { - rep = preset.getFilterRepresentation(pos); - } - } else if (mCategory == MainPanel.BORDERS) { - int pos = preset.getPositionForType(FilterRepresentation.TYPE_BORDER); - if (pos != -1) { - rep = preset.getFilterRepresentation(pos); - } - } - if (rep != null) { - for (int i = 0; i < getCount(); i++) { - if (rep.getName().equalsIgnoreCase( - getItem(i).getRepresentation().getName())) { - selected = i; - break; - } - } - } - if (mSelectedPosition != selected) { - mSelectedPosition = selected; - this.notifyDataSetChanged(); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java b/src/com/android/gallery3d/filtershow/category/CategoryPanel.java deleted file mode 100644 index de2481f3f..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryPanel.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.category; - -import android.app.Activity; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.ListView; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; - -public class CategoryPanel extends Fragment { - - public static final String FRAGMENT_TAG = "CategoryPanel"; - private static final String PARAMETER_TAG = "currentPanel"; - - private int mCurrentAdapter = MainPanel.LOOKS; - private CategoryAdapter mAdapter; - - public void setAdapter(int value) { - mCurrentAdapter = value; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - loadAdapter(mCurrentAdapter); - } - - private void loadAdapter(int adapter) { - FilterShowActivity activity = (FilterShowActivity) getActivity(); - switch (adapter) { - case MainPanel.LOOKS: { - mAdapter = activity.getCategoryLooksAdapter(); - mAdapter.initializeSelection(MainPanel.LOOKS); - activity.updateCategories(); - break; - } - case MainPanel.BORDERS: { - mAdapter = activity.getCategoryBordersAdapter(); - mAdapter.initializeSelection(MainPanel.BORDERS); - activity.updateCategories(); - break; - } - case MainPanel.GEOMETRY: { - mAdapter = activity.getCategoryGeometryAdapter(); - mAdapter.initializeSelection(MainPanel.GEOMETRY); - break; - } - case MainPanel.FILTERS: { - mAdapter = activity.getCategoryFiltersAdapter(); - mAdapter.initializeSelection(MainPanel.FILTERS); - break; - } - } - } - - @Override - public void onSaveInstanceState(Bundle state) { - super.onSaveInstanceState(state); - state.putInt(PARAMETER_TAG, mCurrentAdapter); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - LinearLayout main = (LinearLayout) inflater.inflate( - R.layout.filtershow_category_panel_new, container, - false); - - if (savedInstanceState != null) { - int selectedPanel = savedInstanceState.getInt(PARAMETER_TAG); - loadAdapter(selectedPanel); - } - - View panelView = main.findViewById(R.id.listItems); - if (panelView instanceof CategoryTrack) { - CategoryTrack panel = (CategoryTrack) panelView; - mAdapter.setOrientation(CategoryView.HORIZONTAL); - panel.setAdapter(mAdapter); - mAdapter.setContainer(panel); - } else { - ListView panel = (ListView) main.findViewById(R.id.listItems); - panel.setAdapter(mAdapter); - mAdapter.setContainer(panel); - } - return main; - } - -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java b/src/com/android/gallery3d/filtershow/category/CategoryTrack.java deleted file mode 100644 index ac8245a3b..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryTrack.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.category; - -import android.content.Context; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.util.AttributeSet; -import android.util.Log; -import android.view.View; -import android.widget.LinearLayout; -import com.android.gallery3d.R; - -public class CategoryTrack extends LinearLayout { - - private CategoryAdapter mAdapter; - private int mElemSize; - private DataSetObserver mDataSetObserver = new DataSetObserver() { - @Override - public void onChanged() { - super.onChanged(); - invalidate(); - } - @Override - public void onInvalidated() { - super.onInvalidated(); - fillContent(); - } - }; - - public CategoryTrack(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CategoryTrack); - mElemSize = a.getDimensionPixelSize(R.styleable.CategoryTrack_iconSize, 0); - } - - public void setAdapter(CategoryAdapter adapter) { - mAdapter = adapter; - mAdapter.registerDataSetObserver(mDataSetObserver); - fillContent(); - } - - public void fillContent() { - removeAllViews(); - mAdapter.setItemWidth(mElemSize); - mAdapter.setItemHeight(LayoutParams.MATCH_PARENT); - int n = mAdapter.getCount(); - for (int i = 0; i < n; i++) { - View view = mAdapter.getView(i, null, this); - addView(view, i); - } - requestLayout(); - } - - @Override - public void invalidate() { - for (int i = 0; i < this.getChildCount(); i++) { - View child = getChildAt(i); - child.invalidate(); - } - } - -} diff --git a/src/com/android/gallery3d/filtershow/category/CategoryView.java b/src/com/android/gallery3d/filtershow/category/CategoryView.java deleted file mode 100644 index c456dc207..000000000 --- a/src/com/android/gallery3d/filtershow/category/CategoryView.java +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.category; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.Typeface; -import android.view.View; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.ui.SelectionRenderer; - -public class CategoryView extends View implements View.OnClickListener { - - private static final String LOGTAG = "CategoryView"; - public static final int VERTICAL = 0; - public static final int HORIZONTAL = 1; - private Paint mPaint = new Paint(); - private Action mAction; - private Rect mTextBounds = new Rect(); - private int mMargin = 16; - private int mTextSize = 32; - private int mTextColor; - private int mBackgroundColor; - private Paint mSelectPaint; - CategoryAdapter mAdapter; - private int mSelectionStroke; - private Paint mBorderPaint; - private int mBorderStroke; - private int mOrientation = VERTICAL; - - public CategoryView(Context context) { - super(context); - setOnClickListener(this); - Resources res = getResources(); - mBackgroundColor = res.getColor(R.color.filtershow_categoryview_background); - mTextColor = res.getColor(R.color.filtershow_categoryview_text); - mSelectionStroke = res.getDimensionPixelSize(R.dimen.thumbnail_margin); - mTextSize = res.getDimensionPixelSize(R.dimen.category_panel_text_size); - mMargin = res.getDimensionPixelOffset(R.dimen.category_panel_margin); - mSelectPaint = new Paint(); - mSelectPaint.setStyle(Paint.Style.FILL); - mSelectPaint.setColor(res.getColor(R.color.filtershow_category_selection)); - mBorderPaint = new Paint(mSelectPaint); - mBorderPaint.setColor(Color.BLACK); - mBorderStroke = mSelectionStroke / 3; - } - - private void computeTextPosition(String text) { - if (text == null) { - return; - } - mPaint.setTextSize(mTextSize); - if (mOrientation == VERTICAL) { - text = text.toUpperCase(); - // TODO: set this in xml - mPaint.setTypeface(Typeface.DEFAULT_BOLD); - } - mPaint.getTextBounds(text, 0, text.length(), mTextBounds); - } - - public void drawText(Canvas canvas, String text) { - if (text == null) { - return; - } - float textWidth = mPaint.measureText(text); - int x = (int) (canvas.getWidth() - textWidth - mMargin); - if (mOrientation == HORIZONTAL) { - x = (int) ((canvas.getWidth() - textWidth) / 2.0f); - } - if (x < 0) { - // If the text takes more than the view width, - // justify to the left. - x = mMargin; - } - int y = canvas.getHeight() - mMargin; - canvas.drawText(text, x, y, mPaint); - } - - @Override - public CharSequence getContentDescription () { - if (mAction != null) { - return mAction.getName(); - } - return null; - } - - @Override - public void onDraw(Canvas canvas) { - canvas.drawColor(mBackgroundColor); - if (mAction != null) { - mPaint.reset(); - mPaint.setAntiAlias(true); - computeTextPosition(mAction.getName()); - if (mAction.getImage() == null) { - mAction.setImageFrame(new Rect(0, 0, getWidth(), getHeight()), mOrientation); - } else { - Bitmap bitmap = mAction.getImage(); - canvas.save(); - Rect clipRect = new Rect(mSelectionStroke, mSelectionStroke, - getWidth() - mSelectionStroke, - getHeight() - 2* mMargin - mTextSize); - int offsetx = 0; - int offsety = 0; - if (mOrientation == HORIZONTAL) { - canvas.clipRect(clipRect); - offsetx = - (bitmap.getWidth() - clipRect.width()) / 2; - offsety = - (bitmap.getHeight() - clipRect.height()) / 2; - } - canvas.drawBitmap(bitmap, offsetx, offsety, mPaint); - canvas.restore(); - if (mAdapter.isSelected(this)) { - if (mOrientation == HORIZONTAL) { - SelectionRenderer.drawSelection(canvas, 0, 0, - getWidth(), getHeight() - mMargin - mTextSize, - mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint); - } else { - SelectionRenderer.drawSelection(canvas, 0, 0, - Math.min(bitmap.getWidth(), getWidth()), - Math.min(bitmap.getHeight(), getHeight()), - mSelectionStroke, mSelectPaint, mBorderStroke, mBorderPaint); - } - } - } - mPaint.setColor(mBackgroundColor); - mPaint.setStyle(Paint.Style.STROKE); - mPaint.setStrokeWidth(3); - drawText(canvas, mAction.getName()); - mPaint.setColor(mTextColor); - mPaint.setStyle(Paint.Style.FILL); - mPaint.setStrokeWidth(1); - drawText(canvas, mAction.getName()); - } - } - - public void setAction(Action action, CategoryAdapter adapter) { - mAction = action; - mAdapter = adapter; - invalidate(); - } - - public FilterRepresentation getRepresentation() { - return mAction.getRepresentation(); - } - - @Override - public void onClick(View view) { - FilterShowActivity activity = (FilterShowActivity) getContext(); - activity.showRepresentation(mAction.getRepresentation()); - mAdapter.setSelected(this); - } - - public void setOrientation(int orientation) { - mOrientation = orientation; - } -} diff --git a/src/com/android/gallery3d/filtershow/category/MainPanel.java b/src/com/android/gallery3d/filtershow/category/MainPanel.java deleted file mode 100644 index 9a64ffbf3..000000000 --- a/src/com/android/gallery3d/filtershow/category/MainPanel.java +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.category; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.state.StatePanel; - -public class MainPanel extends Fragment { - - private static final String LOGTAG = "MainPanel"; - - private LinearLayout mMainView; - private ImageButton looksButton; - private ImageButton bordersButton; - private ImageButton geometryButton; - private ImageButton filtersButton; - - public static final String FRAGMENT_TAG = "MainPanel"; - public static final int LOOKS = 0; - public static final int BORDERS = 1; - public static final int GEOMETRY = 2; - public static final int FILTERS = 3; - - private int mCurrentSelected = -1; - - private void selection(int position, boolean value) { - if (value) { - FilterShowActivity activity = (FilterShowActivity) getActivity(); - activity.setCurrentPanel(position); - } - switch (position) { - case LOOKS: { - looksButton.setSelected(value); - break; - } - case BORDERS: { - bordersButton.setSelected(value); - break; - } - case GEOMETRY: { - geometryButton.setSelected(value); - break; - } - case FILTERS: { - filtersButton.setSelected(value); - break; - } - } - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - if (mMainView != null) { - if (mMainView.getParent() != null) { - ViewGroup parent = (ViewGroup) mMainView.getParent(); - parent.removeView(mMainView); - } - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - - mMainView = (LinearLayout) inflater.inflate( - R.layout.filtershow_main_panel, null, false); - - looksButton = (ImageButton) mMainView.findViewById(R.id.fxButton); - bordersButton = (ImageButton) mMainView.findViewById(R.id.borderButton); - geometryButton = (ImageButton) mMainView.findViewById(R.id.geometryButton); - filtersButton = (ImageButton) mMainView.findViewById(R.id.colorsButton); - - looksButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(LOOKS); - } - }); - bordersButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(BORDERS); - } - }); - geometryButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(GEOMETRY); - } - }); - filtersButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showPanel(FILTERS); - } - }); - - FilterShowActivity activity = (FilterShowActivity) getActivity(); - showImageStatePanel(activity.isShowingImageStatePanel()); - showPanel(activity.getCurrentPanel()); - return mMainView; - } - - private boolean isRightAnimation(int newPos) { - if (newPos < mCurrentSelected) { - return false; - } - return true; - } - - private void setCategoryFragment(CategoryPanel category, boolean fromRight) { - FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); - if (fromRight) { - transaction.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_right); - } else { - transaction.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_left); - } - transaction.replace(R.id.category_panel_container, category, CategoryPanel.FRAGMENT_TAG); - transaction.commit(); - } - - public void loadCategoryLookPanel() { - if (mCurrentSelected == LOOKS) { - return; - } - boolean fromRight = isRightAnimation(LOOKS); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(LOOKS); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = LOOKS; - selection(mCurrentSelected, true); - } - - public void loadCategoryBorderPanel() { - if (mCurrentSelected == BORDERS) { - return; - } - boolean fromRight = isRightAnimation(BORDERS); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(BORDERS); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = BORDERS; - selection(mCurrentSelected, true); - } - - public void loadCategoryGeometryPanel() { - if (mCurrentSelected == GEOMETRY) { - return; - } - boolean fromRight = isRightAnimation(GEOMETRY); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(GEOMETRY); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = GEOMETRY; - selection(mCurrentSelected, true); - } - - public void loadCategoryFiltersPanel() { - if (mCurrentSelected == FILTERS) { - return; - } - boolean fromRight = isRightAnimation(FILTERS); - selection(mCurrentSelected, false); - CategoryPanel categoryPanel = new CategoryPanel(); - categoryPanel.setAdapter(FILTERS); - setCategoryFragment(categoryPanel, fromRight); - mCurrentSelected = FILTERS; - selection(mCurrentSelected, true); - } - - public void showPanel(int currentPanel) { - switch (currentPanel) { - case LOOKS: { - loadCategoryLookPanel(); - break; - } - case BORDERS: { - loadCategoryBorderPanel(); - break; - } - case GEOMETRY: { - loadCategoryGeometryPanel(); - break; - } - case FILTERS: { - loadCategoryFiltersPanel(); - break; - } - } - } - - public void showImageStatePanel(boolean show) { - if (mMainView.findViewById(R.id.state_panel_container) == null) { - return; - } - FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); - final View container = mMainView.findViewById(R.id.state_panel_container); - if (show) { - container.setVisibility(View.VISIBLE); - StatePanel statePanel = new StatePanel(); - transaction.replace(R.id.state_panel_container, statePanel, StatePanel.FRAGMENT_TAG); - } else { - container.setVisibility(View.GONE); - Fragment statePanel = getChildFragmentManager().findFragmentByTag(StatePanel.FRAGMENT_TAG); - if (statePanel != null) { - transaction.remove(statePanel); - } - } - transaction.commit(); - } -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java deleted file mode 100644 index dd4df7dc8..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/ColorGridDialog.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.colorpicker; - -import android.app.Dialog; -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.GradientDrawable; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class ColorGridDialog extends Dialog { - RGBListener mCallback; - private static final String LOGTAG = "ColorGridDialog"; - - public ColorGridDialog(Context context, final RGBListener cl) { - super(context); - mCallback = cl; - setTitle(R.string.color_pick_title); - setContentView(R.layout.filtershow_color_gird); - Button sel = (Button) findViewById(R.id.filtershow_cp_custom); - ArrayList<Button> b = getButtons((ViewGroup) getWindow().getDecorView()); - int k = 0; - float[] hsv = new float[3]; - - for (Button button : b) { - if (!button.equals(sel)){ - hsv[0] = (k % 5) * 360 / 5; - hsv[1] = (k / 5) / 3.0f; - hsv[2] = (k < 5) ? (k / 4f) : 1; - final int c = (Color.HSVToColor(hsv) & 0x00FFFFFF) | 0xAA000000; - GradientDrawable sd = ((GradientDrawable) button.getBackground()); - button.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mCallback.setColor(c); - dismiss(); - } - }); - sd.setColor(c); - k++; - } - - } - sel.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - showColorPicker(); - ColorGridDialog.this.dismiss(); - } - }); - } - - private ArrayList<Button> getButtons(ViewGroup vg) { - ArrayList<Button> list = new ArrayList<Button>(); - for (int i = 0; i < vg.getChildCount(); i++) { - View v = vg.getChildAt(i); - if (v instanceof Button) { - list.add((Button) v); - } else if (v instanceof ViewGroup) { - list.addAll(getButtons((ViewGroup) v)); - } - } - return list; - } - - public void showColorPicker() { - ColorListener cl = new ColorListener() { - @Override - public void setColor(float[] hsvo) { - int c = Color.HSVToColor(hsvo) & 0xFFFFFF; - int alpha = (int) (hsvo[3] * 255); - c |= alpha << 24; - mCallback.setColor(c); - } - }; - ColorPickerDialog cpd = new ColorPickerDialog(this.getContext(), cl); - cpd.show(); - } - -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java deleted file mode 100644 index 5127dad26..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/ColorListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.colorpicker; - -public interface ColorListener { - void setColor(float[] hsvo); -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java deleted file mode 100644 index 2bff501f7..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/ColorOpacityView.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.colorpicker; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapShader; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.LinearGradient; -import android.graphics.Paint; -import android.graphics.RadialGradient; -import android.graphics.Shader; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class ColorOpacityView extends View implements ColorListener { - - private float mRadius; - private float mWidth; - private Paint mBarPaint1; - private Paint mLinePaint1; - private Paint mLinePaint2; - private Paint mCheckPaint; - - private float mHeight; - private Paint mDotPaint; - private int mBgcolor = 0; - - private float mDotRadius; - private float mBorder; - - private float[] mHSVO = new float[4]; - private int mSliderColor; - private float mDotX = mBorder; - private float mDotY = mBorder; - private final static float DOT_SIZE = ColorRectView.DOT_SIZE; - public final static float BORDER_SIZE = 20;; - - public ColorOpacityView(Context ctx, AttributeSet attrs) { - super(ctx, attrs); - DisplayMetrics metrics = ctx.getResources().getDisplayMetrics(); - float mDpToPix = metrics.density; - mDotRadius = DOT_SIZE * mDpToPix; - mBorder = BORDER_SIZE * mDpToPix; - mBarPaint1 = new Paint(); - - mDotPaint = new Paint(); - - mDotPaint.setStyle(Paint.Style.FILL); - mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color)); - mSliderColor = ctx.getResources().getColor(R.color.slider_line_color); - - mBarPaint1.setStyle(Paint.Style.FILL); - - mLinePaint1 = new Paint(); - mLinePaint1.setColor(Color.GRAY); - mLinePaint2 = new Paint(); - mLinePaint2.setColor(mSliderColor); - mLinePaint2.setStrokeWidth(4); - - int[] colors = new int[16 * 16]; - for (int i = 0; i < colors.length; i++) { - int y = i / (16 * 8); - int x = (i / 8) % 2; - colors[i] = (x == y) ? 0xFFAAAAAA : 0xFF444444; - } - Bitmap bitmap = Bitmap.createBitmap(colors, 16, 16, Bitmap.Config.ARGB_8888); - BitmapShader bs = new BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT); - mCheckPaint = new Paint(); - mCheckPaint.setShader(bs); - } - - public boolean onDown(MotionEvent e) { - return true; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - float ox = mDotX; - float oy = mDotY; - - float x = event.getX(); - float y = event.getY(); - - mDotX = x; - - if (mDotX < mBorder) { - mDotX = mBorder; - } - - if (mDotX > mWidth - mBorder) { - mDotX = mWidth - mBorder; - } - mHSVO[3] = (mDotX - mBorder) / (mWidth - mBorder * 2); - notifyColorListeners(mHSVO); - setupButton(); - invalidate((int) (ox - mDotRadius), (int) (oy - mDotRadius), (int) (ox + mDotRadius), - (int) (oy + mDotRadius)); - invalidate( - (int) (mDotX - mDotRadius), (int) (mDotY - mDotRadius), (int) (mDotX + mDotRadius), - (int) (mDotY + mDotRadius)); - - return true; - } - - private void setupButton() { - float pos = mHSVO[3] * (mWidth - mBorder * 2); - mDotX = pos + mBorder; - - int[] colors3 = new int[] { - mSliderColor, mSliderColor, 0x66000000, 0 }; - RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadius, colors3, new float[] { - 0, .3f, .31f, 1 }, Shader.TileMode.CLAMP); - mDotPaint.setShader(g); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - mWidth = w; - mHeight = h; - mDotY = mHeight / 2; - updatePaint(); - setupButton(); - } - - private void updatePaint() { - - int color2 = Color.HSVToColor(mHSVO); - int color1 = color2 & 0xFFFFFF; - - Shader sg = new LinearGradient( - mBorder, mBorder, mWidth - mBorder, mBorder, color1, color2, Shader.TileMode.CLAMP); - mBarPaint1.setShader(sg); - - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - canvas.drawColor(mBgcolor); - canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mCheckPaint); - canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mBarPaint1); - canvas.drawLine(mDotX, mDotY, mWidth - mBorder, mDotY, mLinePaint1); - canvas.drawLine(mBorder, mDotY, mDotX, mDotY, mLinePaint2); - if (mDotX != Float.NaN) { - canvas.drawCircle(mDotX, mDotY, mDotRadius, mDotPaint); - } - } - - @Override - public void setColor(float[] hsv) { - System.arraycopy(hsv, 0, mHSVO, 0, mHSVO.length); - - float oy = mDotY; - - updatePaint(); - setupButton(); - invalidate(); - } - - ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>(); - - public void notifyColorListeners(float[] hsvo) { - for (ColorListener l : mColorListeners) { - l.setColor(hsvo); - } - } - - public void addColorListener(ColorListener l) { - mColorListeners.add(l); - } - - public void removeColorListener(ColorListener l) { - mColorListeners.remove(l); - } -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java deleted file mode 100644 index 73a5c907c..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/ColorPickerDialog.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.colorpicker; - -import android.app.Dialog; -import android.content.Context; -import android.graphics.Color; -import android.graphics.drawable.GradientDrawable; -import android.view.View; -import android.widget.Button; -import android.widget.ToggleButton; - -import com.android.gallery3d.R; - -public class ColorPickerDialog extends Dialog implements ColorListener { - ToggleButton mSelectedButton; - GradientDrawable mSelectRect; - - float[] mHSVO = new float[4]; - - public ColorPickerDialog(Context context, final ColorListener cl) { - super(context); - - setContentView(R.layout.filtershow_color_picker); - ColorValueView csv = (ColorValueView) findViewById(R.id.colorValueView); - ColorRectView cwv = (ColorRectView) findViewById(R.id.colorRectView); - ColorOpacityView cvv = (ColorOpacityView) findViewById(R.id.colorOpacityView); - float[] hsvo = new float[] { - 123, .9f, 1, 1 }; - - mSelectRect = (GradientDrawable) getContext() - .getResources().getDrawable(R.drawable.filtershow_color_picker_roundrect); - Button selButton = (Button) findViewById(R.id.btnSelect); - selButton.setCompoundDrawablesWithIntrinsicBounds(null, null, mSelectRect, null); - Button sel = (Button) findViewById(R.id.btnSelect); - - sel.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - ColorPickerDialog.this.dismiss(); - if (cl != null) { - cl.setColor(mHSVO); - } - } - }); - - cwv.setColor(hsvo); - cvv.setColor(hsvo); - csv.setColor(hsvo); - csv.addColorListener(cwv); - cwv.addColorListener(csv); - csv.addColorListener(cvv); - cwv.addColorListener(cvv); - cvv.addColorListener(cwv); - cvv.addColorListener(csv); - cvv.addColorListener(this); - csv.addColorListener(this); - cwv.addColorListener(this); - - } - - void toggleClick(ToggleButton v, int[] buttons, boolean isChecked) { - int id = v.getId(); - if (!isChecked) { - mSelectedButton = null; - return; - } - for (int i = 0; i < buttons.length; i++) { - if (id != buttons[i]) { - ToggleButton b = (ToggleButton) findViewById(buttons[i]); - b.setChecked(false); - } - } - mSelectedButton = v; - - float[] hsv = (float[]) v.getTag(); - - ColorValueView csv = (ColorValueView) findViewById(R.id.colorValueView); - ColorRectView cwv = (ColorRectView) findViewById(R.id.colorRectView); - ColorOpacityView cvv = (ColorOpacityView) findViewById(R.id.colorOpacityView); - cwv.setColor(hsv); - cvv.setColor(hsv); - csv.setColor(hsv); - } - - @Override - public void setColor(float[] hsvo) { - System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length); - int color = Color.HSVToColor(hsvo); - mSelectRect.setColor(color); - setButtonColor(mSelectedButton, hsvo); - } - - private void setButtonColor(ToggleButton button, float[] hsv) { - if (button == null) { - return; - } - int color = Color.HSVToColor(hsv); - button.setBackgroundColor(color); - float[] fg = new float[] { - (hsv[0] + 180) % 360, - hsv[1], - (hsv[2] > .5f) ? .1f : .9f - }; - button.setTextColor(Color.HSVToColor(fg)); - button.setTag(hsv); - } - -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java deleted file mode 100644 index 07d7c7126..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/ColorRectView.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.colorpicker; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.LinearGradient; -import android.graphics.Paint; -import android.graphics.RadialGradient; -import android.graphics.RectF; -import android.graphics.Shader; -import android.graphics.SweepGradient; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class ColorRectView extends View implements ColorListener { - private float mDpToPix; - private float mRadius = 80; - private float mCtrY = 100; - private Paint mWheelPaint1; - private Paint mWheelPaint2; - private Paint mWheelPaint3; - private float mCtrX = 100; - private Paint mDotPaint; - private float mDotRadus; - private float mBorder; - private int mBgcolor = 0; - private float mDotX = Float.NaN; - private float mDotY; - private int mSliderColor = 0xFF33B5E5; - private float[] mHSVO = new float[4]; - private int[] mColors = new int[] { - 0xFFFF0000,// red - 0xFFFFFF00,// yellow - 0xFF00FF00,// green - 0xFF00FFFF,// cyan - 0xFF0000FF,// blue - 0xFFFF00FF,// magenta - 0xFFFF0000,// red - }; - private int mWidth; - private int mHeight; - public final static float DOT_SIZE = 20; - public final static float BORDER_SIZE = 10; - - public ColorRectView(Context ctx, AttributeSet attrs) { - super(ctx, attrs); - - DisplayMetrics metrics = ctx.getResources().getDisplayMetrics(); - mDpToPix = metrics.density; - mDotRadus = DOT_SIZE * mDpToPix; - mBorder = BORDER_SIZE * mDpToPix; - - mWheelPaint1 = new Paint(); - mWheelPaint2 = new Paint(); - mWheelPaint3 = new Paint(); - mDotPaint = new Paint(); - - mDotPaint.setStyle(Paint.Style.FILL); - mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color)); - mSliderColor = ctx.getResources().getColor(R.color.slider_line_color); - mWheelPaint1.setStyle(Paint.Style.FILL); - mWheelPaint2.setStyle(Paint.Style.FILL); - mWheelPaint3.setStyle(Paint.Style.FILL); - } - - public boolean onDown(MotionEvent e) { - return true; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - - invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus), - (int) (mDotY + mDotRadus)); - float x = event.getX(); - float y = event.getY(); - - x = Math.max(Math.min(x, mWidth - mBorder), mBorder); - y = Math.max(Math.min(y, mHeight - mBorder), mBorder); - mDotX = x; - mDotY = y; - float sat = 1 - (mDotY - mBorder) / (mHeight - 2 * mBorder); - if (sat > 1) { - sat = 1; - } - - double hue = Math.PI * 2 * (mDotX - mBorder) / (mHeight - 2 * mBorder); - mHSVO[0] = ((float) Math.toDegrees(hue) + 360) % 360; - mHSVO[1] = sat; - notifyColorListeners(mHSVO); - updateDotPaint(); - invalidate((int) (mDotX - mDotRadus), (int) (mDotY - mDotRadus), (int) (mDotX + mDotRadus), - (int) (mDotY + mDotRadus)); - - return true; - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - mWidth = w; - mHeight = h; - mCtrY = h / 2f; - mCtrX = w / 2f; - mRadius = Math.min(mCtrY, mCtrX) - 2 * mBorder; - setUpColorPanel(); - } - - private void setUpColorPanel() { - float val = mHSVO[2]; - int v = 0xFF000000 | 0x10101 * (int) (val * 0xFF); - int[] colors = new int[] { - 0x0000000, v }; - int[] colors2 = new int[] { - 0x0000000, 0xFF000000 }; - int[] wheelColor = new int[mColors.length]; - float[] hsv = new float[3]; - for (int i = 0; i < wheelColor.length; i++) { - Color.colorToHSV(mColors[i], hsv); - hsv[2] = mHSVO[2]; - wheelColor[i] = Color.HSVToColor(hsv); - } - updateDot(); - updateDotPaint(); - SweepGradient sg = new SweepGradient(mCtrX, mCtrY, wheelColor, null); - LinearGradient lg = new LinearGradient( - mBorder, 0, mWidth - mBorder, 0, wheelColor, null, Shader.TileMode.CLAMP); - - mWheelPaint1.setShader(lg); - LinearGradient rg = new LinearGradient( - 0, mBorder, 0, mHeight - mBorder, colors, null, Shader.TileMode.CLAMP); - mWheelPaint2.setShader(rg); - LinearGradient rg2 = new LinearGradient( - 0, mBorder, 0, mHeight - mBorder, colors2, null, Shader.TileMode.CLAMP); - mWheelPaint3.setShader(rg2); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - canvas.drawColor(mBgcolor); - RectF rect = new RectF(); - rect.left = mBorder; - rect.right = mWidth - mBorder; - rect.top = mBorder; - rect.bottom = mHeight - mBorder; - - canvas.drawRect(rect, mWheelPaint1); - canvas.drawRect(rect, mWheelPaint3); - canvas.drawRect(rect, mWheelPaint2); - - if (mDotX != Float.NaN) { - - canvas.drawCircle(mDotX, mDotY, mDotRadus, mDotPaint); - } - } - - private void updateDot() { - - double hue = mHSVO[0]; - double sat = mHSVO[1]; - - mDotX = (float) (mBorder + (mHeight - 2 * mBorder) * Math.toRadians(hue) / (Math.PI * 2)); - mDotY = (float) ((1 - sat) * (mHeight - 2 * mBorder) + mBorder); - - } - - private void updateDotPaint() { - int[] colors3 = new int[] { - mSliderColor, mSliderColor, 0x66000000, 0 }; - RadialGradient g = new RadialGradient(mDotX, mDotY, mDotRadus, colors3, new float[] { - 0, .3f, .31f, 1 }, Shader.TileMode.CLAMP); - mDotPaint.setShader(g); - - } - - @Override - public void setColor(float[] hsvo) { - System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length); - - setUpColorPanel(); - invalidate(); - - updateDot(); - updateDotPaint(); - - } - - ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>(); - - public void notifyColorListeners(float[] hsv) { - for (ColorListener l : mColorListeners) { - l.setColor(hsv); - } - } - - public void addColorListener(ColorListener l) { - mColorListeners.add(l); - } - - public void removeColorListener(ColorListener l) { - mColorListeners.remove(l); - } -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java b/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java deleted file mode 100644 index 13cb44bad..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/ColorValueView.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.colorpicker; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.LinearGradient; -import android.graphics.Paint; -import android.graphics.RadialGradient; -import android.graphics.Shader; -import android.util.AttributeSet; -import android.util.DisplayMetrics; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class ColorValueView extends View implements ColorListener { - - private float mRadius; - private float mWidth; - private Paint mBarPaint1; - private Paint mLinePaint1; - private Paint mLinePaint2; - private float mHeight; - private int mBgcolor = 0; - private Paint mDotPaint; - private float dotRadus; - private float mBorder; - - private float[] mHSVO = new float[4]; - private int mSliderColor; - private float mDotX; - private float mDotY = mBorder; - private final static float DOT_SIZE = ColorRectView.DOT_SIZE; - private final static float BORDER_SIZE = ColorRectView.DOT_SIZE; - - public ColorValueView(Context ctx, AttributeSet attrs) { - super(ctx, attrs); - DisplayMetrics metrics = ctx.getResources().getDisplayMetrics(); - float mDpToPix = metrics.density; - dotRadus = DOT_SIZE * mDpToPix; - mBorder = BORDER_SIZE * mDpToPix; - - mBarPaint1 = new Paint(); - - mDotPaint = new Paint(); - - mDotPaint.setStyle(Paint.Style.FILL); - mDotPaint.setColor(ctx.getResources().getColor(R.color.slider_dot_color)); - - mBarPaint1.setStyle(Paint.Style.FILL); - - mLinePaint1 = new Paint(); - mLinePaint1.setColor(Color.GRAY); - mLinePaint2 = new Paint(); - mSliderColor = ctx.getResources().getColor(R.color.slider_line_color); - mLinePaint2.setColor(mSliderColor); - mLinePaint2.setStrokeWidth(4); - } - - public boolean onDown(MotionEvent e) { - return true; - } - - public boolean onTouchEvent(MotionEvent event) { - float ox = mDotX; - float oy = mDotY; - - float x = event.getX(); - float y = event.getY(); - - mDotY = y; - - if (mDotY < mBorder) { - mDotY = mBorder; - } - - if (mDotY > mHeight - mBorder) { - mDotY = mHeight - mBorder; - } - mHSVO[2] = (mDotY - mBorder) / (mHeight - mBorder * 2); - notifyColorListeners(mHSVO); - setupButton(); - invalidate((int) (ox - dotRadus), (int) (oy - dotRadus), (int) (ox + dotRadus), - (int) (oy + dotRadus)); - invalidate((int) (mDotX - dotRadus), (int) (mDotY - dotRadus), (int) (mDotX + dotRadus), - (int) (mDotY + dotRadus)); - - return true; - } - - private void setupButton() { - float pos = mHSVO[2] * (mHeight - mBorder * 2); - mDotY = pos + mBorder; - - int[] colors3 = new int[] { - mSliderColor, mSliderColor, 0x66000000, 0 }; - RadialGradient g = new RadialGradient(mDotX, mDotY, dotRadus, colors3, new float[] { - 0, .3f, .31f, 1 }, Shader.TileMode.CLAMP); - mDotPaint.setShader(g); - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - mWidth = w; - mHeight = h; - mDotX = mWidth / 2; - updatePaint(); - setupButton(); - } - - private void updatePaint() { - float[] hsv = new float[] { - mHSVO[0], mHSVO[1], 0f }; - int color1 = Color.HSVToColor(hsv); - hsv[2] = 1; - int color2 = Color.HSVToColor(hsv); - - Shader sg = new LinearGradient(mBorder, mBorder, mBorder, mHeight - mBorder, color1, color2, - Shader.TileMode.CLAMP); - mBarPaint1.setShader(sg); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - canvas.drawColor(mBgcolor); - canvas.drawRect(mBorder, mBorder, mWidth - mBorder, mHeight - mBorder, mBarPaint1); - canvas.drawLine(mDotX, mDotY, mDotX, mHeight - mBorder, mLinePaint2); - canvas.drawLine(mDotX, mBorder, mDotX, mDotY, mLinePaint1); - if (mDotX != Float.NaN) { - canvas.drawCircle(mDotX, mDotY, dotRadus, mDotPaint); - } - } - - @Override - public void setColor(float[] hsvo) { - System.arraycopy(hsvo, 0, mHSVO, 0, mHSVO.length); - - float oy = mDotY; - updatePaint(); - setupButton(); - invalidate(); - - } - - ArrayList<ColorListener> mColorListeners = new ArrayList<ColorListener>(); - - public void notifyColorListeners(float[] hsv) { - for (ColorListener l : mColorListeners) { - l.setColor(hsv); - } - } - - public void addColorListener(ColorListener l) { - mColorListeners.add(l); - } - - public void removeColorListener(ColorListener l) { - mColorListeners.remove(l); - } -} diff --git a/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java b/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java deleted file mode 100644 index 147fb91a4..000000000 --- a/src/com/android/gallery3d/filtershow/colorpicker/RGBListener.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.colorpicker; - -public interface RGBListener { - void setColor(int hsv); -} diff --git a/src/com/android/gallery3d/filtershow/controller/ActionSlider.java b/src/com/android/gallery3d/filtershow/controller/ActionSlider.java deleted file mode 100644 index f80a1cacb..000000000 --- a/src/com/android/gallery3d/filtershow/controller/ActionSlider.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.ViewGroup; -import android.widget.ImageButton; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.Editor; - -public class ActionSlider extends TitledSlider { - private static final String LOGTAG = "ActionSlider"; - ImageButton mLeftButton; - ImageButton mRightButton; - public ActionSlider() { - mLayoutID = R.layout.filtershow_control_action_slider; - } - - @Override - public void setUp(ViewGroup container, Parameter parameter, Editor editor) { - super.setUp(container, parameter, editor); - mLeftButton = (ImageButton) mTopView.findViewById(R.id.leftActionButton); - mLeftButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - ((ParameterActionAndInt) mParameter).fireLeftAction(); - } - }); - - mRightButton = (ImageButton) mTopView.findViewById(R.id.rightActionButton); - mRightButton.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View v) { - ((ParameterActionAndInt) mParameter).fireRightAction(); - } - }); - updateUI(); - } - - @Override - public void updateUI() { - super.updateUI(); - if (mLeftButton != null) { - int iconId = ((ParameterActionAndInt) mParameter).getLeftIcon(); - mLeftButton.setImageResource(iconId); - } - if (mRightButton != null) { - int iconId = ((ParameterActionAndInt) mParameter).getRightIcon(); - mRightButton.setImageResource(iconId); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java b/src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java deleted file mode 100644 index 92145e9be..000000000 --- a/src/com/android/gallery3d/filtershow/controller/BasicParameterInt.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import android.util.Log; - -public class BasicParameterInt implements ParameterInteger { - protected String mParameterName; - protected Control mControl; - protected int mMaximum = 100; - protected int mMinimum = 0; - protected int mDefaultValue; - protected int mValue; - public final int ID; - protected FilterView mEditor; - private final String LOGTAG = "BasicParameterInt"; - - @Override - public void copyFrom(Parameter src) { - if (!(src instanceof BasicParameterInt)) { - throw new IllegalArgumentException(src.getClass().getName()); - } - BasicParameterInt p = (BasicParameterInt) src; - mMaximum = p.mMaximum; - mMinimum = p.mMinimum; - mDefaultValue = p.mDefaultValue; - mValue = p.mValue; - } - - public BasicParameterInt(int id, int value) { - ID = id; - mValue = value; - } - - public BasicParameterInt(int id, int value, int min, int max) { - ID = id; - mValue = value; - mMinimum = min; - mMaximum = max; - } - - @Override - public String getParameterName() { - return mParameterName; - } - - @Override - public String getParameterType() { - return sParameterType; - } - - @Override - public String getValueString() { - return mParameterName + mValue; - } - - @Override - public void setController(Control control) { - mControl = control; - } - - @Override - public int getMaximum() { - return mMaximum; - } - - @Override - public int getMinimum() { - return mMinimum; - } - - @Override - public int getDefaultValue() { - return mDefaultValue; - } - - @Override - public int getValue() { - return mValue; - } - - @Override - public void setValue(int value) { - mValue = value; - if (mEditor != null) { - mEditor.commitLocalRepresentation(); - } - } - - @Override - public String toString() { - return getValueString(); - } - - @Override - public void setFilterView(FilterView editor) { - mEditor = editor; - } -} diff --git a/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java b/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java deleted file mode 100644 index fb9f95e97..000000000 --- a/src/com/android/gallery3d/filtershow/controller/BasicParameterStyle.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import android.content.Context; - -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; - -public class BasicParameterStyle implements ParameterStyles { - protected String mParameterName; - protected int mSelectedStyle; - protected int mNumberOfStyles; - protected int mDefaultStyle = 0; - protected Control mControl; - protected FilterView mEditor; - public final int ID; - private final String LOGTAG = "BasicParameterStyle"; - - @Override - public void copyFrom(Parameter src) { - if (!(src instanceof BasicParameterStyle)) { - throw new IllegalArgumentException(src.getClass().getName()); - } - BasicParameterStyle p = (BasicParameterStyle) src; - mNumberOfStyles = p.mNumberOfStyles; - mSelectedStyle = p.mSelectedStyle; - mDefaultStyle = p.mDefaultStyle; - } - - public BasicParameterStyle(int id, int numberOfStyles) { - ID = id; - mNumberOfStyles = numberOfStyles; - } - - @Override - public String getParameterName() { - return mParameterName; - } - - @Override - public String getParameterType() { - return sParameterType; - } - - @Override - public String getValueString() { - return mParameterName + mSelectedStyle; - } - - @Override - public void setController(Control control) { - mControl = control; - } - - @Override - public int getNumberOfStyles() { - return mNumberOfStyles; - } - - @Override - public int getDefaultSelected() { - return mDefaultStyle; - } - - @Override - public int getSelected() { - return mSelectedStyle; - } - - @Override - public void setSelected(int selectedStyle) { - mSelectedStyle = selectedStyle; - if (mEditor != null) { - mEditor.commitLocalRepresentation(); - } - } - - @Override - public void getIcon(int index, RenderingRequestCaller caller) { - mEditor.computeIcon(index, caller); - } - - @Override - public String getStyleTitle(int index, Context context) { - return ""; - } - - @Override - public String toString() { - return getValueString(); - } - - @Override - public void setFilterView(FilterView editor) { - mEditor = editor; - } -} diff --git a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java b/src/com/android/gallery3d/filtershow/controller/BasicSlider.java deleted file mode 100644 index 9d8278d52..000000000 --- a/src/com/android/gallery3d/filtershow/controller/BasicSlider.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.Editor; - -public class BasicSlider implements Control { - private SeekBar mSeekBar; - private ParameterInteger mParameter; - Editor mEditor; - - @Override - public void setUp(ViewGroup container, Parameter parameter, Editor editor) { - container.removeAllViews(); - mEditor = editor; - Context context = container.getContext(); - mParameter = (ParameterInteger) parameter; - LayoutInflater inflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - LinearLayout lp = (LinearLayout) inflater.inflate( - R.layout.filtershow_seekbar, container, true); - mSeekBar = (SeekBar) lp.findViewById(R.id.primarySeekBar); - - updateUI(); - mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (mParameter != null) { - mParameter.setValue(progress + mParameter.getMinimum()); - mEditor.commitLocalRepresentation(); - - } - } - }); - } - - @Override - public View getTopView() { - return mSeekBar; - } - - @Override - public void setPrameter(Parameter parameter) { - mParameter = (ParameterInteger) parameter; - if (mSeekBar != null) { - updateUI(); - } - } - - @Override - public void updateUI() { - mSeekBar.setMax(mParameter.getMaximum() - mParameter.getMinimum()); - mSeekBar.setProgress(mParameter.getValue() - mParameter.getMinimum()); - } -} diff --git a/src/com/android/gallery3d/filtershow/controller/Control.java b/src/com/android/gallery3d/filtershow/controller/Control.java deleted file mode 100644 index 43422904c..000000000 --- a/src/com/android/gallery3d/filtershow/controller/Control.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import android.view.View; -import android.view.ViewGroup; - -import com.android.gallery3d.filtershow.editors.Editor; - -public interface Control { - public void setUp(ViewGroup container, Parameter parameter, Editor editor); - - public View getTopView(); - - public void setPrameter(Parameter parameter); - - public void updateUI(); -} diff --git a/src/com/android/gallery3d/filtershow/controller/FilterView.java b/src/com/android/gallery3d/filtershow/controller/FilterView.java deleted file mode 100644 index 9ca81dc35..000000000 --- a/src/com/android/gallery3d/filtershow/controller/FilterView.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; - -public interface FilterView { - public void computeIcon(int index, RenderingRequestCaller caller); - - public void commitLocalRepresentation(); -} diff --git a/src/com/android/gallery3d/filtershow/controller/Parameter.java b/src/com/android/gallery3d/filtershow/controller/Parameter.java deleted file mode 100644 index 8f4d5c0a5..000000000 --- a/src/com/android/gallery3d/filtershow/controller/Parameter.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import com.android.gallery3d.filtershow.editors.Editor; - -public interface Parameter { - String getParameterName(); - - String getParameterType(); - - String getValueString(); - - public void setController(Control c); - - public void setFilterView(FilterView editor); - - public void copyFrom(Parameter src); -} diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterActionAndInt.java b/src/com/android/gallery3d/filtershow/controller/ParameterActionAndInt.java deleted file mode 100644 index 8a05c3aa6..000000000 --- a/src/com/android/gallery3d/filtershow/controller/ParameterActionAndInt.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -public interface ParameterActionAndInt extends ParameterInteger { - static String sParameterType = "ParameterActionAndInt"; - - public void fireLeftAction(); - - public int getLeftIcon(); - - public void fireRightAction(); - - public int getRightIcon(); -} diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterInteger.java b/src/com/android/gallery3d/filtershow/controller/ParameterInteger.java deleted file mode 100644 index 0bfd20135..000000000 --- a/src/com/android/gallery3d/filtershow/controller/ParameterInteger.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -public interface ParameterInteger extends Parameter { - static String sParameterType = "ParameterInteger"; - - int getMaximum(); - - int getMinimum(); - - int getDefaultValue(); - - int getValue(); - - void setValue(int value); -} diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterSet.java b/src/com/android/gallery3d/filtershow/controller/ParameterSet.java deleted file mode 100644 index 6b50a4d0b..000000000 --- a/src/com/android/gallery3d/filtershow/controller/ParameterSet.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -public interface ParameterSet { - int getNumberOfParameters(); - - Parameter getFilterParameter(int index); -} diff --git a/src/com/android/gallery3d/filtershow/controller/ParameterStyles.java b/src/com/android/gallery3d/filtershow/controller/ParameterStyles.java deleted file mode 100644 index 7d250a0bf..000000000 --- a/src/com/android/gallery3d/filtershow/controller/ParameterStyles.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import android.content.Context; - -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; - -public interface ParameterStyles extends Parameter { - public static String sParameterType = "ParameterStyles"; - - int getNumberOfStyles(); - - int getDefaultSelected(); - - int getSelected(); - - void setSelected(int value); - - void getIcon(int index, RenderingRequestCaller caller); - - String getStyleTitle(int index, Context context); -} diff --git a/src/com/android/gallery3d/filtershow/controller/StyleChooser.java b/src/com/android/gallery3d/filtershow/controller/StyleChooser.java deleted file mode 100644 index fb613abc7..000000000 --- a/src/com/android/gallery3d/filtershow/controller/StyleChooser.java +++ /dev/null @@ -1,88 +0,0 @@ -package com.android.gallery3d.filtershow.controller; - -import android.app.ActionBar.LayoutParams; -import android.content.Context; -import android.graphics.Bitmap; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageButton; -import android.widget.ImageView.ScaleType; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.pipeline.RenderingRequest; -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; -import com.android.gallery3d.filtershow.editors.Editor; - -import java.util.Vector; - -public class StyleChooser implements Control { - private final String LOGTAG = "StyleChooser"; - protected ParameterStyles mParameter; - protected LinearLayout mLinearLayout; - protected Editor mEditor; - private View mTopView; - private Vector<ImageButton> mIconButton = new Vector<ImageButton>(); - protected int mLayoutID = R.layout.filtershow_control_style_chooser; - - @Override - public void setUp(ViewGroup container, Parameter parameter, Editor editor) { - container.removeAllViews(); - mEditor = editor; - Context context = container.getContext(); - mParameter = (ParameterStyles) parameter; - LayoutInflater inflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mTopView = inflater.inflate(mLayoutID, container, true); - mLinearLayout = (LinearLayout) mTopView.findViewById(R.id.listStyles); - mTopView.setVisibility(View.VISIBLE); - int n = mParameter.getNumberOfStyles(); - mIconButton.clear(); - LayoutParams lp = new LayoutParams(120, 120); - for (int i = 0; i < n; i++) { - final ImageButton button = new ImageButton(context); - button.setScaleType(ScaleType.CENTER_CROP); - button.setLayoutParams(lp); - button.setBackgroundResource(android.R.color.transparent); - mIconButton.add(button); - final int buttonNo = i; - button.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View arg0) { - mParameter.setSelected(buttonNo); - } - }); - mLinearLayout.addView(button); - mParameter.getIcon(i, new RenderingRequestCaller() { - @Override - public void available(RenderingRequest request) { - Bitmap bmap = request.getBitmap(); - if (bmap == null) { - return; - } - button.setImageBitmap(bmap); - } - }); - } - } - - @Override - public View getTopView() { - return mTopView; - } - - @Override - public void setPrameter(Parameter parameter) { - mParameter = (ParameterStyles) parameter; - updateUI(); - } - - @Override - public void updateUI() { - if (mParameter == null) { - return; - } - } - -} diff --git a/src/com/android/gallery3d/filtershow/controller/TitledSlider.java b/src/com/android/gallery3d/filtershow/controller/TitledSlider.java deleted file mode 100644 index f29442bb9..000000000 --- a/src/com/android/gallery3d/filtershow/controller/TitledSlider.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.controller; - -import android.content.Context; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.TextView; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.Editor; - -public class TitledSlider implements Control { - private final String LOGTAG = "ParametricEditor"; - private SeekBar mSeekBar; - private TextView mControlName; - private TextView mControlValue; - protected ParameterInteger mParameter; - Editor mEditor; - View mTopView; - protected int mLayoutID = R.layout.filtershow_control_title_slider; - - @Override - public void setUp(ViewGroup container, Parameter parameter, Editor editor) { - container.removeAllViews(); - mEditor = editor; - Context context = container.getContext(); - mParameter = (ParameterInteger) parameter; - LayoutInflater inflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - mTopView = inflater.inflate(mLayoutID, container, true); - mTopView.setVisibility(View.VISIBLE); - mSeekBar = (SeekBar) mTopView.findViewById(R.id.controlValueSeekBar); - mControlName = (TextView) mTopView.findViewById(R.id.controlName); - mControlValue = (TextView) mTopView.findViewById(R.id.controlValue); - updateUI(); - mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { - - @Override - public void onStopTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onStartTrackingTouch(SeekBar seekBar) { - } - - @Override - public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (mParameter != null) { - mParameter.setValue(progress + mParameter.getMinimum()); - if (mControlName != null) { - mControlName.setText(mParameter.getParameterName()); - } - if (mControlValue != null) { - mControlValue.setText(Integer.toString(mParameter.getValue())); - } - mEditor.commitLocalRepresentation(); - } - } - }); - } - - @Override - public void setPrameter(Parameter parameter) { - mParameter = (ParameterInteger) parameter; - if (mSeekBar != null) - updateUI(); - } - - @Override - public void updateUI() { - if (mControlName != null && mParameter.getParameterName() != null) { - mControlName.setText(mParameter.getParameterName().toUpperCase()); - } - if (mControlValue != null) { - mControlValue.setText( - Integer.toString(mParameter.getValue())); - } - mSeekBar.setMax(mParameter.getMaximum() - mParameter.getMinimum()); - mSeekBar.setProgress(mParameter.getValue() - mParameter.getMinimum()); - mEditor.commitLocalRepresentation(); - } - - @Override - public View getTopView() { - return mTopView; - } -} diff --git a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java b/src/com/android/gallery3d/filtershow/crop/BoundedRect.java deleted file mode 100644 index 13b8d6de1..000000000 --- a/src/com/android/gallery3d/filtershow/crop/BoundedRect.java +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.crop; - -import android.graphics.Matrix; -import android.graphics.Rect; -import android.graphics.RectF; - -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; - -import java.util.Arrays; - -/** - * Maintains invariant that inner rectangle is constrained to be within the - * outer, rotated rectangle. - */ -public class BoundedRect { - private float rot; - private RectF outer; - private RectF inner; - private float[] innerRotated; - - public BoundedRect(float rotation, Rect outerRect, Rect innerRect) { - rot = rotation; - outer = new RectF(outerRect); - inner = new RectF(innerRect); - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - public BoundedRect(float rotation, RectF outerRect, RectF innerRect) { - rot = rotation; - outer = new RectF(outerRect); - inner = new RectF(innerRect); - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - public void resetTo(float rotation, RectF outerRect, RectF innerRect) { - rot = rotation; - outer.set(outerRect); - inner.set(innerRect); - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - /** - * Sets inner, and re-constrains it to fit within the rotated bounding rect. - */ - public void setInner(RectF newInner) { - if (inner.equals(newInner)) - return; - inner = newInner; - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - /** - * Sets rotation, and re-constrains inner to fit within the rotated bounding rect. - */ - public void setRotation(float rotation) { - if (rotation == rot) - return; - rot = rotation; - innerRotated = CropMath.getCornersFromRect(inner); - rotateInner(); - if (!isConstrained()) - reconstrain(); - } - - public void setToInner(RectF r) { - r.set(inner); - } - - public void setToOuter(RectF r) { - r.set(outer); - } - - public RectF getInner() { - return new RectF(inner); - } - - public RectF getOuter() { - return new RectF(outer); - } - - /** - * Tries to move the inner rectangle by (dx, dy). If this would cause it to leave - * the bounding rectangle, snaps the inner rectangle to the edge of the bounding - * rectangle. - */ - public void moveInner(float dx, float dy) { - Matrix m0 = getInverseRotMatrix(); - - RectF translatedInner = new RectF(inner); - translatedInner.offset(dx, dy); - - float[] translatedInnerCorners = CropMath.getCornersFromRect(translatedInner); - float[] outerCorners = CropMath.getCornersFromRect(outer); - - m0.mapPoints(translatedInnerCorners); - float[] correction = { - 0, 0 - }; - - // find correction vectors for corners that have moved out of bounds - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) { - float[] badCorner = { - correctedInnerX, correctedInnerY - }; - float[] nearestSide = CropMath.closestSide(badCorner, outerCorners); - float[] correctionVec = - GeometryMathUtils.shortestVectorFromPointToLine(badCorner, nearestSide); - correction[0] += correctionVec[0]; - correction[1] += correctionVec[1]; - } - } - - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - if (!CropMath.inclusiveContains(outer, correctedInnerX, correctedInnerY)) { - float[] correctionVec = { - correctedInnerX, correctedInnerY - }; - CropMath.getEdgePoints(outer, correctionVec); - correctionVec[0] -= correctedInnerX; - correctionVec[1] -= correctedInnerY; - correction[0] += correctionVec[0]; - correction[1] += correctionVec[1]; - } - } - - // Set correction - for (int i = 0; i < translatedInnerCorners.length; i += 2) { - float correctedInnerX = translatedInnerCorners[i] + correction[0]; - float correctedInnerY = translatedInnerCorners[i + 1] + correction[1]; - // update translated corners with correction vectors - translatedInnerCorners[i] = correctedInnerX; - translatedInnerCorners[i + 1] = correctedInnerY; - } - - innerRotated = translatedInnerCorners; - // reconstrain to update inner - reconstrain(); - } - - /** - * Attempts to resize the inner rectangle. If this would cause it to leave - * the bounding rect, clips the inner rectangle to fit. - */ - public void resizeInner(RectF newInner) { - Matrix m = getRotMatrix(); - Matrix m0 = getInverseRotMatrix(); - - float[] outerCorners = CropMath.getCornersFromRect(outer); - m.mapPoints(outerCorners); - float[] oldInnerCorners = CropMath.getCornersFromRect(inner); - float[] newInnerCorners = CropMath.getCornersFromRect(newInner); - RectF ret = new RectF(newInner); - - for (int i = 0; i < newInnerCorners.length; i += 2) { - float[] c = { - newInnerCorners[i], newInnerCorners[i + 1] - }; - float[] c0 = Arrays.copyOf(c, 2); - m0.mapPoints(c0); - if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) { - float[] outerSide = CropMath.closestSide(c, outerCorners); - float[] pathOfCorner = { - newInnerCorners[i], newInnerCorners[i + 1], - oldInnerCorners[i], oldInnerCorners[i + 1] - }; - float[] p = GeometryMathUtils.lineIntersect(pathOfCorner, outerSide); - if (p == null) { - // lines are parallel or not well defined, so don't resize - p = new float[2]; - p[0] = oldInnerCorners[i]; - p[1] = oldInnerCorners[i + 1]; - } - // relies on corners being in same order as method - // getCornersFromRect - switch (i) { - case 0: - case 1: - ret.left = (p[0] > ret.left) ? p[0] : ret.left; - ret.top = (p[1] > ret.top) ? p[1] : ret.top; - break; - case 2: - case 3: - ret.right = (p[0] < ret.right) ? p[0] : ret.right; - ret.top = (p[1] > ret.top) ? p[1] : ret.top; - break; - case 4: - case 5: - ret.right = (p[0] < ret.right) ? p[0] : ret.right; - ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom; - break; - case 6: - case 7: - ret.left = (p[0] > ret.left) ? p[0] : ret.left; - ret.bottom = (p[1] < ret.bottom) ? p[1] : ret.bottom; - break; - default: - break; - } - } - } - float[] retCorners = CropMath.getCornersFromRect(ret); - m0.mapPoints(retCorners); - innerRotated = retCorners; - // reconstrain to update inner - reconstrain(); - } - - /** - * Attempts to resize the inner rectangle. If this would cause it to leave - * the bounding rect, clips the inner rectangle to fit while maintaining - * aspect ratio. - */ - public void fixedAspectResizeInner(RectF newInner) { - Matrix m = getRotMatrix(); - Matrix m0 = getInverseRotMatrix(); - - float aspectW = inner.width(); - float aspectH = inner.height(); - float aspRatio = aspectW / aspectH; - float[] corners = CropMath.getCornersFromRect(outer); - - m.mapPoints(corners); - float[] oldInnerCorners = CropMath.getCornersFromRect(inner); - float[] newInnerCorners = CropMath.getCornersFromRect(newInner); - - // find fixed corner - int fixed = -1; - if (inner.top == newInner.top) { - if (inner.left == newInner.left) - fixed = 0; // top left - else if (inner.right == newInner.right) - fixed = 2; // top right - } else if (inner.bottom == newInner.bottom) { - if (inner.right == newInner.right) - fixed = 4; // bottom right - else if (inner.left == newInner.left) - fixed = 6; // bottom left - } - // no fixed corner, return without update - if (fixed == -1) - return; - float widthSoFar = newInner.width(); - int moved = -1; - for (int i = 0; i < newInnerCorners.length; i += 2) { - float[] c = { - newInnerCorners[i], newInnerCorners[i + 1] - }; - float[] c0 = Arrays.copyOf(c, 2); - m0.mapPoints(c0); - if (!CropMath.inclusiveContains(outer, c0[0], c0[1])) { - moved = i; - if (moved == fixed) - continue; - float[] l2 = CropMath.closestSide(c, corners); - float[] l1 = { - newInnerCorners[i], newInnerCorners[i + 1], - oldInnerCorners[i], oldInnerCorners[i + 1] - }; - float[] p = GeometryMathUtils.lineIntersect(l1, l2); - if (p == null) { - // lines are parallel or not well defined, so set to old - // corner - p = new float[2]; - p[0] = oldInnerCorners[i]; - p[1] = oldInnerCorners[i + 1]; - } - // relies on corners being in same order as method - // getCornersFromRect - float fixed_x = oldInnerCorners[fixed]; - float fixed_y = oldInnerCorners[fixed + 1]; - float newWidth = Math.abs(fixed_x - p[0]); - float newHeight = Math.abs(fixed_y - p[1]); - newWidth = Math.max(newWidth, aspRatio * newHeight); - if (newWidth < widthSoFar) - widthSoFar = newWidth; - } - } - - float heightSoFar = widthSoFar / aspRatio; - RectF ret = new RectF(inner); - if (fixed == 0) { - ret.right = ret.left + widthSoFar; - ret.bottom = ret.top + heightSoFar; - } else if (fixed == 2) { - ret.left = ret.right - widthSoFar; - ret.bottom = ret.top + heightSoFar; - } else if (fixed == 4) { - ret.left = ret.right - widthSoFar; - ret.top = ret.bottom - heightSoFar; - } else if (fixed == 6) { - ret.right = ret.left + widthSoFar; - ret.top = ret.bottom - heightSoFar; - } - float[] retCorners = CropMath.getCornersFromRect(ret); - m0.mapPoints(retCorners); - innerRotated = retCorners; - // reconstrain to update inner - reconstrain(); - } - - // internal methods - - private boolean isConstrained() { - for (int i = 0; i < 8; i += 2) { - if (!CropMath.inclusiveContains(outer, innerRotated[i], innerRotated[i + 1])) - return false; - } - return true; - } - - private void reconstrain() { - // innerRotated has been changed to have incorrect values - CropMath.getEdgePoints(outer, innerRotated); - Matrix m = getRotMatrix(); - float[] unrotated = Arrays.copyOf(innerRotated, 8); - m.mapPoints(unrotated); - inner = CropMath.trapToRect(unrotated); - } - - private void rotateInner() { - Matrix m = getInverseRotMatrix(); - m.mapPoints(innerRotated); - } - - private Matrix getRotMatrix() { - Matrix m = new Matrix(); - m.setRotate(rot, outer.centerX(), outer.centerY()); - return m; - } - - private Matrix getInverseRotMatrix() { - Matrix m = new Matrix(); - m.setRotate(-rot, outer.centerX(), outer.centerY()); - return m; - } -} diff --git a/src/com/android/gallery3d/filtershow/crop/CropActivity.java b/src/com/android/gallery3d/filtershow/crop/CropActivity.java deleted file mode 100644 index 0a0c36703..000000000 --- a/src/com/android/gallery3d/filtershow/crop/CropActivity.java +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.crop; - -import android.app.ActionBar; -import android.app.Activity; -import android.app.WallpaperManager; -import android.content.Context; -import android.content.Intent; -import android.content.res.Configuration; -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Bundle; -import android.provider.MediaStore; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.WindowManager; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.tools.SaveImage; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Activity for cropping an image. - */ -public class CropActivity extends Activity { - private static final String LOGTAG = "CropActivity"; - public static final String CROP_ACTION = "com.android.camera.action.CROP"; - private CropExtras mCropExtras = null; - private LoadBitmapTask mLoadBitmapTask = null; - - private int mOutputX = 0; - private int mOutputY = 0; - private Bitmap mOriginalBitmap = null; - private RectF mOriginalBounds = null; - private int mOriginalRotation = 0; - private Uri mSourceUri = null; - private CropView mCropView = null; - private View mSaveButton = null; - private boolean finalIOGuard = false; - - private static final int SELECT_PICTURE = 1; // request code for picker - - private static final int DEFAULT_COMPRESS_QUALITY = 90; - /** - * The maximum bitmap size we allow to be returned through the intent. - * Intents have a maximum of 1MB in total size. However, the Bitmap seems to - * have some overhead to hit so that we go way below the limit here to make - * sure the intent stays below 1MB.We should consider just returning a byte - * array instead of a Bitmap instance to avoid overhead. - */ - public static final int MAX_BMAP_IN_INTENT = 750000; - - // Flags - private static final int DO_SET_WALLPAPER = 1; - private static final int DO_RETURN_DATA = 1 << 1; - private static final int DO_EXTRA_OUTPUT = 1 << 2; - - private static final int FLAG_CHECK = DO_SET_WALLPAPER | DO_RETURN_DATA | DO_EXTRA_OUTPUT; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Intent intent = getIntent(); - setResult(RESULT_CANCELED, new Intent()); - mCropExtras = getExtrasFromIntent(intent); - if (mCropExtras != null && mCropExtras.getShowWhenLocked()) { - getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); - } - - setContentView(R.layout.crop_activity); - mCropView = (CropView) findViewById(R.id.cropView); - - ActionBar actionBar = getActionBar(); - actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - actionBar.setCustomView(R.layout.filtershow_actionbar); - - View mSaveButton = actionBar.getCustomView(); - mSaveButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View view) { - startFinishOutput(); - } - }); - - if (intent.getData() != null) { - mSourceUri = intent.getData(); - startLoadBitmap(mSourceUri); - } else { - pickImage(); - } - } - - private void enableSave(boolean enable) { - if (mSaveButton != null) { - mSaveButton.setEnabled(enable); - } - } - - @Override - protected void onDestroy() { - if (mLoadBitmapTask != null) { - mLoadBitmapTask.cancel(false); - } - super.onDestroy(); - } - - @Override - public void onConfigurationChanged (Configuration newConfig) { - super.onConfigurationChanged(newConfig); - mCropView.configChanged(); - } - - /** - * Opens a selector in Gallery to chose an image for use when none was given - * in the CROP intent. - */ - private void pickImage() { - Intent intent = new Intent(); - intent.setType("image/*"); - intent.setAction(Intent.ACTION_GET_CONTENT); - startActivityForResult(Intent.createChooser(intent, getString(R.string.select_image)), - SELECT_PICTURE); - } - - /** - * Callback for pickImage(). - */ - @Override - public void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode == RESULT_OK && requestCode == SELECT_PICTURE) { - mSourceUri = data.getData(); - startLoadBitmap(mSourceUri); - } - } - - /** - * Gets screen size metric. - */ - private int getScreenImageSize() { - DisplayMetrics outMetrics = new DisplayMetrics(); - getWindowManager().getDefaultDisplay().getMetrics(outMetrics); - return (int) Math.max(outMetrics.heightPixels, outMetrics.widthPixels); - } - - /** - * Method that loads a bitmap in an async task. - */ - private void startLoadBitmap(Uri uri) { - if (uri != null) { - enableSave(false); - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.VISIBLE); - mLoadBitmapTask = new LoadBitmapTask(); - mLoadBitmapTask.execute(uri); - } else { - cannotLoadImage(); - done(); - } - } - - /** - * Method called on UI thread with loaded bitmap. - */ - private void doneLoadBitmap(Bitmap bitmap, RectF bounds, int orientation) { - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - mOriginalBitmap = bitmap; - mOriginalBounds = bounds; - mOriginalRotation = orientation; - if (bitmap != null && bitmap.getWidth() != 0 && bitmap.getHeight() != 0) { - RectF imgBounds = new RectF(0, 0, bitmap.getWidth(), bitmap.getHeight()); - mCropView.initialize(bitmap, imgBounds, imgBounds, orientation); - if (mCropExtras != null) { - int aspectX = mCropExtras.getAspectX(); - int aspectY = mCropExtras.getAspectY(); - mOutputX = mCropExtras.getOutputX(); - mOutputY = mCropExtras.getOutputY(); - if (mOutputX > 0 && mOutputY > 0) { - mCropView.applyAspect(mOutputX, mOutputY); - - } - float spotX = mCropExtras.getSpotlightX(); - float spotY = mCropExtras.getSpotlightY(); - if (spotX > 0 && spotY > 0) { - mCropView.setWallpaperSpotlight(spotX, spotY); - } - if (aspectX > 0 && aspectY > 0) { - mCropView.applyAspect(aspectX, aspectY); - } - } - enableSave(true); - } else { - Log.w(LOGTAG, "could not load image for cropping"); - cannotLoadImage(); - setResult(RESULT_CANCELED, new Intent()); - done(); - } - } - - /** - * Display toast for image loading failure. - */ - private void cannotLoadImage() { - CharSequence text = getString(R.string.cannot_load_image); - Toast toast = Toast.makeText(this, text, Toast.LENGTH_SHORT); - toast.show(); - } - - /** - * AsyncTask for loading a bitmap into memory. - * - * @see #startLoadBitmap(Uri) - * @see #doneLoadBitmap(Bitmap) - */ - private class LoadBitmapTask extends AsyncTask<Uri, Void, Bitmap> { - int mBitmapSize; - Context mContext; - Rect mOriginalBounds; - int mOrientation; - - public LoadBitmapTask() { - mBitmapSize = getScreenImageSize(); - mContext = getApplicationContext(); - mOriginalBounds = new Rect(); - mOrientation = 0; - } - - @Override - protected Bitmap doInBackground(Uri... params) { - Uri uri = params[0]; - Bitmap bmap = ImageLoader.loadConstrainedBitmap(uri, mContext, mBitmapSize, - mOriginalBounds, false); - mOrientation = ImageLoader.getMetadataRotation(mContext, uri); - return bmap; - } - - @Override - protected void onPostExecute(Bitmap result) { - doneLoadBitmap(result, new RectF(mOriginalBounds), mOrientation); - } - } - - private void startFinishOutput() { - if (finalIOGuard) { - return; - } else { - finalIOGuard = true; - } - enableSave(false); - Uri destinationUri = null; - int flags = 0; - if (mOriginalBitmap != null && mCropExtras != null) { - if (mCropExtras.getExtraOutput() != null) { - destinationUri = mCropExtras.getExtraOutput(); - if (destinationUri != null) { - flags |= DO_EXTRA_OUTPUT; - } - } - if (mCropExtras.getSetAsWallpaper()) { - flags |= DO_SET_WALLPAPER; - } - if (mCropExtras.getReturnData()) { - flags |= DO_RETURN_DATA; - } - } - if (flags == 0) { - destinationUri = SaveImage.makeAndInsertUri(this, mSourceUri); - if (destinationUri != null) { - flags |= DO_EXTRA_OUTPUT; - } - } - if ((flags & FLAG_CHECK) != 0 && mOriginalBitmap != null) { - RectF photo = new RectF(0, 0, mOriginalBitmap.getWidth(), mOriginalBitmap.getHeight()); - RectF crop = getBitmapCrop(photo); - startBitmapIO(flags, mOriginalBitmap, mSourceUri, destinationUri, crop, - photo, mOriginalBounds, - (mCropExtras == null) ? null : mCropExtras.getOutputFormat(), mOriginalRotation); - return; - } - setResult(RESULT_CANCELED, new Intent()); - done(); - return; - } - - private void startBitmapIO(int flags, Bitmap currentBitmap, Uri sourceUri, Uri destUri, - RectF cropBounds, RectF photoBounds, RectF currentBitmapBounds, String format, - int rotation) { - if (cropBounds == null || photoBounds == null || currentBitmap == null - || currentBitmap.getWidth() == 0 || currentBitmap.getHeight() == 0 - || cropBounds.width() == 0 || cropBounds.height() == 0 || photoBounds.width() == 0 - || photoBounds.height() == 0) { - return; // fail fast - } - if ((flags & FLAG_CHECK) == 0) { - return; // no output options - } - if ((flags & DO_SET_WALLPAPER) != 0) { - Toast.makeText(this, R.string.setting_wallpaper, Toast.LENGTH_LONG).show(); - } - - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.VISIBLE); - BitmapIOTask ioTask = new BitmapIOTask(sourceUri, destUri, format, flags, cropBounds, - photoBounds, currentBitmapBounds, rotation, mOutputX, mOutputY); - ioTask.execute(currentBitmap); - } - - private void doneBitmapIO(boolean success, Intent intent) { - final View loading = findViewById(R.id.loading); - loading.setVisibility(View.GONE); - if (success) { - setResult(RESULT_OK, intent); - } else { - setResult(RESULT_CANCELED, intent); - } - done(); - } - - private class BitmapIOTask extends AsyncTask<Bitmap, Void, Boolean> { - - private final WallpaperManager mWPManager; - InputStream mInStream = null; - OutputStream mOutStream = null; - String mOutputFormat = null; - Uri mOutUri = null; - Uri mInUri = null; - int mFlags = 0; - RectF mCrop = null; - RectF mPhoto = null; - RectF mOrig = null; - Intent mResultIntent = null; - int mRotation = 0; - - // Helper to setup input stream - private void regenerateInputStream() { - if (mInUri == null) { - Log.w(LOGTAG, "cannot read original file, no input URI given"); - } else { - Utils.closeSilently(mInStream); - try { - mInStream = getContentResolver().openInputStream(mInUri); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "cannot read file: " + mInUri.toString(), e); - } - } - } - - public BitmapIOTask(Uri sourceUri, Uri destUri, String outputFormat, int flags, - RectF cropBounds, RectF photoBounds, RectF originalBitmapBounds, int rotation, - int outputX, int outputY) { - mOutputFormat = outputFormat; - mOutStream = null; - mOutUri = destUri; - mInUri = sourceUri; - mFlags = flags; - mCrop = cropBounds; - mPhoto = photoBounds; - mOrig = originalBitmapBounds; - mWPManager = WallpaperManager.getInstance(getApplicationContext()); - mResultIntent = new Intent(); - mRotation = (rotation < 0) ? -rotation : rotation; - mRotation %= 360; - mRotation = 90 * (int) (mRotation / 90); // now mRotation is a multiple of 90 - mOutputX = outputX; - mOutputY = outputY; - - if ((flags & DO_EXTRA_OUTPUT) != 0) { - if (mOutUri == null) { - Log.w(LOGTAG, "cannot write file, no output URI given"); - } else { - try { - mOutStream = getContentResolver().openOutputStream(mOutUri); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "cannot write file: " + mOutUri.toString(), e); - } - } - } - - if ((flags & (DO_EXTRA_OUTPUT | DO_SET_WALLPAPER)) != 0) { - regenerateInputStream(); - } - } - - @Override - protected Boolean doInBackground(Bitmap... params) { - boolean failure = false; - Bitmap img = params[0]; - - // Set extra for crop bounds - if (mCrop != null && mPhoto != null && mOrig != null) { - RectF trueCrop = CropMath.getScaledCropBounds(mCrop, mPhoto, mOrig); - Matrix m = new Matrix(); - m.setRotate(mRotation); - m.mapRect(trueCrop); - if (trueCrop != null) { - Rect rounded = new Rect(); - trueCrop.roundOut(rounded); - mResultIntent.putExtra(CropExtras.KEY_CROPPED_RECT, rounded); - } - } - - // Find the small cropped bitmap that is returned in the intent - if ((mFlags & DO_RETURN_DATA) != 0) { - assert (img != null); - Bitmap ret = getCroppedImage(img, mCrop, mPhoto); - if (ret != null) { - ret = getDownsampledBitmap(ret, MAX_BMAP_IN_INTENT); - } - if (ret == null) { - Log.w(LOGTAG, "could not downsample bitmap to return in data"); - failure = true; - } else { - if (mRotation > 0) { - Matrix m = new Matrix(); - m.setRotate(mRotation); - Bitmap tmp = Bitmap.createBitmap(ret, 0, 0, ret.getWidth(), - ret.getHeight(), m, true); - if (tmp != null) { - ret = tmp; - } - } - mResultIntent.putExtra(CropExtras.KEY_DATA, ret); - } - } - - // Do the large cropped bitmap and/or set the wallpaper - if ((mFlags & (DO_EXTRA_OUTPUT | DO_SET_WALLPAPER)) != 0 && mInStream != null) { - // Find crop bounds (scaled to original image size) - RectF trueCrop = CropMath.getScaledCropBounds(mCrop, mPhoto, mOrig); - if (trueCrop == null) { - Log.w(LOGTAG, "cannot find crop for full size image"); - failure = true; - return false; - } - Rect roundedTrueCrop = new Rect(); - trueCrop.roundOut(roundedTrueCrop); - - if (roundedTrueCrop.width() <= 0 || roundedTrueCrop.height() <= 0) { - Log.w(LOGTAG, "crop has bad values for full size image"); - failure = true; - return false; - } - - // Attempt to open a region decoder - BitmapRegionDecoder decoder = null; - try { - decoder = BitmapRegionDecoder.newInstance(mInStream, true); - } catch (IOException e) { - Log.w(LOGTAG, "cannot open region decoder for file: " + mInUri.toString(), e); - } - - Bitmap crop = null; - if (decoder != null) { - // Do region decoding to get crop bitmap - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inMutable = true; - crop = decoder.decodeRegion(roundedTrueCrop, options); - decoder.recycle(); - } - - if (crop == null) { - // BitmapRegionDecoder has failed, try to crop in-memory - regenerateInputStream(); - Bitmap fullSize = null; - if (mInStream != null) { - fullSize = BitmapFactory.decodeStream(mInStream); - } - if (fullSize != null) { - crop = Bitmap.createBitmap(fullSize, roundedTrueCrop.left, - roundedTrueCrop.top, roundedTrueCrop.width(), - roundedTrueCrop.height()); - } - } - - if (crop == null) { - Log.w(LOGTAG, "cannot decode file: " + mInUri.toString()); - failure = true; - return false; - } - if (mOutputX > 0 && mOutputY > 0) { - Matrix m = new Matrix(); - RectF cropRect = new RectF(0, 0, crop.getWidth(), crop.getHeight()); - if (mRotation > 0) { - m.setRotate(mRotation); - m.mapRect(cropRect); - } - RectF returnRect = new RectF(0, 0, mOutputX, mOutputY); - m.setRectToRect(cropRect, returnRect, Matrix.ScaleToFit.FILL); - m.preRotate(mRotation); - Bitmap tmp = Bitmap.createBitmap((int) returnRect.width(), - (int) returnRect.height(), Bitmap.Config.ARGB_8888); - if (tmp != null) { - Canvas c = new Canvas(tmp); - c.drawBitmap(crop, m, new Paint()); - crop = tmp; - } - } else if (mRotation > 0) { - Matrix m = new Matrix(); - m.setRotate(mRotation); - Bitmap tmp = Bitmap.createBitmap(crop, 0, 0, crop.getWidth(), - crop.getHeight(), m, true); - if (tmp != null) { - crop = tmp; - } - } - // Get output compression format - CompressFormat cf = - convertExtensionToCompressFormat(getFileExtension(mOutputFormat)); - - // If we only need to output to a URI, compress straight to file - if (mFlags == DO_EXTRA_OUTPUT) { - if (mOutStream == null - || !crop.compress(cf, DEFAULT_COMPRESS_QUALITY, mOutStream)) { - Log.w(LOGTAG, "failed to compress bitmap to file: " + mOutUri.toString()); - failure = true; - } else { - mResultIntent.setData(mOutUri); - } - } else { - // Compress to byte array - ByteArrayOutputStream tmpOut = new ByteArrayOutputStream(2048); - if (crop.compress(cf, DEFAULT_COMPRESS_QUALITY, tmpOut)) { - - // If we need to output to a Uri, write compressed - // bitmap out - if ((mFlags & DO_EXTRA_OUTPUT) != 0) { - if (mOutStream == null) { - Log.w(LOGTAG, - "failed to compress bitmap to file: " + mOutUri.toString()); - failure = true; - } else { - try { - mOutStream.write(tmpOut.toByteArray()); - mResultIntent.setData(mOutUri); - } catch (IOException e) { - Log.w(LOGTAG, - "failed to compress bitmap to file: " - + mOutUri.toString(), e); - failure = true; - } - } - } - - // If we need to set to the wallpaper, set it - if ((mFlags & DO_SET_WALLPAPER) != 0 && mWPManager != null) { - if (mWPManager == null) { - Log.w(LOGTAG, "no wallpaper manager"); - failure = true; - } else { - try { - mWPManager.setStream(new ByteArrayInputStream(tmpOut - .toByteArray())); - } catch (IOException e) { - Log.w(LOGTAG, "cannot write stream to wallpaper", e); - failure = true; - } - } - } - } else { - Log.w(LOGTAG, "cannot compress bitmap"); - failure = true; - } - } - } - return !failure; // True if any of the operations failed - } - - @Override - protected void onPostExecute(Boolean result) { - Utils.closeSilently(mOutStream); - Utils.closeSilently(mInStream); - doneBitmapIO(result.booleanValue(), mResultIntent); - } - - } - - private void done() { - finish(); - } - - protected static Bitmap getCroppedImage(Bitmap image, RectF cropBounds, RectF photoBounds) { - RectF imageBounds = new RectF(0, 0, image.getWidth(), image.getHeight()); - RectF crop = CropMath.getScaledCropBounds(cropBounds, photoBounds, imageBounds); - if (crop == null) { - return null; - } - Rect intCrop = new Rect(); - crop.roundOut(intCrop); - return Bitmap.createBitmap(image, intCrop.left, intCrop.top, intCrop.width(), - intCrop.height()); - } - - protected static Bitmap getDownsampledBitmap(Bitmap image, int max_size) { - if (image == null || image.getWidth() == 0 || image.getHeight() == 0 || max_size < 16) { - throw new IllegalArgumentException("Bad argument to getDownsampledBitmap()"); - } - int shifts = 0; - int size = CropMath.getBitmapSize(image); - while (size > max_size) { - shifts++; - size /= 4; - } - Bitmap ret = Bitmap.createScaledBitmap(image, image.getWidth() >> shifts, - image.getHeight() >> shifts, true); - if (ret == null) { - return null; - } - // Handle edge case for rounding. - if (CropMath.getBitmapSize(ret) > max_size) { - return Bitmap.createScaledBitmap(ret, ret.getWidth() >> 1, ret.getHeight() >> 1, true); - } - return ret; - } - - /** - * Gets the crop extras from the intent, or null if none exist. - */ - protected static CropExtras getExtrasFromIntent(Intent intent) { - Bundle extras = intent.getExtras(); - if (extras != null) { - return new CropExtras(extras.getInt(CropExtras.KEY_OUTPUT_X, 0), - extras.getInt(CropExtras.KEY_OUTPUT_Y, 0), - extras.getBoolean(CropExtras.KEY_SCALE, true) && - extras.getBoolean(CropExtras.KEY_SCALE_UP_IF_NEEDED, false), - extras.getInt(CropExtras.KEY_ASPECT_X, 0), - extras.getInt(CropExtras.KEY_ASPECT_Y, 0), - extras.getBoolean(CropExtras.KEY_SET_AS_WALLPAPER, false), - extras.getBoolean(CropExtras.KEY_RETURN_DATA, false), - (Uri) extras.getParcelable(MediaStore.EXTRA_OUTPUT), - extras.getString(CropExtras.KEY_OUTPUT_FORMAT), - extras.getBoolean(CropExtras.KEY_SHOW_WHEN_LOCKED, false), - extras.getFloat(CropExtras.KEY_SPOTLIGHT_X), - extras.getFloat(CropExtras.KEY_SPOTLIGHT_Y)); - } - return null; - } - - protected static CompressFormat convertExtensionToCompressFormat(String extension) { - return extension.equals("png") ? CompressFormat.PNG : CompressFormat.JPEG; - } - - protected static String getFileExtension(String requestFormat) { - String outputFormat = (requestFormat == null) - ? "jpg" - : requestFormat; - outputFormat = outputFormat.toLowerCase(); - return (outputFormat.equals("png") || outputFormat.equals("gif")) - ? "png" // We don't support gif compression. - : "jpg"; - } - - private RectF getBitmapCrop(RectF imageBounds) { - RectF crop = mCropView.getCrop(); - RectF photo = mCropView.getPhoto(); - if (crop == null || photo == null) { - Log.w(LOGTAG, "could not get crop"); - return null; - } - RectF scaledCrop = CropMath.getScaledCropBounds(crop, photo, imageBounds); - return scaledCrop; - } -} diff --git a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java b/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java deleted file mode 100644 index b0d324cbb..000000000 --- a/src/com/android/gallery3d/filtershow/crop/CropDrawingUtils.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.crop; - -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; -import android.graphics.Region; -import android.graphics.drawable.Drawable; - -public abstract class CropDrawingUtils { - - public static void drawRuleOfThird(Canvas canvas, RectF bounds) { - Paint p = new Paint(); - p.setStyle(Paint.Style.STROKE); - p.setColor(Color.argb(128, 255, 255, 255)); - p.setStrokeWidth(2); - float stepX = bounds.width() / 3.0f; - float stepY = bounds.height() / 3.0f; - float x = bounds.left + stepX; - float y = bounds.top + stepY; - for (int i = 0; i < 2; i++) { - canvas.drawLine(x, bounds.top, x, bounds.bottom, p); - x += stepX; - } - for (int j = 0; j < 2; j++) { - canvas.drawLine(bounds.left, y, bounds.right, y, p); - y += stepY; - } - } - - public static void drawCropRect(Canvas canvas, RectF bounds) { - Paint p = new Paint(); - p.setStyle(Paint.Style.STROKE); - p.setColor(Color.WHITE); - p.setStrokeWidth(3); - canvas.drawRect(bounds, p); - } - - public static void drawIndicator(Canvas canvas, Drawable indicator, int indicatorSize, - float centerX, float centerY) { - int left = (int) centerX - indicatorSize / 2; - int top = (int) centerY - indicatorSize / 2; - indicator.setBounds(left, top, left + indicatorSize, top + indicatorSize); - indicator.draw(canvas); - } - - public static void drawIndicators(Canvas canvas, Drawable cropIndicator, int indicatorSize, - RectF bounds, boolean fixedAspect, int selection) { - boolean notMoving = (selection == CropObject.MOVE_NONE); - if (fixedAspect) { - if ((selection == CropObject.TOP_LEFT) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.top); - } - if ((selection == CropObject.TOP_RIGHT) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.top); - } - if ((selection == CropObject.BOTTOM_LEFT) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.bottom); - } - if ((selection == CropObject.BOTTOM_RIGHT) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.bottom); - } - } else { - if (((selection & CropObject.MOVE_TOP) != 0) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.centerX(), bounds.top); - } - if (((selection & CropObject.MOVE_BOTTOM) != 0) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.centerX(), bounds.bottom); - } - if (((selection & CropObject.MOVE_LEFT) != 0) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.left, bounds.centerY()); - } - if (((selection & CropObject.MOVE_RIGHT) != 0) || notMoving) { - drawIndicator(canvas, cropIndicator, indicatorSize, bounds.right, bounds.centerY()); - } - } - } - - public static void drawWallpaperSelectionFrame(Canvas canvas, RectF cropBounds, float spotX, - float spotY, Paint p, Paint shadowPaint) { - float sx = cropBounds.width() * spotX; - float sy = cropBounds.height() * spotY; - float cx = cropBounds.centerX(); - float cy = cropBounds.centerY(); - RectF r1 = new RectF(cx - sx / 2, cy - sy / 2, cx + sx / 2, cy + sy / 2); - float temp = sx; - sx = sy; - sy = temp; - RectF r2 = new RectF(cx - sx / 2, cy - sy / 2, cx + sx / 2, cy + sy / 2); - canvas.save(); - canvas.clipRect(cropBounds); - canvas.clipRect(r1, Region.Op.DIFFERENCE); - canvas.clipRect(r2, Region.Op.DIFFERENCE); - canvas.drawPaint(shadowPaint); - canvas.restore(); - Path path = new Path(); - path.moveTo(r1.left, r1.top); - path.lineTo(r1.right, r1.top); - path.moveTo(r1.left, r1.top); - path.lineTo(r1.left, r1.bottom); - path.moveTo(r1.left, r1.bottom); - path.lineTo(r1.right, r1.bottom); - path.moveTo(r1.right, r1.top); - path.lineTo(r1.right, r1.bottom); - path.moveTo(r2.left, r2.top); - path.lineTo(r2.right, r2.top); - path.moveTo(r2.right, r2.top); - path.lineTo(r2.right, r2.bottom); - path.moveTo(r2.left, r2.bottom); - path.lineTo(r2.right, r2.bottom); - path.moveTo(r2.left, r2.top); - path.lineTo(r2.left, r2.bottom); - canvas.drawPath(path, p); - } - - public static void drawShadows(Canvas canvas, Paint p, RectF innerBounds, RectF outerBounds) { - canvas.drawRect(outerBounds.left, outerBounds.top, innerBounds.right, innerBounds.top, p); - canvas.drawRect(innerBounds.right, outerBounds.top, outerBounds.right, innerBounds.bottom, - p); - canvas.drawRect(innerBounds.left, innerBounds.bottom, outerBounds.right, - outerBounds.bottom, p); - canvas.drawRect(outerBounds.left, innerBounds.top, innerBounds.left, outerBounds.bottom, p); - } - - public static Matrix getBitmapToDisplayMatrix(RectF imageBounds, RectF displayBounds) { - Matrix m = new Matrix(); - CropDrawingUtils.setBitmapToDisplayMatrix(m, imageBounds, displayBounds); - return m; - } - - public static boolean setBitmapToDisplayMatrix(Matrix m, RectF imageBounds, - RectF displayBounds) { - m.reset(); - return m.setRectToRect(imageBounds, displayBounds, Matrix.ScaleToFit.CENTER); - } - - public static boolean setImageToScreenMatrix(Matrix dst, RectF image, - RectF screen, int rotation) { - RectF rotatedImage = new RectF(); - dst.setRotate(rotation, image.centerX(), image.centerY()); - if (!dst.mapRect(rotatedImage, image)) { - return false; // fails for rotations that are not multiples of 90 - // degrees - } - boolean rToR = dst.setRectToRect(rotatedImage, screen, Matrix.ScaleToFit.CENTER); - boolean rot = dst.preRotate(rotation, image.centerX(), image.centerY()); - return rToR && rot; - } - -} diff --git a/src/com/android/gallery3d/filtershow/crop/CropMath.java b/src/com/android/gallery3d/filtershow/crop/CropMath.java deleted file mode 100644 index 02c65310e..000000000 --- a/src/com/android/gallery3d/filtershow/crop/CropMath.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.crop; - -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.RectF; - -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; - -import java.util.Arrays; - -public class CropMath { - - /** - * Gets a float array of the 2D coordinates representing a rectangles - * corners. - * The order of the corners in the float array is: - * 0------->1 - * ^ | - * | v - * 3<-------2 - * - * @param r the rectangle to get the corners of - * @return the float array of corners (8 floats) - */ - - public static float[] getCornersFromRect(RectF r) { - float[] corners = { - r.left, r.top, - r.right, r.top, - r.right, r.bottom, - r.left, r.bottom - }; - return corners; - } - - /** - * Returns true iff point (x, y) is within or on the rectangle's bounds. - * RectF's "contains" function treats points on the bottom and right bound - * as not being contained. - * - * @param r the rectangle - * @param x the x value of the point - * @param y the y value of the point - * @return - */ - public static boolean inclusiveContains(RectF r, float x, float y) { - return !(x > r.right || x < r.left || y > r.bottom || y < r.top); - } - - /** - * Takes an array of 2D coordinates representing corners and returns the - * smallest rectangle containing those coordinates. - * - * @param array array of 2D coordinates - * @return smallest rectangle containing coordinates - */ - public static RectF trapToRect(float[] array) { - RectF r = new RectF(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY, - Float.NEGATIVE_INFINITY, Float.NEGATIVE_INFINITY); - for (int i = 1; i < array.length; i += 2) { - float x = array[i - 1]; - float y = array[i]; - r.left = (x < r.left) ? x : r.left; - r.top = (y < r.top) ? y : r.top; - r.right = (x > r.right) ? x : r.right; - r.bottom = (y > r.bottom) ? y : r.bottom; - } - r.sort(); - return r; - } - - /** - * 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. - * - * @param imageBound the rectangle to clamp edge points to. - * @param array an array of points to clamp to the rectangle, gets set to - * the clamped values. - */ - public static void getEdgePoints(RectF imageBound, float[] array) { - if (array.length < 2) - return; - for (int x = 0; x < array.length; x += 2) { - array[x] = GeometryMathUtils.clamp(array[x], imageBound.left, imageBound.right); - array[x + 1] = GeometryMathUtils.clamp(array[x + 1], imageBound.top, imageBound.bottom); - } - } - - /** - * Takes a point and the corners of a rectangle and returns the two corners - * representing the side of the rectangle closest to the point. - * - * @param point the point which is being checked - * @param corners the corners of the rectangle - * @return two corners representing the side of the rectangle - */ - public static float[] closestSide(float[] point, float[] corners) { - int len = corners.length; - float oldMag = Float.POSITIVE_INFINITY; - float[] bestLine = null; - for (int i = 0; i < len; i += 2) { - float[] line = { - corners[i], corners[(i + 1) % len], - corners[(i + 2) % len], corners[(i + 3) % len] - }; - float mag = GeometryMathUtils.vectorLength( - GeometryMathUtils.shortestVectorFromPointToLine(point, line)); - if (mag < oldMag) { - oldMag = mag; - bestLine = line; - } - } - return bestLine; - } - - /** - * Checks if a given point is within a rotated rectangle. - * - * @param point 2D point to check - * @param bound rectangle to rotate - * @param rot angle of rotation about rectangle center - * @return true if point is within rotated rectangle - */ - public static boolean pointInRotatedRect(float[] point, RectF bound, float rot) { - Matrix m = new Matrix(); - float[] p = Arrays.copyOf(point, 2); - m.setRotate(rot, bound.centerX(), bound.centerY()); - Matrix m0 = new Matrix(); - if (!m.invert(m0)) - return false; - m0.mapPoints(p); - return inclusiveContains(bound, p[0], p[1]); - } - - /** - * Checks if a given point is within a rotated rectangle. - * - * @param point 2D point to check - * @param rotatedRect corners of a rotated rectangle - * @param center center of the rotated rectangle - * @return true if point is within rotated rectangle - */ - public static boolean pointInRotatedRect(float[] point, float[] rotatedRect, float[] center) { - RectF unrotated = new RectF(); - float angle = getUnrotated(rotatedRect, center, unrotated); - return pointInRotatedRect(point, unrotated, angle); - } - - /** - * Resizes rectangle to have a certain aspect ratio (center remains - * stationary). - * - * @param r rectangle to resize - * @param w new width aspect - * @param h new height aspect - */ - public 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); - } - - /** - * Resizes rectangle to have a certain aspect ratio (center remains - * stationary) while constraining it to remain within the original rect. - * - * @param r rectangle to resize - * @param w new width aspect - * @param h new height aspect - */ - public static void fixAspectRatioContained(RectF r, float w, float h) { - float origW = r.width(); - float origH = r.height(); - float origA = origW / origH; - float a = w / h; - float finalW = origW; - float finalH = origH; - if (origA < a) { - finalH = origW / a; - r.top = r.centerY() - finalH / 2; - r.bottom = r.top + finalH; - } else { - finalW = origH * a; - r.left = r.centerX() - finalW / 2; - r.right = r.left + finalW; - } - } - - /** - * Stretches/Scales/Translates photoBounds to match displayBounds, and - * and returns an equivalent stretched/scaled/translated cropBounds or null - * if the mapping is invalid. - * @param cropBounds cropBounds to transform - * @param photoBounds original bounds containing crop bounds - * @param displayBounds final bounds for crop - * @return the stretched/scaled/translated crop bounds that fit within displayBounds - */ - public static RectF getScaledCropBounds(RectF cropBounds, RectF photoBounds, - RectF displayBounds) { - Matrix m = new Matrix(); - m.setRectToRect(photoBounds, displayBounds, Matrix.ScaleToFit.FILL); - RectF trueCrop = new RectF(cropBounds); - if (!m.mapRect(trueCrop)) { - return null; - } - return trueCrop; - } - - /** - * Returns the size of a bitmap in bytes. - * @param bmap bitmap whose size to check - * @return bitmap size in bytes - */ - public static int getBitmapSize(Bitmap bmap) { - return bmap.getRowBytes() * bmap.getHeight(); - } - - /** - * Constrains rotation to be in [0, 90, 180, 270] rounding down. - * @param rotation any rotation value, in degrees - * @return integer rotation in [0, 90, 180, 270] - */ - public static int constrainedRotation(float rotation) { - int r = (int) ((rotation % 360) / 90); - r = (r < 0) ? (r + 4) : r; - return r * 90; - } - - private static float getUnrotated(float[] rotatedRect, float[] center, RectF unrotated) { - float dy = rotatedRect[1] - rotatedRect[3]; - float dx = rotatedRect[0] - rotatedRect[2]; - float angle = (float) (Math.atan(dy / dx) * 180 / Math.PI); - Matrix m = new Matrix(); - m.setRotate(-angle, center[0], center[1]); - float[] unrotatedRect = new float[rotatedRect.length]; - m.mapPoints(unrotatedRect, rotatedRect); - unrotated.set(trapToRect(unrotatedRect)); - return angle; - } - -} diff --git a/src/com/android/gallery3d/filtershow/crop/CropObject.java b/src/com/android/gallery3d/filtershow/crop/CropObject.java deleted file mode 100644 index b98ed1bfd..000000000 --- a/src/com/android/gallery3d/filtershow/crop/CropObject.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.crop; - -import android.graphics.Rect; -import android.graphics.RectF; - -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; - -public class CropObject { - private BoundedRect mBoundedRect; - private float mAspectWidth = 1; - private float mAspectHeight = 1; - private boolean mFixAspectRatio = false; - private float mRotation = 0; - private float mTouchTolerance = 45; - private float mMinSideSize = 20; - - public static final int MOVE_NONE = 0; - // Sides - public static final int MOVE_LEFT = 1; - public static final int MOVE_TOP = 2; - public static final int MOVE_RIGHT = 4; - public static final int MOVE_BOTTOM = 8; - public static final int MOVE_BLOCK = 16; - - // Corners - public static final int TOP_LEFT = MOVE_TOP | MOVE_LEFT; - public static final int TOP_RIGHT = MOVE_TOP | MOVE_RIGHT; - public static final int BOTTOM_RIGHT = MOVE_BOTTOM | MOVE_RIGHT; - public static final int BOTTOM_LEFT = MOVE_BOTTOM | MOVE_LEFT; - - private int mMovingEdges = MOVE_NONE; - - public CropObject(Rect outerBound, Rect innerBound, int outerAngle) { - mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound); - } - - public CropObject(RectF outerBound, RectF innerBound, int outerAngle) { - mBoundedRect = new BoundedRect(outerAngle % 360, outerBound, innerBound); - } - - public void resetBoundsTo(RectF inner, RectF outer) { - mBoundedRect.resetTo(0, outer, inner); - } - - public void getInnerBounds(RectF r) { - mBoundedRect.setToInner(r); - } - - public void getOuterBounds(RectF r) { - mBoundedRect.setToOuter(r); - } - - public RectF getInnerBounds() { - return mBoundedRect.getInner(); - } - - public RectF getOuterBounds() { - return mBoundedRect.getOuter(); - } - - public int getSelectState() { - return mMovingEdges; - } - - public boolean isFixedAspect() { - return mFixAspectRatio; - } - - public void rotateOuter(int angle) { - mRotation = angle % 360; - mBoundedRect.setRotation(mRotation); - clearSelectState(); - } - - public boolean setInnerAspectRatio(float width, float height) { - if (width <= 0 || height <= 0) { - throw new IllegalArgumentException("Width and Height must be greater than zero"); - } - RectF inner = mBoundedRect.getInner(); - CropMath.fixAspectRatioContained(inner, width, height); - if (inner.width() < mMinSideSize || inner.height() < mMinSideSize) { - return false; - } - mAspectWidth = width; - mAspectHeight = height; - mFixAspectRatio = true; - mBoundedRect.setInner(inner); - clearSelectState(); - return true; - } - - public void setTouchTolerance(float tolerance) { - if (tolerance <= 0) { - throw new IllegalArgumentException("Tolerance must be greater than zero"); - } - mTouchTolerance = tolerance; - } - - public void setMinInnerSideSize(float minSide) { - if (minSide <= 0) { - throw new IllegalArgumentException("Min dide must be greater than zero"); - } - mMinSideSize = minSide; - } - - public void unsetAspectRatio() { - mFixAspectRatio = false; - clearSelectState(); - } - - public boolean hasSelectedEdge() { - return mMovingEdges != MOVE_NONE; - } - - public static boolean checkCorner(int selected) { - return selected == TOP_LEFT || selected == TOP_RIGHT || selected == BOTTOM_RIGHT - || selected == BOTTOM_LEFT; - } - - public static boolean checkEdge(int selected) { - return selected == MOVE_LEFT || selected == MOVE_TOP || selected == MOVE_RIGHT - || selected == MOVE_BOTTOM; - } - - public static boolean checkBlock(int selected) { - return selected == MOVE_BLOCK; - } - - public static boolean checkValid(int selected) { - return selected == MOVE_NONE || checkBlock(selected) || checkEdge(selected) - || checkCorner(selected); - } - - public void clearSelectState() { - mMovingEdges = MOVE_NONE; - } - - public int wouldSelectEdge(float x, float y) { - int edgeSelected = calculateSelectedEdge(x, y); - if (edgeSelected != MOVE_NONE && edgeSelected != MOVE_BLOCK) { - return edgeSelected; - } - return MOVE_NONE; - } - - public boolean selectEdge(int edge) { - if (!checkValid(edge)) { - // temporary - throw new IllegalArgumentException("bad edge selected"); - // return false; - } - if ((mFixAspectRatio && !checkCorner(edge)) && !checkBlock(edge) && edge != MOVE_NONE) { - // temporary - throw new IllegalArgumentException("bad corner selected"); - // return false; - } - mMovingEdges = edge; - return true; - } - - public boolean selectEdge(float x, float y) { - int edgeSelected = calculateSelectedEdge(x, y); - if (mFixAspectRatio) { - edgeSelected = fixEdgeToCorner(edgeSelected); - } - if (edgeSelected == MOVE_NONE) { - return false; - } - return selectEdge(edgeSelected); - } - - public boolean moveCurrentSelection(float dX, float dY) { - if (mMovingEdges == MOVE_NONE) { - return false; - } - RectF crop = mBoundedRect.getInner(); - - float minWidthHeight = mMinSideSize; - - int movingEdges = mMovingEdges; - if (movingEdges == MOVE_BLOCK) { - mBoundedRect.moveInner(dX, dY); - return true; - } else { - float dx = 0; - float dy = 0; - - if ((movingEdges & MOVE_LEFT) != 0) { - dx = Math.min(crop.left + dX, crop.right - minWidthHeight) - crop.left; - } - if ((movingEdges & MOVE_TOP) != 0) { - dy = Math.min(crop.top + dY, crop.bottom - minWidthHeight) - crop.top; - } - if ((movingEdges & MOVE_RIGHT) != 0) { - dx = Math.max(crop.right + dX, crop.left + minWidthHeight) - - crop.right; - } - if ((movingEdges & MOVE_BOTTOM) != 0) { - dy = Math.max(crop.bottom + dY, crop.top + minWidthHeight) - - crop.bottom; - } - - if (mFixAspectRatio) { - float[] l1 = { - crop.left, crop.bottom - }; - float[] l2 = { - crop.right, crop.top - }; - if (movingEdges == TOP_LEFT || movingEdges == BOTTOM_RIGHT) { - l1[1] = crop.top; - l2[1] = crop.bottom; - } - float[] b = { - l1[0] - l2[0], l1[1] - l2[1] - }; - float[] disp = { - dx, dy - }; - float[] bUnit = GeometryMathUtils.normalize(b); - float sp = GeometryMathUtils.scalarProjection(disp, bUnit); - dx = sp * bUnit[0]; - dy = sp * bUnit[1]; - RectF newCrop = fixedCornerResize(crop, movingEdges, dx, dy); - - mBoundedRect.fixedAspectResizeInner(newCrop); - } else { - if ((movingEdges & MOVE_LEFT) != 0) { - crop.left += dx; - } - if ((movingEdges & MOVE_TOP) != 0) { - crop.top += dy; - } - if ((movingEdges & MOVE_RIGHT) != 0) { - crop.right += dx; - } - if ((movingEdges & MOVE_BOTTOM) != 0) { - crop.bottom += dy; - } - mBoundedRect.resizeInner(crop); - } - } - return true; - } - - // Helper methods - - private int calculateSelectedEdge(float x, float y) { - RectF cropped = mBoundedRect.getInner(); - - float left = Math.abs(x - cropped.left); - float right = Math.abs(x - cropped.right); - float top = Math.abs(y - cropped.top); - float bottom = Math.abs(y - cropped.bottom); - - int edgeSelected = MOVE_NONE; - // Check left or right. - if ((left <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top) - && ((y - mTouchTolerance) <= cropped.bottom) && (left < right)) { - edgeSelected |= MOVE_LEFT; - } - else if ((right <= mTouchTolerance) && ((y + mTouchTolerance) >= cropped.top) - && ((y - mTouchTolerance) <= cropped.bottom)) { - edgeSelected |= MOVE_RIGHT; - } - - // Check top or bottom. - if ((top <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left) - && ((x - mTouchTolerance) <= cropped.right) && (top < bottom)) { - edgeSelected |= MOVE_TOP; - } - else if ((bottom <= mTouchTolerance) && ((x + mTouchTolerance) >= cropped.left) - && ((x - mTouchTolerance) <= cropped.right)) { - edgeSelected |= MOVE_BOTTOM; - } - return edgeSelected; - } - - private static RectF fixedCornerResize(RectF r, int moving_corner, float dx, float dy) { - RectF newCrop = null; - // Fix opposite corner in place and move sides - if (moving_corner == BOTTOM_RIGHT) { - newCrop = new RectF(r.left, r.top, r.left + r.width() + dx, r.top + r.height() - + dy); - } else if (moving_corner == BOTTOM_LEFT) { - newCrop = new RectF(r.right - r.width() + dx, r.top, r.right, r.top + r.height() - + dy); - } else if (moving_corner == TOP_LEFT) { - newCrop = new RectF(r.right - r.width() + dx, r.bottom - r.height() + dy, - r.right, r.bottom); - } else if (moving_corner == TOP_RIGHT) { - newCrop = new RectF(r.left, r.bottom - r.height() + dy, r.left - + r.width() + dx, r.bottom); - } - return newCrop; - } - - private static int fixEdgeToCorner(int moving_edges) { - if (moving_edges == MOVE_LEFT) { - moving_edges |= MOVE_TOP; - } - if (moving_edges == MOVE_TOP) { - moving_edges |= MOVE_LEFT; - } - if (moving_edges == MOVE_RIGHT) { - moving_edges |= MOVE_BOTTOM; - } - if (moving_edges == MOVE_BOTTOM) { - moving_edges |= MOVE_RIGHT; - } - return moving_edges; - } - -} diff --git a/src/com/android/gallery3d/filtershow/crop/CropView.java b/src/com/android/gallery3d/filtershow/crop/CropView.java deleted file mode 100644 index bbb7cfd4c..000000000 --- a/src/com/android/gallery3d/filtershow/crop/CropView.java +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.crop; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.DashPathEffect; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.NinePatchDrawable; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; -import android.view.View; - -import com.android.gallery3d.R; - - -public class CropView extends View { - private static final String LOGTAG = "CropView"; - - private RectF mImageBounds = new RectF(); - private RectF mScreenBounds = new RectF(); - private RectF mScreenImageBounds = new RectF(); - private RectF mScreenCropBounds = new RectF(); - private Rect mShadowBounds = new Rect(); - - private Bitmap mBitmap; - private Paint mPaint = new Paint(); - - private NinePatchDrawable mShadow; - private CropObject mCropObj = null; - private Drawable mCropIndicator; - private int mIndicatorSize; - private int mRotation = 0; - private boolean mMovingBlock = false; - private Matrix mDisplayMatrix = null; - private Matrix mDisplayMatrixInverse = null; - private boolean mDirty = false; - - private float mPrevX = 0; - private float mPrevY = 0; - private float mSpotX = 0; - private float mSpotY = 0; - private boolean mDoSpot = false; - - private int mShadowMargin = 15; - private int mMargin = 32; - private int mOverlayShadowColor = 0xCF000000; - private int mOverlayWPShadowColor = 0x5F000000; - private int mWPMarkerColor = 0x7FFFFFFF; - private int mMinSideSize = 90; - private int mTouchTolerance = 40; - private float mDashOnLength = 20; - private float mDashOffLength = 10; - - private enum Mode { - NONE, MOVE - } - - private Mode mState = Mode.NONE; - - public CropView(Context context) { - super(context); - setup(context); - } - - public CropView(Context context, AttributeSet attrs) { - super(context, attrs); - setup(context); - } - - public CropView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - setup(context); - } - - private void setup(Context context) { - Resources rsc = context.getResources(); - mShadow = (NinePatchDrawable) rsc.getDrawable(R.drawable.geometry_shadow); - mCropIndicator = rsc.getDrawable(R.drawable.camera_crop); - mIndicatorSize = (int) rsc.getDimension(R.dimen.crop_indicator_size); - mShadowMargin = (int) rsc.getDimension(R.dimen.shadow_margin); - mMargin = (int) rsc.getDimension(R.dimen.preview_margin); - mMinSideSize = (int) rsc.getDimension(R.dimen.crop_min_side); - mTouchTolerance = (int) rsc.getDimension(R.dimen.crop_touch_tolerance); - mOverlayShadowColor = (int) rsc.getColor(R.color.crop_shadow_color); - mOverlayWPShadowColor = (int) rsc.getColor(R.color.crop_shadow_wp_color); - mWPMarkerColor = (int) rsc.getColor(R.color.crop_wp_markers); - mDashOnLength = rsc.getDimension(R.dimen.wp_selector_dash_length); - mDashOffLength = rsc.getDimension(R.dimen.wp_selector_off_length); - } - - public void initialize(Bitmap image, RectF newCropBounds, RectF newPhotoBounds, int rotation) { - mBitmap = image; - if (mCropObj != null) { - RectF crop = mCropObj.getInnerBounds(); - RectF containing = mCropObj.getOuterBounds(); - if (crop != newCropBounds || containing != newPhotoBounds - || mRotation != rotation) { - mRotation = rotation; - mCropObj.resetBoundsTo(newCropBounds, newPhotoBounds); - clearDisplay(); - } - } else { - mRotation = rotation; - mCropObj = new CropObject(newPhotoBounds, newCropBounds, 0); - clearDisplay(); - } - } - - public RectF getCrop() { - return mCropObj.getInnerBounds(); - } - - public RectF getPhoto() { - return mCropObj.getOuterBounds(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - if (mDisplayMatrix == null || mDisplayMatrixInverse == null) { - return true; - } - float[] touchPoint = { - x, y - }; - mDisplayMatrixInverse.mapPoints(touchPoint); - x = touchPoint[0]; - y = touchPoint[1]; - switch (event.getActionMasked()) { - case (MotionEvent.ACTION_DOWN): - if (mState == Mode.NONE) { - if (!mCropObj.selectEdge(x, y)) { - mMovingBlock = mCropObj.selectEdge(CropObject.MOVE_BLOCK); - } - mPrevX = x; - mPrevY = y; - mState = Mode.MOVE; - } - break; - case (MotionEvent.ACTION_UP): - if (mState == Mode.MOVE) { - mCropObj.selectEdge(CropObject.MOVE_NONE); - mMovingBlock = false; - mPrevX = x; - mPrevY = y; - mState = Mode.NONE; - } - break; - case (MotionEvent.ACTION_MOVE): - if (mState == Mode.MOVE) { - float dx = x - mPrevX; - float dy = y - mPrevY; - mCropObj.moveCurrentSelection(dx, dy); - mPrevX = x; - mPrevY = y; - } - break; - default: - break; - } - invalidate(); - return true; - } - - private void reset() { - Log.w(LOGTAG, "crop reset called"); - mState = Mode.NONE; - mCropObj = null; - mRotation = 0; - mMovingBlock = false; - clearDisplay(); - } - - private void clearDisplay() { - mDisplayMatrix = null; - mDisplayMatrixInverse = null; - invalidate(); - } - - protected void configChanged() { - mDirty = true; - } - - public void applyFreeAspect() { - mCropObj.unsetAspectRatio(); - invalidate(); - } - - public void applyOriginalAspect() { - RectF outer = mCropObj.getOuterBounds(); - float w = outer.width(); - float h = outer.height(); - if (w > 0 && h > 0) { - applyAspect(w, h); - mCropObj.resetBoundsTo(outer, outer); - } else { - Log.w(LOGTAG, "failed to set aspect ratio original"); - } - } - - public void applySquareAspect() { - applyAspect(1, 1); - } - - public void applyAspect(float x, float y) { - if (x <= 0 || y <= 0) { - throw new IllegalArgumentException("Bad arguments to applyAspect"); - } - // If we are rotated by 90 degrees from horizontal, swap x and y - if (((mRotation < 0) ? -mRotation : mRotation) % 180 == 90) { - float tmp = x; - x = y; - y = tmp; - } - if (!mCropObj.setInnerAspectRatio(x, y)) { - Log.w(LOGTAG, "failed to set aspect ratio"); - } - invalidate(); - } - - public void setWallpaperSpotlight(float spotlightX, float spotlightY) { - mSpotX = spotlightX; - mSpotY = spotlightY; - if (mSpotX > 0 && mSpotY > 0) { - mDoSpot = true; - } - } - - public void unsetWallpaperSpotlight() { - mDoSpot = false; - } - - /** - * Rotates first d bits in integer x to the left some number of times. - */ - 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; - } - - /** - * Find the selected edge or corner in screen coordinates. - */ - private int decode(int movingEdges, float rotation) { - int rot = CropMath.constrainedRotation(rotation); - switch (rot) { - case 90: - return bitCycleLeft(movingEdges, 1, 4); - case 180: - return bitCycleLeft(movingEdges, 2, 4); - case 270: - return bitCycleLeft(movingEdges, 3, 4); - default: - return movingEdges; - } - } - - @Override - public void onDraw(Canvas canvas) { - if (mBitmap == null) { - return; - } - if (mDirty) { - mDirty = false; - clearDisplay(); - } - - mImageBounds = new RectF(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); - mScreenBounds = new RectF(0, 0, canvas.getWidth(), canvas.getHeight()); - mScreenBounds.inset(mMargin, mMargin); - - // If crop object doesn't exist, create it and update it from master - // state - if (mCropObj == null) { - reset(); - mCropObj = new CropObject(mImageBounds, mImageBounds, 0); - } - - // If display matrix doesn't exist, create it and its dependencies - if (mDisplayMatrix == null || mDisplayMatrixInverse == null) { - mDisplayMatrix = new Matrix(); - mDisplayMatrix.reset(); - if (!CropDrawingUtils.setImageToScreenMatrix(mDisplayMatrix, mImageBounds, mScreenBounds, - mRotation)) { - Log.w(LOGTAG, "failed to get screen matrix"); - mDisplayMatrix = null; - return; - } - mDisplayMatrixInverse = new Matrix(); - mDisplayMatrixInverse.reset(); - if (!mDisplayMatrix.invert(mDisplayMatrixInverse)) { - Log.w(LOGTAG, "could not invert display matrix"); - mDisplayMatrixInverse = null; - return; - } - // Scale min side and tolerance by display matrix scale factor - mCropObj.setMinInnerSideSize(mDisplayMatrixInverse.mapRadius(mMinSideSize)); - mCropObj.setTouchTolerance(mDisplayMatrixInverse.mapRadius(mTouchTolerance)); - } - - mScreenImageBounds.set(mImageBounds); - - // Draw background shadow - if (mDisplayMatrix.mapRect(mScreenImageBounds)) { - int margin = (int) mDisplayMatrix.mapRadius(mShadowMargin); - mScreenImageBounds.roundOut(mShadowBounds); - mShadowBounds.set(mShadowBounds.left - margin, mShadowBounds.top - - margin, mShadowBounds.right + margin, mShadowBounds.bottom + margin); - mShadow.setBounds(mShadowBounds); - mShadow.draw(canvas); - } - - mPaint.setAntiAlias(true); - mPaint.setFilterBitmap(true); - // Draw actual bitmap - canvas.drawBitmap(mBitmap, mDisplayMatrix, mPaint); - - mCropObj.getInnerBounds(mScreenCropBounds); - - if (mDisplayMatrix.mapRect(mScreenCropBounds)) { - - // Draw overlay shadows - Paint p = new Paint(); - p.setColor(mOverlayShadowColor); - p.setStyle(Paint.Style.FILL); - CropDrawingUtils.drawShadows(canvas, p, mScreenCropBounds, mScreenImageBounds); - - // Draw crop rect and markers - CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds); - if (!mDoSpot) { - CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds); - } else { - Paint wpPaint = new Paint(); - wpPaint.setColor(mWPMarkerColor); - wpPaint.setStrokeWidth(3); - wpPaint.setStyle(Paint.Style.STROKE); - wpPaint.setPathEffect(new DashPathEffect(new float[] - {mDashOnLength, mDashOnLength + mDashOffLength}, 0)); - p.setColor(mOverlayWPShadowColor); - CropDrawingUtils.drawWallpaperSelectionFrame(canvas, mScreenCropBounds, - mSpotX, mSpotY, wpPaint, p); - } - CropDrawingUtils.drawIndicators(canvas, mCropIndicator, mIndicatorSize, - mScreenCropBounds, mCropObj.isFixedAspect(), decode(mCropObj.getSelectState(), mRotation)); - } - - } -} diff --git a/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java b/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java deleted file mode 100644 index e18d3104f..000000000 --- a/src/com/android/gallery3d/filtershow/data/FilterStackDBHelper.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.data; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -public class FilterStackDBHelper extends SQLiteOpenHelper { - - public static final int DATABASE_VERSION = 1; - public static final String DATABASE_NAME = "filterstacks.db"; - private static final String SQL_CREATE_TABLE = "CREATE TABLE "; - - public static interface FilterStack { - /** The row uid */ - public static final String _ID = "_id"; - /** The table name */ - public static final String TABLE = "filterstack"; - /** The stack name */ - public static final String STACK_ID = "stack_id"; - /** A serialized stack of filters. */ - public static final String FILTER_STACK= "stack"; - } - - private static final String[][] CREATE_FILTER_STACK = { - { FilterStack._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" }, - { FilterStack.STACK_ID, "TEXT" }, - { FilterStack.FILTER_STACK, "BLOB" }, - }; - - public FilterStackDBHelper(Context context, String name, int version) { - super(context, name, null, version); - } - - public FilterStackDBHelper(Context context, String name) { - this(context, name, DATABASE_VERSION); - } - - public FilterStackDBHelper(Context context) { - this(context, DATABASE_NAME); - } - - @Override - public void onCreate(SQLiteDatabase db) { - createTable(db, FilterStack.TABLE, CREATE_FILTER_STACK); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - dropTable(db, FilterStack.TABLE); - onCreate(db); - } - - protected static void createTable(SQLiteDatabase db, String table, String[][] columns) { - StringBuilder create = new StringBuilder(SQL_CREATE_TABLE); - create.append(table).append('('); - boolean first = true; - for (String[] column : columns) { - if (!first) { - create.append(','); - } - first = false; - for (String val : column) { - create.append(val).append(' '); - } - } - create.append(')'); - db.beginTransaction(); - try { - db.execSQL(create.toString()); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - protected static void dropTable(SQLiteDatabase db, String table) { - db.beginTransaction(); - try { - db.execSQL("drop table if exists " + table); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/data/FilterStackSource.java b/src/com/android/gallery3d/filtershow/data/FilterStackSource.java deleted file mode 100644 index d283771b4..000000000 --- a/src/com/android/gallery3d/filtershow/data/FilterStackSource.java +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.data; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.util.Log; -import android.util.Pair; - -import com.android.gallery3d.filtershow.data.FilterStackDBHelper.FilterStack; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -import java.util.ArrayList; -import java.util.List; - -public class FilterStackSource { - private static final String LOGTAG = "FilterStackSource"; - - private SQLiteDatabase database = null; - private final FilterStackDBHelper dbHelper; - - public FilterStackSource(Context context) { - dbHelper = new FilterStackDBHelper(context); - } - - public void open() { - try { - database = dbHelper.getWritableDatabase(); - } catch (SQLiteException e) { - Log.w(LOGTAG, "could not open database", e); - } - } - - public void close() { - database = null; - dbHelper.close(); - } - - public boolean insertStack(String stackName, byte[] stackBlob) { - boolean ret = true; - ContentValues val = new ContentValues(); - val.put(FilterStack.STACK_ID, stackName); - val.put(FilterStack.FILTER_STACK, stackBlob); - database.beginTransaction(); - try { - ret = (-1 != database.insert(FilterStack.TABLE, null, val)); - database.setTransactionSuccessful(); - } finally { - database.endTransaction(); - } - return ret; - } - - public void updateStackName(int id, String stackName) { - ContentValues val = new ContentValues(); - val.put(FilterStack.STACK_ID, stackName); - database.beginTransaction(); - try { - database.update(FilterStack.TABLE, val, FilterStack._ID + " = ?", - new String[] { "" + id}); - database.setTransactionSuccessful(); - } finally { - database.endTransaction(); - } - } - - public boolean removeStack(int id) { - boolean ret = true; - database.beginTransaction(); - try { - ret = (0 != database.delete(FilterStack.TABLE, FilterStack._ID + " = ?", - new String[] { "" + id })); - database.setTransactionSuccessful(); - } finally { - database.endTransaction(); - } - return ret; - } - - public void removeAllStacks() { - database.beginTransaction(); - try { - database.delete(FilterStack.TABLE, null, null); - database.setTransactionSuccessful(); - } finally { - database.endTransaction(); - } - } - - public byte[] getStack(String stackName) { - byte[] ret = null; - Cursor c = null; - database.beginTransaction(); - try { - c = database.query(FilterStack.TABLE, - new String[] { FilterStack.FILTER_STACK }, - FilterStack.STACK_ID + " = ?", - new String[] { stackName }, null, null, null, null); - if (c != null && c.moveToFirst() && !c.isNull(0)) { - ret = c.getBlob(0); - } - database.setTransactionSuccessful(); - } finally { - if (c != null) { - c.close(); - } - database.endTransaction(); - } - return ret; - } - - public ArrayList<FilterUserPresetRepresentation> getAllUserPresets() { - ArrayList<FilterUserPresetRepresentation> ret = - new ArrayList<FilterUserPresetRepresentation>(); - - Cursor c = null; - database.beginTransaction(); - try { - c = database.query(FilterStack.TABLE, - new String[] { FilterStack._ID, - FilterStack.STACK_ID, - FilterStack.FILTER_STACK }, - null, null, null, null, null, null); - if (c != null) { - boolean loopCheck = c.moveToFirst(); - while (loopCheck) { - int id = c.getInt(0); - String name = (c.isNull(1)) ? null : c.getString(1); - byte[] b = (c.isNull(2)) ? null : c.getBlob(2); - String json = new String(b); - - ImagePreset preset = new ImagePreset(); - preset.readJsonFromString(json); - FilterUserPresetRepresentation representation = - new FilterUserPresetRepresentation(name, preset, id); - ret.add(representation); - loopCheck = c.moveToNext(); - } - } - database.setTransactionSuccessful(); - } finally { - if (c != null) { - c.close(); - } - database.endTransaction(); - } - - return ret; - } - - public List<Pair<String, byte[]>> getAllStacks() { - List<Pair<String, byte[]>> ret = new ArrayList<Pair<String, byte[]>>(); - Cursor c = null; - database.beginTransaction(); - try { - c = database.query(FilterStack.TABLE, - new String[] { FilterStack.STACK_ID, FilterStack.FILTER_STACK }, - null, null, null, null, null, null); - if (c != null) { - boolean loopCheck = c.moveToFirst(); - while (loopCheck) { - String name = (c.isNull(0)) ? null : c.getString(0); - byte[] b = (c.isNull(1)) ? null : c.getBlob(1); - ret.add(new Pair<String, byte[]>(name, b)); - loopCheck = c.moveToNext(); - } - } - database.setTransactionSuccessful(); - } finally { - if (c != null) { - c.close(); - } - database.endTransaction(); - } - if (ret.size() <= 0) { - return null; - } - return ret; - } -} diff --git a/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java b/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java deleted file mode 100644 index 114cd3ebc..000000000 --- a/src/com/android/gallery3d/filtershow/data/UserPresetsManager.java +++ /dev/null @@ -1,149 +0,0 @@ -package com.android.gallery3d.filtershow.data; - -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -import java.util.ArrayList; - -public class UserPresetsManager implements Handler.Callback { - - private static final String LOGTAG = "UserPresetsManager"; - - private FilterShowActivity mActivity; - private HandlerThread mHandlerThread = null; - private Handler mProcessingHandler = null; - private FilterStackSource mUserPresets; - - private static final int LOAD = 1; - private static final int LOAD_RESULT = 2; - private static final int SAVE = 3; - private static final int DELETE = 4; - private static final int UPDATE = 5; - - private ArrayList<FilterUserPresetRepresentation> mRepresentations; - - private final Handler mResultHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - switch (msg.what) { - case LOAD_RESULT: - resultLoad(msg); - break; - } - } - }; - - @Override - public boolean handleMessage(Message msg) { - switch (msg.what) { - case LOAD: - processLoad(); - return true; - case SAVE: - processSave(msg); - return true; - case DELETE: - processDelete(msg); - return true; - case UPDATE: - processUpdate(msg); - return true; - } - return false; - } - - public UserPresetsManager(FilterShowActivity context) { - mActivity = context; - mHandlerThread = new HandlerThread(LOGTAG, - android.os.Process.THREAD_PRIORITY_BACKGROUND); - mHandlerThread.start(); - mProcessingHandler = new Handler(mHandlerThread.getLooper(), this); - mUserPresets = new FilterStackSource(mActivity); - mUserPresets.open(); - } - - public ArrayList<FilterUserPresetRepresentation> getRepresentations() { - return mRepresentations; - } - - public void load() { - Message msg = mProcessingHandler.obtainMessage(LOAD); - mProcessingHandler.sendMessage(msg); - } - - public void close() { - mUserPresets.close(); - mHandlerThread.quit(); - } - - static class SaveOperation { - String json; - String name; - } - - public void save(ImagePreset preset) { - Message msg = mProcessingHandler.obtainMessage(SAVE); - SaveOperation op = new SaveOperation(); - op.json = preset.getJsonString(mActivity.getString(R.string.saved)); - op.name= mActivity.getString(R.string.filtershow_new_preset); - msg.obj = op; - mProcessingHandler.sendMessage(msg); - } - - public void delete(int id) { - Message msg = mProcessingHandler.obtainMessage(DELETE); - msg.arg1 = id; - mProcessingHandler.sendMessage(msg); - } - - static class UpdateOperation { - int id; - String name; - } - - public void update(FilterUserPresetRepresentation representation) { - Message msg = mProcessingHandler.obtainMessage(UPDATE); - UpdateOperation op = new UpdateOperation(); - op.id = representation.getId(); - op.name = representation.getName(); - msg.obj = op; - mProcessingHandler.sendMessage(msg); - } - - private void processLoad() { - ArrayList<FilterUserPresetRepresentation> list = mUserPresets.getAllUserPresets(); - Message msg = mResultHandler.obtainMessage(LOAD_RESULT); - msg.obj = list; - mResultHandler.sendMessage(msg); - } - - private void resultLoad(Message msg) { - mRepresentations = - (ArrayList<FilterUserPresetRepresentation>) msg.obj; - mActivity.updateUserPresetsFromManager(); - } - - private void processSave(Message msg) { - SaveOperation op = (SaveOperation) msg.obj; - mUserPresets.insertStack(op.name, op.json.getBytes()); - processLoad(); - } - - private void processDelete(Message msg) { - int id = msg.arg1; - mUserPresets.removeStack(id); - processLoad(); - } - - private void processUpdate(Message msg) { - UpdateOperation op = (UpdateOperation) msg.obj; - mUserPresets.updateStackName(op.id, op.name); - processLoad(); - } - -} diff --git a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java b/src/com/android/gallery3d/filtershow/editors/BasicEditor.java deleted file mode 100644 index af694d811..000000000 --- a/src/com/android/gallery3d/filtershow/editors/BasicEditor.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.controller.Control; -import com.android.gallery3d.filtershow.controller.FilterView; -import com.android.gallery3d.filtershow.controller.Parameter; -import com.android.gallery3d.filtershow.controller.ParameterInteger; -import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; - - -/** - * The basic editor that all the one parameter filters - */ -public class BasicEditor extends ParametricEditor implements ParameterInteger { - public static int ID = R.id.basicEditor; - private final String LOGTAG = "BasicEditor"; - - public BasicEditor() { - super(ID, R.layout.filtershow_default_editor, R.id.basicEditor); - } - - protected BasicEditor(int id) { - super(id, R.layout.filtershow_default_editor, R.id.basicEditor); - } - - protected BasicEditor(int id, int layoutID, int viewID) { - super(id, layoutID, viewID); - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - if (getLocalRepresentation() != null && getLocalRepresentation() instanceof FilterBasicRepresentation) { - FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation(); - updateText(); - } - } - - private FilterBasicRepresentation getBasicRepresentation() { - FilterRepresentation tmpRep = getLocalRepresentation(); - if (tmpRep != null && tmpRep instanceof FilterBasicRepresentation) { - return (FilterBasicRepresentation) tmpRep; - - } - return null; - } - - @Override - public int getMaximum() { - FilterBasicRepresentation rep = getBasicRepresentation(); - if (rep == null) { - return 0; - } - return rep.getMaximum(); - } - - @Override - public int getMinimum() { - FilterBasicRepresentation rep = getBasicRepresentation(); - if (rep == null) { - return 0; - } - return rep.getMinimum(); - } - - @Override - public int getDefaultValue() { - return 0; - } - - @Override - public int getValue() { - FilterBasicRepresentation rep = getBasicRepresentation(); - if (rep == null) { - return 0; - } - return rep.getValue(); - } - - @Override - public String getValueString() { - return null; - } - - @Override - public void setValue(int value) { - FilterBasicRepresentation rep = getBasicRepresentation(); - if (rep == null) { - return; - } - rep.setValue(value); - commitLocalRepresentation(); - } - - @Override - public String getParameterName() { - FilterBasicRepresentation rep = getBasicRepresentation(); - return mContext.getString(rep.getTextId()); - } - - @Override - public String getParameterType() { - return sParameterType; - } - - @Override - public void setController(Control c) { - } - - @Override - public void setFilterView(FilterView editor) { - - } - - @Override - public void copyFrom(Parameter src) { - - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/Editor.java b/src/com/android/gallery3d/filtershow/editors/Editor.java deleted file mode 100644 index a9e56e0c1..000000000 --- a/src/com/android/gallery3d/filtershow/editors/Editor.java +++ /dev/null @@ -1,330 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.controller.Control; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageShow; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -import java.util.ArrayList; -import java.util.Collection; - -/** - * Base class for Editors Must contain a mImageShow and a top level view - */ -public class Editor implements OnSeekBarChangeListener, SwapButton.SwapButtonListener { - protected Context mContext; - protected View mView; - protected ImageShow mImageShow; - protected FrameLayout mFrameLayout; - protected SeekBar mSeekBar; - Button mEditTitle; - protected Button mFilterTitle; - protected int mID; - private final String LOGTAG = "Editor"; - protected boolean mChangesGeometry = false; - protected FilterRepresentation mLocalRepresentation = null; - protected byte mShowParameter = SHOW_VALUE_UNDEFINED; - private Button mButton; - public static byte SHOW_VALUE_UNDEFINED = -1; - public static byte SHOW_VALUE_OFF = 0; - public static byte SHOW_VALUE_INT = 1; - - public static void hackFixStrings(Menu menu) { - int count = menu.size(); - for (int i = 0; i < count; i++) { - MenuItem item = menu.getItem(i); - item.setTitle(item.getTitle().toString().toUpperCase()); - } - } - - public String calculateUserMessage(Context context, String effectName, Object parameterValue) { - return effectName.toUpperCase() + " " + parameterValue; - } - - protected Editor(int id) { - mID = id; - } - - public int getID() { - return mID; - } - - public byte showParameterValue() { - return mShowParameter; - } - - public boolean showsSeekBar() { - return true; - } - - public void setUpEditorUI(View actionButton, View editControl, - Button editTitle, Button stateButton) { - mEditTitle = editTitle; - mFilterTitle = stateButton; - mButton = editTitle; - setMenuIcon(true); - setUtilityPanelUI(actionButton, editControl); - } - - public boolean showsPopupIndicator() { - return true; - } - - /** - * @param actionButton the would be the area for menu etc - * @param editControl this is the black area for sliders etc - */ - public void setUtilityPanelUI(View actionButton, View editControl) { - - AttributeSet aset; - Context context = editControl.getContext(); - LayoutInflater inflater = - (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - LinearLayout lp = (LinearLayout) inflater.inflate( - R.layout.filtershow_seekbar, (ViewGroup) editControl, true); - mSeekBar = (SeekBar) lp.findViewById(R.id.primarySeekBar); - mSeekBar.setOnSeekBarChangeListener(this); - - if (showsSeekBar()) { - mSeekBar.setOnSeekBarChangeListener(this); - mSeekBar.setVisibility(View.VISIBLE); - } else { - mSeekBar.setVisibility(View.INVISIBLE); - } - - if (mButton != null) { - if (showsPopupIndicator()) { - mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, - R.drawable.filtershow_menu_marker, 0); - } else { - mButton.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0); - } - } - } - - @Override - public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) { - - } - - public void setPanel() { - - } - - public void createEditor(Context context,FrameLayout frameLayout) { - mContext = context; - mFrameLayout = frameLayout; - mLocalRepresentation = null; - } - - protected void unpack(int viewid, int layoutid) { - - if (mView == null) { - mView = mFrameLayout.findViewById(viewid); - if (mView == null) { - LayoutInflater inflater = (LayoutInflater) mContext.getSystemService - (Context.LAYOUT_INFLATER_SERVICE); - mView = inflater.inflate(layoutid, mFrameLayout, false); - mFrameLayout.addView(mView, mView.getLayoutParams()); - } - } - mImageShow = findImageShow(mView); - } - - private ImageShow findImageShow(View view) { - if (view instanceof ImageShow) { - return (ImageShow) view; - } - if (!(view instanceof ViewGroup)) { - return null; - } - ViewGroup vg = (ViewGroup) view; - int n = vg.getChildCount(); - for (int i = 0; i < n; i++) { - View v = vg.getChildAt(i); - if (v instanceof ImageShow) { - return (ImageShow) v; - } else if (v instanceof ViewGroup) { - return findImageShow(v); - } - } - return null; - } - - public View getTopLevelView() { - return mView; - } - - public ImageShow getImageShow() { - return mImageShow; - } - - public void setVisibility(int visible) { - mView.setVisibility(visible); - } - - public FilterRepresentation getLocalRepresentation() { - if (mLocalRepresentation == null) { - ImagePreset preset = MasterImage.getImage().getPreset(); - FilterRepresentation filterRepresentation = MasterImage.getImage().getCurrentFilterRepresentation(); - mLocalRepresentation = preset.getFilterRepresentationCopyFrom(filterRepresentation); - if (mShowParameter == SHOW_VALUE_UNDEFINED && filterRepresentation != null) { - boolean show = filterRepresentation.showParameterValue(); - mShowParameter = show ? SHOW_VALUE_INT : SHOW_VALUE_OFF; - } - - } - return mLocalRepresentation; - } - - /** - * Call this to update the preset in MasterImage with the current representation - * returned by getLocalRepresentation. This causes the preview bitmap to be - * regenerated. - */ - public void commitLocalRepresentation() { - commitLocalRepresentation(getLocalRepresentation()); - } - - /** - * Call this to update the preset in MasterImage with a given representation. - * This causes the preview bitmap to be regenerated. - */ - public void commitLocalRepresentation(FilterRepresentation rep) { - ArrayList<FilterRepresentation> filter = new ArrayList<FilterRepresentation>(1); - filter.add(rep); - commitLocalRepresentation(filter); - } - - /** - * Call this to update the preset in MasterImage with a collection of FilterRepresnations. - * This causes the preview bitmap to be regenerated. - */ - public void commitLocalRepresentation(Collection<FilterRepresentation> reps) { - ImagePreset preset = MasterImage.getImage().getPreset(); - preset.updateFilterRepresentations(reps); - if (mButton != null) { - updateText(); - } - if (mChangesGeometry) { - // Regenerate both the filtered and the geometry-only bitmaps - MasterImage.getImage().updatePresets(true); - } else { - // Regenerate only the filtered bitmap. - MasterImage.getImage().invalidateFiltersOnly(); - } - preset.fillImageStateAdapter(MasterImage.getImage().getState()); - } - - /** - * This is called in response to a click to apply and leave the editor. - */ - public void finalApplyCalled() { - commitLocalRepresentation(); - } - - protected void updateText() { - String s = ""; - if (mLocalRepresentation != null) { - s = mContext.getString(mLocalRepresentation.getTextId()); - } - mButton.setText(calculateUserMessage(mContext, s, "")); - } - - /** - * called after the filter is set and the select is called - */ - public void reflectCurrentFilter() { - mLocalRepresentation = null; - FilterRepresentation representation = getLocalRepresentation(); - if (representation != null && mFilterTitle != null && representation.getTextId() != 0) { - String text = mContext.getString(representation.getTextId()).toUpperCase(); - mFilterTitle.setText(text); - updateText(); - } - } - - public boolean useUtilityPanel() { - return true; - } - - public void openUtilityPanel(LinearLayout mAccessoryViewList) { - setMenuIcon(false); - if (mImageShow != null) { - mImageShow.openUtilityPanel(mAccessoryViewList); - } - } - - protected void setMenuIcon(boolean on) { - mEditTitle.setCompoundDrawablesRelativeWithIntrinsicBounds( - 0, 0, on ? R.drawable.filtershow_menu_marker : 0, 0); - } - - protected void createMenu(int[] strId, View button) { - PopupMenu pmenu = new PopupMenu(mContext, button); - Menu menu = pmenu.getMenu(); - for (int i = 0; i < strId.length; i++) { - menu.add(Menu.NONE, Menu.FIRST + i, 0, mContext.getString(strId[i])); - } - setMenuIcon(true); - - } - - public Control[] getControls() { - return null; - } - @Override - public void onStartTrackingTouch(SeekBar arg0) { - - } - - @Override - public void onStopTrackingTouch(SeekBar arg0) { - - } - - @Override - public void swapLeft(MenuItem item) { - - } - - @Override - public void swapRight(MenuItem item) { - - } - - public void detach() { - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java b/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java deleted file mode 100644 index 7e31f09ae..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorChanSat.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.graphics.Bitmap; -import android.os.Handler; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.SeekBar.OnSeekBarChangeListener; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.controller.BasicParameterStyle; -import com.android.gallery3d.filtershow.controller.FilterView; -import com.android.gallery3d.filtershow.controller.Parameter; -import com.android.gallery3d.filtershow.filters.FilterChanSatRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.filtershow.pipeline.RenderingRequest; -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; - -public class EditorChanSat extends ParametricEditor implements OnSeekBarChangeListener, FilterView { - public static final int ID = R.id.editorChanSat; - private final String LOGTAG = "EditorGrunge"; - private SwapButton mButton; - private final Handler mHandler = new Handler(); - - int[] mMenuStrings = { - R.string.editor_chan_sat_main, - R.string.editor_chan_sat_red, - R.string.editor_chan_sat_yellow, - R.string.editor_chan_sat_green, - R.string.editor_chan_sat_cyan, - R.string.editor_chan_sat_blue, - R.string.editor_chan_sat_magenta - }; - - String mCurrentlyEditing = null; - - public EditorChanSat() { - super(ID, R.layout.filtershow_default_editor, R.id.basicEditor); - } - - @Override - public String calculateUserMessage(Context context, String effectName, Object parameterValue) { - FilterRepresentation rep = getLocalRepresentation(); - if (rep == null || !(rep instanceof FilterChanSatRepresentation)) { - return ""; - } - FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep; - int mode = csrep.getParameterMode(); - String paramString; - - paramString = mContext.getString(mMenuStrings[mode]); - - int val = csrep.getCurrentParameter(); - return paramString + ((val > 0) ? " +" : " ") + val; - } - - @Override - public void openUtilityPanel(final LinearLayout accessoryViewList) { - mButton = (SwapButton) accessoryViewList.findViewById(R.id.applyEffect); - mButton.setText(mContext.getString(R.string.editor_chan_sat_main)); - - final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), mButton); - - popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_chan_sat, popupMenu.getMenu()); - - popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - selectMenuItem(item); - return true; - } - }); - mButton.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - popupMenu.show(); - } - }); - mButton.setListener(this); - - FilterChanSatRepresentation csrep = getChanSatRep(); - String menuString = mContext.getString(mMenuStrings[0]); - switchToMode(csrep, FilterChanSatRepresentation.MODE_MASTER, menuString); - - } - - public int getParameterIndex(int id) { - switch (id) { - case R.id.editor_chan_sat_main: - return FilterChanSatRepresentation.MODE_MASTER; - case R.id.editor_chan_sat_red: - return FilterChanSatRepresentation.MODE_RED; - case R.id.editor_chan_sat_yellow: - return FilterChanSatRepresentation.MODE_YELLOW; - case R.id.editor_chan_sat_green: - return FilterChanSatRepresentation.MODE_GREEN; - case R.id.editor_chan_sat_cyan: - return FilterChanSatRepresentation.MODE_CYAN; - case R.id.editor_chan_sat_blue: - return FilterChanSatRepresentation.MODE_BLUE; - case R.id.editor_chan_sat_magenta: - return FilterChanSatRepresentation.MODE_MAGENTA; - } - return -1; - } - - @Override - public void detach() { - mButton.setListener(null); - mButton.setOnClickListener(null); - } - - private void updateSeekBar(FilterChanSatRepresentation rep) { - mControl.updateUI(); - } - - @Override - protected Parameter getParameterToEdit(FilterRepresentation rep) { - if (rep instanceof FilterChanSatRepresentation) { - FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep; - Parameter param = csrep.getFilterParameter(csrep.getParameterMode()); - if (param instanceof BasicParameterStyle) { - param.setFilterView(EditorChanSat.this); - } - return param; - } - return null; - } - - private FilterChanSatRepresentation getChanSatRep() { - FilterRepresentation rep = getLocalRepresentation(); - if (rep != null - && rep instanceof FilterChanSatRepresentation) { - FilterChanSatRepresentation csrep = (FilterChanSatRepresentation) rep; - return csrep; - } - return null; - } - - @Override - public void computeIcon(int n, RenderingRequestCaller caller) { - FilterChanSatRepresentation rep = getChanSatRep(); - if (rep == null) return; - rep = (FilterChanSatRepresentation) rep.copy(); - ImagePreset preset = new ImagePreset(); - preset.addFilter(rep); - Bitmap src = MasterImage.getImage().getThumbnailBitmap(); - RenderingRequest.post(null, src, preset, RenderingRequest.STYLE_ICON_RENDERING, - caller); - } - - protected void selectMenuItem(MenuItem item) { - if (getLocalRepresentation() != null - && getLocalRepresentation() instanceof FilterChanSatRepresentation) { - FilterChanSatRepresentation csrep = - (FilterChanSatRepresentation) getLocalRepresentation(); - - switchToMode(csrep, getParameterIndex(item.getItemId()), item.getTitle().toString()); - - } - } - - protected void switchToMode(FilterChanSatRepresentation csrep, int mode, String title) { - csrep.setParameterMode(mode); - mCurrentlyEditing = title; - mButton.setText(mCurrentlyEditing); - { - Parameter param = getParameterToEdit(csrep); - - control(param, mEditControl); - } - updateSeekBar(csrep); - mView.invalidate(); - } - - @Override - public void swapLeft(MenuItem item) { - super.swapLeft(item); - mButton.setTranslationX(0); - mButton.animate().translationX(mButton.getWidth()).setDuration(SwapButton.ANIM_DURATION); - Runnable updateButton = new Runnable() { - @Override - public void run() { - mButton.animate().cancel(); - mButton.setTranslationX(0); - } - }; - mHandler.postDelayed(updateButton, SwapButton.ANIM_DURATION); - selectMenuItem(item); - } - - @Override - public void swapRight(MenuItem item) { - super.swapRight(item); - mButton.setTranslationX(0); - mButton.animate().translationX(-mButton.getWidth()).setDuration(SwapButton.ANIM_DURATION); - Runnable updateButton = new Runnable() { - @Override - public void run() { - mButton.animate().cancel(); - mButton.setTranslationX(0); - } - }; - mHandler.postDelayed(updateButton, SwapButton.ANIM_DURATION); - selectMenuItem(item); - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorCrop.java b/src/com/android/gallery3d/filtershow/editors/EditorCrop.java deleted file mode 100644 index 511d4ff87..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorCrop.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.util.Log; -import android.util.SparseArray; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.PopupMenu; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterCropRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageCrop; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class EditorCrop extends Editor implements EditorInfo { - public static final String TAG = EditorCrop.class.getSimpleName(); - public static final int ID = R.id.editorCrop; - - // Holder for an aspect ratio it's string id - protected static final class AspectInfo { - int mAspectX; - int mAspectY; - int mStringId; - AspectInfo(int stringID, int x, int y) { - mStringId = stringID; - mAspectX = x; - mAspectY = y; - } - }; - - // Mapping from menu id to aspect ratio - protected static final SparseArray<AspectInfo> sAspects; - static { - sAspects = new SparseArray<AspectInfo>(); - sAspects.put(R.id.crop_menu_1to1, new AspectInfo(R.string.aspect1to1_effect, 1, 1)); - sAspects.put(R.id.crop_menu_4to3, new AspectInfo(R.string.aspect4to3_effect, 4, 3)); - sAspects.put(R.id.crop_menu_3to4, new AspectInfo(R.string.aspect3to4_effect, 3, 4)); - sAspects.put(R.id.crop_menu_5to7, new AspectInfo(R.string.aspect5to7_effect, 5, 7)); - sAspects.put(R.id.crop_menu_7to5, new AspectInfo(R.string.aspect7to5_effect, 7, 5)); - sAspects.put(R.id.crop_menu_none, new AspectInfo(R.string.aspectNone_effect, 0, 0)); - sAspects.put(R.id.crop_menu_original, new AspectInfo(R.string.aspectOriginal_effect, 0, 0)); - } - - protected ImageCrop mImageCrop; - private String mAspectString = ""; - - public EditorCrop() { - super(ID); - mChangesGeometry = true; - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - if (mImageCrop == null) { - mImageCrop = new ImageCrop(context); - } - mView = mImageShow = mImageCrop; - mImageCrop.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - MasterImage master = MasterImage.getImage(); - master.setCurrentFilterRepresentation(master.getPreset() - .getFilterWithSerializationName(FilterCropRepresentation.SERIALIZATION_NAME)); - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - if (rep == null || rep instanceof FilterCropRepresentation) { - mImageCrop.setFilterCropRepresentation((FilterCropRepresentation) rep); - } else { - Log.w(TAG, "Could not reflect current filter, not of type: " - + FilterCropRepresentation.class.getSimpleName()); - } - mImageCrop.invalidate(); - } - - @Override - public void finalApplyCalled() { - commitLocalRepresentation(mImageCrop.getFinalRepresentation()); - } - - @Override - public void openUtilityPanel(final LinearLayout accessoryViewList) { - Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect); - view.setText(mContext.getString(R.string.crop)); - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - showPopupMenu(accessoryViewList); - } - }); - } - - private void changeCropAspect(int itemId) { - AspectInfo info = sAspects.get(itemId); - if (info == null) { - throw new IllegalArgumentException("Invalid resource ID: " + itemId); - } - if (itemId == R.id.crop_menu_original) { - mImageCrop.applyOriginalAspect(); - } else if (itemId == R.id.crop_menu_none) { - mImageCrop.applyFreeAspect(); - } else { - mImageCrop.applyAspect(info.mAspectX, info.mAspectY); - } - setAspectString(mContext.getString(info.mStringId)); - } - - private void showPopupMenu(LinearLayout accessoryViewList) { - final Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect); - final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), button); - popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_crop, popupMenu.getMenu()); - popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - changeCropAspect(item.getItemId()); - return true; - } - }); - popupMenu.show(); - } - - @Override - public boolean showsSeekBar() { - return false; - } - - @Override - public int getTextId() { - return R.string.crop; - } - - @Override - public int getOverlayId() { - return R.drawable.filtershow_button_geometry_crop; - } - - @Override - public boolean getOverlayOnly() { - return true; - } - - private void setAspectString(String s) { - mAspectString = s; - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java b/src/com/android/gallery3d/filtershow/editors/EditorCurves.java deleted file mode 100644 index 83fbced79..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorCurves.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.widget.FrameLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageCurves; - -public class EditorCurves extends Editor { - public static final int ID = R.id.imageCurves; - ImageCurves mImageCurves; - - public EditorCurves() { - super(ID); - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - mView = mImageShow = mImageCurves = new ImageCurves(context); - mImageCurves.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - if (rep != null && getLocalRepresentation() instanceof FilterCurvesRepresentation) { - FilterCurvesRepresentation drawRep = (FilterCurvesRepresentation) rep; - mImageCurves.setFilterDrawRepresentation(drawRep); - } - } - - @Override - public boolean showsSeekBar() { - return false; - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java b/src/com/android/gallery3d/filtershow/editors/EditorDraw.java deleted file mode 100644 index 4b09051e2..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorDraw.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.app.Dialog; -import android.content.Context; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.WindowManager.LayoutParams; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.SeekBar; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.colorpicker.ColorGridDialog; -import com.android.gallery3d.filtershow.colorpicker.RGBListener; -import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.ImageFilterDraw; -import com.android.gallery3d.filtershow.imageshow.ImageDraw; - -public class EditorDraw extends Editor { - private static final String LOGTAG = "EditorDraw"; - public static final int ID = R.id.editorDraw; - public ImageDraw mImageDraw; - - public EditorDraw() { - super(ID); - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - mView = mImageShow = mImageDraw = new ImageDraw(context); - mImageDraw.setEditor(this); - - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - - if (rep != null && getLocalRepresentation() instanceof FilterDrawRepresentation) { - FilterDrawRepresentation drawRep = (FilterDrawRepresentation) getLocalRepresentation(); - mImageDraw.setFilterDrawRepresentation(drawRep); - } - } - - @Override - public void openUtilityPanel(final LinearLayout accessoryViewList) { - Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect); - view.setText(mContext.getString(R.string.draw_style)); - view.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View arg0) { - showPopupMenu(accessoryViewList); - } - }); - } - - @Override - public boolean showsSeekBar() { - return false; - } - - private void showPopupMenu(LinearLayout accessoryViewList) { - final Button button = (Button) accessoryViewList.findViewById( - R.id.applyEffect); - if (button == null) { - return; - } - final PopupMenu popupMenu = new PopupMenu(mImageShow.getActivity(), button); - popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_draw, popupMenu.getMenu()); - popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - - @Override - public boolean onMenuItemClick(MenuItem item) { - ImageFilterDraw filter = (ImageFilterDraw) mImageShow.getCurrentFilter(); - if (item.getItemId() == R.id.draw_menu_color) { - showColorGrid(item); - } else if (item.getItemId() == R.id.draw_menu_size) { - showSizeDialog(item); - } else if (item.getItemId() == R.id.draw_menu_style_brush_marker) { - ImageDraw idraw = (ImageDraw) mImageShow; - idraw.setStyle(ImageFilterDraw.BRUSH_STYLE_MARKER); - } else if (item.getItemId() == R.id.draw_menu_style_brush_spatter) { - ImageDraw idraw = (ImageDraw) mImageShow; - idraw.setStyle(ImageFilterDraw.BRUSH_STYLE_SPATTER); - } else if (item.getItemId() == R.id.draw_menu_style_line) { - ImageDraw idraw = (ImageDraw) mImageShow; - idraw.setStyle(ImageFilterDraw.SIMPLE_STYLE); - } else if (item.getItemId() == R.id.draw_menu_clear) { - ImageDraw idraw = (ImageDraw) mImageShow; - idraw.resetParameter(); - commitLocalRepresentation(); - } - mView.invalidate(); - return true; - } - }); - popupMenu.show(); - } - - public void showSizeDialog(final MenuItem item) { - FilterShowActivity ctx = mImageShow.getActivity(); - final Dialog dialog = new Dialog(ctx); - dialog.setTitle(R.string.draw_size_title); - dialog.setContentView(R.layout.filtershow_draw_size); - final SeekBar bar = (SeekBar) dialog.findViewById(R.id.sizeSeekBar); - ImageDraw idraw = (ImageDraw) mImageShow; - bar.setProgress(idraw.getSize()); - Button button = (Button) dialog.findViewById(R.id.sizeAcceptButton); - button.setOnClickListener(new OnClickListener() { - - @Override - public void onClick(View arg0) { - int p = bar.getProgress(); - ImageDraw idraw = (ImageDraw) mImageShow; - idraw.setSize(p + 1); - dialog.dismiss(); - } - }); - dialog.show(); - } - - public void showColorGrid(final MenuItem item) { - RGBListener cl = new RGBListener() { - @Override - public void setColor(int rgb) { - ImageDraw idraw = (ImageDraw) mImageShow; - idraw.setColor(rgb); - } - }; - ColorGridDialog cpd = new ColorGridDialog(mImageShow.getActivity(), cl); - cpd.show(); - LayoutParams params = cpd.getWindow().getAttributes(); - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorGrad.java b/src/com/android/gallery3d/filtershow/editors/EditorGrad.java deleted file mode 100644 index f427ccbd8..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorGrad.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.view.MenuItem; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.PopupMenu; -import android.widget.SeekBar; -import android.widget.SeekBar.OnSeekBarChangeListener; -import android.widget.ToggleButton; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.controller.Control; -import com.android.gallery3d.filtershow.controller.FilterView; -import com.android.gallery3d.filtershow.controller.Parameter; -import com.android.gallery3d.filtershow.controller.ParameterActionAndInt; -import com.android.gallery3d.filtershow.filters.FilterGradRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageGrad; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class EditorGrad extends ParametricEditor - implements OnSeekBarChangeListener, ParameterActionAndInt { - private static final String LOGTAG = "EditorGrad"; - public static final int ID = R.id.editorGrad; - PopupMenu mPopupMenu; - ToggleButton mAddModeButton; - String mEffectName = ""; - private static final int MODE_BRIGHTNESS = FilterGradRepresentation.PARAM_BRIGHTNESS; - private static final int MODE_SATURATION = FilterGradRepresentation.PARAM_SATURATION; - private static final int MODE_CONTRAST = FilterGradRepresentation.PARAM_CONTRAST; - private static final int ADD_ICON = R.drawable.ic_grad_add; - private static final int DEL_ICON = R.drawable.ic_grad_del; - private int mSliderMode = MODE_BRIGHTNESS; - ImageGrad mImageGrad; - - public EditorGrad() { - super(ID, R.layout.filtershow_grad_editor, R.id.gradEditor); - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - mImageGrad = (ImageGrad) mImageShow; - mImageGrad.setEditor(this); - - } - - public void clearAddMode() { - mAddModeButton.setChecked(false); - FilterRepresentation tmpRep = getLocalRepresentation(); - if (tmpRep instanceof FilterGradRepresentation) { - updateMenuItems((FilterGradRepresentation) tmpRep); - } - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - FilterRepresentation tmpRep = getLocalRepresentation(); - if (tmpRep instanceof FilterGradRepresentation) { - FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep; - boolean f = rep.showParameterValue(); - - mImageGrad.setRepresentation(rep); - } - } - - public void updateSeekBar(FilterGradRepresentation rep) { - mControl.updateUI(); - } - - @Override - public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) { - FilterRepresentation tmpRep = getLocalRepresentation(); - if (tmpRep instanceof FilterGradRepresentation) { - FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep; - int min = rep.getParameterMin(mSliderMode); - int value = progress + min; - rep.setParameter(mSliderMode, value); - mView.invalidate(); - commitLocalRepresentation(); - } - } - - @Override - public void openUtilityPanel(final LinearLayout accessoryViewList) { - Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect); - view.setText(mContext.getString(R.string.editor_grad_brightness)); - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - showPopupMenu(accessoryViewList); - } - }); - - setUpPopupMenu(view); - setEffectName(); - } - - private void updateMenuItems(FilterGradRepresentation rep) { - int n = rep.getNumberOfBands(); - } - - public void setEffectName() { - if (mPopupMenu != null) { - MenuItem item = mPopupMenu.getMenu().findItem(R.id.editor_grad_brightness); - mEffectName = item.getTitle().toString(); - } - } - - private void showPopupMenu(LinearLayout accessoryViewList) { - Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect); - if (button == null) { - return; - } - - if (mPopupMenu == null) { - setUpPopupMenu(button); - } - mPopupMenu.show(); - } - - private void setUpPopupMenu(Button button) { - mPopupMenu = new PopupMenu(mImageShow.getActivity(), button); - mPopupMenu.getMenuInflater() - .inflate(R.menu.filtershow_menu_grad, mPopupMenu.getMenu()); - FilterGradRepresentation rep = (FilterGradRepresentation) getLocalRepresentation(); - if (rep == null) { - return; - } - updateMenuItems(rep); - hackFixStrings(mPopupMenu.getMenu()); - setEffectName(); - updateText(); - - mPopupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - FilterRepresentation tmpRep = getLocalRepresentation(); - - if (tmpRep instanceof FilterGradRepresentation) { - FilterGradRepresentation rep = (FilterGradRepresentation) tmpRep; - int cmdID = item.getItemId(); - switch (cmdID) { - case R.id.editor_grad_brightness: - mSliderMode = MODE_BRIGHTNESS; - mEffectName = item.getTitle().toString(); - break; - case R.id.editor_grad_contrast: - mSliderMode = MODE_CONTRAST; - mEffectName = item.getTitle().toString(); - break; - case R.id.editor_grad_saturation: - mSliderMode = MODE_SATURATION; - mEffectName = item.getTitle().toString(); - break; - } - updateMenuItems(rep); - updateSeekBar(rep); - - commitLocalRepresentation(); - mView.invalidate(); - } - return true; - } - }); - } - - @Override - public String calculateUserMessage(Context context, String effectName, Object parameterValue) { - FilterGradRepresentation rep = getGradRepresentation(); - if (rep == null) { - return mEffectName; - } - int val = rep.getParameter(mSliderMode); - return mEffectName.toUpperCase() + ((val > 0) ? " +" : " ") + val; - } - - private FilterGradRepresentation getGradRepresentation() { - FilterRepresentation tmpRep = getLocalRepresentation(); - if (tmpRep instanceof FilterGradRepresentation) { - return (FilterGradRepresentation) tmpRep; - } - return null; - } - - @Override - public int getMaximum() { - FilterGradRepresentation rep = getGradRepresentation(); - if (rep == null) { - return 0; - } - return rep.getParameterMax(mSliderMode); - } - - @Override - public int getMinimum() { - FilterGradRepresentation rep = getGradRepresentation(); - if (rep == null) { - return 0; - } - return rep.getParameterMin(mSliderMode); - } - - @Override - public int getDefaultValue() { - return 0; - } - - @Override - public int getValue() { - FilterGradRepresentation rep = getGradRepresentation(); - if (rep == null) { - return 0; - } - return rep.getParameter(mSliderMode); - } - - @Override - public String getValueString() { - return null; - } - - @Override - public void setValue(int value) { - FilterGradRepresentation rep = getGradRepresentation(); - if (rep == null) { - return; - } - rep.setParameter(mSliderMode, value); - } - - @Override - public String getParameterName() { - return mEffectName; - } - - @Override - public String getParameterType() { - return sParameterType; - } - - @Override - public void setController(Control c) { - - } - - @Override - public void fireLeftAction() { - FilterGradRepresentation rep = getGradRepresentation(); - if (rep == null) { - return; - } - rep.addBand(MasterImage.getImage().getOriginalBounds()); - updateMenuItems(rep); - updateSeekBar(rep); - - commitLocalRepresentation(); - mView.invalidate(); - } - - @Override - public int getLeftIcon() { - return ADD_ICON; - } - - @Override - public void fireRightAction() { - FilterGradRepresentation rep = getGradRepresentation(); - if (rep == null) { - return; - } - rep.deleteCurrentBand(); - - updateMenuItems(rep); - updateSeekBar(rep); - commitLocalRepresentation(); - mView.invalidate(); - } - - @Override - public int getRightIcon() { - return DEL_ICON; - } - - @Override - public void setFilterView(FilterView editor) { - - } - - @Override - public void copyFrom(Parameter src) { - - } - -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorInfo.java b/src/com/android/gallery3d/filtershow/editors/EditorInfo.java deleted file mode 100644 index 75afe49c2..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorInfo.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -public interface EditorInfo { - public int getTextId(); - public int getOverlayId(); - public boolean getOverlayOnly(); -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorMirror.java b/src/com/android/gallery3d/filtershow/editors/EditorMirror.java deleted file mode 100644 index d6d9ee75d..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorMirror.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageMirror; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class EditorMirror extends Editor implements EditorInfo { - public static final String TAG = EditorMirror.class.getSimpleName(); - public static final int ID = R.id.editorFlip; - ImageMirror mImageMirror; - - public EditorMirror() { - super(ID); - mChangesGeometry = true; - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - if (mImageMirror == null) { - mImageMirror = new ImageMirror(context); - } - mView = mImageShow = mImageMirror; - mImageMirror.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - MasterImage master = MasterImage.getImage(); - master.setCurrentFilterRepresentation(master.getPreset() - .getFilterWithSerializationName(FilterMirrorRepresentation.SERIALIZATION_NAME)); - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - if (rep == null || rep instanceof FilterMirrorRepresentation) { - mImageMirror.setFilterMirrorRepresentation((FilterMirrorRepresentation) rep); - } else { - Log.w(TAG, "Could not reflect current filter, not of type: " - + FilterMirrorRepresentation.class.getSimpleName()); - } - mImageMirror.invalidate(); - } - - @Override - public void openUtilityPanel(final LinearLayout accessoryViewList) { - final Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect); - button.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - mImageMirror.flip(); - } - }); - } - - @Override - public void finalApplyCalled() { - commitLocalRepresentation(mImageMirror.getFinalRepresentation()); - } - - @Override - public int getTextId() { - return R.string.mirror; - } - - @Override - public int getOverlayId() { - return R.drawable.filtershow_button_geometry_flip; - } - - @Override - public boolean getOverlayOnly() { - return true; - } - - @Override - public boolean showsSeekBar() { - return false; - } - - @Override - public boolean showsPopupIndicator() { - return false; - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java b/src/com/android/gallery3d/filtershow/editors/EditorPanel.java deleted file mode 100644 index bc4ca6ab6..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorPanel.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.app.Activity; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentTransaction; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.history.HistoryManager; -import com.android.gallery3d.filtershow.category.MainPanel; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.state.StatePanel; - -public class EditorPanel extends Fragment { - - private static final String LOGTAG = "EditorPanel"; - - private LinearLayout mMainView; - private Editor mEditor; - private int mEditorID; - - public void setEditor(int editor) { - mEditorID = editor; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - FilterShowActivity filterShowActivity = (FilterShowActivity) activity; - mEditor = filterShowActivity.getEditor(mEditorID); - } - - public void cancelCurrentFilter() { - MasterImage masterImage = MasterImage.getImage(); - HistoryManager adapter = masterImage.getHistory(); - - int position = adapter.undo(); - masterImage.onHistoryItemClick(position); - ((FilterShowActivity)getActivity()).invalidateViews(); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - FilterShowActivity activity = (FilterShowActivity) getActivity(); - if (mMainView != null) { - if (mMainView.getParent() != null) { - ViewGroup parent = (ViewGroup) mMainView.getParent(); - parent.removeView(mMainView); - } - showImageStatePanel(activity.isShowingImageStatePanel()); - return mMainView; - } - mMainView = (LinearLayout) inflater.inflate(R.layout.filtershow_editor_panel, null); - - View actionControl = mMainView.findViewById(R.id.panelAccessoryViewList); - View editControl = mMainView.findViewById(R.id.controlArea); - ImageButton cancelButton = (ImageButton) mMainView.findViewById(R.id.cancelFilter); - ImageButton applyButton = (ImageButton) mMainView.findViewById(R.id.applyFilter); - Button editTitle = (Button) mMainView.findViewById(R.id.applyEffect); - cancelButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - cancelCurrentFilter(); - FilterShowActivity activity = (FilterShowActivity) getActivity(); - activity.backToMain(); - } - }); - - Button toggleState = (Button) mMainView.findViewById(R.id.toggle_state); - mEditor = activity.getEditor(mEditorID); - if (mEditor != null) { - mEditor.setUpEditorUI(actionControl, editControl, editTitle, toggleState); - mEditor.reflectCurrentFilter(); - if (mEditor.useUtilityPanel()) { - mEditor.openUtilityPanel((LinearLayout) actionControl); - } - } - applyButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - FilterShowActivity activity = (FilterShowActivity) getActivity(); - mEditor.finalApplyCalled(); - activity.backToMain(); - } - }); - - showImageStatePanel(activity.isShowingImageStatePanel()); - return mMainView; - } - - @Override - public void onDetach() { - if (mEditor != null) { - mEditor.detach(); - } - super.onDetach(); - } - - public void showImageStatePanel(boolean show) { - if (mMainView.findViewById(R.id.state_panel_container) == null) { - return; - } - FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); - Fragment panel = getActivity().getSupportFragmentManager().findFragmentByTag( - MainPanel.FRAGMENT_TAG); - if (panel == null || panel instanceof MainPanel) { - transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); - } - if (show) { - StatePanel statePanel = new StatePanel(); - transaction.replace(R.id.state_panel_container, statePanel, StatePanel.FRAGMENT_TAG); - } else { - Fragment statePanel = getChildFragmentManager().findFragmentByTag(StatePanel.FRAGMENT_TAG); - if (statePanel != null) { - transaction.remove(statePanel); - } - } - transaction.commit(); - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java b/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java deleted file mode 100644 index b0e88dd44..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorRedEye.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.widget.FrameLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterRedEyeRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageRedEye; - -/** - * The editor with no slider for filters without UI - */ -public class EditorRedEye extends Editor { - public static int ID = R.id.editorRedEye; - private final String LOGTAG = "EditorRedEye"; - ImageRedEye mImageRedEyes; - - public EditorRedEye() { - super(ID); - } - - protected EditorRedEye(int id) { - super(id); - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - mView = mImageShow = mImageRedEyes= new ImageRedEye(context); - mImageRedEyes.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - if (rep != null && getLocalRepresentation() instanceof FilterRedEyeRepresentation) { - FilterRedEyeRepresentation redEyeRep = (FilterRedEyeRepresentation) rep; - - mImageRedEyes.setRepresentation(redEyeRep); - } - } - - @Override - public boolean showsSeekBar() { - return false; - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorRotate.java b/src/com/android/gallery3d/filtershow/editors/EditorRotate.java deleted file mode 100644 index 9452bf0c0..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorRotate.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.util.Log; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.FrameLayout; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageRotate; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class EditorRotate extends Editor implements EditorInfo { - public static final String TAG = EditorRotate.class.getSimpleName(); - public static final int ID = R.id.editorRotate; - ImageRotate mImageRotate; - - public EditorRotate() { - super(ID); - mChangesGeometry = true; - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - if (mImageRotate == null) { - mImageRotate = new ImageRotate(context); - } - mView = mImageShow = mImageRotate; - mImageRotate.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - MasterImage master = MasterImage.getImage(); - master.setCurrentFilterRepresentation(master.getPreset() - .getFilterWithSerializationName(FilterRotateRepresentation.SERIALIZATION_NAME)); - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - if (rep == null || rep instanceof FilterRotateRepresentation) { - mImageRotate.setFilterRotateRepresentation((FilterRotateRepresentation) rep); - } else { - Log.w(TAG, "Could not reflect current filter, not of type: " - + FilterRotateRepresentation.class.getSimpleName()); - } - mImageRotate.invalidate(); - } - - @Override - public void openUtilityPanel(final LinearLayout accessoryViewList) { - final Button button = (Button) accessoryViewList.findViewById(R.id.applyEffect); - button.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - mImageRotate.rotate(); - String displayVal = mContext.getString(getTextId()) + " " - + mImageRotate.getLocalValue(); - button.setText(displayVal); - } - }); - } - - @Override - public void finalApplyCalled() { - commitLocalRepresentation(mImageRotate.getFinalRepresentation()); - } - - @Override - public int getTextId() { - return R.string.rotate; - } - - @Override - public int getOverlayId() { - return R.drawable.filtershow_button_geometry_rotate; - } - - @Override - public boolean getOverlayOnly() { - return true; - } - - @Override - public boolean showsSeekBar() { - return false; - } - - @Override - public boolean showsPopupIndicator() { - return false; - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java b/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java deleted file mode 100644 index ff84ba8f9..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorStraighten.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.util.Log; -import android.widget.FrameLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageStraighten; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class EditorStraighten extends Editor implements EditorInfo { - public static final String TAG = EditorStraighten.class.getSimpleName(); - public static final int ID = R.id.editorStraighten; - ImageStraighten mImageStraighten; - - public EditorStraighten() { - super(ID); - mShowParameter = SHOW_VALUE_INT; - mChangesGeometry = true; - } - - @Override - public String calculateUserMessage(Context context, String effectName, Object parameterValue) { - String apply = context.getString(R.string.apply_effect); - apply += " " + effectName; - return apply.toUpperCase(); - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - if (mImageStraighten == null) { - mImageStraighten = new ImageStraighten(context); - } - mView = mImageShow = mImageStraighten; - mImageStraighten.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - MasterImage master = MasterImage.getImage(); - master.setCurrentFilterRepresentation(master.getPreset().getFilterWithSerializationName( - FilterStraightenRepresentation.SERIALIZATION_NAME)); - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - if (rep == null || rep instanceof FilterStraightenRepresentation) { - mImageStraighten - .setFilterStraightenRepresentation((FilterStraightenRepresentation) rep); - } else { - Log.w(TAG, "Could not reflect current filter, not of type: " - + FilterStraightenRepresentation.class.getSimpleName()); - } - mImageStraighten.invalidate(); - } - - @Override - public void finalApplyCalled() { - commitLocalRepresentation(mImageStraighten.getFinalRepresentation()); - } - - @Override - public int getTextId() { - return R.string.straighten; - } - - @Override - public int getOverlayId() { - return R.drawable.filtershow_button_geometry_straighten; - } - - @Override - public boolean getOverlayOnly() { - return true; - } - - @Override - public boolean showsSeekBar() { - return false; - } - - @Override - public boolean showsPopupIndicator() { - return false; - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java b/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java deleted file mode 100644 index 9376fbef0..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorTinyPlanet.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.widget.FrameLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageTinyPlanet; - -public class EditorTinyPlanet extends BasicEditor { - public static final int ID = R.id.tinyPlanetEditor; - private static final String LOGTAG = "EditorTinyPlanet"; - ImageTinyPlanet mImageTinyPlanet; - - public EditorTinyPlanet() { - super(ID, R.layout.filtershow_tiny_planet_editor, R.id.imageTinyPlanet); - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - mImageTinyPlanet = (ImageTinyPlanet) mImageShow; - mImageTinyPlanet.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - FilterRepresentation rep = getLocalRepresentation(); - if (rep != null && rep instanceof FilterTinyPlanetRepresentation) { - FilterTinyPlanetRepresentation drawRep = (FilterTinyPlanetRepresentation) rep; - mImageTinyPlanet.setRepresentation(drawRep); - } - } - - public void updateUI() { - if (mControl != null) { - mControl.updateUI(); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java b/src/com/android/gallery3d/filtershow/editors/EditorVignette.java deleted file mode 100644 index 7127b2188..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorVignette.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.widget.FrameLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterVignetteRepresentation; -import com.android.gallery3d.filtershow.imageshow.ImageVignette; - -public class EditorVignette extends ParametricEditor { - public static final int ID = R.id.vignetteEditor; - private static final String LOGTAG = "EditorVignettePlanet"; - ImageVignette mImageVignette; - - public EditorVignette() { - super(ID, R.layout.filtershow_vignette_editor, R.id.imageVignette); - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - mImageVignette = (ImageVignette) mImageShow; - mImageVignette.setEditor(this); - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - - FilterRepresentation rep = getLocalRepresentation(); - if (rep != null && getLocalRepresentation() instanceof FilterVignetteRepresentation) { - FilterVignetteRepresentation drawRep = (FilterVignetteRepresentation) rep; - mImageVignette.setRepresentation(drawRep); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/EditorZoom.java b/src/com/android/gallery3d/filtershow/editors/EditorZoom.java deleted file mode 100644 index ea8e3d140..000000000 --- a/src/com/android/gallery3d/filtershow/editors/EditorZoom.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import com.android.gallery3d.R; - -public class EditorZoom extends BasicEditor { - public static final int ID = R.id.imageZoom; - - public EditorZoom() { - super(ID, R.layout.filtershow_zoom_editor,R.id.imageZoom); - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java b/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java deleted file mode 100644 index d4e66edf8..000000000 --- a/src/com/android/gallery3d/filtershow/editors/ImageOnlyEditor.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.widget.FrameLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.imageshow.ImageShow; - -/** - * The editor with no slider for filters without UI - */ -public class ImageOnlyEditor extends Editor { - public final static int ID = R.id.imageOnlyEditor; - private final String LOGTAG = "ImageOnlyEditor"; - - public ImageOnlyEditor() { - super(ID); - } - - protected ImageOnlyEditor(int id) { - super(id); - } - - public boolean useUtilityPanel() { - return false; - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - mView = mImageShow = new ImageShow(context); - } - -} diff --git a/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java b/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java deleted file mode 100644 index 9ec858ca5..000000000 --- a/src/com/android/gallery3d/filtershow/editors/ParametricEditor.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.graphics.Point; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; -import android.view.ViewGroup.LayoutParams; -import android.view.WindowManager; -import android.widget.FrameLayout; -import android.widget.LinearLayout; -import android.widget.SeekBar; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.controller.ActionSlider; -import com.android.gallery3d.filtershow.controller.BasicSlider; -import com.android.gallery3d.filtershow.controller.Control; -import com.android.gallery3d.filtershow.controller.Parameter; -import com.android.gallery3d.filtershow.controller.ParameterActionAndInt; -import com.android.gallery3d.filtershow.controller.ParameterInteger; -import com.android.gallery3d.filtershow.controller.ParameterStyles; -import com.android.gallery3d.filtershow.controller.StyleChooser; -import com.android.gallery3d.filtershow.controller.TitledSlider; -import com.android.gallery3d.filtershow.filters.FilterBasicRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; - -import java.lang.reflect.Constructor; -import java.util.HashMap; - -public class ParametricEditor extends Editor { - private int mLayoutID; - private int mViewID; - public static int ID = R.id.editorParametric; - private final String LOGTAG = "ParametricEditor"; - protected Control mControl; - public static final int MINIMUM_WIDTH = 600; - public static final int MINIMUM_HEIGHT = 800; - View mActionButton; - View mEditControl; - static HashMap<String, Class> portraitMap = new HashMap<String, Class>(); - static HashMap<String, Class> landscapeMap = new HashMap<String, Class>(); - static { - portraitMap.put(ParameterInteger.sParameterType, BasicSlider.class); - landscapeMap.put(ParameterInteger.sParameterType, TitledSlider.class); - portraitMap.put(ParameterActionAndInt.sParameterType, ActionSlider.class); - landscapeMap.put(ParameterActionAndInt.sParameterType, ActionSlider.class); - portraitMap.put(ParameterStyles.sParameterType, StyleChooser.class); - landscapeMap.put(ParameterStyles.sParameterType, StyleChooser.class); - } - - static Constructor getConstructor(Class cl) { - try { - return cl.getConstructor(Context.class, ViewGroup.class); - } catch (Exception e) { - return null; - } - } - - public ParametricEditor() { - super(ID); - } - - protected ParametricEditor(int id) { - super(id); - } - - protected ParametricEditor(int id, int layoutID, int viewID) { - super(id); - mLayoutID = layoutID; - mViewID = viewID; - } - - @Override - public String calculateUserMessage(Context context, String effectName, Object parameterValue) { - String apply = ""; - - if (mShowParameter == SHOW_VALUE_INT & useCompact(context)) { - if (getLocalRepresentation() instanceof FilterBasicRepresentation) { - FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation(); - apply += " " + effectName.toUpperCase() + " " + interval.getStateRepresentation(); - } else { - apply += " " + effectName.toUpperCase() + " " + parameterValue; - } - } else { - apply += " " + effectName.toUpperCase(); - } - return apply; - } - - @Override - public void createEditor(Context context, FrameLayout frameLayout) { - super.createEditor(context, frameLayout); - unpack(mViewID, mLayoutID); - } - - @Override - public void reflectCurrentFilter() { - super.reflectCurrentFilter(); - if (getLocalRepresentation() != null - && getLocalRepresentation() instanceof FilterBasicRepresentation) { - FilterBasicRepresentation interval = (FilterBasicRepresentation) getLocalRepresentation(); - mControl.setPrameter(interval); - } - } - - @Override - public Control[] getControls() { - BasicSlider slider = new BasicSlider(); - return new Control[] { - slider - }; - } - - // TODO: need a better way to decide which representation - static boolean useCompact(Context context) { - WindowManager w = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)); - Point size = new Point(); - w.getDefaultDisplay().getSize(size); - if (size.x < size.y) { // if tall than wider - return true; - } - if (size.x < MINIMUM_WIDTH) { - return true; - } - if (size.y < MINIMUM_HEIGHT) { - return true; - } - return false; - } - - protected Parameter getParameterToEdit(FilterRepresentation rep) { - if (this instanceof Parameter) { - return (Parameter) this; - } else if (rep instanceof Parameter) { - return ((Parameter) rep); - } - return null; - } - - @Override - public void setUtilityPanelUI(View actionButton, View editControl) { - mActionButton = actionButton; - mEditControl = editControl; - FilterRepresentation rep = getLocalRepresentation(); - Parameter param = getParameterToEdit(rep); - if (param != null) { - control(param, editControl); - } else { - mSeekBar = new SeekBar(editControl.getContext()); - LayoutParams lp = new LinearLayout.LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); - mSeekBar.setLayoutParams(lp); - ((LinearLayout) editControl).addView(mSeekBar); - mSeekBar.setOnSeekBarChangeListener(this); - } - } - - protected void control(Parameter p, View editControl) { - String pType = p.getParameterType(); - Context context = editControl.getContext(); - Class c = ((useCompact(context)) ? portraitMap : landscapeMap).get(pType); - - if (c != null) { - try { - mControl = (Control) c.newInstance(); - p.setController(mControl); - mControl.setUp((ViewGroup) editControl, p, this); - } catch (Exception e) { - Log.e(LOGTAG, "Error in loading Control ", e); - } - } else { - Log.e(LOGTAG, "Unable to find class for " + pType); - for (String string : portraitMap.keySet()) { - Log.e(LOGTAG, "for " + string + " use " + portraitMap.get(string)); - } - } - } - - @Override - public void onProgressChanged(SeekBar sbar, int progress, boolean arg2) { - } - - @Override - public void onStartTrackingTouch(SeekBar arg0) { - } - - @Override - public void onStopTrackingTouch(SeekBar arg0) { - } -} diff --git a/src/com/android/gallery3d/filtershow/editors/SwapButton.java b/src/com/android/gallery3d/filtershow/editors/SwapButton.java deleted file mode 100644 index bb4432e28..000000000 --- a/src/com/android/gallery3d/filtershow/editors/SwapButton.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.editors; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.Menu; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.widget.Button; - -public class SwapButton extends Button implements GestureDetector.OnGestureListener { - - public static int ANIM_DURATION = 200; - - public interface SwapButtonListener { - public void swapLeft(MenuItem item); - public void swapRight(MenuItem item); - } - - private GestureDetector mDetector; - private SwapButtonListener mListener; - private Menu mMenu; - private int mCurrentMenuIndex; - - public SwapButton(Context context, AttributeSet attrs) { - super(context, attrs); - mDetector = new GestureDetector(context, this); - } - - public SwapButtonListener getListener() { - return mListener; - } - - public void setListener(SwapButtonListener listener) { - mListener = listener; - } - - public boolean onTouchEvent(MotionEvent me) { - if (!mDetector.onTouchEvent(me)) { - return super.onTouchEvent(me); - } - return true; - } - - @Override - public boolean onDown(MotionEvent e) { - return true; - } - - @Override - public void onShowPress(MotionEvent e) { - } - - @Override - public boolean onSingleTapUp(MotionEvent e) { - callOnClick(); - return true; - } - - @Override - public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { - return false; - } - - @Override - public void onLongPress(MotionEvent e) { - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - if (mMenu == null) { - return false; - } - if (e1.getX() - e2.getX() > 0) { - // right to left - mCurrentMenuIndex++; - if (mCurrentMenuIndex == mMenu.size()) { - mCurrentMenuIndex = 0; - } - if (mListener != null) { - mListener.swapRight(mMenu.getItem(mCurrentMenuIndex)); - } - } else { - // left to right - mCurrentMenuIndex--; - if (mCurrentMenuIndex < 0) { - mCurrentMenuIndex = mMenu.size() - 1; - } - if (mListener != null) { - mListener.swapLeft(mMenu.getItem(mCurrentMenuIndex)); - } - } - return true; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java b/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java deleted file mode 100644 index 3fa91916d..000000000 --- a/src/com/android/gallery3d/filtershow/filters/BaseFiltersManager.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.filters; - -import android.content.Context; -import android.content.res.Resources; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorCrop; -import com.android.gallery3d.filtershow.editors.EditorMirror; -import com.android.gallery3d.filtershow.editors.EditorRotate; -import com.android.gallery3d.filtershow.editors.EditorStraighten; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Vector; - -public abstract class BaseFiltersManager implements FiltersManagerInterface { - protected HashMap<Class, ImageFilter> mFilters = null; - protected HashMap<String, FilterRepresentation> mRepresentationLookup = null; - private static final String LOGTAG = "BaseFiltersManager"; - - protected ArrayList<FilterRepresentation> mLooks = new ArrayList<FilterRepresentation>(); - protected ArrayList<FilterRepresentation> mBorders = new ArrayList<FilterRepresentation>(); - protected ArrayList<FilterRepresentation> mTools = new ArrayList<FilterRepresentation>(); - protected ArrayList<FilterRepresentation> mEffects = new ArrayList<FilterRepresentation>(); - - protected void init() { - mFilters = new HashMap<Class, ImageFilter>(); - mRepresentationLookup = new HashMap<String, FilterRepresentation>(); - Vector<Class> filters = new Vector<Class>(); - addFilterClasses(filters); - for (Class filterClass : filters) { - try { - Object filterInstance = filterClass.newInstance(); - if (filterInstance instanceof ImageFilter) { - mFilters.put(filterClass, (ImageFilter) filterInstance); - - FilterRepresentation rep = - ((ImageFilter) filterInstance).getDefaultRepresentation(); - if (rep != null) { - addRepresentation(rep); - } - } - } catch (InstantiationException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } - } - } - - public void addRepresentation(FilterRepresentation rep) { - mRepresentationLookup.put(rep.getSerializationName(), rep); - } - - public FilterRepresentation createFilterFromName(String name) { - try { - return mRepresentationLookup.get(name).copy(); - } catch (Exception e) { - Log.v(LOGTAG, "unable to generate a filter representation for \"" + name + "\""); - e.printStackTrace(); - } - return null; - } - - public ImageFilter getFilter(Class c) { - return mFilters.get(c); - } - - @Override - public ImageFilter getFilterForRepresentation(FilterRepresentation representation) { - return mFilters.get(representation.getFilterClass()); - } - - public FilterRepresentation getRepresentation(Class c) { - ImageFilter filter = mFilters.get(c); - if (filter != null) { - return filter.getDefaultRepresentation(); - } - return null; - } - - public void freeFilterResources(ImagePreset preset) { - if (preset == null) { - return; - } - Vector<ImageFilter> usedFilters = preset.getUsedFilters(this); - for (Class c : mFilters.keySet()) { - ImageFilter filter = mFilters.get(c); - if (!usedFilters.contains(filter)) { - filter.freeResources(); - } - } - } - - public void freeRSFilterScripts() { - for (Class c : mFilters.keySet()) { - ImageFilter filter = mFilters.get(c); - if (filter != null && filter instanceof ImageFilterRS) { - ((ImageFilterRS) filter).resetScripts(); - } - } - } - - protected void addFilterClasses(Vector<Class> filters) { - filters.add(ImageFilterTinyPlanet.class); - filters.add(ImageFilterRedEye.class); - filters.add(ImageFilterWBalance.class); - filters.add(ImageFilterExposure.class); - filters.add(ImageFilterVignette.class); - filters.add(ImageFilterGrad.class); - filters.add(ImageFilterContrast.class); - filters.add(ImageFilterShadows.class); - filters.add(ImageFilterHighlights.class); - filters.add(ImageFilterVibrance.class); - filters.add(ImageFilterSharpen.class); - filters.add(ImageFilterCurves.class); - filters.add(ImageFilterDraw.class); - filters.add(ImageFilterHue.class); - filters.add(ImageFilterChanSat.class); - filters.add(ImageFilterSaturated.class); - filters.add(ImageFilterBwFilter.class); - filters.add(ImageFilterNegative.class); - filters.add(ImageFilterEdge.class); - filters.add(ImageFilterKMeans.class); - filters.add(ImageFilterFx.class); - filters.add(ImageFilterBorder.class); - filters.add(ImageFilterParametricBorder.class); - } - - public ArrayList<FilterRepresentation> getLooks() { - return mLooks; - } - - public ArrayList<FilterRepresentation> getBorders() { - return mBorders; - } - - public ArrayList<FilterRepresentation> getTools() { - return mTools; - } - - public ArrayList<FilterRepresentation> getEffects() { - return mEffects; - } - - public void addBorders(Context context) { - - } - - public void addLooks(Context context) { - int[] drawid = { - R.drawable.filtershow_fx_0005_punch, - R.drawable.filtershow_fx_0000_vintage, - R.drawable.filtershow_fx_0004_bw_contrast, - R.drawable.filtershow_fx_0002_bleach, - R.drawable.filtershow_fx_0001_instant, - R.drawable.filtershow_fx_0007_washout, - R.drawable.filtershow_fx_0003_blue_crush, - R.drawable.filtershow_fx_0008_washout_color, - R.drawable.filtershow_fx_0006_x_process - }; - - int[] fxNameid = { - R.string.ffx_punch, - R.string.ffx_vintage, - R.string.ffx_bw_contrast, - R.string.ffx_bleach, - R.string.ffx_instant, - R.string.ffx_washout, - R.string.ffx_blue_crush, - R.string.ffx_washout_color, - R.string.ffx_x_process - }; - - // Do not localize. - String[] serializationNames = { - "LUT3D_PUNCH", - "LUT3D_VINTAGE", - "LUT3D_BW", - "LUT3D_BLEACH", - "LUT3D_INSTANT", - "LUT3D_WASHOUT", - "LUT3D_BLUECRUSH", - "LUT3D_WASHOUT", - "LUT3D_XPROCESS" - }; - - FilterFxRepresentation nullFx = - new FilterFxRepresentation(context.getString(R.string.none), - 0, R.string.none); - mLooks.add(nullFx); - - for (int i = 0; i < drawid.length; i++) { - FilterFxRepresentation fx = new FilterFxRepresentation( - context.getString(fxNameid[i]), drawid[i], fxNameid[i]); - fx.setSerializationName(serializationNames[i]); - ImagePreset preset = new ImagePreset(); - preset.addFilter(fx); - FilterUserPresetRepresentation rep = new FilterUserPresetRepresentation( - context.getString(fxNameid[i]), preset, -1); - mLooks.add(rep); - addRepresentation(fx); - } - } - - public void addEffects() { - mEffects.add(getRepresentation(ImageFilterTinyPlanet.class)); - mEffects.add(getRepresentation(ImageFilterWBalance.class)); - mEffects.add(getRepresentation(ImageFilterExposure.class)); - mEffects.add(getRepresentation(ImageFilterVignette.class)); - mEffects.add(getRepresentation(ImageFilterGrad.class)); - mEffects.add(getRepresentation(ImageFilterContrast.class)); - mEffects.add(getRepresentation(ImageFilterShadows.class)); - mEffects.add(getRepresentation(ImageFilterHighlights.class)); - mEffects.add(getRepresentation(ImageFilterVibrance.class)); - mEffects.add(getRepresentation(ImageFilterSharpen.class)); - mEffects.add(getRepresentation(ImageFilterCurves.class)); - mEffects.add(getRepresentation(ImageFilterHue.class)); - mEffects.add(getRepresentation(ImageFilterChanSat.class)); - mEffects.add(getRepresentation(ImageFilterBwFilter.class)); - mEffects.add(getRepresentation(ImageFilterNegative.class)); - mEffects.add(getRepresentation(ImageFilterEdge.class)); - mEffects.add(getRepresentation(ImageFilterKMeans.class)); - } - - public void addTools(Context context) { - - int[] editorsId = { - EditorCrop.ID, - EditorStraighten.ID, - EditorRotate.ID, - EditorMirror.ID - }; - - int[] textId = { - R.string.crop, - R.string.straighten, - R.string.rotate, - R.string.mirror - }; - - int[] overlayId = { - R.drawable.filtershow_button_geometry_crop, - R.drawable.filtershow_button_geometry_straighten, - R.drawable.filtershow_button_geometry_rotate, - R.drawable.filtershow_button_geometry_flip - }; - - FilterRepresentation[] geometryFilters = { - new FilterCropRepresentation(), - new FilterStraightenRepresentation(), - new FilterRotateRepresentation(), - new FilterMirrorRepresentation() - }; - - for (int i = 0; i < editorsId.length; i++) { - int editorId = editorsId[i]; - FilterRepresentation geometry = geometryFilters[i]; - geometry.setEditorId(editorId); - geometry.setTextId(textId[i]); - geometry.setOverlayId(overlayId[i]); - geometry.setOverlayOnly(true); - if (geometry.getTextId() != 0) { - geometry.setName(context.getString(geometry.getTextId())); - } - mTools.add(geometry); - } - - mTools.add(getRepresentation(ImageFilterRedEye.class)); - mTools.add(getRepresentation(ImageFilterDraw.class)); - } - - public void setFilterResources(Resources resources) { - ImageFilterBorder filterBorder = (ImageFilterBorder) getFilter(ImageFilterBorder.class); - filterBorder.setResources(resources); - ImageFilterFx filterFx = (ImageFilterFx) getFilter(ImageFilterFx.class); - filterFx.setResources(resources); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java b/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java deleted file mode 100644 index 7c307a9e7..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ColorSpaceMatrix.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import java.util.Arrays; - -public class ColorSpaceMatrix { - private final float[] mMatrix = new float[16]; - private static final float RLUM = 0.3086f; - private static final float GLUM = 0.6094f; - private static final float BLUM = 0.0820f; - - public ColorSpaceMatrix() { - identity(); - } - - /** - * Copy constructor - * - * @param matrix - */ - public ColorSpaceMatrix(ColorSpaceMatrix matrix) { - System.arraycopy(matrix.mMatrix, 0, mMatrix, 0, matrix.mMatrix.length); - } - - /** - * get the matrix - * - * @return the internal matrix - */ - public float[] getMatrix() { - return mMatrix; - } - - /** - * set matrix to identity - */ - public void identity() { - Arrays.fill(mMatrix, 0); - mMatrix[0] = mMatrix[5] = mMatrix[10] = mMatrix[15] = 1; - } - - public void convertToLuminance() { - mMatrix[0] = mMatrix[1] = mMatrix[2] = 0.3086f; - mMatrix[4] = mMatrix[5] = mMatrix[6] = 0.6094f; - mMatrix[8] = mMatrix[9] = mMatrix[10] = 0.0820f; - } - - private void multiply(float[] a) - { - int x, y; - float[] temp = new float[16]; - - for (y = 0; y < 4; y++) { - int y4 = y * 4; - for (x = 0; x < 4; x++) { - temp[y4 + x] = mMatrix[y4 + 0] * a[x] - + mMatrix[y4 + 1] * a[4 + x] - + mMatrix[y4 + 2] * a[8 + x] - + mMatrix[y4 + 3] * a[12 + x]; - } - } - for (int i = 0; i < 16; i++) - mMatrix[i] = temp[i]; - } - - private void xRotateMatrix(float rs, float rc) - { - ColorSpaceMatrix c = new ColorSpaceMatrix(); - float[] tmp = c.mMatrix; - - tmp[5] = rc; - tmp[6] = rs; - tmp[9] = -rs; - tmp[10] = rc; - - multiply(tmp); - } - - private void yRotateMatrix(float rs, float rc) - { - ColorSpaceMatrix c = new ColorSpaceMatrix(); - float[] tmp = c.mMatrix; - - tmp[0] = rc; - tmp[2] = -rs; - tmp[8] = rs; - tmp[10] = rc; - - multiply(tmp); - } - - private void zRotateMatrix(float rs, float rc) - { - ColorSpaceMatrix c = new ColorSpaceMatrix(); - float[] tmp = c.mMatrix; - - tmp[0] = rc; - tmp[1] = rs; - tmp[4] = -rs; - tmp[5] = rc; - multiply(tmp); - } - - private void zShearMatrix(float dx, float dy) - { - ColorSpaceMatrix c = new ColorSpaceMatrix(); - float[] tmp = c.mMatrix; - - tmp[2] = dx; - tmp[6] = dy; - multiply(tmp); - } - - /** - * sets the transform to a shift in Hue - * - * @param rot rotation in degrees - */ - public void setHue(float rot) - { - float mag = (float) Math.sqrt(2.0); - float xrs = 1 / mag; - float xrc = 1 / mag; - xRotateMatrix(xrs, xrc); - mag = (float) Math.sqrt(3.0); - float yrs = -1 / mag; - float yrc = (float) Math.sqrt(2.0) / mag; - yRotateMatrix(yrs, yrc); - - float lx = getRedf(RLUM, GLUM, BLUM); - float ly = getGreenf(RLUM, GLUM, BLUM); - float lz = getBluef(RLUM, GLUM, BLUM); - float zsx = lx / lz; - float zsy = ly / lz; - zShearMatrix(zsx, zsy); - - float zrs = (float) Math.sin(rot * Math.PI / 180.0); - float zrc = (float) Math.cos(rot * Math.PI / 180.0); - zRotateMatrix(zrs, zrc); - zShearMatrix(-zsx, -zsy); - yRotateMatrix(-yrs, yrc); - xRotateMatrix(-xrs, xrc); - } - - /** - * set it to a saturation matrix - * - * @param s - */ - public void changeSaturation(float s) { - mMatrix[0] = (1 - s) * RLUM + s; - mMatrix[1] = (1 - s) * RLUM; - mMatrix[2] = (1 - s) * RLUM; - mMatrix[4] = (1 - s) * GLUM; - mMatrix[5] = (1 - s) * GLUM + s; - mMatrix[6] = (1 - s) * GLUM; - mMatrix[8] = (1 - s) * BLUM; - mMatrix[9] = (1 - s) * BLUM; - mMatrix[10] = (1 - s) * BLUM + s; - } - - /** - * Transform RGB value - * - * @param r red pixel value - * @param g green pixel value - * @param b blue pixel value - * @return computed red pixel value - */ - public float getRed(int r, int g, int b) { - return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12]; - } - - /** - * Transform RGB value - * - * @param r red pixel value - * @param g green pixel value - * @param b blue pixel value - * @return computed green pixel value - */ - public float getGreen(int r, int g, int b) { - return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13]; - } - - /** - * Transform RGB value - * - * @param r red pixel value - * @param g green pixel value - * @param b blue pixel value - * @return computed blue pixel value - */ - public float getBlue(int r, int g, int b) { - return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14]; - } - - private float getRedf(float r, float g, float b) { - return r * mMatrix[0] + g * mMatrix[4] + b * mMatrix[8] + mMatrix[12]; - } - - private float getGreenf(float r, float g, float b) { - return r * mMatrix[1] + g * mMatrix[5] + b * mMatrix[9] + mMatrix[13]; - } - - private float getBluef(float r, float g, float b) { - return r * mMatrix[2] + g * mMatrix[6] + b * mMatrix[10] + mMatrix[14]; - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java deleted file mode 100644 index 1eebdb571..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterBasicRepresentation.java +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - - -import android.util.Log; - -import com.android.gallery3d.filtershow.controller.Control; -import com.android.gallery3d.filtershow.controller.FilterView; -import com.android.gallery3d.filtershow.controller.Parameter; -import com.android.gallery3d.filtershow.controller.ParameterInteger; - -public class FilterBasicRepresentation extends FilterRepresentation implements ParameterInteger { - private static final String LOGTAG = "FilterBasicRep"; - private int mMinimum; - private int mValue; - private int mMaximum; - private int mDefaultValue; - private int mPreviewValue; - public static final String SERIAL_NAME = "Name"; - public static final String SERIAL_VALUE = "Value"; - private boolean mLogVerbose = Log.isLoggable(LOGTAG, Log.VERBOSE); - - public FilterBasicRepresentation(String name, int minimum, int value, int maximum) { - super(name); - mMinimum = minimum; - mMaximum = maximum; - setValue(value); - } - - @Override - public String toString() { - return getName() + " : " + mMinimum + " < " + mValue + " < " + mMaximum; - } - - @Override - public FilterRepresentation copy() { - FilterBasicRepresentation representation = new FilterBasicRepresentation(getName(),0,0,0); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (a instanceof FilterBasicRepresentation) { - FilterBasicRepresentation representation = (FilterBasicRepresentation) a; - setMinimum(representation.getMinimum()); - setMaximum(representation.getMaximum()); - setValue(representation.getValue()); - setDefaultValue(representation.getDefaultValue()); - setPreviewValue(representation.getPreviewValue()); - } - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - if (representation instanceof FilterBasicRepresentation) { - FilterBasicRepresentation basic = (FilterBasicRepresentation) representation; - if (basic.mMinimum == mMinimum - && basic.mMaximum == mMaximum - && basic.mValue == mValue - && basic.mDefaultValue == mDefaultValue - && basic.mPreviewValue == mPreviewValue) { - return true; - } - } - return false; - } - - @Override - public int getMinimum() { - return mMinimum; - } - - public void setMinimum(int minimum) { - mMinimum = minimum; - } - - @Override - public int getValue() { - return mValue; - } - - @Override - public void setValue(int value) { - mValue = value; - if (mValue < mMinimum) { - mValue = mMinimum; - } - if (mValue > mMaximum) { - mValue = mMaximum; - } - } - - @Override - public int getMaximum() { - return mMaximum; - } - - public void setMaximum(int maximum) { - mMaximum = maximum; - } - - public void setDefaultValue(int defaultValue) { - mDefaultValue = defaultValue; - } - - @Override - public int getDefaultValue() { - return mDefaultValue; - } - - public int getPreviewValue() { - return mPreviewValue; - } - - public void setPreviewValue(int previewValue) { - mPreviewValue = previewValue; - } - - @Override - public String getStateRepresentation() { - int val = getValue(); - return ((val > 0) ? "+" : "") + val; - } - - @Override - public String getParameterType(){ - return sParameterType; - } - - @Override - public void setController(Control control) { - } - - @Override - public String getValueString() { - return getStateRepresentation(); - } - - @Override - public String getParameterName() { - return getName(); - } - - @Override - public void setFilterView(FilterView editor) { - } - - @Override - public void copyFrom(Parameter src) { - useParametersFrom((FilterBasicRepresentation) src); - } - - @Override - public String[][] serializeRepresentation() { - String[][] ret = { - {SERIAL_NAME , getName() }, - {SERIAL_VALUE , Integer.toString(mValue)}}; - return ret; - } - - @Override - public void deSerializeRepresentation(String[][] rep) { - super.deSerializeRepresentation(rep); - for (int i = 0; i < rep.length; i++) { - if (SERIAL_VALUE.equals(rep[i][0])) { - mValue = Integer.parseInt(rep[i][1]); - break; - } - } - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java deleted file mode 100644 index 7ce67dd96..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterChanSatRepresentation.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.util.JsonReader; -import android.util.JsonWriter; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.controller.BasicParameterInt; -import com.android.gallery3d.filtershow.controller.Parameter; -import com.android.gallery3d.filtershow.controller.ParameterSet; -import com.android.gallery3d.filtershow.editors.EditorChanSat; -import com.android.gallery3d.filtershow.imageshow.ControlPoint; -import com.android.gallery3d.filtershow.imageshow.Spline; - -import java.io.IOException; -import java.util.Vector; - -/** - * Representation for a filter that has per channel & Master saturation - */ -public class FilterChanSatRepresentation extends FilterRepresentation implements ParameterSet { - private static final String LOGTAG = "FilterChanSatRepresentation"; - private static final String ARGS = "ARGS"; - private static final String SERIALIZATION_NAME = "channelsaturation"; - - public static final int MODE_MASTER = 0; - public static final int MODE_RED = 1; - public static final int MODE_YELLOW = 2; - public static final int MODE_GREEN = 3; - public static final int MODE_CYAN = 4; - public static final int MODE_BLUE = 5; - public static final int MODE_MAGENTA = 6; - private int mParameterMode = MODE_MASTER; - - private static int MINSAT = -100; - private static int MAXSAT = 100; - private BasicParameterInt mParamMaster = new BasicParameterInt(MODE_MASTER, 0, MINSAT, MAXSAT); - private BasicParameterInt mParamRed = new BasicParameterInt(MODE_RED, 0, MINSAT, MAXSAT); - private BasicParameterInt mParamYellow = new BasicParameterInt(MODE_YELLOW, 0, MINSAT, MAXSAT); - private BasicParameterInt mParamGreen = new BasicParameterInt(MODE_GREEN, 0, MINSAT, MAXSAT); - private BasicParameterInt mParamCyan = new BasicParameterInt(MODE_CYAN, 0, MINSAT, MAXSAT); - private BasicParameterInt mParamBlue = new BasicParameterInt(MODE_BLUE, 0, MINSAT, MAXSAT); - private BasicParameterInt mParamMagenta = new BasicParameterInt(MODE_MAGENTA, 0, MINSAT, MAXSAT); - - private BasicParameterInt[] mAllParam = { - mParamMaster, - mParamRed, - mParamYellow, - mParamGreen, - mParamCyan, - mParamBlue, - mParamMagenta}; - - public FilterChanSatRepresentation() { - super("ChannelSaturation"); - setTextId(R.string.saturation); - setFilterType(FilterRepresentation.TYPE_NORMAL); - setSerializationName(SERIALIZATION_NAME); - setFilterClass(ImageFilterChanSat.class); - setEditorId(EditorChanSat.ID); - } - - public String toString() { - return getName() + " : " + mParamRed + ", " + mParamCyan + ", " + mParamRed - + ", " + mParamGreen + ", " + mParamMaster + ", " + mParamYellow; - } - - @Override - public FilterRepresentation copy() { - FilterChanSatRepresentation representation = new FilterChanSatRepresentation(); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - public void useParametersFrom(FilterRepresentation a) { - if (a instanceof FilterChanSatRepresentation) { - FilterChanSatRepresentation representation = (FilterChanSatRepresentation) a; - - for (int i = 0; i < mAllParam.length; i++) { - mAllParam[i].copyFrom(representation.mAllParam[i]); - } - } - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - if (representation instanceof FilterChanSatRepresentation) { - FilterChanSatRepresentation rep = (FilterChanSatRepresentation) representation; - for (int i = 0; i < mAllParam.length; i++) { - if (rep.getValue(i) != getValue(i)) - return false; - } - return true; - } - return false; - } - - public int getValue(int mode) { - return mAllParam[mode].getValue(); - } - - public void setValue(int mode, int value) { - mAllParam[mode].setValue(value); - } - - public int getMinimum() { - return mParamMaster.getMinimum(); - } - - public int getMaximum() { - return mParamMaster.getMaximum(); - } - - public int getParameterMode() { - return mParameterMode; - } - - public void setParameterMode(int parameterMode) { - mParameterMode = parameterMode; - } - - public int getCurrentParameter() { - return getValue(mParameterMode); - } - - public void setCurrentParameter(int value) { - setValue(mParameterMode, value); - } - - @Override - public int getNumberOfParameters() { - return 6; - } - - @Override - public Parameter getFilterParameter(int index) { - return mAllParam[index]; - } - - @Override - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - - writer.name(ARGS); - writer.beginArray(); - writer.value(getValue(MODE_MASTER)); - writer.value(getValue(MODE_RED)); - writer.value(getValue(MODE_YELLOW)); - writer.value(getValue(MODE_GREEN)); - writer.value(getValue(MODE_CYAN)); - writer.value(getValue(MODE_BLUE)); - writer.value(getValue(MODE_MAGENTA)); - writer.endArray(); - writer.endObject(); - } - - @Override - public void deSerializeRepresentation(JsonReader sreader) throws IOException { - sreader.beginObject(); - - while (sreader.hasNext()) { - String name = sreader.nextName(); - if (name.startsWith(ARGS)) { - sreader.beginArray(); - sreader.hasNext(); - setValue(MODE_MASTER, sreader.nextInt()); - sreader.hasNext(); - setValue(MODE_RED, sreader.nextInt()); - sreader.hasNext(); - setValue(MODE_YELLOW, sreader.nextInt()); - sreader.hasNext(); - setValue(MODE_GREEN, sreader.nextInt()); - sreader.hasNext(); - setValue(MODE_CYAN, sreader.nextInt()); - sreader.hasNext(); - setValue(MODE_BLUE, sreader.nextInt()); - sreader.hasNext(); - setValue(MODE_MAGENTA, sreader.nextInt()); - sreader.hasNext(); - sreader.endArray(); - } else { - sreader.skipValue(); - } - } - sreader.endObject(); - } -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java deleted file mode 100644 index 94eb20631..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterColorBorderRepresentation.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; - -public class FilterColorBorderRepresentation extends FilterRepresentation { - private int mColor; - private int mBorderSize; - private int mBorderRadius; - - public FilterColorBorderRepresentation(int color, int size, int radius) { - super("ColorBorder"); - mColor = color; - mBorderSize = size; - mBorderRadius = radius; - setFilterType(FilterRepresentation.TYPE_BORDER); - setTextId(R.string.borders); - setEditorId(ImageOnlyEditor.ID); - setShowParameterValue(false); - } - - public String toString() { - return "FilterBorder: " + getName(); - } - - @Override - public FilterRepresentation copy() { - FilterColorBorderRepresentation representation = new FilterColorBorderRepresentation(0,0,0); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - public void useParametersFrom(FilterRepresentation a) { - if (a instanceof FilterColorBorderRepresentation) { - FilterColorBorderRepresentation representation = (FilterColorBorderRepresentation) a; - setName(representation.getName()); - setColor(representation.getColor()); - setBorderSize(representation.getBorderSize()); - setBorderRadius(representation.getBorderRadius()); - } - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - if (representation instanceof FilterColorBorderRepresentation) { - FilterColorBorderRepresentation border = (FilterColorBorderRepresentation) representation; - if (border.mColor == mColor - && border.mBorderSize == mBorderSize - && border.mBorderRadius == mBorderRadius) { - return true; - } - } - return false; - } - - public boolean allowsSingleInstanceOnly() { - return true; - } - - @Override - public int getTextId() { - return R.string.borders; - } - - public int getColor() { - return mColor; - } - - public void setColor(int color) { - mColor = color; - } - - public int getBorderSize() { - return mBorderSize; - } - - public void setBorderSize(int borderSize) { - mBorderSize = borderSize; - } - - public int getBorderRadius() { - return mBorderRadius; - } - - public void setBorderRadius(int borderRadius) { - mBorderRadius = borderRadius; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java deleted file mode 100644 index c1bd7b3bb..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterCropRepresentation.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.RectF; -import android.util.JsonReader; -import android.util.JsonWriter; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorCrop; - -import java.io.IOException; - -public class FilterCropRepresentation extends FilterRepresentation { - public static final String SERIALIZATION_NAME = "CROP"; - public static final String[] BOUNDS = { - "C0", "C1", "C2", "C3" - }; - private static final String TAG = FilterCropRepresentation.class.getSimpleName(); - - RectF mCrop = getNil(); - - public FilterCropRepresentation(RectF crop) { - super(FilterCropRepresentation.class.getSimpleName()); - setSerializationName(SERIALIZATION_NAME); - setShowParameterValue(true); - setFilterClass(FilterCropRepresentation.class); - setFilterType(FilterRepresentation.TYPE_GEOMETRY); - setTextId(R.string.crop); - setEditorId(EditorCrop.ID); - setCrop(crop); - } - - public FilterCropRepresentation(FilterCropRepresentation m) { - this(m.mCrop); - } - - public FilterCropRepresentation() { - this(sNilRect); - } - - public void set(FilterCropRepresentation r) { - mCrop.set(r.mCrop); - } - - @Override - public boolean equals(FilterRepresentation rep) { - if (!(rep instanceof FilterCropRepresentation)) { - return false; - } - FilterCropRepresentation crop = (FilterCropRepresentation) rep; - if (mCrop.bottom != crop.mCrop.bottom - || mCrop.left != crop.mCrop.left - || mCrop.right != crop.mCrop.right - || mCrop.top != crop.mCrop.top) { - return false; - } - return true; - } - - public RectF getCrop() { - return new RectF(mCrop); - } - - public void getCrop(RectF r) { - r.set(mCrop); - } - - public void setCrop(RectF crop) { - if (crop == null) { - throw new IllegalArgumentException("Argument to setCrop is null"); - } - mCrop.set(crop); - } - - /** - * Takes a crop rect contained by [0, 0, 1, 1] and scales it by the height - * and width of the image rect. - */ - public static void findScaledCrop(RectF crop, int bitmapWidth, int bitmapHeight) { - crop.left *= bitmapWidth; - crop.top *= bitmapHeight; - crop.right *= bitmapWidth; - crop.bottom *= bitmapHeight; - } - - /** - * Takes crop rect and normalizes it by scaling down by the height and width - * of the image rect. - */ - public static void findNormalizedCrop(RectF crop, int bitmapWidth, int bitmapHeight) { - crop.left /= bitmapWidth; - crop.top /= bitmapHeight; - crop.right /= bitmapWidth; - crop.bottom /= bitmapHeight; - } - - @Override - public boolean allowsSingleInstanceOnly() { - return true; - } - - @Override - public FilterRepresentation copy() { - return new FilterCropRepresentation(this); - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - if (!(representation instanceof FilterCropRepresentation)) { - throw new IllegalArgumentException("calling copyAllParameters with incompatible types!"); - } - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (!(a instanceof FilterCropRepresentation)) { - throw new IllegalArgumentException("calling useParametersFrom with incompatible types!"); - } - setCrop(((FilterCropRepresentation) a).mCrop); - } - - private static final RectF sNilRect = new RectF(0, 0, 1, 1); - - @Override - public boolean isNil() { - return mCrop.equals(sNilRect); - } - - public static RectF getNil() { - return new RectF(sNilRect); - } - - @Override - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - writer.name(BOUNDS[0]).value(mCrop.left); - writer.name(BOUNDS[1]).value(mCrop.top); - writer.name(BOUNDS[2]).value(mCrop.right); - writer.name(BOUNDS[3]).value(mCrop.bottom); - writer.endObject(); - } - - @Override - public void deSerializeRepresentation(JsonReader reader) throws IOException { - reader.beginObject(); - while (reader.hasNext()) { - String name = reader.nextName(); - if (BOUNDS[0].equals(name)) { - mCrop.left = (float) reader.nextDouble(); - } else if (BOUNDS[1].equals(name)) { - mCrop.top = (float) reader.nextDouble(); - } else if (BOUNDS[2].equals(name)) { - mCrop.right = (float) reader.nextDouble(); - } else if (BOUNDS[3].equals(name)) { - mCrop.bottom = (float) reader.nextDouble(); - } else { - reader.skipValue(); - } - } - reader.endObject(); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java deleted file mode 100644 index edab2a08d..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterCurvesRepresentation.java +++ /dev/null @@ -1,170 +0,0 @@ -package com.android.gallery3d.filtershow.filters; - -import android.util.JsonReader; -import android.util.JsonWriter; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.imageshow.ControlPoint; -import com.android.gallery3d.filtershow.imageshow.Spline; - -import java.io.IOException; - -/** - * TODO: Insert description here. (generated by hoford) - */ -public class FilterCurvesRepresentation extends FilterRepresentation { - private static final String LOGTAG = "FilterCurvesRepresentation"; - public static final String SERIALIZATION_NAME = "Curve"; - private static final int MAX_SPLINE_NUMBER = 4; - - private Spline[] mSplines = new Spline[MAX_SPLINE_NUMBER]; - - public FilterCurvesRepresentation() { - super("Curves"); - setSerializationName("CURVES"); - setFilterClass(ImageFilterCurves.class); - setTextId(R.string.curvesRGB); - setOverlayId(R.drawable.filtershow_button_colors_curve); - setEditorId(R.id.imageCurves); - setShowParameterValue(false); - setSupportsPartialRendering(true); - reset(); - } - - @Override - public FilterRepresentation copy() { - FilterCurvesRepresentation representation = new FilterCurvesRepresentation(); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (!(a instanceof FilterCurvesRepresentation)) { - Log.v(LOGTAG, "cannot use parameters from " + a); - return; - } - FilterCurvesRepresentation representation = (FilterCurvesRepresentation) a; - Spline[] spline = new Spline[MAX_SPLINE_NUMBER]; - for (int i = 0; i < spline.length; i++) { - Spline sp = representation.mSplines[i]; - if (sp != null) { - spline[i] = new Spline(sp); - } else { - spline[i] = new Spline(); - } - } - mSplines = spline; - } - - @Override - public boolean isNil() { - for (int i = 0; i < MAX_SPLINE_NUMBER; i++) { - if (getSpline(i) != null && !getSpline(i).isOriginal()) { - return false; - } - } - return true; - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - - if (!(representation instanceof FilterCurvesRepresentation)) { - return false; - } else { - FilterCurvesRepresentation curve = - (FilterCurvesRepresentation) representation; - for (int i = 0; i < MAX_SPLINE_NUMBER; i++) { - if (!getSpline(i).sameValues(curve.getSpline(i))) { - return false; - } - } - } - // Every spline matches, therefore they are the same. - return true; - } - - public void reset() { - Spline spline = new Spline(); - - spline.addPoint(0.0f, 1.0f); - spline.addPoint(1.0f, 0.0f); - - for (int i = 0; i < MAX_SPLINE_NUMBER; i++) { - mSplines[i] = new Spline(spline); - } - } - - public void setSpline(int splineIndex, Spline s) { - mSplines[splineIndex] = s; - } - - public Spline getSpline(int splineIndex) { - return mSplines[splineIndex]; - } - - @Override - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - { - writer.name(NAME_TAG); - writer.value(getName()); - for (int i = 0; i < mSplines.length; i++) { - writer.name(SERIALIZATION_NAME + i); - writer.beginArray(); - int nop = mSplines[i].getNbPoints(); - for (int j = 0; j < nop; j++) { - ControlPoint p = mSplines[i].getPoint(j); - writer.beginArray(); - writer.value(p.x); - writer.value(p.y); - writer.endArray(); - } - writer.endArray(); - } - - } - writer.endObject(); - } - - @Override - public void deSerializeRepresentation(JsonReader sreader) throws IOException { - sreader.beginObject(); - Spline[] spline = new Spline[MAX_SPLINE_NUMBER]; - while (sreader.hasNext()) { - String name = sreader.nextName(); - if (NAME_TAG.equals(name)) { - setName(sreader.nextString()); - } else if (name.startsWith(SERIALIZATION_NAME)) { - int curveNo = Integer.parseInt(name.substring(SERIALIZATION_NAME.length())); - spline[curveNo] = new Spline(); - sreader.beginArray(); - while (sreader.hasNext()) { - sreader.beginArray(); - sreader.hasNext(); - float x = (float) sreader.nextDouble(); - sreader.hasNext(); - float y = (float) sreader.nextDouble(); - sreader.endArray(); - spline[curveNo].addPoint(x, y); - } - sreader.endArray(); - - } - } - mSplines = spline; - sreader.endObject(); - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java deleted file mode 100644 index ac0cb7492..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterDirectRepresentation.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -public class FilterDirectRepresentation extends FilterRepresentation { - - @Override - public FilterRepresentation copy() { - FilterDirectRepresentation representation = new FilterDirectRepresentation(getName()); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - public FilterDirectRepresentation(String name) { - super(name); - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java deleted file mode 100644 index 977dbeac5..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterDrawRepresentation.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Path; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorDraw; - -import java.util.Vector; - -public class FilterDrawRepresentation extends FilterRepresentation { - private static final String LOGTAG = "FilterDrawRepresentation"; - - public static class StrokeData implements Cloneable { - public byte mType; - public Path mPath; - public float mRadius; - public int mColor; - public int noPoints = 0; - @Override - public String toString() { - return "stroke(" + mType + ", path(" + (mPath) + "), " + mRadius + " , " - + Integer.toHexString(mColor) + ")"; - } - @Override - public StrokeData clone() throws CloneNotSupportedException { - return (StrokeData) super.clone(); - } - } - - private Vector<StrokeData> mDrawing = new Vector<StrokeData>(); - private StrokeData mCurrent; // used in the currently drawing style - - public FilterDrawRepresentation() { - super("Draw"); - setFilterClass(ImageFilterDraw.class); - setSerializationName("DRAW"); - setFilterType(FilterRepresentation.TYPE_VIGNETTE); - setTextId(R.string.imageDraw); - setEditorId(EditorDraw.ID); - setOverlayId(R.drawable.filtershow_drawing); - setOverlayOnly(true); - } - - @Override - public String toString() { - return getName() + " : strokes=" + mDrawing.size() - + ((mCurrent == null) ? " no current " - : ("draw=" + mCurrent.mType + " " + mCurrent.noPoints)); - } - - public Vector<StrokeData> getDrawing() { - return mDrawing; - } - - public StrokeData getCurrentDrawing() { - return mCurrent; - } - - @Override - public FilterRepresentation copy() { - FilterDrawRepresentation representation = new FilterDrawRepresentation(); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public boolean isNil() { - return getDrawing().isEmpty(); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (a instanceof FilterDrawRepresentation) { - FilterDrawRepresentation representation = (FilterDrawRepresentation) a; - try { - if (representation.mCurrent != null) { - mCurrent = (StrokeData) representation.mCurrent.clone(); - } else { - mCurrent = null; - } - if (representation.mDrawing != null) { - mDrawing = (Vector<StrokeData>) representation.mDrawing.clone(); - } else { - mDrawing = null; - } - - } catch (CloneNotSupportedException e) { - e.printStackTrace(); - } - } else { - Log.v(LOGTAG, "cannot use parameters from " + a); - } - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - if (representation instanceof FilterDrawRepresentation) { - FilterDrawRepresentation fdRep = (FilterDrawRepresentation) representation; - if (fdRep.mDrawing.size() != mDrawing.size()) - return false; - if (fdRep.mCurrent == null && mCurrent.mPath == null) { - return true; - } - if (fdRep.mCurrent != null && mCurrent.mPath != null) { - if (fdRep.mCurrent.noPoints == mCurrent.noPoints) { - return true; - } - return false; - } - } - return false; - } - - public void startNewSection(byte type, int color, float size, float x, float y) { - mCurrent = new StrokeData(); - mCurrent.mColor = color; - mCurrent.mRadius = size; - mCurrent.mType = type; - mCurrent.mPath = new Path(); - mCurrent.mPath.moveTo(x, y); - mCurrent.noPoints = 0; - } - - public void addPoint(float x, float y) { - mCurrent.noPoints++; - mCurrent.mPath.lineTo(x, y); - } - - public void endSection(float x, float y) { - mCurrent.mPath.lineTo(x, y); - mCurrent.noPoints++; - mDrawing.add(mCurrent); - mCurrent = null; - } - - public void clearCurrentSection() { - mCurrent = null; - } - - public void clear() { - mCurrent = null; - mDrawing.clear(); - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java deleted file mode 100644 index e5a6fdd23..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterFxRepresentation.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; - -public class FilterFxRepresentation extends FilterRepresentation { - private static final String LOGTAG = "FilterFxRepresentation"; - // TODO: When implementing serialization, we should find a unique way of - // specifying bitmaps / names (the resource IDs being random) - private int mBitmapResource = 0; - private int mNameResource = 0; - - public FilterFxRepresentation(String name, int bitmapResource, int nameResource) { - super(name); - setFilterClass(ImageFilterFx.class); - mBitmapResource = bitmapResource; - mNameResource = nameResource; - setFilterType(FilterRepresentation.TYPE_FX); - setTextId(nameResource); - setEditorId(ImageOnlyEditor.ID); - setShowParameterValue(false); - setSupportsPartialRendering(true); - } - - @Override - public String toString() { - return "FilterFx: " + hashCode() + " : " + getName() + " bitmap rsc: " + mBitmapResource; - } - - @Override - public FilterRepresentation copy() { - FilterFxRepresentation representation = new FilterFxRepresentation(getName(),0,0); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public synchronized void useParametersFrom(FilterRepresentation a) { - if (a instanceof FilterFxRepresentation) { - FilterFxRepresentation representation = (FilterFxRepresentation) a; - setName(representation.getName()); - setSerializationName(representation.getSerializationName()); - setBitmapResource(representation.getBitmapResource()); - setNameResource(representation.getNameResource()); - } - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - if (representation instanceof FilterFxRepresentation) { - FilterFxRepresentation fx = (FilterFxRepresentation) representation; - if (fx.mNameResource == mNameResource - && fx.mBitmapResource == mBitmapResource) { - return true; - } - } - return false; - } - - @Override - public boolean same(FilterRepresentation representation) { - if (!super.same(representation)) { - return false; - } - return equals(representation); - } - - @Override - public boolean allowsSingleInstanceOnly() { - return true; - } - - public int getNameResource() { - return mNameResource; - } - - public void setNameResource(int nameResource) { - mNameResource = nameResource; - } - - public int getBitmapResource() { - return mBitmapResource; - } - - public void setBitmapResource(int bitmapResource) { - mBitmapResource = bitmapResource; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java deleted file mode 100644 index 0c272d48a..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterGradRepresentation.java +++ /dev/null @@ -1,497 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Rect; -import android.util.JsonReader; -import android.util.JsonWriter; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorGrad; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.imageshow.Line; - -import java.io.IOException; -import java.util.Vector; - -public class FilterGradRepresentation extends FilterRepresentation - implements Line { - private static final String LOGTAG = "FilterGradRepresentation"; - public static final int MAX_POINTS = 16; - public static final int PARAM_BRIGHTNESS = 0; - public static final int PARAM_SATURATION = 1; - public static final int PARAM_CONTRAST = 2; - private static final double ADD_MIN_DIST = .05; - private static String LINE_NAME = "Point"; - private static final String SERIALIZATION_NAME = "grad"; - - public FilterGradRepresentation() { - super("Grad"); - setSerializationName(SERIALIZATION_NAME); - creatExample(); - setOverlayId(R.drawable.filtershow_button_grad); - setFilterClass(ImageFilterGrad.class); - setTextId(R.string.grad); - setEditorId(EditorGrad.ID); - } - - public void trimVector(){ - int n = mBands.size(); - for (int i = n; i < MAX_POINTS; i++) { - mBands.add(new Band()); - } - for (int i = MAX_POINTS; i < n; i++) { - mBands.remove(i); - } - } - - Vector<Band> mBands = new Vector<Band>(); - Band mCurrentBand; - - static class Band { - private boolean mask = true; - - private int xPos1 = -1; - private int yPos1 = 100; - private int xPos2 = -1; - private int yPos2 = 100; - private int brightness = 40; - private int contrast = 0; - private int saturation = 0; - - - public Band() { - } - - public Band(int x, int y) { - xPos1 = x; - yPos1 = y+30; - xPos2 = x; - yPos2 = y-30; - } - - public Band(Band copy) { - mask = copy.mask; - xPos1 = copy.xPos1; - yPos1 = copy.yPos1; - xPos2 = copy.xPos2; - yPos2 = copy.yPos2; - brightness = copy.brightness; - contrast = copy.contrast; - saturation = copy.saturation; - } - - } - - @Override - public String toString() { - int count = 0; - for (Band point : mBands) { - if (!point.mask) { - count++; - } - } - return "c=" + mBands.indexOf(mBands) + "[" + mBands.size() + "]" + count; - } - - private void creatExample() { - Band p = new Band(); - p.mask = false; - p.xPos1 = -1; - p.yPos1 = 100; - p.xPos2 = -1; - p.yPos2 = 100; - p.brightness = 40; - p.contrast = 0; - p.saturation = 0; - mBands.add(0, p); - mCurrentBand = p; - trimVector(); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - FilterGradRepresentation rep = (FilterGradRepresentation) a; - Vector<Band> tmpBands = new Vector<Band>(); - int n = (rep.mCurrentBand == null) ? 0 : rep.mBands.indexOf(rep.mCurrentBand); - for (Band band : rep.mBands) { - tmpBands.add(new Band(band)); - } - mCurrentBand = null; - mBands = tmpBands; - mCurrentBand = mBands.elementAt(n); - } - - @Override - public FilterRepresentation copy() { - FilterGradRepresentation representation = new FilterGradRepresentation(); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (representation instanceof FilterGradRepresentation) { - FilterGradRepresentation rep = (FilterGradRepresentation) representation; - int n = getNumberOfBands(); - if (rep.getNumberOfBands() != n) { - return false; - } - for (int i = 0; i < mBands.size(); i++) { - Band b1 = mBands.get(i); - Band b2 = rep.mBands.get(i); - if (b1.mask != b2.mask - || b1.brightness != b2.brightness - || b1.contrast != b2.contrast - || b1.saturation != b2.saturation - || b1.xPos1 != b2.xPos1 - || b1.xPos2 != b2.xPos2 - || b1.yPos1 != b2.yPos1 - || b1.yPos2 != b2.yPos2) { - return false; - } - } - return true; - } - return false; - } - - public int getNumberOfBands() { - int count = 0; - for (Band point : mBands) { - if (!point.mask) { - count++; - } - } - return count; - } - - public int addBand(Rect rect) { - mBands.add(0, mCurrentBand = new Band(rect.centerX(), rect.centerY())); - mCurrentBand.mask = false; - int x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2; - int y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2; - double addDelta = ADD_MIN_DIST * Math.max(rect.width(), rect.height()); - boolean moved = true; - int count = 0; - int toMove = mBands.indexOf(mCurrentBand); - - while (moved) { - moved = false; - count++; - if (count > 14) { - break; - } - - for (Band point : mBands) { - if (point.mask) { - break; - } - } - - for (Band point : mBands) { - if (point.mask) { - break; - } - int index = mBands.indexOf(point); - - if (toMove != index) { - double dist = Math.hypot(point.xPos1 - x, point.yPos1 - y); - if (dist < addDelta) { - moved = true; - mCurrentBand.xPos1 += addDelta; - mCurrentBand.yPos1 += addDelta; - mCurrentBand.xPos2 += addDelta; - mCurrentBand.yPos2 += addDelta; - x = (mCurrentBand.xPos1 + mCurrentBand.xPos2)/2; - y = (mCurrentBand.yPos1 + mCurrentBand.yPos2)/2; - - if (mCurrentBand.yPos1 > rect.bottom) { - mCurrentBand.yPos1 = (int) (rect.top + addDelta); - } - if (mCurrentBand.xPos1 > rect.right) { - mCurrentBand.xPos1 = (int) (rect.left + addDelta); - } - } - } - } - } - trimVector(); - return 0; - } - - public void deleteCurrentBand() { - int index = mBands.indexOf(mCurrentBand); - mBands.remove(mCurrentBand); - trimVector(); - if (getNumberOfBands() == 0) { - addBand(MasterImage.getImage().getOriginalBounds()); - } - mCurrentBand = mBands.get(0); - } - - public void nextPoint(){ - int index = mBands.indexOf(mCurrentBand); - int tmp = index; - Band point; - int k = 0; - do { - index = (index+1)% mBands.size(); - point = mBands.get(index); - if (k++ >= mBands.size()) { - break; - } - } - while (point.mask == true); - mCurrentBand = mBands.get(index); - } - - public void setSelectedPoint(int pos) { - mCurrentBand = mBands.get(pos); - } - - public int getSelectedPoint() { - return mBands.indexOf(mCurrentBand); - } - - public boolean[] getMask() { - boolean[] ret = new boolean[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = !point.mask; - } - return ret; - } - - public int[] getXPos1() { - int[] ret = new int[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = point.xPos1; - } - return ret; - } - - public int[] getYPos1() { - int[] ret = new int[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = point.yPos1; - } - return ret; - } - - public int[] getXPos2() { - int[] ret = new int[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = point.xPos2; - } - return ret; - } - - public int[] getYPos2() { - int[] ret = new int[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = point.yPos2; - } - return ret; - } - - public int[] getBrightness() { - int[] ret = new int[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = point.brightness; - } - return ret; - } - - public int[] getContrast() { - int[] ret = new int[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = point.contrast; - } - return ret; - } - - public int[] getSaturation() { - int[] ret = new int[mBands.size()]; - int i = 0; - for (Band point : mBands) { - ret[i++] = point.saturation; - } - return ret; - } - - public int getParameter(int type) { - switch (type){ - case PARAM_BRIGHTNESS: - return mCurrentBand.brightness; - case PARAM_SATURATION: - return mCurrentBand.saturation; - case PARAM_CONTRAST: - return mCurrentBand.contrast; - } - throw new IllegalArgumentException("no such type " + type); - } - - public int getParameterMax(int type) { - switch (type) { - case PARAM_BRIGHTNESS: - return 100; - case PARAM_SATURATION: - return 100; - case PARAM_CONTRAST: - return 100; - } - throw new IllegalArgumentException("no such type " + type); - } - - public int getParameterMin(int type) { - switch (type) { - case PARAM_BRIGHTNESS: - return -100; - case PARAM_SATURATION: - return -100; - case PARAM_CONTRAST: - return -100; - } - throw new IllegalArgumentException("no such type " + type); - } - - public void setParameter(int type, int value) { - mCurrentBand.mask = false; - switch (type) { - case PARAM_BRIGHTNESS: - mCurrentBand.brightness = value; - break; - case PARAM_SATURATION: - mCurrentBand.saturation = value; - break; - case PARAM_CONTRAST: - mCurrentBand.contrast = value; - break; - default: - throw new IllegalArgumentException("no such type " + type); - } - } - - @Override - public void setPoint1(float x, float y) { - mCurrentBand.xPos1 = (int)x; - mCurrentBand.yPos1 = (int)y; - } - - @Override - public void setPoint2(float x, float y) { - mCurrentBand.xPos2 = (int)x; - mCurrentBand.yPos2 = (int)y; - } - - @Override - public float getPoint1X() { - return mCurrentBand.xPos1; - } - - @Override - public float getPoint1Y() { - return mCurrentBand.yPos1; - } - @Override - public float getPoint2X() { - return mCurrentBand.xPos2; - } - - @Override - public float getPoint2Y() { - return mCurrentBand.yPos2; - } - - @Override - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - int len = mBands.size(); - int count = 0; - - for (int i = 0; i < len; i++) { - Band point = mBands.get(i); - if (point.mask) { - continue; - } - writer.name(LINE_NAME + count); - count++; - writer.beginArray(); - writer.value(point.xPos1); - writer.value(point.yPos1); - writer.value(point.xPos2); - writer.value(point.yPos2); - writer.value(point.brightness); - writer.value(point.contrast); - writer.value(point.saturation); - writer.endArray(); - } - writer.endObject(); - } - - @Override - public void deSerializeRepresentation(JsonReader sreader) throws IOException { - sreader.beginObject(); - Vector<Band> points = new Vector<Band>(); - - while (sreader.hasNext()) { - String name = sreader.nextName(); - if (name.startsWith(LINE_NAME)) { - int pointNo = Integer.parseInt(name.substring(LINE_NAME.length())); - sreader.beginArray(); - Band p = new Band(); - p.mask = false; - sreader.hasNext(); - p.xPos1 = sreader.nextInt(); - sreader.hasNext(); - p.yPos1 = sreader.nextInt(); - sreader.hasNext(); - p.xPos2 = sreader.nextInt(); - sreader.hasNext(); - p.yPos2 = sreader.nextInt(); - sreader.hasNext(); - p.brightness = sreader.nextInt(); - sreader.hasNext(); - p.contrast = sreader.nextInt(); - sreader.hasNext(); - p.saturation = sreader.nextInt(); - sreader.hasNext(); - sreader.endArray(); - points.add(p); - - } else { - sreader.skipValue(); - } - } - mBands = points; - trimVector(); - mCurrentBand = mBands.get(0); - sreader.endObject(); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java deleted file mode 100644 index f310a2be1..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterImageBorderRepresentation.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; - -public class FilterImageBorderRepresentation extends FilterRepresentation { - private int mDrawableResource = 0; - - public FilterImageBorderRepresentation(int drawableResource) { - super("ImageBorder"); - setFilterClass(ImageFilterBorder.class); - mDrawableResource = drawableResource; - setFilterType(FilterRepresentation.TYPE_BORDER); - setTextId(R.string.borders); - setEditorId(ImageOnlyEditor.ID); - setShowParameterValue(false); - } - - public String toString() { - return "FilterBorder: " + getName(); - } - - @Override - public FilterRepresentation copy() { - FilterImageBorderRepresentation representation = - new FilterImageBorderRepresentation(mDrawableResource); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - public void useParametersFrom(FilterRepresentation a) { - if (a instanceof FilterImageBorderRepresentation) { - FilterImageBorderRepresentation representation = (FilterImageBorderRepresentation) a; - setName(representation.getName()); - setDrawableResource(representation.getDrawableResource()); - } - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - if (representation instanceof FilterImageBorderRepresentation) { - FilterImageBorderRepresentation border = (FilterImageBorderRepresentation) representation; - if (border.mDrawableResource == mDrawableResource) { - return true; - } - } - return false; - } - - @Override - public int getTextId() { - return R.string.none; - } - - public boolean allowsSingleInstanceOnly() { - return true; - } - - public int getDrawableResource() { - return mDrawableResource; - } - - public void setDrawableResource(int drawableResource) { - mDrawableResource = drawableResource; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java deleted file mode 100644 index 8dcff0d16..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterMirrorRepresentation.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.util.JsonReader; -import android.util.JsonWriter; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorMirror; - -import java.io.IOException; - -public class FilterMirrorRepresentation extends FilterRepresentation { - public static final String SERIALIZATION_NAME = "MIRROR"; - private static final String SERIALIZATION_MIRROR_VALUE = "value"; - private static final String TAG = FilterMirrorRepresentation.class.getSimpleName(); - - Mirror mMirror; - - public enum Mirror { - NONE('N'), VERTICAL('V'), HORIZONTAL('H'), BOTH('B'); - char mValue; - - private Mirror(char value) { - mValue = value; - } - - public char value() { - return mValue; - } - - public static Mirror fromValue(char value) { - switch (value) { - case 'N': - return NONE; - case 'V': - return VERTICAL; - case 'H': - return HORIZONTAL; - case 'B': - return BOTH; - default: - return null; - } - } - } - - public FilterMirrorRepresentation(Mirror mirror) { - super(FilterMirrorRepresentation.class.getSimpleName()); - setSerializationName(SERIALIZATION_NAME); - setShowParameterValue(true); - setFilterClass(FilterMirrorRepresentation.class); - setFilterType(FilterRepresentation.TYPE_GEOMETRY); - setTextId(R.string.mirror); - setEditorId(EditorMirror.ID); - setMirror(mirror); - } - - public FilterMirrorRepresentation(FilterMirrorRepresentation m) { - this(m.getMirror()); - } - - public FilterMirrorRepresentation() { - this(getNil()); - } - - @Override - public boolean equals(FilterRepresentation rep) { - if (!(rep instanceof FilterMirrorRepresentation)) { - return false; - } - FilterMirrorRepresentation mirror = (FilterMirrorRepresentation) rep; - if (mMirror != mirror.mMirror) { - return false; - } - return true; - } - - public Mirror getMirror() { - return mMirror; - } - - public void set(FilterMirrorRepresentation r) { - mMirror = r.mMirror; - } - - public void setMirror(Mirror mirror) { - if (mirror == null) { - throw new IllegalArgumentException("Argument to setMirror is null"); - } - mMirror = mirror; - } - - public void cycle() { - switch (mMirror) { - case NONE: - mMirror = Mirror.HORIZONTAL; - break; - case HORIZONTAL: - mMirror = Mirror.VERTICAL; - break; - case VERTICAL: - mMirror = Mirror.BOTH; - break; - case BOTH: - mMirror = Mirror.NONE; - break; - } - } - - @Override - public boolean allowsSingleInstanceOnly() { - return true; - } - - @Override - public FilterRepresentation copy() { - return new FilterMirrorRepresentation(this); - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - if (!(representation instanceof FilterMirrorRepresentation)) { - throw new IllegalArgumentException("calling copyAllParameters with incompatible types!"); - } - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (!(a instanceof FilterMirrorRepresentation)) { - throw new IllegalArgumentException("calling useParametersFrom with incompatible types!"); - } - setMirror(((FilterMirrorRepresentation) a).getMirror()); - } - - @Override - public boolean isNil() { - return mMirror == getNil(); - } - - public static Mirror getNil() { - return Mirror.NONE; - } - - @Override - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - writer.name(SERIALIZATION_MIRROR_VALUE).value(mMirror.value()); - writer.endObject(); - } - - @Override - public void deSerializeRepresentation(JsonReader reader) throws IOException { - boolean unset = true; - reader.beginObject(); - while (reader.hasNext()) { - String name = reader.nextName(); - if (SERIALIZATION_MIRROR_VALUE.equals(name)) { - Mirror r = Mirror.fromValue((char) reader.nextInt()); - if (r != null) { - setMirror(r); - unset = false; - } - } else { - reader.skipValue(); - } - } - if (unset) { - Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME); - } - reader.endObject(); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPoint.java b/src/com/android/gallery3d/filtershow/filters/FilterPoint.java deleted file mode 100644 index 4520717a1..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterPoint.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -public interface FilterPoint { - -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java deleted file mode 100644 index 9bd1699d9..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterPointRepresentation.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import java.util.Vector; - -public abstract class FilterPointRepresentation extends FilterRepresentation { - private static final String LOGTAG = "FilterPointRepresentation"; - private Vector<FilterPoint> mCandidates = new Vector<FilterPoint>(); - - public FilterPointRepresentation(String type, int textid, int editorID) { - super(type); - setFilterClass(ImageFilterRedEye.class); - setFilterType(FilterRepresentation.TYPE_NORMAL); - setTextId(textid); - setEditorId(editorID); - } - - @Override - public abstract FilterRepresentation copy(); - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - public boolean hasCandidates() { - return mCandidates != null; - } - - public Vector<FilterPoint> getCandidates() { - return mCandidates; - } - - @Override - public boolean isNil() { - if (getCandidates() != null && getCandidates().size() > 0) { - return false; - } - return true; - } - - public Object getCandidate(int index) { - return this.mCandidates.get(index); - } - - public void addCandidate(FilterPoint c) { - this.mCandidates.add(c); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (a instanceof FilterPointRepresentation) { - FilterPointRepresentation representation = (FilterPointRepresentation) a; - mCandidates.clear(); - for (FilterPoint redEyeCandidate : representation.mCandidates) { - mCandidates.add(redEyeCandidate); - } - } - } - - public void removeCandidate(RedEyeCandidate c) { - this.mCandidates.remove(c); - } - - public void clearCandidates() { - this.mCandidates.clear(); - } - - public int getNumberOfCandidates() { - return mCandidates.size(); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java deleted file mode 100644 index dd06a9760..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterRedEyeRepresentation.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.RectF; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorRedEye; - -import java.util.Vector; - -public class FilterRedEyeRepresentation extends FilterPointRepresentation { - private static final String LOGTAG = "FilterRedEyeRepresentation"; - - public FilterRedEyeRepresentation() { - super("RedEye",R.string.redeye,EditorRedEye.ID); - setSerializationName("REDEYE"); - setFilterClass(ImageFilterRedEye.class); - setOverlayId(R.drawable.photoeditor_effect_redeye); - setOverlayOnly(true); - } - - @Override - public FilterRepresentation copy() { - FilterRedEyeRepresentation representation = new FilterRedEyeRepresentation(); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - public void addRect(RectF rect, RectF bounds) { - Vector<RedEyeCandidate> intersects = new Vector<RedEyeCandidate>(); - for (int i = 0; i < getCandidates().size(); i++) { - RedEyeCandidate r = (RedEyeCandidate) getCandidate(i); - if (r.intersect(rect)) { - intersects.add(r); - } - } - for (int i = 0; i < intersects.size(); i++) { - RedEyeCandidate r = intersects.elementAt(i); - rect.union(r.mRect); - bounds.union(r.mBounds); - removeCandidate(r); - } - addCandidate(new RedEyeCandidate(rect, bounds)); - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java deleted file mode 100644 index 5b33ffba5..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterRepresentation.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.util.JsonReader; -import android.util.JsonWriter; -import android.util.Log; - -import com.android.gallery3d.filtershow.editors.BasicEditor; - -import java.io.IOException; -import java.util.ArrayList; - -public class FilterRepresentation { - private static final String LOGTAG = "FilterRepresentation"; - private static final boolean DEBUG = false; - private String mName; - private int mPriority = TYPE_NORMAL; - private Class<?> mFilterClass; - private boolean mSupportsPartialRendering = false; - private int mTextId = 0; - private int mEditorId = BasicEditor.ID; - private int mButtonId = 0; - private int mOverlayId = 0; - private boolean mOverlayOnly = false; - private boolean mShowParameterValue = true; - private String mSerializationName; - public static final byte TYPE_BORDER = 1; - public static final byte TYPE_FX = 2; - public static final byte TYPE_WBALANCE = 3; - public static final byte TYPE_VIGNETTE = 4; - public static final byte TYPE_NORMAL = 5; - public static final byte TYPE_TINYPLANET = 6; - public static final byte TYPE_GEOMETRY = 7; - protected static final String NAME_TAG = "Name"; - - public FilterRepresentation(String name) { - mName = name; - } - - public FilterRepresentation copy(){ - FilterRepresentation representation = new FilterRepresentation(mName); - representation.useParametersFrom(this); - return representation; - } - - protected void copyAllParameters(FilterRepresentation representation) { - representation.setName(getName()); - representation.setFilterClass(getFilterClass()); - representation.setFilterType(getFilterType()); - representation.setSupportsPartialRendering(supportsPartialRendering()); - representation.setTextId(getTextId()); - representation.setEditorId(getEditorId()); - representation.setOverlayId(getOverlayId()); - representation.setOverlayOnly(getOverlayOnly()); - representation.setShowParameterValue(showParameterValue()); - representation.mSerializationName = mSerializationName; - - } - - public boolean equals(FilterRepresentation representation) { - if (representation == null) { - return false; - } - if (representation.mFilterClass == mFilterClass - && representation.mName.equalsIgnoreCase(mName) - && representation.mPriority == mPriority - // TODO: After we enable partial rendering, we can switch back - // to use member variable here. - && representation.supportsPartialRendering() == supportsPartialRendering() - && representation.mTextId == mTextId - && representation.mEditorId == mEditorId - && representation.mButtonId == mButtonId - && representation.mOverlayId == mOverlayId - && representation.mOverlayOnly == mOverlayOnly - && representation.mShowParameterValue == mShowParameterValue) { - return true; - } - return false; - } - - @Override - public String toString() { - return mName; - } - - public void setName(String name) { - mName = name; - } - - public String getName() { - return mName; - } - - public void setSerializationName(String sname) { - mSerializationName = sname; - } - - public String getSerializationName() { - return mSerializationName; - } - - public void setFilterType(int priority) { - mPriority = priority; - } - - public int getFilterType() { - return mPriority; - } - - public boolean isNil() { - return false; - } - - public boolean supportsPartialRendering() { - return false && mSupportsPartialRendering; // disable for now - } - - public void setSupportsPartialRendering(boolean value) { - mSupportsPartialRendering = value; - } - - public void useParametersFrom(FilterRepresentation a) { - } - - public boolean allowsSingleInstanceOnly() { - return false; - } - - public Class<?> getFilterClass() { - return mFilterClass; - } - - public void setFilterClass(Class<?> filterClass) { - mFilterClass = filterClass; - } - - // This same() function is different from equals(), basically it checks - // whether 2 FilterRepresentations are the same type. It doesn't care about - // the values. - public boolean same(FilterRepresentation b) { - if (b == null) { - return false; - } - return getFilterClass() == b.getFilterClass(); - } - - public int getTextId() { - return mTextId; - } - - public void setTextId(int textId) { - mTextId = textId; - } - - public int getOverlayId() { - return mOverlayId; - } - - public void setOverlayId(int overlayId) { - mOverlayId = overlayId; - } - - public boolean getOverlayOnly() { - return mOverlayOnly; - } - - public void setOverlayOnly(boolean value) { - mOverlayOnly = value; - } - - final public int getEditorId() { - return mEditorId; - } - - public int[] getEditorIds() { - return new int[] { - mEditorId }; - } - - public void setEditorId(int editorId) { - mEditorId = editorId; - } - - public boolean showParameterValue() { - return mShowParameterValue; - } - - public void setShowParameterValue(boolean showParameterValue) { - mShowParameterValue = showParameterValue; - } - - public String getStateRepresentation() { - return ""; - } - - /** - * Method must "beginObject()" add its info and "endObject()" - * @param writer - * @throws IOException - */ - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - { - String[][] rep = serializeRepresentation(); - for (int k = 0; k < rep.length; k++) { - writer.name(rep[k][0]); - writer.value(rep[k][1]); - } - } - writer.endObject(); - } - - // this is the old way of doing this and will be removed soon - public String[][] serializeRepresentation() { - String[][] ret = {{NAME_TAG, getName()}}; - return ret; - } - - public void deSerializeRepresentation(JsonReader reader) throws IOException { - ArrayList<String[]> al = new ArrayList<String[]>(); - reader.beginObject(); - while (reader.hasNext()) { - String[] kv = {reader.nextName(), reader.nextString()}; - al.add(kv); - - } - reader.endObject(); - String[][] oldFormat = al.toArray(new String[al.size()][]); - - deSerializeRepresentation(oldFormat); - } - - // this is the old way of doing this and will be removed soon - public void deSerializeRepresentation(String[][] rep) { - for (int i = 0; i < rep.length; i++) { - if (NAME_TAG.equals(rep[i][0])) { - mName = rep[i][1]; - break; - } - } - } - - // Override this in subclasses - public int getStyle() { - return -1; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java deleted file mode 100644 index eb89de036..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterRotateRepresentation.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.util.JsonReader; -import android.util.JsonWriter; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorRotate; - -import java.io.IOException; - -public class FilterRotateRepresentation extends FilterRepresentation { - public static final String SERIALIZATION_NAME = "ROTATION"; - public static final String SERIALIZATION_ROTATE_VALUE = "value"; - private static final String TAG = FilterRotateRepresentation.class.getSimpleName(); - - Rotation mRotation; - - public enum Rotation { - ZERO(0), NINETY(90), ONE_EIGHTY(180), TWO_SEVENTY(270); - private final int mValue; - - private Rotation(int value) { - mValue = value; - } - - public int value() { - return mValue; - } - - public static Rotation fromValue(int value) { - switch (value) { - case 0: - return ZERO; - case 90: - return NINETY; - case 180: - return ONE_EIGHTY; - case 270: - return TWO_SEVENTY; - default: - return null; - } - } - } - - public FilterRotateRepresentation(Rotation rotation) { - super(FilterRotateRepresentation.class.getSimpleName()); - setSerializationName(SERIALIZATION_NAME); - setShowParameterValue(true); - setFilterClass(FilterRotateRepresentation.class); - setFilterType(FilterRepresentation.TYPE_GEOMETRY); - setTextId(R.string.rotate); - setEditorId(EditorRotate.ID); - setRotation(rotation); - } - - public FilterRotateRepresentation(FilterRotateRepresentation r) { - this(r.getRotation()); - } - - public FilterRotateRepresentation() { - this(getNil()); - } - - public Rotation getRotation() { - return mRotation; - } - - public void rotateCW() { - switch(mRotation) { - case ZERO: - mRotation = Rotation.NINETY; - break; - case NINETY: - mRotation = Rotation.ONE_EIGHTY; - break; - case ONE_EIGHTY: - mRotation = Rotation.TWO_SEVENTY; - break; - case TWO_SEVENTY: - mRotation = Rotation.ZERO; - break; - } - } - - public void set(FilterRotateRepresentation r) { - mRotation = r.mRotation; - } - - public void setRotation(Rotation rotation) { - if (rotation == null) { - throw new IllegalArgumentException("Argument to setRotation is null"); - } - mRotation = rotation; - } - - @Override - public boolean allowsSingleInstanceOnly() { - return true; - } - - @Override - public FilterRepresentation copy() { - return new FilterRotateRepresentation(this); - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - if (!(representation instanceof FilterRotateRepresentation)) { - throw new IllegalArgumentException("calling copyAllParameters with incompatible types!"); - } - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (!(a instanceof FilterRotateRepresentation)) { - throw new IllegalArgumentException("calling useParametersFrom with incompatible types!"); - } - setRotation(((FilterRotateRepresentation) a).getRotation()); - } - - @Override - public boolean isNil() { - return mRotation == getNil(); - } - - public static Rotation getNil() { - return Rotation.ZERO; - } - - @Override - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - writer.name(SERIALIZATION_ROTATE_VALUE).value(mRotation.value()); - writer.endObject(); - } - - @Override - public boolean equals(FilterRepresentation rep) { - if (!(rep instanceof FilterRotateRepresentation)) { - return false; - } - FilterRotateRepresentation rotate = (FilterRotateRepresentation) rep; - if (rotate.mRotation.value() != mRotation.value()) { - return false; - } - return true; - } - - @Override - public void deSerializeRepresentation(JsonReader reader) throws IOException { - boolean unset = true; - reader.beginObject(); - while (reader.hasNext()) { - String name = reader.nextName(); - if (SERIALIZATION_ROTATE_VALUE.equals(name)) { - Rotation r = Rotation.fromValue(reader.nextInt()); - if (r != null) { - setRotation(r); - unset = false; - } - } else { - reader.skipValue(); - } - } - if (unset) { - Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME); - } - reader.endObject(); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java deleted file mode 100644 index 94c9497fc..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterStraightenRepresentation.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.util.JsonReader; -import android.util.JsonWriter; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorStraighten; - -import java.io.IOException; - -public class FilterStraightenRepresentation extends FilterRepresentation { - public static final String SERIALIZATION_NAME = "STRAIGHTEN"; - public static final String SERIALIZATION_STRAIGHTEN_VALUE = "value"; - private static final String TAG = FilterStraightenRepresentation.class.getSimpleName(); - public static final int MAX_STRAIGHTEN_ANGLE = 45; - public static final int MIN_STRAIGHTEN_ANGLE = -45; - - float mStraighten; - - public FilterStraightenRepresentation(float straighten) { - super(FilterStraightenRepresentation.class.getSimpleName()); - setSerializationName(SERIALIZATION_NAME); - setShowParameterValue(true); - setFilterClass(FilterStraightenRepresentation.class); - setFilterType(FilterRepresentation.TYPE_GEOMETRY); - setTextId(R.string.straighten); - setEditorId(EditorStraighten.ID); - setStraighten(straighten); - } - - public FilterStraightenRepresentation(FilterStraightenRepresentation s) { - this(s.getStraighten()); - } - - public FilterStraightenRepresentation() { - this(getNil()); - } - - public void set(FilterStraightenRepresentation r) { - mStraighten = r.mStraighten; - } - - @Override - public boolean equals(FilterRepresentation rep) { - if (!(rep instanceof FilterStraightenRepresentation)) { - return false; - } - FilterStraightenRepresentation straighten = (FilterStraightenRepresentation) rep; - if (straighten.mStraighten != mStraighten) { - return false; - } - return true; - } - - public float getStraighten() { - return mStraighten; - } - - public void setStraighten(float straighten) { - if (!rangeCheck(straighten)) { - straighten = Math.min(Math.max(straighten, MIN_STRAIGHTEN_ANGLE), MAX_STRAIGHTEN_ANGLE); - } - mStraighten = straighten; - } - - @Override - public boolean allowsSingleInstanceOnly() { - return true; - } - - @Override - public FilterRepresentation copy() { - return new FilterStraightenRepresentation(this); - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - if (!(representation instanceof FilterStraightenRepresentation)) { - throw new IllegalArgumentException("calling copyAllParameters with incompatible types!"); - } - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - if (!(a instanceof FilterStraightenRepresentation)) { - throw new IllegalArgumentException("calling useParametersFrom with incompatible types!"); - } - setStraighten(((FilterStraightenRepresentation) a).getStraighten()); - } - - @Override - public boolean isNil() { - return mStraighten == getNil(); - } - - public static float getNil() { - return 0; - } - - @Override - public void serializeRepresentation(JsonWriter writer) throws IOException { - writer.beginObject(); - writer.name(SERIALIZATION_STRAIGHTEN_VALUE).value(mStraighten); - writer.endObject(); - } - - @Override - public void deSerializeRepresentation(JsonReader reader) throws IOException { - boolean unset = true; - reader.beginObject(); - while (reader.hasNext()) { - String name = reader.nextName(); - if (SERIALIZATION_STRAIGHTEN_VALUE.equals(name)) { - float s = (float) reader.nextDouble(); - if (rangeCheck(s)) { - setStraighten(s); - unset = false; - } - } else { - reader.skipValue(); - } - } - if (unset) { - Log.w(TAG, "WARNING: bad value when deserializing " + SERIALIZATION_NAME); - } - reader.endObject(); - } - - private boolean rangeCheck(double s) { - if (s < -45 || s > 45) { - return false; - } - return true; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java deleted file mode 100644 index be1812957..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterTinyPlanetRepresentation.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorTinyPlanet; - -public class FilterTinyPlanetRepresentation extends FilterBasicRepresentation { - private static final String SERIALIZATION_NAME = "TINYPLANET"; - private static final String LOGTAG = "FilterTinyPlanetRepresentation"; - private static final String SERIAL_ANGLE = "Angle"; - private float mAngle = 0; - - public FilterTinyPlanetRepresentation() { - super("TinyPlanet", 0, 50, 100); - setSerializationName(SERIALIZATION_NAME); - setShowParameterValue(true); - setFilterClass(ImageFilterTinyPlanet.class); - setFilterType(FilterRepresentation.TYPE_TINYPLANET); - setTextId(R.string.tinyplanet); - setEditorId(EditorTinyPlanet.ID); - setMinimum(1); - } - - @Override - public FilterRepresentation copy() { - FilterTinyPlanetRepresentation representation = new FilterTinyPlanetRepresentation(); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - FilterTinyPlanetRepresentation representation = (FilterTinyPlanetRepresentation) a; - super.useParametersFrom(a); - mAngle = representation.mAngle; - setZoom(representation.getZoom()); - } - - public void setAngle(float angle) { - mAngle = angle; - } - - public float getAngle() { - return mAngle; - } - - public int getZoom() { - return getValue(); - } - - public void setZoom(int zoom) { - setValue(zoom); - } - - public boolean isNil() { - // TinyPlanet always has an effect - return false; - } - - @Override - public String[][] serializeRepresentation() { - String[][] ret = { - {SERIAL_NAME , getName() }, - {SERIAL_VALUE , Integer.toString(getValue())}, - {SERIAL_ANGLE , Float.toString(mAngle)}}; - return ret; - } - - @Override - public void deSerializeRepresentation(String[][] rep) { - super.deSerializeRepresentation(rep); - for (int i = 0; i < rep.length; i++) { - if (SERIAL_VALUE.equals(rep[i][0])) { - setValue(Integer.parseInt(rep[i][1])); - } else if (SERIAL_ANGLE.equals(rep[i][0])) { - setAngle(Float.parseFloat(rep[i][1])); - } - } - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java deleted file mode 100644 index dfdb6fcf0..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterUserPresetRepresentation.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -public class FilterUserPresetRepresentation extends FilterRepresentation { - - private ImagePreset mPreset; - private int mId; - - public FilterUserPresetRepresentation(String name, ImagePreset preset, int id) { - super(name); - setEditorId(ImageOnlyEditor.ID); - setFilterType(FilterRepresentation.TYPE_FX); - mPreset = preset; - mId = id; - } - - public ImagePreset getImagePreset() { - return mPreset; - } - - public int getId() { - return mId; - } - - public FilterRepresentation copy(){ - FilterRepresentation representation = new FilterUserPresetRepresentation(getName(), - new ImagePreset(mPreset), mId); - return representation; - } - - @Override - public boolean allowsSingleInstanceOnly() { - return true; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java b/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java deleted file mode 100644 index 42a7406bc..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FilterVignetteRepresentation.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorVignette; -import com.android.gallery3d.filtershow.imageshow.Oval; - -public class FilterVignetteRepresentation extends FilterBasicRepresentation implements Oval { - private static final String LOGTAG = "FilterVignetteRepresentation"; - private float mCenterX = Float.NaN; - private float mCenterY; - private float mRadiusX = Float.NaN; - private float mRadiusY; - - public FilterVignetteRepresentation() { - super("Vignette", -100, 50, 100); - setSerializationName("VIGNETTE"); - setShowParameterValue(true); - setFilterType(FilterRepresentation.TYPE_VIGNETTE); - setTextId(R.string.vignette); - setEditorId(EditorVignette.ID); - setName("Vignette"); - setFilterClass(ImageFilterVignette.class); - setMinimum(-100); - setMaximum(100); - setDefaultValue(0); - } - - @Override - public void useParametersFrom(FilterRepresentation a) { - super.useParametersFrom(a); - mCenterX = ((FilterVignetteRepresentation) a).mCenterX; - mCenterY = ((FilterVignetteRepresentation) a).mCenterY; - mRadiusX = ((FilterVignetteRepresentation) a).mRadiusX; - mRadiusY = ((FilterVignetteRepresentation) a).mRadiusY; - } - - @Override - public FilterRepresentation copy() { - FilterVignetteRepresentation representation = new FilterVignetteRepresentation(); - copyAllParameters(representation); - return representation; - } - - @Override - protected void copyAllParameters(FilterRepresentation representation) { - super.copyAllParameters(representation); - representation.useParametersFrom(this); - } - - @Override - public void setCenter(float centerX, float centerY) { - mCenterX = centerX; - mCenterY = centerY; - } - - @Override - public float getCenterX() { - return mCenterX; - } - - @Override - public float getCenterY() { - return mCenterY; - } - - @Override - public void setRadius(float radiusX, float radiusY) { - mRadiusX = radiusX; - mRadiusY = radiusY; - } - - @Override - public void setRadiusX(float radiusX) { - mRadiusX = radiusX; - } - - @Override - public void setRadiusY(float radiusY) { - mRadiusY = radiusY; - } - - @Override - public float getRadiusX() { - return mRadiusX; - } - - @Override - public float getRadiusY() { - return mRadiusY; - } - - public boolean isCenterSet() { - return mCenterX != Float.NaN; - } - - @Override - public boolean isNil() { - return getValue() == 0; - } - - @Override - public boolean equals(FilterRepresentation representation) { - if (!super.equals(representation)) { - return false; - } - if (representation instanceof FilterVignetteRepresentation) { - FilterVignetteRepresentation rep = (FilterVignetteRepresentation) representation; - if (rep.getCenterX() == getCenterX() - && rep.getCenterY() == getCenterY() - && rep.getRadiusX() == getRadiusX() - && rep.getRadiusY() == getRadiusY()) { - return true; - } - } - return false; - } - - private static final String[] sParams = { - "Name", "value", "mCenterX", "mCenterY", "mRadiusX", - "mRadiusY" - }; - - @Override - public String[][] serializeRepresentation() { - String[][] ret = { - { sParams[0], getName() }, - { sParams[1], Integer.toString(getValue()) }, - { sParams[2], Float.toString(mCenterX) }, - { sParams[3], Float.toString(mCenterY) }, - { sParams[4], Float.toString(mRadiusX) }, - { sParams[5], Float.toString(mRadiusY) } - }; - return ret; - } - - @Override - public void deSerializeRepresentation(String[][] rep) { - super.deSerializeRepresentation(rep); - for (int i = 0; i < rep.length; i++) { - String key = rep[i][0]; - String value = rep[i][1]; - if (sParams[0].equals(key)) { - setName(value); - } else if (sParams[1].equals(key)) { - setValue(Integer.parseInt(value)); - } else if (sParams[2].equals(key)) { - mCenterX = Float.parseFloat(value); - } else if (sParams[3].equals(key)) { - mCenterY = Float.parseFloat(value); - } else if (sParams[4].equals(key)) { - mRadiusX = Float.parseFloat(value); - } else if (sParams[5].equals(key)) { - mRadiusY = Float.parseFloat(value); - } - } - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java b/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java deleted file mode 100644 index 710128f99..000000000 --- a/src/com/android/gallery3d/filtershow/filters/FiltersManagerInterface.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -public interface FiltersManagerInterface { - ImageFilter getFilterForRepresentation(FilterRepresentation representation); -} diff --git a/src/com/android/gallery3d/filtershow/filters/IconUtilities.java b/src/com/android/gallery3d/filtershow/filters/IconUtilities.java deleted file mode 100644 index e2a01472d..000000000 --- a/src/com/android/gallery3d/filtershow/filters/IconUtilities.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; - -import com.android.gallery3d.R; - -public class IconUtilities { - public static final int PUNCH = R.drawable.filtershow_fx_0005_punch; - public static final int VINTAGE = R.drawable.filtershow_fx_0000_vintage; - public static final int BW_CONTRAST = R.drawable.filtershow_fx_0004_bw_contrast; - public static final int BLEACH = R.drawable.filtershow_fx_0002_bleach; - public static final int INSTANT = R.drawable.filtershow_fx_0001_instant; - public static final int WASHOUT = R.drawable.filtershow_fx_0007_washout; - public static final int BLUECRUSH = R.drawable.filtershow_fx_0003_blue_crush; - public static final int WASHOUT_COLOR = R.drawable.filtershow_fx_0008_washout_color; - public static final int X_PROCESS = R.drawable.filtershow_fx_0006_x_process; - - public static Bitmap getFXBitmap(Resources res, int id) { - Bitmap ret; - BitmapFactory.Options o = new BitmapFactory.Options(); - o.inScaled = false; - - if (id != 0) { - return BitmapFactory.decodeResource(res, id, o); - } - return null; - } - - public static Bitmap loadBitmap(Resources res, int resource) { - - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - Bitmap bitmap = BitmapFactory.decodeResource( - res, - resource, options); - - return bitmap; - } - - public static Bitmap applyFX(Bitmap bitmap, final Bitmap fxBitmap) { - ImageFilterFx fx = new ImageFilterFx() { - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - int fxw = fxBitmap.getWidth(); - int fxh = fxBitmap.getHeight(); - int start = 0; - int end = w * h * 4; - nativeApplyFilter(bitmap, w, h, fxBitmap, fxw, fxh, start, end); - return bitmap; - } - }; - return fx.apply(bitmap, 0, 0); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilter.java deleted file mode 100644 index 437137416..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilter.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.app.Activity; -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.support.v8.renderscript.Allocation; -import android.widget.Toast; - -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.FilterEnvironment; - -public abstract class ImageFilter implements Cloneable { - private FilterEnvironment mEnvironment = null; - - protected String mName = "Original"; - private final String LOGTAG = "ImageFilter"; - protected static final boolean SIMPLE_ICONS = true; - // TODO: Temporary, for dogfood note memory issues with toasts for better - // feedback. Remove this when filters actually work in low memory - // situations. - private static Activity sActivity = null; - - public static void setActivityForMemoryToasts(Activity activity) { - sActivity = activity; - } - - public static void resetStatics() { - sActivity = null; - } - - public void freeResources() {} - - public void displayLowMemoryToast() { - if (sActivity != null) { - sActivity.runOnUiThread(new Runnable() { - public void run() { - Toast.makeText(sActivity, "Memory too low for filter " + getName() + - ", please file a bug report", Toast.LENGTH_SHORT).show(); - } - }); - } - } - - public void setName(String name) { - mName = name; - } - - public String getName() { - return mName; - } - - public boolean supportsAllocationInput() { return false; } - - public void apply(Allocation in, Allocation out) { - setGeneralParameters(); - } - - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - // do nothing here, subclasses will implement filtering here - setGeneralParameters(); - return bitmap; - } - - public abstract void useRepresentation(FilterRepresentation representation); - - native protected void nativeApplyGradientFilter(Bitmap bitmap, int w, int h, - int[] redGradient, int[] greenGradient, int[] blueGradient); - - public FilterRepresentation getDefaultRepresentation() { - return null; - } - - protected Matrix getOriginalToScreenMatrix(int w, int h) { - return GeometryMathUtils.getImageToScreenMatrix(getEnvironment().getImagePreset() - .getGeometryFilters(), true, MasterImage.getImage().getOriginalBounds(), w, h); - } - - public void setEnvironment(FilterEnvironment environment) { - mEnvironment = environment; - } - - public FilterEnvironment getEnvironment() { - return mEnvironment; - } - - public void setGeneralParameters() { - // should implement in subclass which like to transport - // some information to other filters. (like the style setting from RetroLux - // and Film to FixedFrame) - mEnvironment.clearGeneralParameters(); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java deleted file mode 100644 index a7286f0fa..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBorder.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; - -import java.util.HashMap; - -public class ImageFilterBorder extends ImageFilter { - private static final float NINEPATCH_ICON_SCALING = 10; - private static final float BITMAP_ICON_SCALING = 1 / 3.0f; - private FilterImageBorderRepresentation mParameters = null; - private Resources mResources = null; - - private HashMap<Integer, Drawable> mDrawables = new HashMap<Integer, Drawable>(); - - public ImageFilterBorder() { - mName = "Border"; - } - - public void useRepresentation(FilterRepresentation representation) { - FilterImageBorderRepresentation parameters = (FilterImageBorderRepresentation) representation; - mParameters = parameters; - } - - public FilterImageBorderRepresentation getParameters() { - return mParameters; - } - - public void freeResources() { - mDrawables.clear(); - } - - public Bitmap applyHelper(Bitmap bitmap, float scale1, float scale2 ) { - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - Rect bounds = new Rect(0, 0, (int) (w * scale1), (int) (h * scale1)); - Canvas canvas = new Canvas(bitmap); - canvas.scale(scale2, scale2); - Drawable drawable = getDrawable(getParameters().getDrawableResource()); - drawable.setBounds(bounds); - drawable.draw(canvas); - return bitmap; - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null || getParameters().getDrawableResource() == 0) { - return bitmap; - } - float scale2 = scaleFactor * 2.0f; - float scale1 = 1 / scale2; - return applyHelper(bitmap, scale1, scale2); - } - - public void setResources(Resources resources) { - if (mResources != resources) { - mResources = resources; - mDrawables.clear(); - } - } - - public Drawable getDrawable(int rsc) { - Drawable drawable = mDrawables.get(rsc); - if (drawable == null && mResources != null && rsc != 0) { - drawable = new BitmapDrawable(mResources, BitmapFactory.decodeResource(mResources, rsc)); - mDrawables.put(rsc, drawable); - } - return drawable; - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java deleted file mode 100644 index 50837ca2f..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterBwFilter.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; - -import android.graphics.Bitmap; -import android.graphics.Color; - - -public class ImageFilterBwFilter extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "BWFILTER"; - - public ImageFilterBwFilter() { - mName = "BW Filter"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("BW Filter"); - representation.setSerializationName(SERIALIZATION_NAME); - - representation.setFilterClass(ImageFilterBwFilter.class); - representation.setMaximum(180); - representation.setMinimum(-180); - representation.setTextId(R.string.bwfilter); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int r, int g, int b); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float[] hsv = new float[] { - 180 + getParameters().getValue(), 1, 1 - }; - int rgb = Color.HSVToColor(hsv); - int r = 0xFF & (rgb >> 16); - int g = 0xFF & (rgb >> 8); - int b = 0xFF & (rgb >> 0); - nativeApplyFilter(bitmap, w, h, r, g, b); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java deleted file mode 100644 index 1ea8edfb8..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterChanSat.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.support.v8.renderscript.Allocation; -import android.support.v8.renderscript.Element; -import android.support.v8.renderscript.RenderScript; -import android.support.v8.renderscript.Script.LaunchOptions; -import android.support.v8.renderscript.Type; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.pipeline.FilterEnvironment; - -public class ImageFilterChanSat extends ImageFilterRS { - private static final String LOGTAG = "ImageFilterChanSat"; - private ScriptC_saturation mScript; - private Bitmap mSourceBitmap; - - private static final int STRIP_SIZE = 64; - - FilterChanSatRepresentation mParameters = new FilterChanSatRepresentation(); - private Bitmap mOverlayBitmap; - - public ImageFilterChanSat() { - mName = "ChannelSat"; - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - return new FilterChanSatRepresentation(); - } - - @Override - public void useRepresentation(FilterRepresentation representation) { - mParameters = (FilterChanSatRepresentation) representation; - } - - @Override - protected void resetAllocations() { - - } - - @Override - public void resetScripts() { - if (mScript != null) { - mScript.destroy(); - mScript = null; - } - } - @Override - protected void createFilter(android.content.res.Resources res, float scaleFactor, - int quality) { - createFilter(res, scaleFactor, quality, getInPixelsAllocation()); - } - - @Override - protected void createFilter(android.content.res.Resources res, float scaleFactor, - int quality, Allocation in) { - RenderScript rsCtx = getRenderScriptContext(); - - Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx)); - tb_float.setX(in.getType().getX()); - tb_float.setY(in.getType().getY()); - mScript = new ScriptC_saturation(rsCtx, res, R.raw.saturation); - } - - - private Bitmap getSourceBitmap() { - assert (mSourceBitmap != null); - return mSourceBitmap; - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) { - return bitmap; - } - - mSourceBitmap = bitmap; - Bitmap ret = super.apply(bitmap, scaleFactor, quality); - mSourceBitmap = null; - - return ret; - } - - @Override - protected void bindScriptValues() { - int width = getInPixelsAllocation().getType().getX(); - int height = getInPixelsAllocation().getType().getY(); - } - - - - @Override - protected void runFilter() { - int []sat = new int[7]; - for(int i = 0;i<sat.length ;i ++){ - sat[i] = mParameters.getValue(i); - } - - - int width = getInPixelsAllocation().getType().getX(); - int height = getInPixelsAllocation().getType().getY(); - Matrix m = getOriginalToScreenMatrix(width, height); - - - mScript.set_saturation(sat); - - mScript.invoke_setupGradParams(); - runSelectiveAdjust( - getInPixelsAllocation(), getOutPixelsAllocation()); - - } - - private void runSelectiveAdjust(Allocation in, Allocation out) { - int width = in.getType().getX(); - int height = in.getType().getY(); - - LaunchOptions options = new LaunchOptions(); - int ty; - options.setX(0, width); - - for (ty = 0; ty < height; ty += STRIP_SIZE) { - int endy = ty + STRIP_SIZE; - if (endy > height) { - endy = height; - } - options.setY(ty, endy); - mScript.forEach_selectiveAdjust(in, out, options); - if (checkStop()) { - return; - } - } - } - - private boolean checkStop() { - RenderScript rsCtx = getRenderScriptContext(); - rsCtx.finish(); - if (getEnvironment().needsStop()) { - return true; - } - return false; - } -} - diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java deleted file mode 100644 index 27c0e0877..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterContrast.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; - -import android.graphics.Bitmap; - -public class ImageFilterContrast extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "CONTRAST"; - - public ImageFilterContrast() { - mName = "Contrast"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = - (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Contrast"); - representation.setSerializationName(SERIALIZATION_NAME); - - representation.setFilterClass(ImageFilterContrast.class); - representation.setTextId(R.string.contrast); - representation.setMinimum(-100); - representation.setMaximum(100); - representation.setDefaultValue(0); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float strength); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float value = getParameters().getValue(); - nativeApplyFilter(bitmap, w, h, value); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java deleted file mode 100644 index 61b60d2e3..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterCurves.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; - -import com.android.gallery3d.filtershow.imageshow.Spline; - -public class ImageFilterCurves extends ImageFilter { - - private static final String LOGTAG = "ImageFilterCurves"; - FilterCurvesRepresentation mParameters = new FilterCurvesRepresentation(); - - @Override - public FilterRepresentation getDefaultRepresentation() { - return new FilterCurvesRepresentation(); - } - - @Override - public void useRepresentation(FilterRepresentation representation) { - FilterCurvesRepresentation parameters = (FilterCurvesRepresentation) representation; - mParameters = parameters; - } - - public ImageFilterCurves() { - mName = "Curves"; - reset(); - } - - public void populateArray(int[] array, int curveIndex) { - Spline spline = mParameters.getSpline(curveIndex); - if (spline == null) { - return; - } - float[] curve = spline.getAppliedCurve(); - for (int i = 0; i < 256; i++) { - array[i] = (int) (curve[i] * 255); - } - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (!mParameters.getSpline(Spline.RGB).isOriginal()) { - int[] rgbGradient = new int[256]; - populateArray(rgbGradient, Spline.RGB); - nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(), - rgbGradient, rgbGradient, rgbGradient); - } - - int[] redGradient = null; - if (!mParameters.getSpline(Spline.RED).isOriginal()) { - redGradient = new int[256]; - populateArray(redGradient, Spline.RED); - } - int[] greenGradient = null; - if (!mParameters.getSpline(Spline.GREEN).isOriginal()) { - greenGradient = new int[256]; - populateArray(greenGradient, Spline.GREEN); - } - int[] blueGradient = null; - if (!mParameters.getSpline(Spline.BLUE).isOriginal()) { - blueGradient = new int[256]; - populateArray(blueGradient, Spline.BLUE); - } - - nativeApplyGradientFilter(bitmap, bitmap.getWidth(), bitmap.getHeight(), - redGradient, greenGradient, blueGradient); - return bitmap; - } - - public void setSpline(Spline spline, int splineIndex) { - mParameters.setSpline(splineIndex, new Spline(spline)); - } - - public Spline getSpline(int splineIndex) { - return mParameters.getSpline(splineIndex); - } - - public void reset() { - Spline spline = new Spline(); - - spline.addPoint(0.0f, 1.0f); - spline.addPoint(1.0f, 0.0f); - - for (int i = 0; i < 4; i++) { - mParameters.setSpline(i, new Spline(spline)); - } - } - - public void useFilter(ImageFilter a) { - ImageFilterCurves c = (ImageFilterCurves) a; - for (int i = 0; i < 4; i++) { - if (c.mParameters.getSpline(i) != null) { - setSpline(c.mParameters.getSpline(i), i); - } - } - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java deleted file mode 100644 index efb9cde71..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDownsample.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class ImageFilterDownsample extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "DOWNSAMPLE"; - private static final int ICON_DOWNSAMPLE_FRACTION = 8; - private ImageLoader mImageLoader; - - public ImageFilterDownsample(ImageLoader loader) { - mName = "Downsample"; - mImageLoader = loader; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Downsample"); - representation.setSerializationName(SERIALIZATION_NAME); - - representation.setFilterClass(ImageFilterDownsample.class); - representation.setMaximum(100); - representation.setMinimum(1); - representation.setValue(50); - representation.setDefaultValue(50); - representation.setPreviewValue(3); - representation.setTextId(R.string.downsample); - return representation; - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - int p = getParameters().getValue(); - - // size of original precached image - Rect size = MasterImage.getImage().getOriginalBounds(); - int orig_w = size.width(); - int orig_h = size.height(); - - if (p > 0 && p < 100) { - // scale preview to same size as the resulting bitmap from a "save" - int newWidth = orig_w * p / 100; - int newHeight = orig_h * p / 100; - - // only scale preview if preview isn't already scaled enough - if (newWidth <= 0 || newHeight <= 0 || newWidth >= w || newHeight >= h) { - return bitmap; - } - Bitmap ret = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true); - if (ret != bitmap) { - bitmap.recycle(); - } - return ret; - } - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java deleted file mode 100644 index 7df5ffb64..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterDraw.java +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.Path; -import android.graphics.PathMeasure; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffColorFilter; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation.StrokeData; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.FilterEnvironment; - -import java.util.Vector; - -public class ImageFilterDraw extends ImageFilter { - private static final String LOGTAG = "ImageFilterDraw"; - public final static byte SIMPLE_STYLE = 0; - public final static byte BRUSH_STYLE_SPATTER = 1; - public final static byte BRUSH_STYLE_MARKER = 2; - public final static int NUMBER_OF_STYLES = 3; - Bitmap mOverlayBitmap; // this accelerates interaction - int mCachedStrokes = -1; - int mCurrentStyle = 0; - - FilterDrawRepresentation mParameters = new FilterDrawRepresentation(); - - public ImageFilterDraw() { - mName = "Image Draw"; - } - - DrawStyle[] mDrawingsTypes = new DrawStyle[] { - new SimpleDraw(), - new Brush(R.drawable.brush_marker), - new Brush(R.drawable.brush_spatter) - }; - { - for (int i = 0; i < mDrawingsTypes.length; i++) { - mDrawingsTypes[i].setType((byte) i); - } - - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - return new FilterDrawRepresentation(); - } - - @Override - public void useRepresentation(FilterRepresentation representation) { - FilterDrawRepresentation parameters = (FilterDrawRepresentation) representation; - mParameters = parameters; - } - - public void setStyle(byte style) { - mCurrentStyle = style % mDrawingsTypes.length; - } - - public int getStyle() { - return mCurrentStyle; - } - - public static interface DrawStyle { - public void setType(byte type); - public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, - int quality); - } - - class SimpleDraw implements DrawStyle { - byte mType; - - @Override - public void setType(byte type) { - mType = type; - } - - @Override - public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, - int quality) { - if (sd == null) { - return; - } - if (sd.mPath == null) { - return; - } - Paint paint = new Paint(); - - paint.setStyle(Style.STROKE); - paint.setColor(sd.mColor); - paint.setStrokeWidth(toScrMatrix.mapRadius(sd.mRadius)); - - // done this way because of a bug in path.transform(matrix) - Path mCacheTransPath = new Path(); - mCacheTransPath.addPath(sd.mPath, toScrMatrix); - - canvas.drawPath(mCacheTransPath, paint); - } - } - - class Brush implements DrawStyle { - int mBrushID; - Bitmap mBrush; - byte mType; - - public Brush(int brushID) { - mBrushID = brushID; - } - - public Bitmap getBrush() { - if (mBrush == null) { - BitmapFactory.Options opt = new BitmapFactory.Options(); - opt.inPreferredConfig = Bitmap.Config.ALPHA_8; - mBrush = BitmapFactory.decodeResource(MasterImage.getImage().getActivity() - .getResources(), mBrushID, opt); - mBrush = mBrush.extractAlpha(); - } - return mBrush; - } - - @Override - public void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, - Matrix toScrMatrix, - int quality) { - if (sd == null || sd.mPath == null) { - return; - } - Paint paint = new Paint(); - paint.setStyle(Style.STROKE); - paint.setAntiAlias(true); - Path mCacheTransPath = new Path(); - mCacheTransPath.addPath(sd.mPath, toScrMatrix); - draw(canvas, paint, sd.mColor, toScrMatrix.mapRadius(sd.mRadius) * 2, - mCacheTransPath); - } - - public Bitmap createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) - { - Matrix m = new Matrix(); - m.setScale(dstWidth / (float) src.getWidth(), dstHeight / (float) src.getHeight()); - Bitmap result = Bitmap.createBitmap(dstWidth, dstHeight, src.getConfig()); - Canvas canvas = new Canvas(result); - - Paint paint = new Paint(); - paint.setFilterBitmap(filter); - canvas.drawBitmap(src, m, paint); - - return result; - - } - void draw(Canvas canvas, Paint paint, int color, float size, Path path) { - PathMeasure mPathMeasure = new PathMeasure(); - float[] mPosition = new float[2]; - float[] mTan = new float[2]; - - mPathMeasure.setPath(path, false); - - paint.setAntiAlias(true); - paint.setColor(color); - - paint.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)); - Bitmap brush; - // done this way because of a bug in - // Bitmap.createScaledBitmap(getBrush(),(int) size,(int) size,true); - brush = createScaledBitmap(getBrush(), (int) size, (int) size, true); - float len = mPathMeasure.getLength(); - float s2 = size / 2; - float step = s2 / 8; - for (float i = 0; i < len; i += step) { - mPathMeasure.getPosTan(i, mPosition, mTan); - // canvas.drawCircle(pos[0], pos[1], size, paint); - canvas.drawBitmap(brush, mPosition[0] - s2, mPosition[1] - s2, paint); - } - } - - @Override - public void setType(byte type) { - mType = type; - } - } - - void paint(FilterDrawRepresentation.StrokeData sd, Canvas canvas, Matrix toScrMatrix, - int quality) { - mDrawingsTypes[sd.mType].paint(sd, canvas, toScrMatrix, quality); - } - - public void drawData(Canvas canvas, Matrix originalRotateToScreen, int quality) { - Paint paint = new Paint(); - if (quality == FilterEnvironment.QUALITY_FINAL) { - paint.setAntiAlias(true); - } - paint.setStyle(Style.STROKE); - paint.setColor(Color.RED); - paint.setStrokeWidth(40); - - if (mParameters.getDrawing().isEmpty() && mParameters.getCurrentDrawing() == null) { - return; - } - if (quality == FilterEnvironment.QUALITY_FINAL) { - for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) { - paint(strokeData, canvas, originalRotateToScreen, quality); - } - return; - } - - if (mOverlayBitmap == null || - mOverlayBitmap.getWidth() != canvas.getWidth() || - mOverlayBitmap.getHeight() != canvas.getHeight() || - mParameters.getDrawing().size() < mCachedStrokes) { - - mOverlayBitmap = Bitmap.createBitmap( - canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888); - mCachedStrokes = 0; - } - - if (mCachedStrokes < mParameters.getDrawing().size()) { - fillBuffer(originalRotateToScreen); - } - canvas.drawBitmap(mOverlayBitmap, 0, 0, paint); - - StrokeData stroke = mParameters.getCurrentDrawing(); - if (stroke != null) { - paint(stroke, canvas, originalRotateToScreen, quality); - } - } - - public void fillBuffer(Matrix originalRotateToScreen) { - Canvas drawCache = new Canvas(mOverlayBitmap); - Vector<FilterDrawRepresentation.StrokeData> v = mParameters.getDrawing(); - int n = v.size(); - - for (int i = mCachedStrokes; i < n; i++) { - paint(v.get(i), drawCache, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); - } - mCachedStrokes = n; - } - - public void draw(Canvas canvas, Matrix originalRotateToScreen) { - for (FilterDrawRepresentation.StrokeData strokeData : mParameters.getDrawing()) { - paint(strokeData, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); - } - mDrawingsTypes[mCurrentStyle].paint( - null, canvas, originalRotateToScreen, FilterEnvironment.QUALITY_PREVIEW); - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - Matrix m = getOriginalToScreenMatrix(w, h); - drawData(new Canvas(bitmap), m, quality); - return bitmap; - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java deleted file mode 100644 index 2d0d7653d..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterEdge.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; - -import com.android.gallery3d.R; - -public class ImageFilterEdge extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "EDGE"; - public ImageFilterEdge() { - mName = "Edge"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterRepresentation representation = super.getDefaultRepresentation(); - representation.setName("Edge"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterEdge.class); - representation.setTextId(R.string.edge); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float p); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float p = getParameters().getValue() + 101; - p = (float) p / 100; - nativeApplyFilter(bitmap, w, h, p); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java deleted file mode 100644 index 69eab7330..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterExposure.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; - -import android.graphics.Bitmap; - -public class ImageFilterExposure extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "EXPOSURE"; - public ImageFilterExposure() { - mName = "Exposure"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = - (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Exposure"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterExposure.class); - representation.setTextId(R.string.exposure); - representation.setMinimum(-100); - representation.setMaximum(100); - representation.setDefaultValue(0); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float value = getParameters().getValue(); - nativeApplyFilter(bitmap, w, h, value); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java deleted file mode 100644 index 19bea593b..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterFx.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import com.android.gallery3d.app.Log; - -public class ImageFilterFx extends ImageFilter { - private static final String LOGTAG = "ImageFilterFx"; - private FilterFxRepresentation mParameters = null; - private Bitmap mFxBitmap = null; - private Resources mResources = null; - private int mFxBitmapId = 0; - - public ImageFilterFx() { - } - - @Override - public void freeResources() { - if (mFxBitmap != null) mFxBitmap.recycle(); - mFxBitmap = null; - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - return null; - } - - public void useRepresentation(FilterRepresentation representation) { - FilterFxRepresentation parameters = (FilterFxRepresentation) representation; - mParameters = parameters; - } - - public FilterFxRepresentation getParameters() { - return mParameters; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, - Bitmap fxBitmap, int fxw, int fxh, - int start, int end); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null || mResources == null) { - return bitmap; - } - - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - int bitmapResourceId = getParameters().getBitmapResource(); - if (bitmapResourceId == 0) { // null filter fx - return bitmap; - } - - if (mFxBitmap == null || mFxBitmapId != bitmapResourceId) { - BitmapFactory.Options o = new BitmapFactory.Options(); - o.inScaled = false; - mFxBitmapId = bitmapResourceId; - if (mFxBitmapId != 0) { - mFxBitmap = BitmapFactory.decodeResource(mResources, mFxBitmapId, o); - } else { - Log.w(LOGTAG, "bad resource for filter: " + mName); - } - } - - if (mFxBitmap == null) { - return bitmap; - } - - int fxw = mFxBitmap.getWidth(); - int fxh = mFxBitmap.getHeight(); - - int stride = w * 4; - int max = stride * h; - int increment = stride * 256; // 256 lines - for (int i = 0; i < max; i += increment) { - int start = i; - int end = i + increment; - if (end > max) { - end = max; - } - if (!getEnvironment().needsStop()) { - nativeApplyFilter(bitmap, w, h, mFxBitmap, fxw, fxh, start, end); - } - } - - return bitmap; - } - - public void setResources(Resources resources) { - mResources = resources; - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java deleted file mode 100644 index cbdfaa623..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterGrad.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.Matrix; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.pipeline.FilterEnvironment; - -import android.graphics.Bitmap; -import android.graphics.Color; -import android.graphics.Matrix; -import android.support.v8.renderscript.Allocation; -import android.support.v8.renderscript.Element; -import android.support.v8.renderscript.RenderScript; -import android.support.v8.renderscript.Script.LaunchOptions; -import android.support.v8.renderscript.Type; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.pipeline.FilterEnvironment; - -public class ImageFilterGrad extends ImageFilterRS { - private static final String LOGTAG = "ImageFilterGrad"; - private ScriptC_grad mScript; - private Bitmap mSourceBitmap; - private static final int RADIUS_SCALE_FACTOR = 160; - - private static final int STRIP_SIZE = 64; - - FilterGradRepresentation mParameters = new FilterGradRepresentation(); - private Bitmap mOverlayBitmap; - - public ImageFilterGrad() { - mName = "grad"; - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - return new FilterGradRepresentation(); - } - - @Override - public void useRepresentation(FilterRepresentation representation) { - mParameters = (FilterGradRepresentation) representation; - } - - @Override - protected void resetAllocations() { - - } - - @Override - public void resetScripts() { - if (mScript != null) { - mScript.destroy(); - mScript = null; - } - } - @Override - protected void createFilter(android.content.res.Resources res, float scaleFactor, - int quality) { - createFilter(res, scaleFactor, quality, getInPixelsAllocation()); - } - - @Override - protected void createFilter(android.content.res.Resources res, float scaleFactor, - int quality, Allocation in) { - RenderScript rsCtx = getRenderScriptContext(); - - Type.Builder tb_float = new Type.Builder(rsCtx, Element.F32_4(rsCtx)); - tb_float.setX(in.getType().getX()); - tb_float.setY(in.getType().getY()); - mScript = new ScriptC_grad(rsCtx, res, R.raw.grad); - } - - - private Bitmap getSourceBitmap() { - assert (mSourceBitmap != null); - return mSourceBitmap; - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) { - return bitmap; - } - - mSourceBitmap = bitmap; - Bitmap ret = super.apply(bitmap, scaleFactor, quality); - mSourceBitmap = null; - - return ret; - } - - @Override - protected void bindScriptValues() { - int width = getInPixelsAllocation().getType().getX(); - int height = getInPixelsAllocation().getType().getY(); - mScript.set_inputWidth(width); - mScript.set_inputHeight(height); - } - - @Override - protected void runFilter() { - int[] x1 = mParameters.getXPos1(); - int[] y1 = mParameters.getYPos1(); - int[] x2 = mParameters.getXPos2(); - int[] y2 = mParameters.getYPos2(); - - int width = getInPixelsAllocation().getType().getX(); - int height = getInPixelsAllocation().getType().getY(); - Matrix m = getOriginalToScreenMatrix(width, height); - float[] coord = new float[2]; - for (int i = 0; i < x1.length; i++) { - coord[0] = x1[i]; - coord[1] = y1[i]; - m.mapPoints(coord); - x1[i] = (int) coord[0]; - y1[i] = (int) coord[1]; - coord[0] = x2[i]; - coord[1] = y2[i]; - m.mapPoints(coord); - x2[i] = (int) coord[0]; - y2[i] = (int) coord[1]; - } - - mScript.set_mask(mParameters.getMask()); - mScript.set_xPos1(x1); - mScript.set_yPos1(y1); - mScript.set_xPos2(x2); - mScript.set_yPos2(y2); - - mScript.set_brightness(mParameters.getBrightness()); - mScript.set_contrast(mParameters.getContrast()); - mScript.set_saturation(mParameters.getSaturation()); - - mScript.invoke_setupGradParams(); - runSelectiveAdjust( - getInPixelsAllocation(), getOutPixelsAllocation()); - - } - - private void runSelectiveAdjust(Allocation in, Allocation out) { - int width = in.getType().getX(); - int height = in.getType().getY(); - - LaunchOptions options = new LaunchOptions(); - int ty; - options.setX(0, width); - - for (ty = 0; ty < height; ty += STRIP_SIZE) { - int endy = ty + STRIP_SIZE; - if (endy > height) { - endy = height; - } - options.setY(ty, endy); - mScript.forEach_selectiveAdjust(in, out, options); - if (checkStop()) { - return; - } - } - } - - private boolean checkStop() { - RenderScript rsCtx = getRenderScriptContext(); - rsCtx.finish(); - if (getEnvironment().needsStop()) { - return true; - } - return false; - } -} - diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java deleted file mode 100644 index 4c837e0bf..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHighlights.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; - -import com.android.gallery3d.R; - -public class ImageFilterHighlights extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "HIGHLIGHTS"; - private static final String LOGTAG = "ImageFilterVignette"; - - public ImageFilterHighlights() { - mName = "Highlights"; - } - - SplineMath mSpline = new SplineMath(5); - double[] mHighlightCurve = { 0.0, 0.32, 0.418, 0.476, 0.642 }; - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = - (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Highlights"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterHighlights.class); - representation.setTextId(R.string.highlight_recovery); - representation.setMinimum(-100); - representation.setMaximum(100); - representation.setDefaultValue(0); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float[] luminanceMap); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - float p = getParameters().getValue(); - double t = p/100.; - for (int i = 0; i < 5; i++) { - double x = i / 4.; - double y = mHighlightCurve[i] *t+x*(1-t); - mSpline.setPoint(i, x, y); - } - - float[][] curve = mSpline.calculatetCurve(256); - float[] luminanceMap = new float[curve.length]; - for (int i = 0; i < luminanceMap.length; i++) { - luminanceMap[i] = curve[i][1]; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - nativeApplyFilter(bitmap, w, h, luminanceMap); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java deleted file mode 100644 index b87c25490..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterHue.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.BasicEditor; - -import android.graphics.Bitmap; - -public class ImageFilterHue extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "HUE"; - private ColorSpaceMatrix cmatrix = null; - - public ImageFilterHue() { - mName = "Hue"; - cmatrix = new ColorSpaceMatrix(); - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = - (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Hue"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterHue.class); - representation.setMinimum(-180); - representation.setMaximum(180); - representation.setTextId(R.string.hue); - representation.setEditorId(BasicEditor.ID); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float []matrix); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float value = getParameters().getValue(); - cmatrix.identity(); - cmatrix.setHue(value); - - nativeApplyFilter(bitmap, w, h, cmatrix.getMatrix()); - - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java deleted file mode 100644 index 77cdf47b3..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterKMeans.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.text.format.Time; - -import com.android.gallery3d.R; - -public class ImageFilterKMeans extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "KMEANS"; - private int mSeed = 0; - - public ImageFilterKMeans() { - mName = "KMeans"; - - // set random seed for session - Time t = new Time(); - t.setToNow(); - mSeed = (int) t.toMillis(false); - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("KMeans"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterKMeans.class); - representation.setMaximum(20); - representation.setMinimum(2); - representation.setValue(4); - representation.setDefaultValue(4); - representation.setPreviewValue(4); - representation.setTextId(R.string.kmeans); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int width, int height, - Bitmap large_ds_bm, int lwidth, int lheight, Bitmap small_ds_bm, - int swidth, int sheight, int p, int seed); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - Bitmap large_bm_ds = bitmap; - Bitmap small_bm_ds = bitmap; - - // find width/height for larger downsampled bitmap - int lw = w; - int lh = h; - while (lw > 256 && lh > 256) { - lw /= 2; - lh /= 2; - } - if (lw != w) { - large_bm_ds = Bitmap.createScaledBitmap(bitmap, lw, lh, true); - } - - // find width/height for smaller downsampled bitmap - int sw = lw; - int sh = lh; - while (sw > 64 && sh > 64) { - sw /= 2; - sh /= 2; - } - if (sw != lw) { - small_bm_ds = Bitmap.createScaledBitmap(large_bm_ds, sw, sh, true); - } - - if (getParameters() != null) { - int p = Math.max(getParameters().getValue(), getParameters().getMinimum()) % (getParameters().getMaximum() + 1); - nativeApplyFilter(bitmap, w, h, large_bm_ds, lw, lh, small_bm_ds, sw, sh, p, mSeed); - } - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java deleted file mode 100644 index 98497596b..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterNegative.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; - -public class ImageFilterNegative extends ImageFilter { - private static final String SERIALIZATION_NAME = "NEGATIVE"; - public ImageFilterNegative() { - mName = "Negative"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterRepresentation representation = new FilterDirectRepresentation("Negative"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterNegative.class); - representation.setTextId(R.string.negative); - representation.setShowParameterValue(false); - representation.setEditorId(ImageOnlyEditor.ID); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h); - - @Override - public void useRepresentation(FilterRepresentation representation) { - - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - nativeApplyFilter(bitmap, w, h); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java deleted file mode 100644 index 25e5d1476..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterParametricBorder.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.RectF; - -public class ImageFilterParametricBorder extends ImageFilter { - private FilterColorBorderRepresentation mParameters = null; - - public ImageFilterParametricBorder() { - mName = "Border"; - } - - public void useRepresentation(FilterRepresentation representation) { - FilterColorBorderRepresentation parameters = (FilterColorBorderRepresentation) representation; - mParameters = parameters; - } - - public FilterColorBorderRepresentation getParameters() { - return mParameters; - } - - private void applyHelper(Canvas canvas, int w, int h) { - if (getParameters() == null) { - return; - } - Path border = new Path(); - border.moveTo(0, 0); - float bs = getParameters().getBorderSize() / 100.0f * w; - float r = getParameters().getBorderRadius() / 100.0f * w; - border.lineTo(0, h); - border.lineTo(w, h); - border.lineTo(w, 0); - border.lineTo(0, 0); - border.addRoundRect(new RectF(bs, bs, w - bs, h - bs), - r, r, Path.Direction.CW); - - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setColor(getParameters().getColor()); - canvas.drawPath(border, paint); - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - Canvas canvas = new Canvas(bitmap); - applyHelper(canvas, bitmap.getWidth(), bitmap.getHeight()); - return bitmap; - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java deleted file mode 100644 index 5695ef53e..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.support.v8.renderscript.*; -import android.util.Log; -import android.content.res.Resources; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.pipeline.PipelineInterface; - -public abstract class ImageFilterRS extends ImageFilter { - private static final String LOGTAG = "ImageFilterRS"; - private boolean DEBUG = false; - private int mLastInputWidth = 0; - private int mLastInputHeight = 0; - private long mLastTimeCalled; - - public static boolean PERF_LOGGING = false; - - private static ScriptC_grey mGreyConvert = null; - private static RenderScript mRScache = null; - - private volatile boolean mResourcesLoaded = false; - - protected abstract void createFilter(android.content.res.Resources res, - float scaleFactor, int quality); - - protected void createFilter(android.content.res.Resources res, - float scaleFactor, int quality, Allocation in) {} - protected void bindScriptValues(Allocation in) {} - - protected abstract void runFilter(); - - protected void update(Bitmap bitmap) { - getOutPixelsAllocation().copyTo(bitmap); - } - - protected RenderScript getRenderScriptContext() { - PipelineInterface pipeline = getEnvironment().getPipeline(); - return pipeline.getRSContext(); - } - - protected Allocation getInPixelsAllocation() { - PipelineInterface pipeline = getEnvironment().getPipeline(); - return pipeline.getInPixelsAllocation(); - } - - protected Allocation getOutPixelsAllocation() { - PipelineInterface pipeline = getEnvironment().getPipeline(); - return pipeline.getOutPixelsAllocation(); - } - - @Override - public void apply(Allocation in, Allocation out) { - long startOverAll = System.nanoTime(); - if (PERF_LOGGING) { - long delay = (startOverAll - mLastTimeCalled) / 1000; - String msg = String.format("%s; image size %dx%d; ", getName(), - in.getType().getX(), in.getType().getY()); - msg += String.format("called after %.2f ms (%.2f FPS); ", - delay / 1000.f, 1000000.f / delay); - Log.i(LOGTAG, msg); - } - mLastTimeCalled = startOverAll; - long startFilter = 0; - long endFilter = 0; - if (!mResourcesLoaded) { - PipelineInterface pipeline = getEnvironment().getPipeline(); - createFilter(pipeline.getResources(), getEnvironment().getScaleFactor(), - getEnvironment().getQuality(), in); - mResourcesLoaded = true; - } - startFilter = System.nanoTime(); - bindScriptValues(in); - run(in, out); - if (PERF_LOGGING) { - getRenderScriptContext().finish(); - endFilter = System.nanoTime(); - long endOverAll = System.nanoTime(); - String msg = String.format("%s; image size %dx%d; ", getName(), - in.getType().getX(), in.getType().getY()); - long timeOverAll = (endOverAll - startOverAll) / 1000; - long timeFilter = (endFilter - startFilter) / 1000; - msg += String.format("over all %.2f ms (%.2f FPS); ", - timeOverAll / 1000.f, 1000000.f / timeOverAll); - msg += String.format("run filter %.2f ms (%.2f FPS)", - timeFilter / 1000.f, 1000000.f / timeFilter); - Log.i(LOGTAG, msg); - } - } - - protected void run(Allocation in, Allocation out) {} - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (bitmap == null || bitmap.getWidth() == 0 || bitmap.getHeight() == 0) { - return bitmap; - } - try { - PipelineInterface pipeline = getEnvironment().getPipeline(); - if (DEBUG) { - Log.v(LOGTAG, "apply filter " + getName() + " in pipeline " + pipeline.getName()); - } - Resources rsc = pipeline.getResources(); - boolean sizeChanged = false; - if (getInPixelsAllocation() != null - && ((getInPixelsAllocation().getType().getX() != mLastInputWidth) - || (getInPixelsAllocation().getType().getY() != mLastInputHeight))) { - sizeChanged = true; - } - if (pipeline.prepareRenderscriptAllocations(bitmap) - || !isResourcesLoaded() || sizeChanged) { - freeResources(); - createFilter(rsc, scaleFactor, quality); - setResourcesLoaded(true); - mLastInputWidth = getInPixelsAllocation().getType().getX(); - mLastInputHeight = getInPixelsAllocation().getType().getY(); - } - bindScriptValues(); - runFilter(); - update(bitmap); - if (DEBUG) { - Log.v(LOGTAG, "DONE apply filter " + getName() + " in pipeline " + pipeline.getName()); - } - } catch (android.renderscript.RSIllegalArgumentException e) { - Log.e(LOGTAG, "Illegal argument? " + e); - } catch (android.renderscript.RSRuntimeException e) { - Log.e(LOGTAG, "RS runtime exception ? " + e); - } catch (java.lang.OutOfMemoryError e) { - // Many of the renderscript filters allocated large (>16Mb resources) in order to apply. - System.gc(); - displayLowMemoryToast(); - Log.e(LOGTAG, "not enough memory for filter " + getName(), e); - } - return bitmap; - } - - protected static Allocation convertBitmap(RenderScript RS, Bitmap bitmap) { - return Allocation.createFromBitmap(RS, bitmap, - Allocation.MipmapControl.MIPMAP_NONE, - Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE); - } - - private static Allocation convertRGBAtoA(RenderScript RS, Bitmap bitmap) { - if (RS != mRScache || mGreyConvert == null) { - mGreyConvert = new ScriptC_grey(RS, RS.getApplicationContext().getResources(), - R.raw.grey); - mRScache = RS; - } - - Type.Builder tb_a8 = new Type.Builder(RS, Element.A_8(RS)); - - Allocation bitmapTemp = convertBitmap(RS, bitmap); - if (bitmapTemp.getType().getElement().isCompatible(Element.A_8(RS))) { - return bitmapTemp; - } - - tb_a8.setX(bitmapTemp.getType().getX()); - tb_a8.setY(bitmapTemp.getType().getY()); - Allocation bitmapAlloc = Allocation.createTyped(RS, tb_a8.create(), - Allocation.MipmapControl.MIPMAP_NONE, - Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE); - mGreyConvert.forEach_RGBAtoA(bitmapTemp, bitmapAlloc); - bitmapTemp.destroy(); - return bitmapAlloc; - } - - public Allocation loadScaledResourceAlpha(int resource, int inSampleSize) { - Resources res = getEnvironment().getPipeline().getResources(); - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ALPHA_8; - options.inSampleSize = inSampleSize; - Bitmap bitmap = BitmapFactory.decodeResource( - res, - resource, options); - Allocation ret = convertRGBAtoA(getRenderScriptContext(), bitmap); - bitmap.recycle(); - return ret; - } - - public Allocation loadScaledResourceAlpha(int resource, int w, int h, int inSampleSize) { - Resources res = getEnvironment().getPipeline().getResources(); - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ALPHA_8; - options.inSampleSize = inSampleSize; - Bitmap bitmap = BitmapFactory.decodeResource( - res, - resource, options); - Bitmap resizeBitmap = Bitmap.createScaledBitmap(bitmap, w, h, true); - Allocation ret = convertRGBAtoA(getRenderScriptContext(), resizeBitmap); - resizeBitmap.recycle(); - bitmap.recycle(); - return ret; - } - - public Allocation loadResourceAlpha(int resource) { - return loadScaledResourceAlpha(resource, 1); - } - - public Allocation loadResource(int resource) { - Resources res = getEnvironment().getPipeline().getResources(); - final BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - Bitmap bitmap = BitmapFactory.decodeResource( - res, - resource, options); - Allocation ret = convertBitmap(getRenderScriptContext(), bitmap); - bitmap.recycle(); - return ret; - } - - private boolean isResourcesLoaded() { - return mResourcesLoaded; - } - - private void setResourcesLoaded(boolean resourcesLoaded) { - mResourcesLoaded = resourcesLoaded; - } - - /** - * Bitmaps and RS Allocations should be cleared here - */ - abstract protected void resetAllocations(); - - /** - * RS Script objects (and all other RS objects) should be cleared here - */ - public abstract void resetScripts(); - - /** - * Scripts values should be bound here - */ - abstract protected void bindScriptValues(); - - public void freeResources() { - if (!isResourcesLoaded()) { - return; - } - resetAllocations(); - mLastInputWidth = 0; - mLastInputHeight = 0; - setResourcesLoaded(false); - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java deleted file mode 100644 index 511f9e90f..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRedEye.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.RectF; - -import java.util.Vector; - -public class ImageFilterRedEye extends ImageFilter { - private static final String LOGTAG = "ImageFilterRedEye"; - FilterRedEyeRepresentation mParameters = new FilterRedEyeRepresentation(); - - public ImageFilterRedEye() { - mName = "Red Eye"; - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - return new FilterRedEyeRepresentation(); - } - - public boolean isNil() { - return mParameters.isNil(); - } - - public Vector<FilterPoint> getCandidates() { - return mParameters.getCandidates(); - } - - public void clear() { - mParameters.clearCandidates(); - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, short[] matrix); - - @Override - public void useRepresentation(FilterRepresentation representation) { - FilterRedEyeRepresentation parameters = (FilterRedEyeRepresentation) representation; - mParameters = parameters; - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - short[] rect = new short[4]; - - int size = mParameters.getNumberOfCandidates(); - Matrix originalToScreen = getOriginalToScreenMatrix(w, h); - for (int i = 0; i < size; i++) { - RectF r = new RectF(((RedEyeCandidate) (mParameters.getCandidate(i))).mRect); - originalToScreen.mapRect(r); - if (r.intersect(0, 0, w, h)) { - rect[0] = (short) r.left; - rect[1] = (short) r.top; - rect[2] = (short) r.width(); - rect[3] = (short) r.height(); - nativeApplyFilter(bitmap, w, h, rect); - } - } - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java deleted file mode 100644 index c3124ff77..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSaturated.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; - -import android.graphics.Bitmap; - -public class ImageFilterSaturated extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "SATURATED"; - public ImageFilterSaturated() { - mName = "Saturated"; - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = - (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Saturated"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterSaturated.class); - representation.setTextId(R.string.saturation); - representation.setMinimum(-100); - representation.setMaximum(100); - representation.setDefaultValue(0); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float saturation); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - int p = getParameters().getValue(); - float value = 1 + p / 100.0f; - nativeApplyFilter(bitmap, w, h, value); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java deleted file mode 100644 index bd119bbc9..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterShadows.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; - -import android.graphics.Bitmap; - -public class ImageFilterShadows extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "SHADOWS"; - public ImageFilterShadows() { - mName = "Shadows"; - - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = - (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Shadows"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterShadows.class); - representation.setTextId(R.string.shadow_recovery); - representation.setMinimum(-100); - representation.setMaximum(100); - representation.setDefaultValue(0); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float factor); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float p = getParameters().getValue(); - - nativeApplyFilter(bitmap, w, h, p); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java deleted file mode 100644 index 3bd794464..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterSharpen.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; - -public class ImageFilterSharpen extends ImageFilterRS { - private static final String SERIALIZATION_NAME = "SHARPEN"; - private static final String LOGTAG = "ImageFilterSharpen"; - private ScriptC_convolve3x3 mScript; - - private FilterBasicRepresentation mParameters; - - public ImageFilterSharpen() { - mName = "Sharpen"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterRepresentation representation = new FilterBasicRepresentation("Sharpen", 0, 0, 100); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setShowParameterValue(true); - representation.setFilterClass(ImageFilterSharpen.class); - representation.setTextId(R.string.sharpness); - representation.setOverlayId(R.drawable.filtershow_button_colors_sharpen); - representation.setEditorId(R.id.imageShow); - representation.setSupportsPartialRendering(true); - return representation; - } - - public void useRepresentation(FilterRepresentation representation) { - FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation; - mParameters = parameters; - } - - @Override - protected void resetAllocations() { - // nothing to do - } - - @Override - public void resetScripts() { - if (mScript != null) { - mScript.destroy(); - mScript = null; - } - } - - @Override - protected void createFilter(android.content.res.Resources res, float scaleFactor, - int quality) { - if (mScript == null) { - mScript = new ScriptC_convolve3x3(getRenderScriptContext(), res, R.raw.convolve3x3); - } - } - - private void computeKernel() { - float scaleFactor = getEnvironment().getScaleFactor(); - float p1 = mParameters.getValue() * scaleFactor; - float value = p1 / 100.0f; - float f[] = new float[9]; - float p = value; - f[0] = -p; - f[1] = -p; - f[2] = -p; - f[3] = -p; - f[4] = 8 * p + 1; - f[5] = -p; - f[6] = -p; - f[7] = -p; - f[8] = -p; - mScript.set_gCoeffs(f); - } - - @Override - protected void bindScriptValues() { - int w = getInPixelsAllocation().getType().getX(); - int h = getInPixelsAllocation().getType().getY(); - mScript.set_gWidth(w); - mScript.set_gHeight(h); - } - - @Override - protected void runFilter() { - if (mParameters == null) { - return; - } - computeKernel(); - mScript.set_gIn(getInPixelsAllocation()); - mScript.bind_gPixels(getInPixelsAllocation()); - mScript.forEach_root(getInPixelsAllocation(), getOutPixelsAllocation()); - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java deleted file mode 100644 index 77250bd7a..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterTinyPlanet.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.RectF; - -import com.adobe.xmp.XMPException; -import com.adobe.xmp.XMPMeta; -import com.android.gallery3d.app.Log; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -/** - * An image filter which creates a tiny planet projection. - */ -public class ImageFilterTinyPlanet extends SimpleImageFilter { - - - private static final String LOGTAG = ImageFilterTinyPlanet.class.getSimpleName(); - public static final String GOOGLE_PANO_NAMESPACE = "http://ns.google.com/photos/1.0/panorama/"; - FilterTinyPlanetRepresentation mParameters = new FilterTinyPlanetRepresentation(); - - public static final String CROPPED_AREA_IMAGE_WIDTH_PIXELS = - "CroppedAreaImageWidthPixels"; - public static final String CROPPED_AREA_IMAGE_HEIGHT_PIXELS = - "CroppedAreaImageHeightPixels"; - public static final String CROPPED_AREA_FULL_PANO_WIDTH_PIXELS = - "FullPanoWidthPixels"; - public static final String CROPPED_AREA_FULL_PANO_HEIGHT_PIXELS = - "FullPanoHeightPixels"; - public static final String CROPPED_AREA_LEFT = - "CroppedAreaLeftPixels"; - public static final String CROPPED_AREA_TOP = - "CroppedAreaTopPixels"; - - public ImageFilterTinyPlanet() { - mName = "TinyPlanet"; - } - - @Override - public void useRepresentation(FilterRepresentation representation) { - FilterTinyPlanetRepresentation parameters = (FilterTinyPlanetRepresentation) representation; - mParameters = parameters; - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - return new FilterTinyPlanetRepresentation(); - } - - - native protected void nativeApplyFilter( - Bitmap bitmapIn, int width, int height, Bitmap bitmapOut, int outSize, float scale, - float angle); - - - @Override - public Bitmap apply(Bitmap bitmapIn, float scaleFactor, int quality) { - int w = bitmapIn.getWidth(); - int h = bitmapIn.getHeight(); - int outputSize = (int) (w / 2f); - ImagePreset preset = getEnvironment().getImagePreset(); - Bitmap mBitmapOut = null; - if (preset != null) { - XMPMeta xmp = ImageLoader.getXmpObject(MasterImage.getImage().getActivity()); - // Do nothing, just use bitmapIn as is if we don't have XMP. - if(xmp != null) { - bitmapIn = applyXmp(bitmapIn, xmp, w); - } - } - if (mBitmapOut != null) { - if (outputSize != mBitmapOut.getHeight()) { - mBitmapOut = null; - } - } - while (mBitmapOut == null) { - try { - mBitmapOut = getEnvironment().getBitmap(outputSize, outputSize); - } catch (java.lang.OutOfMemoryError e) { - System.gc(); - outputSize /= 2; - Log.v(LOGTAG, "No memory to create Full Tiny Planet create half"); - } - } - nativeApplyFilter(bitmapIn, bitmapIn.getWidth(), bitmapIn.getHeight(), mBitmapOut, - outputSize, mParameters.getZoom() / 100f, mParameters.getAngle()); - - return mBitmapOut; - } - - private Bitmap applyXmp(Bitmap bitmapIn, XMPMeta xmp, int intermediateWidth) { - try { - int croppedAreaWidth = - getInt(xmp, CROPPED_AREA_IMAGE_WIDTH_PIXELS); - int croppedAreaHeight = - getInt(xmp, CROPPED_AREA_IMAGE_HEIGHT_PIXELS); - int fullPanoWidth = - getInt(xmp, CROPPED_AREA_FULL_PANO_WIDTH_PIXELS); - int fullPanoHeight = - getInt(xmp, CROPPED_AREA_FULL_PANO_HEIGHT_PIXELS); - int left = getInt(xmp, CROPPED_AREA_LEFT); - int top = getInt(xmp, CROPPED_AREA_TOP); - - if (fullPanoWidth == 0 || fullPanoHeight == 0) { - return bitmapIn; - } - // Make sure the intermediate image has the similar size to the - // input. - Bitmap paddedBitmap = null; - float scale = intermediateWidth / (float) fullPanoWidth; - while (paddedBitmap == null) { - try { - paddedBitmap = Bitmap.createBitmap( - (int) (fullPanoWidth * scale), (int) (fullPanoHeight * scale), - Bitmap.Config.ARGB_8888); - } catch (java.lang.OutOfMemoryError e) { - System.gc(); - scale /= 2; - } - } - Canvas paddedCanvas = new Canvas(paddedBitmap); - - int right = left + croppedAreaWidth; - int bottom = top + croppedAreaHeight; - RectF destRect = new RectF(left * scale, top * scale, right * scale, bottom * scale); - paddedCanvas.drawBitmap(bitmapIn, null, destRect, null); - bitmapIn = paddedBitmap; - } catch (XMPException ex) { - // Do nothing, just use bitmapIn as is. - } - return bitmapIn; - } - - private static int getInt(XMPMeta xmp, String key) throws XMPException { - if (xmp.doesPropertyExist(GOOGLE_PANO_NAMESPACE, key)) { - return xmp.getPropertyInteger(GOOGLE_PANO_NAMESPACE, key); - } else { - return 0; - } - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java deleted file mode 100644 index 86be9a155..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVibrance.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; - -import android.graphics.Bitmap; - -public class ImageFilterVibrance extends SimpleImageFilter { - private static final String SERIALIZATION_NAME = "VIBRANCE"; - public ImageFilterVibrance() { - mName = "Vibrance"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterBasicRepresentation representation = - (FilterBasicRepresentation) super.getDefaultRepresentation(); - representation.setName("Vibrance"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterVibrance.class); - representation.setTextId(R.string.vibrance); - representation.setMinimum(-100); - representation.setMaximum(100); - representation.setDefaultValue(0); - representation.setSupportsPartialRendering(true); - return representation; - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, float bright); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (getParameters() == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float value = getParameters().getValue(); - nativeApplyFilter(bitmap, w, h, value); - - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java deleted file mode 100644 index 7e0a452bf..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterVignette.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Rect; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.pipeline.FilterEnvironment; - -public class ImageFilterVignette extends SimpleImageFilter { - private static final String LOGTAG = "ImageFilterVignette"; - private Bitmap mOverlayBitmap; - - public ImageFilterVignette() { - mName = "Vignette"; - } - - @Override - public FilterRepresentation getDefaultRepresentation() { - FilterVignetteRepresentation representation = new FilterVignetteRepresentation(); - return representation; - } - - native protected void nativeApplyFilter( - Bitmap bitmap, int w, int h, int cx, int cy, float radx, float rady, float strength); - - private float calcRadius(float cx, float cy, int w, int h) { - float d = cx; - if (d < (w - cx)) { - d = w - cx; - } - if (d < cy) { - d = cy; - } - if (d < (h - cy)) { - d = h - cy; - } - return d * d * 2.0f; - } - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - if (SIMPLE_ICONS && FilterEnvironment.QUALITY_ICON == quality) { - if (mOverlayBitmap == null) { - Resources res = getEnvironment().getPipeline().getResources(); - mOverlayBitmap = IconUtilities.getFXBitmap(res, - R.drawable.filtershow_icon_vignette); - } - Canvas c = new Canvas(bitmap); - int dim = Math.max(bitmap.getWidth(), bitmap.getHeight()); - Rect r = new Rect(0, 0, dim, dim); - c.drawBitmap(mOverlayBitmap, null, r, null); - return bitmap; - } - FilterVignetteRepresentation rep = (FilterVignetteRepresentation) getParameters(); - if (rep == null) { - return bitmap; - } - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - float value = rep.getValue() / 100.0f; - float cx = w / 2; - float cy = h / 2; - float r = calcRadius(cx, cy, w, h); - float rx = r; - float ry = r; - if (rep.isCenterSet()) { - Matrix m = getOriginalToScreenMatrix(w, h); - cx = rep.getCenterX(); - cy = rep.getCenterY(); - float[] center = new float[] { cx, cy }; - m.mapPoints(center); - cx = center[0]; - cy = center[1]; - rx = m.mapRadius(rep.getRadiusX()); - ry = m.mapRadius(rep.getRadiusY()); - } - nativeApplyFilter(bitmap, w, h, (int) cx, (int) cy, rx, ry, value); - return bitmap; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java deleted file mode 100644 index 6bb88ec21..000000000 --- a/src/com/android/gallery3d/filtershow/filters/ImageFilterWBalance.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; - -import android.graphics.Bitmap; - -public class ImageFilterWBalance extends ImageFilter { - private static final String SERIALIZATION_NAME = "WBALANCE"; - private static final String TAG = "ImageFilterWBalance"; - - public ImageFilterWBalance() { - mName = "WBalance"; - } - - public FilterRepresentation getDefaultRepresentation() { - FilterRepresentation representation = new FilterDirectRepresentation("WBalance"); - representation.setSerializationName(SERIALIZATION_NAME); - representation.setFilterClass(ImageFilterWBalance.class); - representation.setFilterType(FilterRepresentation.TYPE_WBALANCE); - representation.setTextId(R.string.wbalance); - representation.setShowParameterValue(false); - representation.setEditorId(ImageOnlyEditor.ID); - representation.setSupportsPartialRendering(true); - return representation; - } - - @Override - public void useRepresentation(FilterRepresentation representation) { - - } - - native protected void nativeApplyFilter(Bitmap bitmap, int w, int h, int locX, int locY); - - @Override - public Bitmap apply(Bitmap bitmap, float scaleFactor, int quality) { - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - nativeApplyFilter(bitmap, w, h, -1, -1); - return bitmap; - } - -} diff --git a/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java b/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java deleted file mode 100644 index a40d4fa3b..000000000 --- a/src/com/android/gallery3d/filtershow/filters/RedEyeCandidate.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -import android.graphics.RectF; - -public class RedEyeCandidate implements FilterPoint { - RectF mRect = new RectF(); - RectF mBounds = new RectF(); - - public RedEyeCandidate(RedEyeCandidate candidate) { - mRect.set(candidate.mRect); - mBounds.set(candidate.mBounds); - } - - public RedEyeCandidate(RectF rect, RectF bounds) { - mRect.set(rect); - mBounds.set(bounds); - } - - public boolean equals(RedEyeCandidate candidate) { - if (candidate.mRect.equals(mRect) - && candidate.mBounds.equals(mBounds)) { - return true; - } - return false; - } - - public boolean intersect(RectF rect) { - return mRect.intersect(rect); - } - - public RectF getRect() { - return mRect; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java b/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java deleted file mode 100644 index c891d20f3..000000000 --- a/src/com/android/gallery3d/filtershow/filters/SimpleImageFilter.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.filters; - -public class SimpleImageFilter extends ImageFilter { - - private FilterBasicRepresentation mParameters; - - public FilterRepresentation getDefaultRepresentation() { - FilterRepresentation representation = new FilterBasicRepresentation("Default", 0, 50, 100); - representation.setShowParameterValue(true); - return representation; - } - - public void useRepresentation(FilterRepresentation representation) { - FilterBasicRepresentation parameters = (FilterBasicRepresentation) representation; - mParameters = parameters; - } - - public FilterBasicRepresentation getParameters() { - return mParameters; - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/SplineMath.java b/src/com/android/gallery3d/filtershow/filters/SplineMath.java deleted file mode 100644 index 5b12d0a61..000000000 --- a/src/com/android/gallery3d/filtershow/filters/SplineMath.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.android.gallery3d.filtershow.filters; - - -public class SplineMath { - double[][] mPoints = new double[6][2]; - double[] mDerivatives; - SplineMath(int n) { - mPoints = new double[n][2]; - } - - public void setPoint(int index, double x, double y) { - mPoints[index][0] = x; - mPoints[index][1] = y; - mDerivatives = null; - } - - public float[][] calculatetCurve(int n) { - float[][] curve = new float[n][2]; - double[][] points = new double[mPoints.length][2]; - for (int i = 0; i < mPoints.length; i++) { - - points[i][0] = mPoints[i][0]; - points[i][1] = mPoints[i][1]; - - } - double[] derivatives = solveSystem(points); - float start = (float) points[0][0]; - float end = (float) (points[points.length - 1][0]); - - curve[0][0] = (float) (points[0][0]); - curve[0][1] = (float) (points[0][1]); - int last = curve.length - 1; - curve[last][0] = (float) (points[points.length - 1][0]); - curve[last][1] = (float) (points[points.length - 1][1]); - - for (int i = 0; i < curve.length; i++) { - - double[] cur = null; - double[] next = null; - double x = start + i * (end - start) / (curve.length - 1); - int pivot = 0; - for (int j = 0; j < points.length - 1; j++) { - if (x >= points[j][0] && x <= points[j + 1][0]) { - pivot = j; - } - } - cur = points[pivot]; - next = points[pivot + 1]; - if (x <= next[0]) { - double x1 = cur[0]; - double x2 = next[0]; - double y1 = cur[1]; - double y2 = next[1]; - - // Use the second derivatives to apply the cubic spline - // equation: - double delta = (x2 - x1); - double delta2 = delta * delta; - double b = (x - x1) / delta; - double a = 1 - b; - double ta = a * y1; - double tb = b * y2; - double tc = (a * a * a - a) * derivatives[pivot]; - double td = (b * b * b - b) * derivatives[pivot + 1]; - double y = ta + tb + (delta2 / 6) * (tc + td); - - curve[i][0] = (float) (x); - curve[i][1] = (float) (y); - } else { - curve[i][0] = (float) (next[0]); - curve[i][1] = (float) (next[1]); - } - } - return curve; - } - - public double getValue(double x) { - double[] cur = null; - double[] next = null; - if (mDerivatives == null) - mDerivatives = solveSystem(mPoints); - int pivot = 0; - for (int j = 0; j < mPoints.length - 1; j++) { - pivot = j; - if (x <= mPoints[j][0]) { - break; - } - } - cur = mPoints[pivot]; - next = mPoints[pivot + 1]; - double x1 = cur[0]; - double x2 = next[0]; - double y1 = cur[1]; - double y2 = next[1]; - - // Use the second derivatives to apply the cubic spline - // equation: - double delta = (x2 - x1); - double delta2 = delta * delta; - double b = (x - x1) / delta; - double a = 1 - b; - double ta = a * y1; - double tb = b * y2; - double tc = (a * a * a - a) * mDerivatives[pivot]; - double td = (b * b * b - b) * mDerivatives[pivot + 1]; - double y = ta + tb + (delta2 / 6) * (tc + td); - - return y; - - } - - double[] solveSystem(double[][] points) { - int n = points.length; - double[][] system = new double[n][3]; - double[] result = new double[n]; // d - double[] solution = new double[n]; // returned coefficients - system[0][1] = 1; - system[n - 1][1] = 1; - double d6 = 1.0 / 6.0; - double d3 = 1.0 / 3.0; - - // let's create a tridiagonal matrix representing the - // system, and apply the TDMA algorithm to solve it - // (see http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm) - for (int i = 1; i < n - 1; i++) { - double deltaPrevX = points[i][0] - points[i - 1][0]; - double deltaX = points[i + 1][0] - points[i - 1][0]; - double deltaNextX = points[i + 1][0] - points[i][0]; - double deltaNextY = points[i + 1][1] - points[i][1]; - double deltaPrevY = points[i][1] - points[i - 1][1]; - system[i][0] = d6 * deltaPrevX; // a_i - system[i][1] = d3 * deltaX; // b_i - system[i][2] = d6 * deltaNextX; // c_i - result[i] = (deltaNextY / deltaNextX) - (deltaPrevY / deltaPrevX); // d_i - } - - // Forward sweep - for (int i = 1; i < n; i++) { - // m = a_i/b_i-1 - double m = system[i][0] / system[i - 1][1]; - // b_i = b_i - m(c_i-1) - system[i][1] = system[i][1] - m * system[i - 1][2]; - // d_i = d_i - m(d_i-1) - result[i] = result[i] - m * result[i - 1]; - } - - // Back substitution - solution[n - 1] = result[n - 1] / system[n - 1][1]; - for (int i = n - 2; i >= 0; --i) { - solution[i] = (result[i] - system[i][2] * solution[i + 1]) / system[i][1]; - } - return solution; - } - - public static void main(String[] args) { - SplineMath s = new SplineMath(10); - for (int i = 0; i < 10; i++) { - s.setPoint(i, i, i); - } - float[][] curve = s.calculatetCurve(40); - - for (int j = 0; j < curve.length; j++) { - System.out.println(curve[j][0] + "," + curve[j][1]); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs b/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs deleted file mode 100644 index 2acffab06..000000000 --- a/src/com/android/gallery3d/filtershow/filters/convolve3x3.rs +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma version(1) -#pragma rs java_package_name(com.android.gallery3d.filtershow.filters) -#pragma rs_fp_relaxed - -int32_t gWidth; -int32_t gHeight; -const uchar4 *gPixels; -rs_allocation gIn; - -float gCoeffs[9]; - -void root(const uchar4 *in, uchar4 *out, const void *usrData, uint32_t x, uint32_t y) { - uint32_t x1 = min((int32_t)x+1, gWidth-1); - uint32_t x2 = max((int32_t)x-1, 0); - uint32_t y1 = min((int32_t)y+1, gHeight-1); - uint32_t y2 = max((int32_t)y-1, 0); - - float4 p00 = rsUnpackColor8888(gPixels[x1 + gWidth * y1]); - float4 p01 = rsUnpackColor8888(gPixels[x + gWidth * y1]); - float4 p02 = rsUnpackColor8888(gPixels[x2 + gWidth * y1]); - float4 p10 = rsUnpackColor8888(gPixels[x1 + gWidth * y]); - float4 p11 = rsUnpackColor8888(gPixels[x + gWidth * y]); - float4 p12 = rsUnpackColor8888(gPixels[x2 + gWidth * y]); - float4 p20 = rsUnpackColor8888(gPixels[x1 + gWidth * y2]); - float4 p21 = rsUnpackColor8888(gPixels[x + gWidth * y2]); - float4 p22 = rsUnpackColor8888(gPixels[x2 + gWidth * y2]); - - p00 *= gCoeffs[0]; - p01 *= gCoeffs[1]; - p02 *= gCoeffs[2]; - p10 *= gCoeffs[3]; - p11 *= gCoeffs[4]; - p12 *= gCoeffs[5]; - p20 *= gCoeffs[6]; - p21 *= gCoeffs[7]; - p22 *= gCoeffs[8]; - - p00 += p01; - p02 += p10; - p11 += p12; - p20 += p21; - - p22 += p00; - p02 += p11; - - p20 += p22; - p20 += p02; - - p20 = clamp(p20, 0.f, 1.f); - *out = rsPackColorTo8888(p20.r, p20.g, p20.b); -} diff --git a/src/com/android/gallery3d/filtershow/filters/grad.rs b/src/com/android/gallery3d/filtershow/filters/grad.rs deleted file mode 100644 index ddbafd349..000000000 --- a/src/com/android/gallery3d/filtershow/filters/grad.rs +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2012 Unknown - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma version(1) -#pragma rs java_package_name(com.android.gallery3d.filtershow.filters) - -#define MAX_POINTS 16 - -uint32_t inputWidth; -uint32_t inputHeight; -static const float Rf = 0.2999f; -static const float Gf = 0.587f; -static const float Bf = 0.114f; -//static const float size_scale = 0.01f; - -typedef struct { - rs_matrix3x3 colorMatrix; - float rgbOff; - float dx; - float dy; - float off; -} UPointData; -int mNumberOfLines; -// input data -bool mask[MAX_POINTS]; -int xPos1[MAX_POINTS]; -int yPos1[MAX_POINTS]; -int xPos2[MAX_POINTS]; -int yPos2[MAX_POINTS]; -int size[MAX_POINTS]; -int brightness[MAX_POINTS]; -int contrast[MAX_POINTS]; -int saturation[MAX_POINTS]; - -// generated data -static UPointData grads[MAX_POINTS]; - -void setupGradParams() { - int k = 0; - for (int i = 0; i < MAX_POINTS; i++) { - if (!mask[i]) { - continue; - } - float x1 = xPos1[i]; - float y1 = yPos1[i]; - float x2 = xPos2[i]; - float y2 = yPos2[i]; - - float denom = (y2 * y2 - 2 * y1 * y2 + x2 * x2 - 2 * x1 * x2 + y1 * y1 + x1 * x1); - if (denom == 0) { - continue; - } - grads[k].dy = (y1 - y2) / denom; - grads[k].dx = (x1 - x2) / denom; - grads[k].off = (y2 * y2 + x2 * x2 - x1 * x2 - y1 * y2) / denom; - - float S = 1+saturation[i]/100.f; - float MS = 1-S; - float Rt = Rf * MS; - float Gt = Gf * MS; - float Bt = Bf * MS; - - float b = 1+brightness[i]/100.f; - float c = 1+contrast[i]/100.f; - b *= c; - grads[k].rgbOff = .5f - c/2.f; - rsMatrixSet(&grads[i].colorMatrix, 0, 0, b * (Rt + S)); - rsMatrixSet(&grads[i].colorMatrix, 1, 0, b * Gt); - rsMatrixSet(&grads[i].colorMatrix, 2, 0, b * Bt); - rsMatrixSet(&grads[i].colorMatrix, 0, 1, b * Rt); - rsMatrixSet(&grads[i].colorMatrix, 1, 1, b * (Gt + S)); - rsMatrixSet(&grads[i].colorMatrix, 2, 1, b * Bt); - rsMatrixSet(&grads[i].colorMatrix, 0, 2, b * Rt); - rsMatrixSet(&grads[i].colorMatrix, 1, 2, b * Gt); - rsMatrixSet(&grads[i].colorMatrix, 2, 2, b * (Bt + S)); - - k++; - } - mNumberOfLines = k; -} - -void init() { - -} - -uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x, - uint32_t y) { - float4 pixel = rsUnpackColor8888(in); - - float4 wsum = pixel; - wsum.a = 0.f; - for (int i = 0; i < mNumberOfLines; i++) { - UPointData* grad = &grads[i]; - float t = clamp(x*grad->dx+y*grad->dy+grad->off,0.f,1.0f); - wsum.xyz = wsum.xyz*(1-t)+ - t*(rsMatrixMultiply(&grad->colorMatrix ,wsum.xyz)+grad->rgbOff); - - } - - pixel.rgb = wsum.rgb; - pixel.a = 1.0f; - - uchar4 out = rsPackColorTo8888(clamp(pixel, 0.f, 1.0f)); - return out; -} - - - diff --git a/src/com/android/gallery3d/filtershow/filters/grey.rs b/src/com/android/gallery3d/filtershow/filters/grey.rs deleted file mode 100644 index e01880360..000000000 --- a/src/com/android/gallery3d/filtershow/filters/grey.rs +++ /dev/null @@ -1,22 +0,0 @@ - /* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma version(1) -#pragma rs java_package_name(com.android.gallery3d.filtershow.filters) - -uchar __attribute__((kernel)) RGBAtoA(uchar4 in) { - return in.r; -} diff --git a/src/com/android/gallery3d/filtershow/filters/saturation.rs b/src/com/android/gallery3d/filtershow/filters/saturation.rs deleted file mode 100644 index 5210e34a3..000000000 --- a/src/com/android/gallery3d/filtershow/filters/saturation.rs +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2012 Unknown - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma version(1) -#pragma rs java_package_name(com.android.gallery3d.filtershow.filters) - -#define MAX_CHANELS 7 -#define MAX_HUE 4096 -static const int ABITS = 4; -static const int HSCALE = 256; -static const int k1=255 << ABITS; -static const int k2=HSCALE << ABITS; - -static const float Rf = 0.2999f; -static const float Gf = 0.587f; -static const float Bf = 0.114f; - -rs_matrix3x3 colorMatrix_min; -rs_matrix3x3 colorMatrix_max; - -int mNumberOfLines; -// input data -int saturation[MAX_CHANELS]; -float sat[MAX_CHANELS]; - -float satLut[MAX_HUE]; -// generated data - - -void setupGradParams() { - - int master = saturation[0]; - int max = master+saturation[1]; - int min = max; - - // calculate the minimum and maximum saturation - for (int i = 1; i < MAX_CHANELS; i++) { - int v = master+saturation[i]; - if (max < v) { - max = v; - } - else if (min > v) { - min = v; - } - } - // generate a lookup table for all hue 0 to 4K which goes from 0 to 1 0=min sat 1 = max sat - min = min - 1; - for(int i = 0; i < MAX_HUE ; i++) { - float p = i * 6 / (float)MAX_HUE; - int ip = ((int)(p + .5f)) % 6; - int v = master + saturation[ip + 1]; - satLut[i] = (v - min)/(float)(max - min); - } - - float S = 1 + max / 100.f; - float MS = 1 - S; - float Rt = Rf * MS; - float Gt = Gf * MS; - float Bt = Bf * MS; - float b = 1.f; - - // Generate 2 color matrix one at min sat and one at max - rsMatrixSet(&colorMatrix_max, 0, 0, b * (Rt + S)); - rsMatrixSet(&colorMatrix_max, 1, 0, b * Gt); - rsMatrixSet(&colorMatrix_max, 2, 0, b * Bt); - rsMatrixSet(&colorMatrix_max, 0, 1, b * Rt); - rsMatrixSet(&colorMatrix_max, 1, 1, b * (Gt + S)); - rsMatrixSet(&colorMatrix_max, 2, 1, b * Bt); - rsMatrixSet(&colorMatrix_max, 0, 2, b * Rt); - rsMatrixSet(&colorMatrix_max, 1, 2, b * Gt); - rsMatrixSet(&colorMatrix_max, 2, 2, b * (Bt + S)); - - S = 1 + min / 100.f; - MS = 1-S; - Rt = Rf * MS; - Gt = Gf * MS; - Bt = Bf * MS; - b = 1; - - rsMatrixSet(&colorMatrix_min, 0, 0, b * (Rt + S)); - rsMatrixSet(&colorMatrix_min, 1, 0, b * Gt); - rsMatrixSet(&colorMatrix_min, 2, 0, b * Bt); - rsMatrixSet(&colorMatrix_min, 0, 1, b * Rt); - rsMatrixSet(&colorMatrix_min, 1, 1, b * (Gt + S)); - rsMatrixSet(&colorMatrix_min, 2, 1, b * Bt); - rsMatrixSet(&colorMatrix_min, 0, 2, b * Rt); - rsMatrixSet(&colorMatrix_min, 1, 2, b * Gt); - rsMatrixSet(&colorMatrix_min, 2, 2, b * (Bt + S)); -} - -static ushort rgb2hue( uchar4 rgb) -{ - int iMin,iMax,chroma; - - int ri = rgb.r; - int gi = rgb.g; - int bi = rgb.b; - short rv,rs,rh; - - if (ri > gi) { - iMax = max (ri, bi); - iMin = min (gi, bi); - } else { - iMax = max (gi, bi); - iMin = min (ri, bi); - } - - rv = (short) (iMax << ABITS); - - if (rv == 0) { - return 0; - } - - chroma = iMax - iMin; - rs = (short) ((k1 * chroma) / iMax); - if (rs == 0) { - return 0; - } - - if ( ri == iMax ) { - rh = (short) ((k2 * (6 * chroma + gi - bi))/(6 * chroma)); - if (rh >= k2) { - rh -= k2; - } - return rh; - } - - if (gi == iMax) { - return(short) ((k2 * (2 * chroma + bi - ri)) / (6 * chroma)); - } - - return (short) ((k2 * (4 * chroma + ri - gi)) / (6 * chroma)); -} - -uchar4 __attribute__((kernel)) selectiveAdjust(const uchar4 in, uint32_t x, - uint32_t y) { - float4 pixel = rsUnpackColor8888(in); - - float4 wsum = pixel; - int hue = rgb2hue(in); - - float t = satLut[hue]; - pixel.xyz = rsMatrixMultiply(&colorMatrix_min ,pixel.xyz) * (1 - t) + - t * (rsMatrixMultiply(&colorMatrix_max ,pixel.xyz)); - - pixel.a = 1.0f; - return rsPackColorTo8888(clamp(pixel, 0.f, 1.0f)); -}
\ No newline at end of file diff --git a/src/com/android/gallery3d/filtershow/history/HistoryItem.java b/src/com/android/gallery3d/filtershow/history/HistoryItem.java deleted file mode 100644 index 2baaac327..000000000 --- a/src/com/android/gallery3d/filtershow/history/HistoryItem.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.history; - -import android.graphics.Bitmap; -import android.util.Log; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -public class HistoryItem { - private static final String LOGTAG = "HistoryItem"; - private ImagePreset mImagePreset; - private FilterRepresentation mFilterRepresentation; - private Bitmap mPreviewImage; - - public HistoryItem(ImagePreset preset, FilterRepresentation representation) { - mImagePreset = new ImagePreset(preset); - if (representation != null) { - mFilterRepresentation = representation.copy(); - } - } - - public ImagePreset getImagePreset() { - return mImagePreset; - } - - public FilterRepresentation getFilterRepresentation() { - return mFilterRepresentation; - } - - public Bitmap getPreviewImage() { - return mPreviewImage; - } - - public void setPreviewImage(Bitmap previewImage) { - mPreviewImage = previewImage; - } - -} diff --git a/src/com/android/gallery3d/filtershow/history/HistoryManager.java b/src/com/android/gallery3d/filtershow/history/HistoryManager.java deleted file mode 100644 index 755e2ea58..000000000 --- a/src/com/android/gallery3d/filtershow/history/HistoryManager.java +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.history; - -import android.graphics.drawable.Drawable; -import android.view.MenuItem; - -import java.util.Vector; - -public class HistoryManager { - private static final String LOGTAG = "HistoryManager"; - - private Vector<HistoryItem> mHistoryItems = new Vector<HistoryItem>(); - private int mCurrentPresetPosition = 0; - private MenuItem mUndoMenuItem = null; - private MenuItem mRedoMenuItem = null; - private MenuItem mResetMenuItem = null; - - public void setMenuItems(MenuItem undoItem, MenuItem redoItem, MenuItem resetItem) { - mUndoMenuItem = undoItem; - mRedoMenuItem = redoItem; - mResetMenuItem = resetItem; - updateMenuItems(); - } - - private int getCount() { - return mHistoryItems.size(); - } - - public HistoryItem getItem(int position) { - return mHistoryItems.elementAt(position); - } - - private void clear() { - mHistoryItems.clear(); - } - - private void add(HistoryItem item) { - mHistoryItems.add(item); - } - - private void notifyDataSetChanged() { - // TODO - } - - public boolean canReset() { - if (getCount() <= 1) { - return false; - } - return true; - } - - public boolean canUndo() { - if (mCurrentPresetPosition == getCount() - 1) { - return false; - } - return true; - } - - public boolean canRedo() { - if (mCurrentPresetPosition == 0) { - return false; - } - return true; - } - - public void updateMenuItems() { - if (mUndoMenuItem != null) { - setEnabled(mUndoMenuItem, canUndo()); - } - if (mRedoMenuItem != null) { - setEnabled(mRedoMenuItem, canRedo()); - } - if (mResetMenuItem != null) { - setEnabled(mResetMenuItem, canReset()); - } - } - - private void setEnabled(MenuItem item, boolean enabled) { - item.setEnabled(enabled); - Drawable drawable = item.getIcon(); - if (drawable != null) { - drawable.setAlpha(enabled ? 255 : 80); - } - } - - public void setCurrentPreset(int n) { - mCurrentPresetPosition = n; - updateMenuItems(); - notifyDataSetChanged(); - } - - public void reset() { - if (getCount() == 0) { - return; - } - HistoryItem first = getItem(getCount() - 1); - clear(); - addHistoryItem(first); - updateMenuItems(); - } - - public HistoryItem getLast() { - if (getCount() == 0) { - return null; - } - return getItem(0); - } - - public HistoryItem getCurrent() { - return getItem(mCurrentPresetPosition); - } - - public void addHistoryItem(HistoryItem preset) { - insert(preset, 0); - updateMenuItems(); - } - - private void insert(HistoryItem preset, int position) { - if (mCurrentPresetPosition != 0) { - // in this case, let's discount the presets before the current one - Vector<HistoryItem> oldItems = new Vector<HistoryItem>(); - for (int i = mCurrentPresetPosition; i < getCount(); i++) { - oldItems.add(getItem(i)); - } - clear(); - for (int i = 0; i < oldItems.size(); i++) { - add(oldItems.elementAt(i)); - } - mCurrentPresetPosition = position; - notifyDataSetChanged(); - } - mHistoryItems.insertElementAt(preset, position); - mCurrentPresetPosition = position; - notifyDataSetChanged(); - } - - public int redo() { - mCurrentPresetPosition--; - if (mCurrentPresetPosition < 0) { - mCurrentPresetPosition = 0; - } - notifyDataSetChanged(); - updateMenuItems(); - return mCurrentPresetPosition; - } - - public int undo() { - mCurrentPresetPosition++; - if (mCurrentPresetPosition >= getCount()) { - mCurrentPresetPosition = getCount() - 1; - } - notifyDataSetChanged(); - updateMenuItems(); - return mCurrentPresetPosition; - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ControlPoint.java b/src/com/android/gallery3d/filtershow/imageshow/ControlPoint.java deleted file mode 100644 index aaec728a6..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ControlPoint.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -public class ControlPoint implements Comparable { - public float x; - public float y; - - public ControlPoint(float px, float py) { - x = px; - y = py; - } - - public ControlPoint(ControlPoint point) { - x = point.x; - y = point.y; - } - - public boolean sameValues(ControlPoint other) { - if (this == other) { - return true; - } - if (other == null) { - return false; - } - - if (Float.floatToIntBits(x) != Float.floatToIntBits(other.x)) { - return false; - } - if (Float.floatToIntBits(y) != Float.floatToIntBits(other.y)) { - return false; - } - return true; - } - - public ControlPoint copy() { - return new ControlPoint(x, y); - } - - @Override - public int compareTo(Object another) { - ControlPoint p = (ControlPoint) another; - if (p.x < x) { - return 1; - } else if (p.x > x) { - return -1; - } - return 0; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java b/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java deleted file mode 100644 index 8ceb37599..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/EclipseControl.java +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.RadialGradient; -import android.graphics.RectF; -import android.graphics.Shader; - -import com.android.gallery3d.R; - -public class EclipseControl { - private float mCenterX = Float.NaN; - private float mCenterY = 0; - private float mRadiusX = 200; - private float mRadiusY = 300; - private static int MIN_TOUCH_DIST = 80;// should be a resource & in dips - - private float[] handlex = new float[9]; - private float[] handley = new float[9]; - private int mSliderColor; - private int mCenterDotSize = 40; - private float mDownX; - private float mDownY; - private float mDownCenterX; - private float mDownCenterY; - private float mDownRadiusX; - private float mDownRadiusY; - private Matrix mScrToImg; - - private boolean mShowReshapeHandles = true; - public final static int HAN_CENTER = 0; - public final static int HAN_NORTH = 7; - public final static int HAN_NE = 8; - public final static int HAN_EAST = 1; - public final static int HAN_SE = 2; - public final static int HAN_SOUTH = 3; - public final static int HAN_SW = 4; - public final static int HAN_WEST = 5; - public final static int HAN_NW = 6; - - public EclipseControl(Context context) { - mSliderColor = Color.WHITE; - } - - public void setRadius(float x, float y) { - mRadiusX = x; - mRadiusY = y; - } - - public void setCenter(float x, float y) { - mCenterX = x; - mCenterY = y; - } - - public int getCloseHandle(float x, float y) { - float min = Float.MAX_VALUE; - int handle = -1; - for (int i = 0; i < handlex.length; i++) { - float dx = handlex[i] - x; - float dy = handley[i] - y; - float dist = dx * dx + dy * dy; - if (dist < min) { - min = dist; - handle = i; - } - } - - if (min < MIN_TOUCH_DIST * MIN_TOUCH_DIST) { - return handle; - } - for (int i = 0; i < handlex.length; i++) { - float dx = handlex[i] - x; - float dy = handley[i] - y; - float dist = (float) Math.sqrt(dx * dx + dy * dy); - } - - return -1; - } - - public void setScrToImageMatrix(Matrix scrToImg) { - mScrToImg = scrToImg; - } - - public void actionDown(float x, float y, Oval oval) { - float[] point = new float[] { - x, y }; - mScrToImg.mapPoints(point); - mDownX = point[0]; - mDownY = point[1]; - mDownCenterX = oval.getCenterX(); - mDownCenterY = oval.getCenterY(); - mDownRadiusX = oval.getRadiusX(); - mDownRadiusY = oval.getRadiusY(); - } - - public void actionMove(int handle, float x, float y, Oval oval) { - float[] point = new float[] { - x, y }; - mScrToImg.mapPoints(point); - x = point[0]; - y = point[1]; - - // Test if the matrix is swapping x and y - point[0] = 0; - point[1] = 1; - mScrToImg.mapVectors(point); - boolean swapxy = (point[0] > 0.0f); - - int sign = 1; - switch (handle) { - case HAN_CENTER: - float ctrdx = mDownX - mDownCenterX; - float ctrdy = mDownY - mDownCenterY; - oval.setCenter(x - ctrdx, y - ctrdy); - // setRepresentation(mVignetteRep); - break; - case HAN_NORTH: - sign = -1; - case HAN_SOUTH: - if (swapxy) { - float raddx = mDownRadiusY - Math.abs(mDownX - mDownCenterY); - oval.setRadiusY(Math.abs(x - oval.getCenterY() + sign * raddx)); - } else { - float raddy = mDownRadiusY - Math.abs(mDownY - mDownCenterY); - oval.setRadiusY(Math.abs(y - oval.getCenterY() + sign * raddy)); - } - break; - case HAN_EAST: - sign = -1; - case HAN_WEST: - if (swapxy) { - float raddy = mDownRadiusX - Math.abs(mDownY - mDownCenterX); - oval.setRadiusX(Math.abs(y - oval.getCenterX() + sign * raddy)); - } else { - float raddx = mDownRadiusX - Math.abs(mDownX - mDownCenterX); - oval.setRadiusX(Math.abs(x - oval.getCenterX() - sign * raddx)); - } - break; - case HAN_SE: - case HAN_NE: - case HAN_SW: - case HAN_NW: - float sin45 = (float) Math.sin(45); - float dr = (mDownRadiusX + mDownRadiusY) * sin45; - float ctr_dx = mDownX - mDownCenterX; - float ctr_dy = mDownY - mDownCenterY; - float downRad = Math.abs(ctr_dx) + Math.abs(ctr_dy) - dr; - float rx = oval.getRadiusX(); - float ry = oval.getRadiusY(); - float r = (Math.abs(rx) + Math.abs(ry)) * sin45; - float dx = x - oval.getCenterX(); - float dy = y - oval.getCenterY(); - float nr = Math.abs(Math.abs(dx) + Math.abs(dy) - downRad); - oval.setRadius(rx * nr / r, ry * nr / r); - - break; - } - } - - public void paintGrayPoint(Canvas canvas, float x, float y) { - if (x == Float.NaN) { - return; - } - - Paint paint = new Paint(); - - paint.setStyle(Paint.Style.FILL); - paint.setColor(Color.BLUE); - int[] colors3 = new int[] { - Color.GRAY, Color.LTGRAY, 0x66000000, 0 }; - RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[] { - 0, .3f, .31f, 1 }, Shader.TileMode.CLAMP); - paint.setShader(g); - canvas.drawCircle(x, y, mCenterDotSize, paint); - } - - public void paintPoint(Canvas canvas, float x, float y) { - if (x == Float.NaN) { - return; - } - - Paint paint = new Paint(); - - paint.setStyle(Paint.Style.FILL); - paint.setColor(Color.BLUE); - int[] colors3 = new int[] { - mSliderColor, mSliderColor, 0x66000000, 0 }; - RadialGradient g = new RadialGradient(x, y, mCenterDotSize, colors3, new float[] { - 0, .3f, .31f, 1 }, Shader.TileMode.CLAMP); - paint.setShader(g); - canvas.drawCircle(x, y, mCenterDotSize, paint); - } - - void paintRadius(Canvas canvas, float cx, float cy, float rx, float ry) { - if (cx == Float.NaN) { - return; - } - int mSliderColor = 0xFF33B5E5; - Paint paint = new Paint(); - RectF rect = new RectF(cx - rx, cy - ry, cx + rx, cy + ry); - paint.setAntiAlias(true); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(6); - paint.setColor(Color.BLACK); - paintOvallines(canvas, rect, paint, cx, cy, rx, ry); - - paint.setStrokeWidth(3); - paint.setColor(Color.WHITE); - paintOvallines(canvas, rect, paint, cx, cy, rx, ry); - } - - public void paintOvallines( - Canvas canvas, RectF rect, Paint paint, float cx, float cy, float rx, float ry) { - canvas.drawOval(rect, paint); - float da = 4; - float arclen = da + da; - if (mShowReshapeHandles) { - paint.setStyle(Paint.Style.STROKE); - - for (int i = 0; i < 361; i += 90) { - float dx = rx + 10; - float dy = ry + 10; - rect.left = cx - dx; - rect.top = cy - dy; - rect.right = cx + dx; - rect.bottom = cy + dy; - canvas.drawArc(rect, i - da, arclen, false, paint); - dx = rx - 10; - dy = ry - 10; - rect.left = cx - dx; - rect.top = cy - dy; - rect.right = cx + dx; - rect.bottom = cy + dy; - canvas.drawArc(rect, i - da, arclen, false, paint); - } - } - da *= 2; - paint.setStyle(Paint.Style.FILL); - - for (int i = 45; i < 361; i += 90) { - double angle = Math.PI * i / 180.; - float x = cx + (float) (rx * Math.cos(angle)); - float y = cy + (float) (ry * Math.sin(angle)); - canvas.drawRect(x - da, y - da, x + da, y + da, paint); - } - paint.setStyle(Paint.Style.STROKE); - rect.left = cx - rx; - rect.top = cy - ry; - rect.right = cx + rx; - rect.bottom = cy + ry; - } - - public void fillHandles(Canvas canvas, float cx, float cy, float rx, float ry) { - handlex[0] = cx; - handley[0] = cy; - int k = 1; - - for (int i = 0; i < 360; i += 45) { - double angle = Math.PI * i / 180.; - - float x = cx + (float) (rx * Math.cos(angle)); - float y = cy + (float) (ry * Math.sin(angle)); - handlex[k] = x; - handley[k] = y; - - k++; - } - } - - public void draw(Canvas canvas) { - paintRadius(canvas, mCenterX, mCenterY, mRadiusX, mRadiusY); - fillHandles(canvas, mCenterX, mCenterY, mRadiusX, mRadiusY); - paintPoint(canvas, mCenterX, mCenterY); - } - - public boolean isUndefined() { - return Float.isNaN(mCenterX); - } - - public void setShowReshapeHandles(boolean showReshapeHandles) { - this.mShowReshapeHandles = showReshapeHandles; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java b/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java deleted file mode 100644 index 81394f142..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/GeometryMathUtils.java +++ /dev/null @@ -1,416 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -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.cache.ImageLoader; -import com.android.gallery3d.filtershow.filters.FilterCropRepresentation; -import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation; -import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation.Mirror; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation.Rotation; -import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -import java.util.Collection; -import java.util.Iterator; - -public final class GeometryMathUtils { - private GeometryMathUtils() {}; - - // Holder class for Geometry data. - public static final class GeometryHolder { - public Rotation rotation = FilterRotateRepresentation.getNil(); - public float straighten = FilterStraightenRepresentation.getNil(); - public RectF crop = FilterCropRepresentation.getNil(); - public Mirror mirror = FilterMirrorRepresentation.getNil(); - - public void set(GeometryHolder h) { - rotation = h.rotation; - straighten = h.straighten; - crop.set(h.crop); - mirror = h.mirror; - } - - public void wipe() { - rotation = FilterRotateRepresentation.getNil(); - straighten = FilterStraightenRepresentation.getNil(); - crop = FilterCropRepresentation.getNil(); - mirror = FilterMirrorRepresentation.getNil(); - } - - public boolean isNil() { - return rotation == FilterRotateRepresentation.getNil() && - straighten == FilterStraightenRepresentation.getNil() && - crop.equals(FilterCropRepresentation.getNil()) && - mirror == FilterMirrorRepresentation.getNil(); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (!(o instanceof GeometryHolder)) { - return false; - } - GeometryHolder h = (GeometryHolder) o; - return rotation == h.rotation && straighten == h.straighten && - ((crop == null && h.crop == null) || (crop != null && crop.equals(h.crop))) && - mirror == h.mirror; - } - - @Override - public String toString() { - return getClass().getSimpleName() + "[" + "rotation:" + rotation.value() - + ",straighten:" + straighten + ",crop:" + crop.toString() - + ",mirror:" + mirror.value() + "]"; - } - } - - // Math operations for 2d vectors - public static float clamp(float i, float low, float high) { - return Math.max(Math.min(i, high), low); - } - - public static float[] lineIntersect(float[] line1, float[] line2) { - float a0 = line1[0]; - float a1 = line1[1]; - float b0 = line1[2]; - float b1 = line1[3]; - float c0 = line2[0]; - float c1 = line2[1]; - float d0 = line2[2]; - float d1 = line2[3]; - float t0 = a0 - b0; - float t1 = a1 - b1; - float t2 = b0 - d0; - float t3 = d1 - b1; - float t4 = c0 - d0; - float t5 = c1 - d1; - - float denom = t1 * t4 - t0 * t5; - if (denom == 0) - return null; - float u = (t3 * t4 + t5 * t2) / denom; - float[] intersect = { - b0 + u * t0, b1 + u * t1 - }; - return intersect; - } - - public static float[] shortestVectorFromPointToLine(float[] point, float[] line) { - float x1 = line[0]; - float x2 = line[2]; - float y1 = line[1]; - float y2 = line[3]; - 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)) - }; - float[] vec = { - ret[0] - point[0], ret[1] - point[1] - }; - return vec; - } - - // A . B - public static float dotProduct(float[] a, float[] b) { - return a[0] * b[0] + a[1] * b[1]; - } - - public static float[] normalize(float[] a) { - float length = (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]); - float[] b = { - a[0] / length, a[1] / length - }; - return b; - } - - // A onto B - public static float scalarProjection(float[] a, float[] b) { - float length = (float) Math.sqrt(b[0] * b[0] + b[1] * b[1]); - return dotProduct(a, b) / length; - } - - public static float[] getVectorFromPoints(float[] point1, float[] point2) { - float[] p = { - point2[0] - point1[0], point2[1] - point1[1] - }; - return p; - } - - public static float[] getUnitVectorFromPoints(float[] point1, float[] point2) { - float[] p = { - point2[0] - point1[0], point2[1] - point1[1] - }; - float length = (float) Math.sqrt(p[0] * p[0] + p[1] * p[1]); - p[0] = p[0] / length; - p[1] = p[1] / length; - return p; - } - - public static void scaleRect(RectF r, float scale) { - r.set(r.left * scale, r.top * scale, r.right * scale, r.bottom * scale); - } - - // A - B - public static float[] vectorSubtract(float[] a, float[] b) { - int len = a.length; - if (len != b.length) - return null; - float[] ret = new float[len]; - for (int i = 0; i < len; i++) { - ret[i] = a[i] - b[i]; - } - return ret; - } - - public static float vectorLength(float[] a) { - return (float) Math.sqrt(a[0] * a[0] + a[1] * a[1]); - } - - public static float scale(float oldWidth, float oldHeight, float newWidth, float newHeight) { - if (oldHeight == 0 || oldWidth == 0 || (oldWidth == newWidth && oldHeight == newHeight)) { - return 1; - } - 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; - } - - private static void concatMirrorMatrix(Matrix m, Mirror type) { - if (type == Mirror.HORIZONTAL) { - m.postScale(-1, 1); - } else if (type == Mirror.VERTICAL) { - m.postScale(1, -1); - } else if (type == Mirror.BOTH) { - m.postScale(1, -1); - m.postScale(-1, 1); - } - } - - private static int getRotationForOrientation(int orientation) { - switch (orientation) { - case ImageLoader.ORI_ROTATE_90: - return 90; - case ImageLoader.ORI_ROTATE_180: - return 180; - case ImageLoader.ORI_ROTATE_270: - return 270; - default: - return 0; - } - } - - public static GeometryHolder unpackGeometry(Collection<FilterRepresentation> geometry) { - GeometryHolder holder = new GeometryHolder(); - unpackGeometry(holder, geometry); - return holder; - } - - public static void unpackGeometry(GeometryHolder out, - Collection<FilterRepresentation> geometry) { - out.wipe(); - // Get geometry data from filters - for (FilterRepresentation r : geometry) { - if (r.isNil()) { - continue; - } - if (r.getSerializationName() == FilterRotateRepresentation.SERIALIZATION_NAME) { - out.rotation = ((FilterRotateRepresentation) r).getRotation(); - } else if (r.getSerializationName() == - FilterStraightenRepresentation.SERIALIZATION_NAME) { - out.straighten = ((FilterStraightenRepresentation) r).getStraighten(); - } else if (r.getSerializationName() == FilterCropRepresentation.SERIALIZATION_NAME) { - ((FilterCropRepresentation) r).getCrop(out.crop); - } else if (r.getSerializationName() == FilterMirrorRepresentation.SERIALIZATION_NAME) { - out.mirror = ((FilterMirrorRepresentation) r).getMirror(); - } - } - } - - public static void replaceInstances(Collection<FilterRepresentation> geometry, - FilterRepresentation rep) { - Iterator<FilterRepresentation> iter = geometry.iterator(); - while (iter.hasNext()) { - FilterRepresentation r = iter.next(); - if (ImagePreset.sameSerializationName(rep, r)) { - iter.remove(); - } - } - if (!rep.isNil()) { - geometry.add(rep); - } - } - - public static void initializeHolder(GeometryHolder outHolder, - FilterRepresentation currentLocal) { - Collection<FilterRepresentation> geometry = MasterImage.getImage().getPreset() - .getGeometryFilters(); - replaceInstances(geometry, currentLocal); - unpackGeometry(outHolder, geometry); - } - - private static Bitmap applyFullGeometryMatrix(Bitmap image, GeometryHolder holder) { - int width = image.getWidth(); - int height = image.getHeight(); - RectF crop = getTrueCropRect(holder, width, height); - Rect frame = new Rect(); - crop.roundOut(frame); - Matrix m = getCropSelectionToScreenMatrix(null, holder, width, height, frame.width(), - frame.height()); - Bitmap temp = Bitmap.createBitmap(frame.width(), frame.height(), Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(temp); - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setFilterBitmap(true); - paint.setDither(true); - canvas.drawBitmap(image, m, paint); - return temp; - } - - public static Matrix getImageToScreenMatrix(Collection<FilterRepresentation> geometry, - boolean reflectRotation, Rect bmapDimens, float viewWidth, float viewHeight) { - GeometryHolder h = unpackGeometry(geometry); - return GeometryMathUtils.getOriginalToScreen(h, reflectRotation, bmapDimens.width(), - bmapDimens.height(), viewWidth, viewHeight); - } - - public static Matrix getOriginalToScreen(GeometryHolder holder, boolean rotate, - float originalWidth, - float originalHeight, float viewWidth, float viewHeight) { - int orientation = MasterImage.getImage().getZoomOrientation(); - int rotation = getRotationForOrientation(orientation); - Rotation prev = holder.rotation; - rotation = (rotation + prev.value()) % 360; - holder.rotation = Rotation.fromValue(rotation); - Matrix m = getCropSelectionToScreenMatrix(null, holder, (int) originalWidth, - (int) originalHeight, (int) viewWidth, (int) viewHeight); - holder.rotation = prev; - return m; - } - - public static Bitmap applyGeometryRepresentations(Collection<FilterRepresentation> res, - Bitmap image) { - GeometryHolder holder = unpackGeometry(res); - Bitmap bmap = image; - // If there are geometry changes, apply them to the image - if (!holder.isNil()) { - bmap = applyFullGeometryMatrix(bmap, holder); - } - return bmap; - } - - public static RectF drawTransformedCropped(GeometryHolder holder, Canvas canvas, - Bitmap photo, int viewWidth, int viewHeight) { - if (photo == null) { - return null; - } - RectF crop = new RectF(); - Matrix m = getCropSelectionToScreenMatrix(crop, holder, photo.getWidth(), photo.getHeight(), - viewWidth, viewHeight); - canvas.save(); - canvas.clipRect(crop); - Paint p = new Paint(); - p.setAntiAlias(true); - canvas.drawBitmap(photo, m, p); - canvas.restore(); - return crop; - } - - public static boolean needsDimensionSwap(Rotation rotation) { - switch (rotation) { - case NINETY: - case TWO_SEVENTY: - return true; - default: - return false; - } - } - - // Gives matrix for rotated, straightened, mirrored bitmap centered at 0,0. - private static Matrix getFullGeometryMatrix(GeometryHolder holder, int bitmapWidth, - int bitmapHeight) { - float centerX = bitmapWidth / 2f; - float centerY = bitmapHeight / 2f; - Matrix m = new Matrix(); - m.setTranslate(-centerX, -centerY); - m.postRotate(holder.straighten + holder.rotation.value()); - concatMirrorMatrix(m, holder.mirror); - return m; - } - - public static Matrix getFullGeometryToScreenMatrix(GeometryHolder holder, int bitmapWidth, - int bitmapHeight, int viewWidth, int viewHeight) { - float scale = GeometryMathUtils.scale(bitmapWidth, bitmapHeight, viewWidth, viewHeight); - Matrix m = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight); - m.postScale(scale, scale); - m.postTranslate(viewWidth / 2f, viewHeight / 2f); - return m; - } - - public static RectF getTrueCropRect(GeometryHolder holder, int bitmapWidth, int bitmapHeight) { - RectF r = new RectF(holder.crop); - FilterCropRepresentation.findScaledCrop(r, bitmapWidth, bitmapHeight); - float s = holder.straighten; - holder.straighten = 0; - Matrix m1 = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight); - holder.straighten = s; - m1.mapRect(r); - return r; - } - - public static Matrix getCropSelectionToScreenMatrix(RectF outCrop, GeometryHolder holder, - int bitmapWidth, int bitmapHeight, int viewWidth, int viewHeight) { - Matrix m = getFullGeometryMatrix(holder, bitmapWidth, bitmapHeight); - RectF crop = getTrueCropRect(holder, bitmapWidth, bitmapHeight); - float scale = GeometryMathUtils.scale(crop.width(), crop.height(), viewWidth, viewHeight); - m.postScale(scale, scale); - GeometryMathUtils.scaleRect(crop, scale); - m.postTranslate(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY()); - if (outCrop != null) { - crop.offset(viewWidth / 2f - crop.centerX(), viewHeight / 2f - crop.centerY()); - outCrop.set(crop); - } - return m; - } - - public static Matrix getCropSelectionToScreenMatrix(RectF outCrop, - Collection<FilterRepresentation> res, int bitmapWidth, int bitmapHeight, int viewWidth, - int viewHeight) { - GeometryHolder holder = unpackGeometry(res); - return getCropSelectionToScreenMatrix(outCrop, holder, bitmapWidth, bitmapHeight, - viewWidth, viewHeight); - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/GradControl.java b/src/com/android/gallery3d/filtershow/imageshow/GradControl.java deleted file mode 100644 index 964da99e9..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/GradControl.java +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.DashPathEffect; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.RadialGradient; -import android.graphics.Rect; -import android.graphics.Shader; - -import com.android.gallery3d.R; - -public class GradControl { - private float mPoint1X = Float.NaN; // used to flag parameters have not been set - private float mPoint1Y = 0; - private float mPoint2X = 200; - private float mPoint2Y = 300; - private int mMinTouchDist = 80;// should be a resource & in dips - - private float[] handlex = new float[3]; - private float[] handley = new float[3]; - private int mSliderColor; - private int mCenterDotSize; - private float mDownX; - private float mDownY; - private float mDownPoint1X; - private float mDownPoint1Y; - private float mDownPoint2X; - private float mDownPoint2Y; - Rect mImageBounds; - int mImageHeight; - private Matrix mScrToImg; - Paint mPaint = new Paint(); - DashPathEffect mDash = new DashPathEffect(new float[]{30, 30}, 0); - private boolean mShowReshapeHandles = true; - public final static int HAN_CENTER = 0; - public final static int HAN_NORTH = 2; - public final static int HAN_SOUTH = 1; - private int[] mPointColorPatern; - private int[] mGrayPointColorPatern; - private float[] mPointRadialPos = new float[]{0, .3f, .31f, 1}; - private int mLineColor; - private int mlineShadowColor; - - public GradControl(Context context) { - - Resources res = context.getResources(); - mCenterDotSize = (int) res.getDimension(R.dimen.gradcontrol_dot_size); - mMinTouchDist = (int) res.getDimension(R.dimen.gradcontrol_min_touch_dist); - int grayPointCenterColor = res.getColor(R.color.gradcontrol_graypoint_center); - int grayPointEdgeColor = res.getColor(R.color.gradcontrol_graypoint_edge); - int pointCenterColor = res.getColor(R.color.gradcontrol_point_center); - int pointEdgeColor = res.getColor(R.color.gradcontrol_point_edge); - int pointShadowStartColor = res.getColor(R.color.gradcontrol_point_shadow_start); - int pointShadowEndColor = res.getColor(R.color.gradcontrol_point_shadow_end); - mPointColorPatern = new int[]{ - pointCenterColor, pointEdgeColor, pointShadowStartColor, pointShadowEndColor}; - mGrayPointColorPatern = new int[]{ - grayPointCenterColor, grayPointEdgeColor, pointShadowStartColor, pointShadowEndColor}; - mSliderColor = Color.WHITE; - mLineColor = res.getColor(R.color.gradcontrol_line_color); - mlineShadowColor = res.getColor(R.color.gradcontrol_line_shadow); - } - - public void setPoint2(float x, float y) { - mPoint2X = x; - mPoint2Y = y; - } - - public void setPoint1(float x, float y) { - mPoint1X = x; - mPoint1Y = y; - } - - public int getCloseHandle(float x, float y) { - float min = Float.MAX_VALUE; - int handle = -1; - for (int i = 0; i < handlex.length; i++) { - float dx = handlex[i] - x; - float dy = handley[i] - y; - float dist = dx * dx + dy * dy; - if (dist < min) { - min = dist; - handle = i; - } - } - - if (min < mMinTouchDist * mMinTouchDist) { - return handle; - } - for (int i = 0; i < handlex.length; i++) { - float dx = handlex[i] - x; - float dy = handley[i] - y; - float dist = (float) Math.sqrt(dx * dx + dy * dy); - } - - return -1; - } - - public void setScrImageInfo(Matrix scrToImg, Rect imageBounds) { - mScrToImg = scrToImg; - mImageBounds = new Rect(imageBounds); - } - - private boolean centerIsOutside(float x1, float y1, float x2, float y2) { - return (!mImageBounds.contains((int) ((x1 + x2) / 2), (int) ((y1 + y2) / 2))); - } - - public void actionDown(float x, float y, Line line) { - float[] point = new float[]{ - x, y}; - mScrToImg.mapPoints(point); - mDownX = point[0]; - mDownY = point[1]; - mDownPoint1X = line.getPoint1X(); - mDownPoint1Y = line.getPoint1Y(); - mDownPoint2X = line.getPoint2X(); - mDownPoint2Y = line.getPoint2Y(); - } - - public void actionMove(int handle, float x, float y, Line line) { - float[] point = new float[]{ - x, y}; - mScrToImg.mapPoints(point); - x = point[0]; - y = point[1]; - - // Test if the matrix is swapping x and y - point[0] = 0; - point[1] = 1; - mScrToImg.mapVectors(point); - boolean swapxy = (point[0] > 0.0f); - - int sign = 1; - - float dx = x - mDownX; - float dy = y - mDownY; - switch (handle) { - case HAN_CENTER: - if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy, - mDownPoint2X + dx, mDownPoint2Y + dy)) { - break; - } - line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy); - line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy); - break; - case HAN_SOUTH: - if (centerIsOutside(mDownPoint1X + dx, mDownPoint1Y + dy, - mDownPoint2X, mDownPoint2Y)) { - break; - } - line.setPoint1(mDownPoint1X + dx, mDownPoint1Y + dy); - break; - case HAN_NORTH: - if (centerIsOutside(mDownPoint1X, mDownPoint1Y, - mDownPoint2X + dx, mDownPoint2Y + dy)) { - break; - } - line.setPoint2(mDownPoint2X + dx, mDownPoint2Y + dy); - break; - } - } - - public void paintGrayPoint(Canvas canvas, float x, float y) { - if (isUndefined()) { - return; - } - - Paint paint = new Paint(); - paint.setStyle(Paint.Style.FILL); - RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mGrayPointColorPatern, - mPointRadialPos, Shader.TileMode.CLAMP); - paint.setShader(g); - canvas.drawCircle(x, y, mCenterDotSize, paint); - } - - public void paintPoint(Canvas canvas, float x, float y) { - if (isUndefined()) { - return; - } - - Paint paint = new Paint(); - paint.setStyle(Paint.Style.FILL); - RadialGradient g = new RadialGradient(x, y, mCenterDotSize, mPointColorPatern, - mPointRadialPos, Shader.TileMode.CLAMP); - paint.setShader(g); - canvas.drawCircle(x, y, mCenterDotSize, paint); - } - - void paintLines(Canvas canvas, float p1x, float p1y, float p2x, float p2y) { - if (isUndefined()) { - return; - } - - mPaint.setAntiAlias(true); - mPaint.setStyle(Paint.Style.STROKE); - - mPaint.setStrokeWidth(6); - mPaint.setColor(mlineShadowColor); - mPaint.setPathEffect(mDash); - paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y); - - mPaint.setStrokeWidth(3); - mPaint.setColor(mLineColor); - mPaint.setPathEffect(mDash); - paintOvallines(canvas, mPaint, p1x, p1y, p2x, p2y); - } - - public void paintOvallines( - Canvas canvas, Paint paint, float p1x, float p1y, float p2x, float p2y) { - - - - canvas.drawLine(p1x, p1y, p2x, p2y, paint); - - float cx = (p1x + p2x) / 2; - float cy = (p1y + p2y) / 2; - float dx = p1x - p2x; - float dy = p1y - p2y; - float len = (float) Math.sqrt(dx * dx + dy * dy); - dx *= 2048 / len; - dy *= 2048 / len; - - canvas.drawLine(p1x + dy, p1y - dx, p1x - dy, p1y + dx, paint); - canvas.drawLine(p2x + dy, p2y - dx, p2x - dy, p2y + dx, paint); - } - - public void fillHandles(Canvas canvas, float p1x, float p1y, float p2x, float p2y) { - float cx = (p1x + p2x) / 2; - float cy = (p1y + p2y) / 2; - handlex[0] = cx; - handley[0] = cy; - handlex[1] = p1x; - handley[1] = p1y; - handlex[2] = p2x; - handley[2] = p2y; - - } - - public void draw(Canvas canvas) { - paintLines(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y); - fillHandles(canvas, mPoint1X, mPoint1Y, mPoint2X, mPoint2Y); - paintPoint(canvas, mPoint2X, mPoint2Y); - paintPoint(canvas, mPoint1X, mPoint1Y); - paintPoint(canvas, (mPoint1X + mPoint2X) / 2, (mPoint1Y + mPoint2Y) / 2); - } - - public boolean isUndefined() { - return Float.isNaN(mPoint1X); - } - - public void setShowReshapeHandles(boolean showReshapeHandles) { - this.mShowReshapeHandles = showReshapeHandles; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java deleted file mode 100644 index 7fee03188..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageCrop.java +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.RectF; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.crop.CropDrawingUtils; -import com.android.gallery3d.filtershow.crop.CropMath; -import com.android.gallery3d.filtershow.crop.CropObject; -import com.android.gallery3d.filtershow.editors.EditorCrop; -import com.android.gallery3d.filtershow.filters.FilterCropRepresentation; -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder; - -public class ImageCrop extends ImageShow { - private static final String TAG = ImageCrop.class.getSimpleName(); - private RectF mImageBounds = new RectF(); - private RectF mScreenCropBounds = new RectF(); - private Paint mPaint = new Paint(); - private CropObject mCropObj = null; - private GeometryHolder mGeometry = new GeometryHolder(); - private GeometryHolder mUpdateHolder = new GeometryHolder(); - private Drawable mCropIndicator; - private int mIndicatorSize; - private boolean mMovingBlock = false; - private Matrix mDisplayMatrix = null; - private Matrix mDisplayCropMatrix = null; - private Matrix mDisplayMatrixInverse = null; - private float mPrevX = 0; - private float mPrevY = 0; - private int mMinSideSize = 90; - private int mTouchTolerance = 40; - private enum Mode { - NONE, MOVE - } - private Mode mState = Mode.NONE; - private boolean mValidDraw = false; - FilterCropRepresentation mLocalRep = new FilterCropRepresentation(); - EditorCrop mEditorCrop; - - public ImageCrop(Context context) { - super(context); - setup(context); - } - - public ImageCrop(Context context, AttributeSet attrs) { - super(context, attrs); - setup(context); - } - - public ImageCrop(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - setup(context); - } - - private void setup(Context context) { - Resources rsc = context.getResources(); - mCropIndicator = rsc.getDrawable(R.drawable.camera_crop); - mIndicatorSize = (int) rsc.getDimension(R.dimen.crop_indicator_size); - mMinSideSize = (int) rsc.getDimension(R.dimen.crop_min_side); - mTouchTolerance = (int) rsc.getDimension(R.dimen.crop_touch_tolerance); - } - - public void setFilterCropRepresentation(FilterCropRepresentation crop) { - mLocalRep = (crop == null) ? new FilterCropRepresentation() : crop; - GeometryMathUtils.initializeHolder(mUpdateHolder, mLocalRep); - mValidDraw = true; - } - - public FilterCropRepresentation getFinalRepresentation() { - return mLocalRep; - } - - private void internallyUpdateLocalRep(RectF crop, RectF image) { - FilterCropRepresentation - .findNormalizedCrop(crop, (int) image.width(), (int) image.height()); - mGeometry.crop.set(crop); - mUpdateHolder.set(mGeometry); - mLocalRep.setCrop(crop); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - if (mDisplayMatrix == null || mDisplayMatrixInverse == null) { - return true; - } - float[] touchPoint = { - x, y - }; - mDisplayMatrixInverse.mapPoints(touchPoint); - x = touchPoint[0]; - y = touchPoint[1]; - switch (event.getActionMasked()) { - case (MotionEvent.ACTION_DOWN): - if (mState == Mode.NONE) { - if (!mCropObj.selectEdge(x, y)) { - mMovingBlock = mCropObj.selectEdge(CropObject.MOVE_BLOCK); - } - mPrevX = x; - mPrevY = y; - mState = Mode.MOVE; - } - break; - case (MotionEvent.ACTION_UP): - if (mState == Mode.MOVE) { - mCropObj.selectEdge(CropObject.MOVE_NONE); - mMovingBlock = false; - mPrevX = x; - mPrevY = y; - mState = Mode.NONE; - internallyUpdateLocalRep(mCropObj.getInnerBounds(), mCropObj.getOuterBounds()); - } - break; - case (MotionEvent.ACTION_MOVE): - if (mState == Mode.MOVE) { - float dx = x - mPrevX; - float dy = y - mPrevY; - mCropObj.moveCurrentSelection(dx, dy); - mPrevX = x; - mPrevY = y; - } - break; - default: - break; - } - invalidate(); - return true; - } - - private void clearDisplay() { - mDisplayMatrix = null; - mDisplayMatrixInverse = null; - invalidate(); - } - - public void applyFreeAspect() { - mCropObj.unsetAspectRatio(); - invalidate(); - } - - public void applyOriginalAspect() { - RectF outer = mCropObj.getOuterBounds(); - float w = outer.width(); - float h = outer.height(); - if (w > 0 && h > 0) { - applyAspect(w, h); - mCropObj.resetBoundsTo(outer, outer); - internallyUpdateLocalRep(mCropObj.getInnerBounds(), mCropObj.getOuterBounds()); - } else { - Log.w(TAG, "failed to set aspect ratio original"); - } - invalidate(); - } - - public void applyAspect(float x, float y) { - if (x <= 0 || y <= 0) { - throw new IllegalArgumentException("Bad arguments to applyAspect"); - } - // If we are rotated by 90 degrees from horizontal, swap x and y - if (GeometryMathUtils.needsDimensionSwap(mGeometry.rotation)) { - float tmp = x; - x = y; - y = tmp; - } - if (!mCropObj.setInnerAspectRatio(x, y)) { - Log.w(TAG, "failed to set aspect ratio"); - } - internallyUpdateLocalRep(mCropObj.getInnerBounds(), mCropObj.getOuterBounds()); - invalidate(); - } - - /** - * Rotates first d bits in integer x to the left some number of times. - */ - 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; - } - - /** - * Find the selected edge or corner in screen coordinates. - */ - private int decode(int movingEdges, float rotation) { - int rot = CropMath.constrainedRotation(rotation); - switch (rot) { - case 90: - return bitCycleLeft(movingEdges, 1, 4); - case 180: - return bitCycleLeft(movingEdges, 2, 4); - case 270: - return bitCycleLeft(movingEdges, 3, 4); - default: - return movingEdges; - } - } - - private void forceStateConsistency() { - MasterImage master = MasterImage.getImage(); - Bitmap image = master.getFiltersOnlyImage(); - int width = image.getWidth(); - int height = image.getHeight(); - if (mCropObj == null || !mUpdateHolder.equals(mGeometry) - || mImageBounds.width() != width || mImageBounds.height() != height - || !mLocalRep.getCrop().equals(mUpdateHolder.crop)) { - mImageBounds.set(0, 0, width, height); - mGeometry.set(mUpdateHolder); - mLocalRep.setCrop(mUpdateHolder.crop); - RectF scaledCrop = new RectF(mUpdateHolder.crop); - FilterCropRepresentation.findScaledCrop(scaledCrop, width, height); - mCropObj = new CropObject(mImageBounds, scaledCrop, (int) mUpdateHolder.straighten); - mState = Mode.NONE; - clearDisplay(); - } - } - - @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - clearDisplay(); - } - - @Override - public void onDraw(Canvas canvas) { - Bitmap bitmap = MasterImage.getImage().getFiltersOnlyImage(); - if (!mValidDraw || bitmap == null) { - return; - } - forceStateConsistency(); - mImageBounds.set(0, 0, bitmap.getWidth(), bitmap.getHeight()); - // If display matrix doesn't exist, create it and its dependencies - if (mDisplayCropMatrix == null || mDisplayMatrix == null || mDisplayMatrixInverse == null) { - mDisplayMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry, - bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(), canvas.getHeight()); - float straighten = mGeometry.straighten; - mGeometry.straighten = 0; - mDisplayCropMatrix = GeometryMathUtils.getFullGeometryToScreenMatrix(mGeometry, - bitmap.getWidth(), bitmap.getHeight(), canvas.getWidth(), canvas.getHeight()); - mGeometry.straighten = straighten; - mDisplayMatrixInverse = new Matrix(); - mDisplayMatrixInverse.reset(); - if (!mDisplayCropMatrix.invert(mDisplayMatrixInverse)) { - Log.w(TAG, "could not invert display matrix"); - mDisplayMatrixInverse = null; - return; - } - // Scale min side and tolerance by display matrix scale factor - mCropObj.setMinInnerSideSize(mDisplayMatrixInverse.mapRadius(mMinSideSize)); - mCropObj.setTouchTolerance(mDisplayMatrixInverse.mapRadius(mTouchTolerance)); - } - // Draw actual bitmap - mPaint.reset(); - mPaint.setAntiAlias(true); - mPaint.setFilterBitmap(true); - canvas.drawBitmap(bitmap, mDisplayMatrix, mPaint); - mCropObj.getInnerBounds(mScreenCropBounds); - RectF outer = mCropObj.getOuterBounds(); - FilterCropRepresentation.findNormalizedCrop(mScreenCropBounds, (int) outer.width(), - (int) outer.height()); - FilterCropRepresentation.findScaledCrop(mScreenCropBounds, bitmap.getWidth(), - bitmap.getHeight()); - if (mDisplayCropMatrix.mapRect(mScreenCropBounds)) { - // Draw crop rect and markers - CropDrawingUtils.drawCropRect(canvas, mScreenCropBounds); - CropDrawingUtils.drawRuleOfThird(canvas, mScreenCropBounds); - CropDrawingUtils.drawIndicators(canvas, mCropIndicator, mIndicatorSize, - mScreenCropBounds, mCropObj.isFixedAspect(), - decode(mCropObj.getSelectState(), mGeometry.rotation.value())); - } - } - - public void setEditor(EditorCrop editorCrop) { - mEditorCrop = editorCrop; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java b/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java deleted file mode 100644 index 82c4b2fc7..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageCurves.java +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.os.AsyncTask; -import android.util.AttributeSet; -import android.view.MenuItem; -import android.view.MotionEvent; -import android.view.View; -import android.widget.Button; -import android.widget.LinearLayout; -import android.widget.PopupMenu; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.Editor; -import com.android.gallery3d.filtershow.editors.EditorCurves; -import com.android.gallery3d.filtershow.filters.FilterCurvesRepresentation; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.filters.ImageFilterCurves; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; - -import java.util.HashMap; - -public class ImageCurves extends ImageShow { - - private static final String LOGTAG = "ImageCurves"; - Paint gPaint = new Paint(); - Path gPathSpline = new Path(); - HashMap<Integer, String> mIdStrLut; - - private int mCurrentCurveIndex = Spline.RGB; - 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]; - int[] blueHistogram = new int[256]; - Path gHistoPath = new Path(); - - boolean mDoingTouchMove = false; - private EditorCurves mEditorCurves; - private FilterCurvesRepresentation mFilterCurvesRepresentation; - - public ImageCurves(Context context) { - super(context); - setLayerType(LAYER_TYPE_SOFTWARE, gPaint); - resetCurve(); - } - - public ImageCurves(Context context, AttributeSet attrs) { - super(context, attrs); - setLayerType(LAYER_TYPE_SOFTWARE, gPaint); - resetCurve(); - } - - @Override - protected boolean enableComparison() { - return false; - } - - @Override - public boolean useUtilityPanel() { - return true; - } - - private void showPopupMenu(LinearLayout accessoryViewList) { - final Button button = (Button) accessoryViewList.findViewById( - R.id.applyEffect); - if (button == null) { - return; - } - if (mIdStrLut == null){ - mIdStrLut = new HashMap<Integer, String>(); - mIdStrLut.put(R.id.curve_menu_rgb, - getContext().getString(R.string.curves_channel_rgb)); - mIdStrLut.put(R.id.curve_menu_red, - getContext().getString(R.string.curves_channel_red)); - mIdStrLut.put(R.id.curve_menu_green, - getContext().getString(R.string.curves_channel_green)); - mIdStrLut.put(R.id.curve_menu_blue, - getContext().getString(R.string.curves_channel_blue)); - } - PopupMenu popupMenu = new PopupMenu(getActivity(), button); - popupMenu.getMenuInflater().inflate(R.menu.filtershow_menu_curves, popupMenu.getMenu()); - popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - setChannel(item.getItemId()); - button.setText(mIdStrLut.get(item.getItemId())); - return true; - } - }); - Editor.hackFixStrings(popupMenu.getMenu()); - popupMenu.show(); - } - - @Override - public void openUtilityPanel(final LinearLayout accessoryViewList) { - Context context = accessoryViewList.getContext(); - Button view = (Button) accessoryViewList.findViewById(R.id.applyEffect); - view.setText(context.getString(R.string.curves_channel_rgb)); - view.setVisibility(View.VISIBLE); - - view.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View arg0) { - showPopupMenu(accessoryViewList); - } - }); - - if (view != null) { - view.setVisibility(View.VISIBLE); - } - } - - public void nextChannel() { - mCurrentCurveIndex = ((mCurrentCurveIndex + 1) % 4); - invalidate(); - } - - private ImageFilterCurves curves() { - String filterName = getFilterName(); - ImagePreset p = getImagePreset(); - if (p != null) { - return (ImageFilterCurves) FiltersManager.getManager().getFilter(ImageFilterCurves.class); - } - return null; - } - - private Spline getSpline(int index) { - return mFilterCurvesRepresentation.getSpline(index); - } - - @Override - public void resetParameter() { - super.resetParameter(); - resetCurve(); - mLastPreset = null; - invalidate(); - } - - public void resetCurve() { - if (mFilterCurvesRepresentation != null) { - mFilterCurvesRepresentation.reset(); - updateCachedImage(); - } - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (mFilterCurvesRepresentation == null) { - return; - } - - gPaint.setAntiAlias(true); - - if (getImagePreset() != mLastPreset && getFilteredImage() != null) { - new ComputeHistogramTask().execute(getFilteredImage()); - mLastPreset = getImagePreset(); - } - - if (curves() == null) { - return; - } - - if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.RED) { - drawHistogram(canvas, redHistogram, Color.RED, PorterDuff.Mode.SCREEN); - } - if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.GREEN) { - drawHistogram(canvas, greenHistogram, Color.GREEN, PorterDuff.Mode.SCREEN); - } - if (mCurrentCurveIndex == Spline.RGB || mCurrentCurveIndex == Spline.BLUE) { - drawHistogram(canvas, blueHistogram, Color.BLUE, PorterDuff.Mode.SCREEN); - } - // We only display the other channels curves when showing the RGB curve - if (mCurrentCurveIndex == Spline.RGB) { - for (int i = 0; i < 4; i++) { - Spline spline = getSpline(i); - if (i != mCurrentCurveIndex && !spline.isOriginal()) { - // And we only display a curve if it has more than two - // points - spline.draw(canvas, Spline.colorForCurve(i), getWidth(), - getHeight(), false, mDoingTouchMove); - } - } - } - // ...but we always display the current curve. - getSpline(mCurrentCurveIndex) - .draw(canvas, Spline.colorForCurve(mCurrentCurveIndex), getWidth(), getHeight(), - true, mDoingTouchMove); - - } - - private int pickControlPoint(float x, float y) { - int pick = 0; - Spline spline = getSpline(mCurrentCurveIndex); - float px = spline.getPoint(0).x; - float py = spline.getPoint(0).y; - double delta = Math.sqrt((px - x) * (px - x) + (py - y) * (py - y)); - for (int i = 1; i < spline.getNbPoints(); i++) { - px = spline.getPoint(i).x; - py = spline.getPoint(i).y; - double currentDelta = Math.sqrt((px - x) * (px - x) + (py - y) - * (py - y)); - if (currentDelta < delta) { - delta = currentDelta; - pick = i; - } - } - - if (!mDidAddPoint && (delta * getWidth() > 100) - && (spline.getNbPoints() < 10)) { - return -1; - } - - return pick; - } - - private String getFilterName() { - return "Curves"; - } - - @Override - public synchronized boolean onTouchEvent(MotionEvent e) { - if (e.getPointerCount() != 1) { - return true; - } - - if (didFinishScalingOperation()) { - return true; - } - - float margin = Spline.curveHandleSize() / 2; - float posX = e.getX(); - if (posX < margin) { - posX = margin; - } - float posY = e.getY(); - if (posY < margin) { - posY = margin; - } - if (posX > getWidth() - margin) { - posX = getWidth() - margin; - } - if (posY > getHeight() - margin) { - posY = getHeight() - margin; - } - posX = (posX - margin) / (getWidth() - 2 * margin); - posY = (posY - margin) / (getHeight() - 2 * margin); - - if (e.getActionMasked() == MotionEvent.ACTION_UP) { - mCurrentControlPoint = null; - mCurrentPick = -1; - updateCachedImage(); - mDidAddPoint = false; - if (mDidDelete) { - mDidDelete = false; - } - mDoingTouchMove = false; - return true; - } - - if (mDidDelete) { - return true; - } - - if (curves() == null) { - return true; - } - - if (e.getActionMasked() == MotionEvent.ACTION_MOVE) { - mDoingTouchMove = true; - Spline spline = getSpline(mCurrentCurveIndex); - int pick = mCurrentPick; - if (mCurrentControlPoint == null) { - pick = pickControlPoint(posX, posY); - if (pick == -1) { - mCurrentControlPoint = new ControlPoint(posX, posY); - pick = spline.addPoint(mCurrentControlPoint); - mDidAddPoint = true; - } else { - mCurrentControlPoint = spline.getPoint(pick); - } - mCurrentPick = pick; - } - - if (spline.isPointContained(posX, pick)) { - spline.movePoint(pick, posX, posY); - } else if (pick != -1 && spline.getNbPoints() > 2) { - spline.deletePoint(pick); - mDidDelete = true; - } - updateCachedImage(); - invalidate(); - } - return true; - } - - public synchronized void updateCachedImage() { - if (getImagePreset() != null) { - resetImageCaches(this); - if (mEditorCurves != null) { - mEditorCurves.commitLocalRepresentation(); - } - invalidate(); - } - } - - class ComputeHistogramTask extends AsyncTask<Bitmap, Void, int[]> { - @Override - protected int[] doInBackground(Bitmap... params) { - int[] histo = new int[256 * 3]; - Bitmap bitmap = params[0]; - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - int[] pixels = new int[w * h]; - bitmap.getPixels(pixels, 0, w, 0, 0, w, h); - for (int i = 0; i < w; i++) { - for (int j = 0; j < h; j++) { - int index = j * w + i; - int r = Color.red(pixels[index]); - int g = Color.green(pixels[index]); - int b = Color.blue(pixels[index]); - histo[r]++; - histo[256 + g]++; - histo[512 + b]++; - } - } - return histo; - } - - @Override - protected void onPostExecute(int[] result) { - System.arraycopy(result, 0, redHistogram, 0, 256); - System.arraycopy(result, 256, greenHistogram, 0, 256); - System.arraycopy(result, 512, blueHistogram, 0, 256); - invalidate(); - } - } - - private void drawHistogram(Canvas canvas, int[] histogram, int color, PorterDuff.Mode mode) { - int max = 0; - for (int i = 0; i < histogram.length; i++) { - if (histogram[i] > max) { - max = histogram[i]; - } - } - 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(); - paint.setARGB(100, 255, 255, 255); - paint.setStrokeWidth((int) Math.ceil(wl)); - - Paint paint2 = new Paint(); - paint2.setColor(color); - paint2.setStrokeWidth(6); - paint2.setXfermode(new PorterDuffXfermode(mode)); - gHistoPath.reset(); - 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 + dx; - float l = histogram[i] * wh; - if (l != 0) { - float v = h - (l + prev) / 2.0f; - if (!firstPointEncountered) { - gHistoPath.lineTo(x, h); - firstPointEncountered = true; - } - gHistoPath.lineTo(x, v); - prev = l; - last = x; - } - } - gHistoPath.lineTo(last, h); - gHistoPath.lineTo(w, h); - gHistoPath.close(); - canvas.drawPath(gHistoPath, paint2); - paint2.setStrokeWidth(2); - paint2.setStyle(Paint.Style.STROKE); - paint2.setARGB(255, 200, 200, 200); - canvas.drawPath(gHistoPath, paint2); - } - - public void setChannel(int itemId) { - switch (itemId) { - case R.id.curve_menu_rgb: { - mCurrentCurveIndex = Spline.RGB; - break; - } - case R.id.curve_menu_red: { - mCurrentCurveIndex = Spline.RED; - break; - } - case R.id.curve_menu_green: { - mCurrentCurveIndex = Spline.GREEN; - break; - } - case R.id.curve_menu_blue: { - mCurrentCurveIndex = Spline.BLUE; - break; - } - } - mEditorCurves.commitLocalRepresentation(); - invalidate(); - } - - public void setEditor(EditorCurves editorCurves) { - mEditorCurves = editorCurves; - } - - public void setFilterDrawRepresentation(FilterCurvesRepresentation drawRep) { - mFilterCurvesRepresentation = drawRep; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java deleted file mode 100644 index 9722034e0..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java +++ /dev/null @@ -1,139 +0,0 @@ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.drawable.Drawable; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import com.android.gallery3d.filtershow.editors.EditorDraw; -import com.android.gallery3d.filtershow.filters.FilterDrawRepresentation; -import com.android.gallery3d.filtershow.filters.ImageFilterDraw; - -public class ImageDraw extends ImageShow { - - private static final String LOGTAG = "ImageDraw"; - private int mCurrentColor = Color.RED; - final static float INITAL_STROKE_RADIUS = 40; - private float mCurrentSize = INITAL_STROKE_RADIUS; - private byte mType = 0; - private FilterDrawRepresentation mFRep; - private EditorDraw mEditorDraw; - - public ImageDraw(Context context, AttributeSet attrs) { - super(context, attrs); - resetParameter(); - } - - public ImageDraw(Context context) { - super(context); - resetParameter(); - } - - public void setEditor(EditorDraw editorDraw) { - mEditorDraw = editorDraw; - } - public void setFilterDrawRepresentation(FilterDrawRepresentation fr) { - mFRep = fr; - } - - public Drawable getIcon(Context context) { - - return null; - } - - @Override - public void resetParameter() { - if (mFRep != null) { - mFRep.clear(); - } - } - - public void setColor(int color) { - mCurrentColor = color; - } - - public void setSize(int size) { - mCurrentSize = size; - } - - public void setStyle(byte style) { - mType = (byte) (style % ImageFilterDraw.NUMBER_OF_STYLES); - } - - public int getStyle() { - return mType; - } - - public int getSize() { - return (int) mCurrentSize; - } - - float[] mTmpPoint = new float[2]; // so we do not malloc - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getPointerCount() > 1) { - boolean ret = super.onTouchEvent(event); - if (mFRep.getCurrentDrawing() != null) { - mFRep.clearCurrentSection(); - mEditorDraw.commitLocalRepresentation(); - } - return ret; - } - if (event.getAction() != MotionEvent.ACTION_DOWN) { - if (mFRep.getCurrentDrawing() == null) { - return super.onTouchEvent(event); - } - } - - if (event.getAction() == MotionEvent.ACTION_DOWN) { - calcScreenMapping(); - mTmpPoint[0] = event.getX(); - mTmpPoint[1] = event.getY(); - mToOrig.mapPoints(mTmpPoint); - mFRep.startNewSection(mType, mCurrentColor, mCurrentSize, mTmpPoint[0], mTmpPoint[1]); - } - - if (event.getAction() == MotionEvent.ACTION_MOVE) { - - int historySize = event.getHistorySize(); - for (int h = 0; h < historySize; h++) { - int p = 0; - { - mTmpPoint[0] = event.getHistoricalX(p, h); - mTmpPoint[1] = event.getHistoricalY(p, h); - mToOrig.mapPoints(mTmpPoint); - mFRep.addPoint(mTmpPoint[0], mTmpPoint[1]); - } - } - } - - if (event.getAction() == MotionEvent.ACTION_UP) { - mTmpPoint[0] = event.getX(); - mTmpPoint[1] = event.getY(); - mToOrig.mapPoints(mTmpPoint); - mFRep.endSection(mTmpPoint[0], mTmpPoint[1]); - } - mEditorDraw.commitLocalRepresentation(); - invalidate(); - return true; - } - - Matrix mRotateToScreen = new Matrix(); - Matrix mToOrig; - private void calcScreenMapping() { - mToOrig = getScreenToImageMatrix(true); - mToOrig.invert(mRotateToScreen); - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - calcScreenMapping(); - - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java b/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java deleted file mode 100644 index b55cc2bc4..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageGrad.java +++ /dev/null @@ -1,215 +0,0 @@ -package com.android.gallery3d.filtershow.imageshow; -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.editors.EditorGrad; -import com.android.gallery3d.filtershow.filters.FilterGradRepresentation; - -public class ImageGrad extends ImageShow { - private static final String LOGTAG = "ImageGrad"; - private FilterGradRepresentation mGradRep; - private EditorGrad mEditorGrad; - private float mMinTouchDist; - private int mActiveHandle = -1; - private GradControl mEllipse; - - Matrix mToScr = new Matrix(); - float[] mPointsX = new float[FilterGradRepresentation.MAX_POINTS]; - float[] mPointsY = new float[FilterGradRepresentation.MAX_POINTS]; - - public ImageGrad(Context context) { - super(context); - Resources res = context.getResources(); - mMinTouchDist = res.getDimensionPixelSize(R.dimen.gradcontrol_min_touch_dist); - mEllipse = new GradControl(context); - mEllipse.setShowReshapeHandles(false); - } - - public ImageGrad(Context context, AttributeSet attrs) { - super(context, attrs); - Resources res = context.getResources(); - mMinTouchDist = res.getDimensionPixelSize(R.dimen.gradcontrol_min_touch_dist); - mEllipse = new GradControl(context); - mEllipse.setShowReshapeHandles(false); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - int mask = event.getActionMasked(); - - if (mActiveHandle == -1) { - if (MotionEvent.ACTION_DOWN != mask) { - return super.onTouchEvent(event); - } - if (event.getPointerCount() == 1) { - mActiveHandle = mEllipse.getCloseHandle(event.getX(), event.getY()); - if (mActiveHandle == -1) { - float x = event.getX(); - float y = event.getY(); - float min_d = Float.MAX_VALUE; - int pos = -1; - for (int i = 0; i < mPointsX.length; i++) { - if (mPointsX[i] == -1) { - continue; - } - float d = (float) Math.hypot(x - mPointsX[i], y - mPointsY[i]); - if ( min_d > d) { - min_d = d; - pos = i; - } - } - if (min_d > mMinTouchDist){ - pos = -1; - } - - if (pos != -1) { - mGradRep.setSelectedPoint(pos); - resetImageCaches(this); - mEditorGrad.updateSeekBar(mGradRep); - mEditorGrad.commitLocalRepresentation(); - invalidate(); - } - } - } - if (mActiveHandle == -1) { - return super.onTouchEvent(event); - } - } else { - switch (mask) { - case MotionEvent.ACTION_UP: { - - mActiveHandle = -1; - break; - } - case MotionEvent.ACTION_DOWN: { - break; - } - } - } - float x = event.getX(); - float y = event.getY(); - - mEllipse.setScrImageInfo(getScreenToImageMatrix(true), - MasterImage.getImage().getOriginalBounds()); - - switch (mask) { - case (MotionEvent.ACTION_DOWN): { - mEllipse.actionDown(x, y, mGradRep); - break; - } - case (MotionEvent.ACTION_UP): - case (MotionEvent.ACTION_MOVE): { - mEllipse.actionMove(mActiveHandle, x, y, mGradRep); - setRepresentation(mGradRep); - break; - } - } - invalidate(); - mEditorGrad.commitLocalRepresentation(); - return true; - } - - public void setRepresentation(FilterGradRepresentation pointRep) { - mGradRep = pointRep; - Matrix toImg = getScreenToImageMatrix(false); - - toImg.invert(mToScr); - - float[] c1 = new float[] { mGradRep.getPoint1X(), mGradRep.getPoint1Y() }; - float[] c2 = new float[] { mGradRep.getPoint2X(), mGradRep.getPoint2Y() }; - - if (c1[0] == -1) { - float cx = MasterImage.getImage().getOriginalBounds().width() / 2; - float cy = MasterImage.getImage().getOriginalBounds().height() / 2; - float rx = Math.min(cx, cy) * .4f; - - mGradRep.setPoint1(cx, cy-rx); - mGradRep.setPoint2(cx, cy+rx); - c1[0] = cx; - c1[1] = cy-rx; - mToScr.mapPoints(c1); - if (getWidth() != 0) { - mEllipse.setPoint1(c1[0], c1[1]); - c2[0] = cx; - c2[1] = cy+rx; - mToScr.mapPoints(c2); - mEllipse.setPoint2(c2[0], c2[1]); - } - mEditorGrad.commitLocalRepresentation(); - } else { - mToScr.mapPoints(c1); - mToScr.mapPoints(c2); - mEllipse.setPoint1(c1[0], c1[1]); - mEllipse.setPoint2(c2[0], c2[1]); - } - } - - public void drawOtherPoints(Canvas canvas) { - computCenterLocations(); - for (int i = 0; i < mPointsX.length; i++) { - if (mPointsX[i] != -1) { - mEllipse.paintGrayPoint(canvas, mPointsX[i], mPointsY[i]); - } - } - } - - public void computCenterLocations() { - int x1[] = mGradRep.getXPos1(); - int y1[] = mGradRep.getYPos1(); - int x2[] = mGradRep.getXPos2(); - int y2[] = mGradRep.getYPos2(); - int selected = mGradRep.getSelectedPoint(); - boolean m[] = mGradRep.getMask(); - float[] c = new float[2]; - for (int i = 0; i < m.length; i++) { - if (selected == i || !m[i]) { - mPointsX[i] = -1; - continue; - } - - c[0] = (x1[i]+x2[i])/2; - c[1] = (y1[i]+y2[i])/2; - mToScr.mapPoints(c); - - mPointsX[i] = c[0]; - mPointsY[i] = c[1]; - } - } - - public void setEditor(EditorGrad editorGrad) { - mEditorGrad = editorGrad; - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (mGradRep == null) { - return; - } - setRepresentation(mGradRep); - mEllipse.draw(canvas); - drawOtherPoints(canvas); - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java b/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java deleted file mode 100644 index 26c49b1a8..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageMirror.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import com.android.gallery3d.filtershow.editors.EditorMirror; -import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation; -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder; - -public class ImageMirror extends ImageShow { - private static final String TAG = ImageMirror.class.getSimpleName(); - private EditorMirror mEditorMirror; - private FilterMirrorRepresentation mLocalRep = new FilterMirrorRepresentation(); - private GeometryHolder mDrawHolder = new GeometryHolder(); - - public ImageMirror(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ImageMirror(Context context) { - super(context); - } - - public void setFilterMirrorRepresentation(FilterMirrorRepresentation rep) { - mLocalRep = (rep == null) ? new FilterMirrorRepresentation() : rep; - } - - public void flip() { - mLocalRep.cycle(); - invalidate(); - } - - public FilterMirrorRepresentation getFinalRepresentation() { - return mLocalRep; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - // Treat event as handled. - return true; - } - - @Override - public void onDraw(Canvas canvas) { - MasterImage master = MasterImage.getImage(); - Bitmap image = master.getFiltersOnlyImage(); - if (image == null) { - return; - } - GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep); - GeometryMathUtils.drawTransformedCropped(mDrawHolder, canvas, image, getWidth(), - getHeight()); - } - - public void setEditor(EditorMirror editorFlip) { - mEditorMirror = editorFlip; - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java b/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java deleted file mode 100644 index fd5714139..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImagePoint.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.util.AttributeSet; - -import com.android.gallery3d.filtershow.editors.EditorRedEye; -import com.android.gallery3d.filtershow.filters.FilterPoint; -import com.android.gallery3d.filtershow.filters.FilterRedEyeRepresentation; -import com.android.gallery3d.filtershow.filters.ImageFilterRedEye; - -public abstract class ImagePoint extends ImageShow { - - private static final String LOGTAG = "ImageRedEyes"; - protected EditorRedEye mEditorRedEye; - protected FilterRedEyeRepresentation mRedEyeRep; - protected static float mTouchPadding = 80; - - public static void setTouchPadding(float padding) { - mTouchPadding = padding; - } - - public ImagePoint(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ImagePoint(Context context) { - super(context); - } - - @Override - public void resetParameter() { - ImageFilterRedEye filter = (ImageFilterRedEye) getCurrentFilter(); - if (filter != null) { - filter.clear(); - } - invalidate(); - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - Paint paint = new Paint(); - paint.setStyle(Style.STROKE); - paint.setColor(Color.RED); - paint.setStrokeWidth(2); - - Matrix originalToScreen = getImageToScreenMatrix(false); - Matrix originalRotateToScreen = getImageToScreenMatrix(true); - - if (mRedEyeRep != null) { - for (FilterPoint candidate : mRedEyeRep.getCandidates()) { - drawPoint(candidate, canvas, originalToScreen, originalRotateToScreen, paint); - } - } - } - - protected abstract void drawPoint( - FilterPoint candidate, Canvas canvas, Matrix originalToScreen, - Matrix originalRotateToScreen, Paint paint); - - public void setEditor(EditorRedEye editorRedEye) { - mEditorRedEye = editorRedEye; - } - - public void setRepresentation(FilterRedEyeRepresentation redEyeRep) { - mRedEyeRep = redEyeRep; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java b/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java deleted file mode 100644 index 40433a02e..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageRedEye.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.RectF; -import android.view.MotionEvent; - -import com.android.gallery3d.filtershow.filters.FilterPoint; -import com.android.gallery3d.filtershow.filters.RedEyeCandidate; - -public class ImageRedEye extends ImagePoint { - private static final String LOGTAG = "ImageRedEyes"; - private RectF mCurrentRect = null; - - public ImageRedEye(Context context) { - super(context); - } - - @Override - public void resetParameter() { - super.resetParameter(); - invalidate(); - } - - @Override - - public boolean onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - - if (event.getPointerCount() > 1) { - return true; - } - - if (didFinishScalingOperation()) { - return true; - } - - float ex = event.getX(); - float ey = event.getY(); - - // let's transform (ex, ey) to displayed image coordinates - if (event.getAction() == MotionEvent.ACTION_DOWN) { - mCurrentRect = new RectF(); - mCurrentRect.left = ex - mTouchPadding; - mCurrentRect.top = ey - mTouchPadding; - } - if (event.getAction() == MotionEvent.ACTION_MOVE) { - mCurrentRect.right = ex + mTouchPadding; - mCurrentRect.bottom = ey + mTouchPadding; - } - if (event.getAction() == MotionEvent.ACTION_UP) { - if (mCurrentRect != null) { - // transform to original coordinates - Matrix originalNoRotateToScreen = getImageToScreenMatrix(false); - Matrix originalToScreen = getImageToScreenMatrix(true); - Matrix invert = new Matrix(); - originalToScreen.invert(invert); - RectF r = new RectF(mCurrentRect); - invert.mapRect(r); - RectF r2 = new RectF(mCurrentRect); - invert.reset(); - originalNoRotateToScreen.invert(invert); - invert.mapRect(r2); - mRedEyeRep.addRect(r, r2); - this.resetImageCaches(this); - } - mCurrentRect = null; - } - mEditorRedEye.commitLocalRepresentation(); - invalidate(); - return true; - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - Paint paint = new Paint(); - paint.setStyle(Style.STROKE); - paint.setColor(Color.RED); - paint.setStrokeWidth(2); - if (mCurrentRect != null) { - paint.setColor(Color.RED); - RectF drawRect = new RectF(mCurrentRect); - canvas.drawRect(drawRect, paint); - } - } - - @Override - protected void drawPoint(FilterPoint point, Canvas canvas, Matrix originalToScreen, - Matrix originalRotateToScreen, Paint paint) { - RedEyeCandidate candidate = (RedEyeCandidate) point; - RectF rect = candidate.getRect(); - RectF drawRect = new RectF(); - originalToScreen.mapRect(drawRect, rect); - RectF fullRect = new RectF(); - originalRotateToScreen.mapRect(fullRect, rect); - paint.setColor(Color.BLUE); - canvas.drawRect(fullRect, paint); - canvas.drawLine(fullRect.centerX(), fullRect.top, - fullRect.centerX(), fullRect.bottom, paint); - canvas.drawLine(fullRect.left, fullRect.centerY(), - fullRect.right, fullRect.centerY(), paint); - paint.setColor(Color.GREEN); - float dw = drawRect.width(); - float dh = drawRect.height(); - float dx = fullRect.centerX() - dw / 2; - float dy = fullRect.centerY() - dh / 2; - drawRect.set(dx, dy, dx + dw, dy + dh); - canvas.drawRect(drawRect, paint); - canvas.drawLine(drawRect.centerX(), drawRect.top, - drawRect.centerX(), drawRect.bottom, paint); - canvas.drawLine(drawRect.left, drawRect.centerY(), - drawRect.right, drawRect.centerY(), paint); - canvas.drawCircle(drawRect.centerX(), drawRect.centerY(), - mTouchPadding, paint); - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java b/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java deleted file mode 100644 index 5186c09d7..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageRotate.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import com.android.gallery3d.filtershow.editors.EditorRotate; -import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation; -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder; - -public class ImageRotate extends ImageShow { - private EditorRotate mEditorRotate; - private static final String TAG = ImageRotate.class.getSimpleName(); - private FilterRotateRepresentation mLocalRep = new FilterRotateRepresentation(); - private GeometryHolder mDrawHolder = new GeometryHolder(); - - public ImageRotate(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public ImageRotate(Context context) { - super(context); - } - - public void setFilterRotateRepresentation(FilterRotateRepresentation rep) { - mLocalRep = (rep == null) ? new FilterRotateRepresentation() : rep; - } - - public void rotate() { - mLocalRep.rotateCW(); - invalidate(); - } - - public FilterRotateRepresentation getFinalRepresentation() { - return mLocalRep; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - // Treat event as handled. - return true; - } - - public int getLocalValue() { - return mLocalRep.getRotation().value(); - } - - @Override - public void onDraw(Canvas canvas) { - MasterImage master = MasterImage.getImage(); - Bitmap image = master.getFiltersOnlyImage(); - if (image == null) { - return; - } - GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep); - GeometryMathUtils.drawTransformedCropped(mDrawHolder, canvas, image, canvas.getWidth(), - canvas.getHeight()); - } - - public void setEditor(EditorRotate editorRotate) { - mEditorRotate = editorRotate; - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java b/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java deleted file mode 100644 index 6278b2ad4..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageShow.java +++ /dev/null @@ -1,578 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.GestureDetector; -import android.view.GestureDetector.OnDoubleTapListener; -import android.view.GestureDetector.OnGestureListener; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; -import android.view.View; -import android.widget.LinearLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.filters.ImageFilter; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.filtershow.tools.SaveImage; - -import java.io.File; - -public class ImageShow extends View implements OnGestureListener, - ScaleGestureDetector.OnScaleGestureListener, - OnDoubleTapListener { - - private static final String LOGTAG = "ImageShow"; - private static final boolean ENABLE_ZOOMED_COMPARISON = false; - - protected Paint mPaint = new Paint(); - protected int mTextSize; - protected int mTextPadding; - - protected int mBackgroundColor; - - private GestureDetector mGestureDetector = null; - private ScaleGestureDetector mScaleGestureDetector = null; - - protected Rect mImageBounds = new Rect(); - private boolean mOriginalDisabled = false; - private boolean mTouchShowOriginal = false; - private long mTouchShowOriginalDate = 0; - private final long mTouchShowOriginalDelayMin = 200; // 200ms - private int mShowOriginalDirection = 0; - private static int UNVEIL_HORIZONTAL = 1; - private static int UNVEIL_VERTICAL = 2; - - private Point mTouchDown = new Point(); - private Point mTouch = new Point(); - private boolean mFinishedScalingOperation = false; - - private int mOriginalTextMargin; - private int mOriginalTextSize; - private String mOriginalText; - private boolean mZoomIn = false; - Point mOriginalTranslation = new Point(); - float mOriginalScale; - float mStartFocusX, mStartFocusY; - private enum InteractionMode { - NONE, - SCALE, - MOVE - } - InteractionMode mInteractionMode = InteractionMode.NONE; - - private FilterShowActivity mActivity = null; - - public FilterShowActivity getActivity() { - return mActivity; - } - - public boolean hasModifications() { - return MasterImage.getImage().hasModifications(); - } - - public void resetParameter() { - // TODO: implement reset - } - - public void onNewValue(int parameter) { - invalidate(); - } - - public ImageShow(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - setupImageShow(context); - } - - public ImageShow(Context context, AttributeSet attrs) { - super(context, attrs); - setupImageShow(context); - - } - - public ImageShow(Context context) { - super(context); - setupImageShow(context); - } - - private void setupImageShow(Context context) { - Resources res = context.getResources(); - mTextSize = res.getDimensionPixelSize(R.dimen.photoeditor_text_size); - mTextPadding = res.getDimensionPixelSize(R.dimen.photoeditor_text_padding); - mOriginalTextMargin = res.getDimensionPixelSize(R.dimen.photoeditor_original_text_margin); - mOriginalTextSize = res.getDimensionPixelSize(R.dimen.photoeditor_original_text_size); - mBackgroundColor = res.getColor(R.color.background_screen); - mOriginalText = res.getString(R.string.original_picture_text); - setupGestureDetector(context); - mActivity = (FilterShowActivity) context; - MasterImage.getImage().addObserver(this); - } - - public void setupGestureDetector(Context context) { - mGestureDetector = new GestureDetector(context, this); - mScaleGestureDetector = new ScaleGestureDetector(context, this); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int parentWidth = MeasureSpec.getSize(widthMeasureSpec); - int parentHeight = MeasureSpec.getSize(heightMeasureSpec); - setMeasuredDimension(parentWidth, parentHeight); - } - - public ImageFilter getCurrentFilter() { - return MasterImage.getImage().getCurrentFilter(); - } - - /* consider moving the following 2 methods into a subclass */ - /** - * This function calculates a Image to Screen Transformation matrix - * - * @param reflectRotation set true if you want the rotation encoded - * @return Image to Screen transformation matrix - */ - protected Matrix getImageToScreenMatrix(boolean reflectRotation) { - MasterImage master = MasterImage.getImage(); - if (master.getOriginalBounds() == null) { - return new Matrix(); - } - Matrix m = GeometryMathUtils.getImageToScreenMatrix(master.getPreset().getGeometryFilters(), - reflectRotation, master.getOriginalBounds(), getWidth(), getHeight()); - Point translate = master.getTranslation(); - float scaleFactor = master.getScaleFactor(); - m.postTranslate(translate.x, translate.y); - m.postScale(scaleFactor, scaleFactor, getWidth() / 2.0f, getHeight() / 2.0f); - return m; - } - - /** - * This function calculates a to Screen Image Transformation matrix - * - * @param reflectRotation set true if you want the rotation encoded - * @return Screen to Image transformation matrix - */ - protected Matrix getScreenToImageMatrix(boolean reflectRotation) { - Matrix m = getImageToScreenMatrix(reflectRotation); - Matrix invert = new Matrix(); - m.invert(invert); - return invert; - } - - public ImagePreset getImagePreset() { - return MasterImage.getImage().getPreset(); - } - - @Override - public void onDraw(Canvas canvas) { - MasterImage.getImage().setImageShowSize(getWidth(), getHeight()); - - float cx = canvas.getWidth()/2.0f; - float cy = canvas.getHeight()/2.0f; - float scaleFactor = MasterImage.getImage().getScaleFactor(); - Point translation = MasterImage.getImage().getTranslation(); - - Matrix scalingMatrix = new Matrix(); - scalingMatrix.postScale(scaleFactor, scaleFactor, cx, cy); - scalingMatrix.preTranslate(translation.x, translation.y); - - RectF unscaledClipRect = new RectF(mImageBounds); - scalingMatrix.mapRect(unscaledClipRect, unscaledClipRect); - - canvas.save(); - - boolean enablePartialRendering = false; - - // For now, partial rendering is disabled for all filters, - // so no need to clip. - if (enablePartialRendering && !unscaledClipRect.isEmpty()) { - canvas.clipRect(unscaledClipRect); - } - - canvas.save(); - // TODO: center scale on gesture - canvas.scale(scaleFactor, scaleFactor, cx, cy); - canvas.translate(translation.x, translation.y); - drawImage(canvas, getFilteredImage(), true); - Bitmap highresPreview = MasterImage.getImage().getHighresImage(); - if (highresPreview != null) { - drawImage(canvas, highresPreview, true); - } - canvas.restore(); - - Bitmap partialPreview = MasterImage.getImage().getPartialImage(); - if (partialPreview != null) { - Rect src = new Rect(0, 0, partialPreview.getWidth(), partialPreview.getHeight()); - Rect dest = new Rect(0, 0, getWidth(), getHeight()); - canvas.drawBitmap(partialPreview, src, dest, mPaint); - } - - canvas.save(); - canvas.scale(scaleFactor, scaleFactor, cx, cy); - canvas.translate(translation.x, translation.y); - drawPartialImage(canvas, getGeometryOnlyImage()); - canvas.restore(); - - canvas.restore(); - } - - public void resetImageCaches(ImageShow caller) { - MasterImage.getImage().updatePresets(true); - } - - public Bitmap getFiltersOnlyImage() { - return MasterImage.getImage().getFiltersOnlyImage(); - } - - public Bitmap getGeometryOnlyImage() { - return MasterImage.getImage().getGeometryOnlyImage(); - } - - public Bitmap getFilteredImage() { - return MasterImage.getImage().getFilteredImage(); - } - - public void drawImage(Canvas canvas, Bitmap image, boolean updateBounds) { - if (image != null) { - Rect s = new Rect(0, 0, image.getWidth(), - image.getHeight()); - - float scale = GeometryMathUtils.scale(image.getWidth(), image.getHeight(), getWidth(), - getHeight()); - - float w = image.getWidth() * scale; - float h = image.getHeight() * scale; - float ty = (getHeight() - h) / 2.0f; - float tx = (getWidth() - w) / 2.0f; - - Rect d = new Rect((int) tx, (int) ty, (int) (w + tx), - (int) (h + ty)); - if (updateBounds) { - mImageBounds = d; - } - canvas.drawBitmap(image, s, d, mPaint); - } - } - - public void drawPartialImage(Canvas canvas, Bitmap image) { - boolean showsOriginal = MasterImage.getImage().showsOriginal(); - if (!showsOriginal && !mTouchShowOriginal) - return; - canvas.save(); - if (image != null) { - if (mShowOriginalDirection == 0) { - if (Math.abs(mTouch.y - mTouchDown.y) > Math.abs(mTouch.x - mTouchDown.x)) { - mShowOriginalDirection = UNVEIL_VERTICAL; - } else { - mShowOriginalDirection = UNVEIL_HORIZONTAL; - } - } - - int px = 0; - int py = 0; - if (mShowOriginalDirection == UNVEIL_VERTICAL) { - px = mImageBounds.width(); - py = mTouch.y - mImageBounds.top; - } else { - px = mTouch.x - mImageBounds.left; - py = mImageBounds.height(); - if (showsOriginal) { - px = mImageBounds.width(); - } - } - - Rect d = new Rect(mImageBounds.left, mImageBounds.top, - mImageBounds.left + px, mImageBounds.top + py); - canvas.clipRect(d); - drawImage(canvas, image, false); - Paint paint = new Paint(); - paint.setColor(Color.BLACK); - paint.setStrokeWidth(3); - - if (mShowOriginalDirection == UNVEIL_VERTICAL) { - canvas.drawLine(mImageBounds.left, mTouch.y, - mImageBounds.right, mTouch.y, paint); - } else { - canvas.drawLine(mTouch.x, mImageBounds.top, - mTouch.x, mImageBounds.bottom, paint); - } - - Rect bounds = new Rect(); - paint.setAntiAlias(true); - paint.setTextSize(mOriginalTextSize); - paint.getTextBounds(mOriginalText, 0, mOriginalText.length(), bounds); - paint.setColor(Color.BLACK); - paint.setStyle(Paint.Style.STROKE); - paint.setStrokeWidth(3); - canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin, - mImageBounds.top + bounds.height() + mOriginalTextMargin, paint); - paint.setStyle(Paint.Style.FILL); - paint.setStrokeWidth(1); - paint.setColor(Color.WHITE); - canvas.drawText(mOriginalText, mImageBounds.left + mOriginalTextMargin, - mImageBounds.top + bounds.height() + mOriginalTextMargin, paint); - } - canvas.restore(); - } - - public void bindAsImageLoadListener() { - MasterImage.getImage().addListener(this); - } - - public void updateImage() { - invalidate(); - } - - public void imageLoaded() { - updateImage(); - } - - public void saveImage(FilterShowActivity filterShowActivity, File file) { - SaveImage.saveImage(getImagePreset(), filterShowActivity, file); - } - - - public boolean scaleInProgress() { - return mScaleGestureDetector.isInProgress(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - super.onTouchEvent(event); - int action = event.getAction(); - action = action & MotionEvent.ACTION_MASK; - - mGestureDetector.onTouchEvent(event); - boolean scaleInProgress = scaleInProgress(); - mScaleGestureDetector.onTouchEvent(event); - if (mInteractionMode == InteractionMode.SCALE) { - return true; - } - if (!scaleInProgress() && scaleInProgress) { - // If we were scaling, the scale will stop but we will - // still issue an ACTION_UP. Let the subclasses know. - mFinishedScalingOperation = true; - } - - int ex = (int) event.getX(); - int ey = (int) event.getY(); - if (action == MotionEvent.ACTION_DOWN) { - mInteractionMode = InteractionMode.MOVE; - mTouchDown.x = ex; - mTouchDown.y = ey; - mTouchShowOriginalDate = System.currentTimeMillis(); - mShowOriginalDirection = 0; - MasterImage.getImage().setOriginalTranslation(MasterImage.getImage().getTranslation()); - } - - if (action == MotionEvent.ACTION_MOVE && mInteractionMode == InteractionMode.MOVE) { - mTouch.x = ex; - mTouch.y = ey; - - float scaleFactor = MasterImage.getImage().getScaleFactor(); - if (scaleFactor > 1 && (!ENABLE_ZOOMED_COMPARISON || event.getPointerCount() == 2)) { - float translateX = (mTouch.x - mTouchDown.x) / scaleFactor; - float translateY = (mTouch.y - mTouchDown.y) / scaleFactor; - Point originalTranslation = MasterImage.getImage().getOriginalTranslation(); - Point translation = MasterImage.getImage().getTranslation(); - translation.x = (int) (originalTranslation.x + translateX); - translation.y = (int) (originalTranslation.y + translateY); - constrainTranslation(translation, scaleFactor); - MasterImage.getImage().setTranslation(translation); - mTouchShowOriginal = false; - } else if (enableComparison() && !mOriginalDisabled - && (System.currentTimeMillis() - mTouchShowOriginalDate - > mTouchShowOriginalDelayMin) - && event.getPointerCount() == 1) { - mTouchShowOriginal = true; - } - } - - if (action == MotionEvent.ACTION_UP) { - mInteractionMode = InteractionMode.NONE; - mTouchShowOriginal = false; - mTouchDown.x = 0; - mTouchDown.y = 0; - mTouch.x = 0; - mTouch.y = 0; - if (MasterImage.getImage().getScaleFactor() <= 1) { - MasterImage.getImage().setScaleFactor(1); - MasterImage.getImage().resetTranslation(); - } - } - invalidate(); - return true; - } - - protected boolean enableComparison() { - return true; - } - - @Override - public boolean onDoubleTap(MotionEvent arg0) { - mZoomIn = !mZoomIn; - float scale = 1.0f; - if (mZoomIn) { - scale = MasterImage.getImage().getMaxScaleFactor(); - } - if (scale != MasterImage.getImage().getScaleFactor()) { - MasterImage.getImage().setScaleFactor(scale); - float translateX = (getWidth() / 2 - arg0.getX()); - float translateY = (getHeight() / 2 - arg0.getY()); - Point translation = MasterImage.getImage().getTranslation(); - translation.x = (int) (mOriginalTranslation.x + translateX); - translation.y = (int) (mOriginalTranslation.y + translateY); - constrainTranslation(translation, scale); - MasterImage.getImage().setTranslation(translation); - invalidate(); - } - return true; - } - - private void constrainTranslation(Point translation, float scale) { - float maxTranslationX = getWidth() / scale; - float maxTranslationY = getHeight() / scale; - if (Math.abs(translation.x) > maxTranslationX) { - translation.x = (int) (Math.signum(translation.x) * - maxTranslationX); - if (Math.abs(translation.y) > maxTranslationY) { - translation.y = (int) (Math.signum(translation.y) * - maxTranslationY); - } - - } - } - - @Override - public boolean onDoubleTapEvent(MotionEvent arg0) { - return false; - } - - @Override - public boolean onSingleTapConfirmed(MotionEvent arg0) { - return false; - } - - @Override - public boolean onDown(MotionEvent arg0) { - return false; - } - - @Override - public boolean onFling(MotionEvent startEvent, MotionEvent endEvent, float arg2, float arg3) { - if (mActivity == null) { - return false; - } - if (endEvent.getPointerCount() == 2) { - return false; - } - return true; - } - - @Override - public void onLongPress(MotionEvent arg0) { - } - - @Override - public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2, float arg3) { - return false; - } - - @Override - public void onShowPress(MotionEvent arg0) { - } - - @Override - public boolean onSingleTapUp(MotionEvent arg0) { - return false; - } - - public boolean useUtilityPanel() { - return false; - } - - public void openUtilityPanel(final LinearLayout accessoryViewList) { - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - MasterImage img = MasterImage.getImage(); - float scaleFactor = img.getScaleFactor(); - - scaleFactor = scaleFactor * detector.getScaleFactor(); - if (scaleFactor > MasterImage.getImage().getMaxScaleFactor()) { - scaleFactor = MasterImage.getImage().getMaxScaleFactor(); - } - if (scaleFactor < 0.5) { - scaleFactor = 0.5f; - } - MasterImage.getImage().setScaleFactor(scaleFactor); - scaleFactor = img.getScaleFactor(); - float focusx = detector.getFocusX(); - float focusy = detector.getFocusY(); - float translateX = (focusx - mStartFocusX) / scaleFactor; - float translateY = (focusy - mStartFocusY) / scaleFactor; - Point translation = MasterImage.getImage().getTranslation(); - translation.x = (int) (mOriginalTranslation.x + translateX); - translation.y = (int) (mOriginalTranslation.y + translateY); - constrainTranslation(translation, scaleFactor); - MasterImage.getImage().setTranslation(translation); - - invalidate(); - return true; - } - - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - Point pos = MasterImage.getImage().getTranslation(); - mOriginalTranslation.x = pos.x; - mOriginalTranslation.y = pos.y; - mOriginalScale = MasterImage.getImage().getScaleFactor(); - mStartFocusX = detector.getFocusX(); - mStartFocusY = detector.getFocusY(); - mInteractionMode = InteractionMode.SCALE; - return true; - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - mInteractionMode = InteractionMode.NONE; - if (MasterImage.getImage().getScaleFactor() < 1) { - MasterImage.getImage().setScaleFactor(1); - invalidate(); - } - } - - public boolean didFinishScalingOperation() { - if (mFinishedScalingOperation) { - mFinishedScalingOperation = false; - return true; - } - return false; - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java b/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java deleted file mode 100644 index ff75dcc09..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageStraighten.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Style; -import android.graphics.Path; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.MotionEvent; - -import com.android.gallery3d.filtershow.editors.EditorStraighten; -import com.android.gallery3d.filtershow.filters.FilterCropRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation; -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils.GeometryHolder; - -import java.util.ArrayList; -import java.util.Collection; - - -public class ImageStraighten extends ImageShow { - private static final String TAG = ImageStraighten.class.getSimpleName(); - private float mBaseAngle = 0; - private float mAngle = 0; - private float mInitialAngle = 0; - private boolean mFirstDrawSinceUp = false; - private EditorStraighten mEditorStraighten; - private FilterStraightenRepresentation mLocalRep = new FilterStraightenRepresentation(); - private RectF mPriorCropAtUp = new RectF(); - private RectF mDrawRect = new RectF(); - private Path mDrawPath = new Path(); - private GeometryHolder mDrawHolder = new GeometryHolder(); - private enum MODES { - NONE, MOVE - } - private MODES mState = MODES.NONE; - private static final float MAX_STRAIGHTEN_ANGLE - = FilterStraightenRepresentation.MAX_STRAIGHTEN_ANGLE; - private static final float MIN_STRAIGHTEN_ANGLE - = FilterStraightenRepresentation.MIN_STRAIGHTEN_ANGLE; - private float mCurrentX; - private float mCurrentY; - private float mTouchCenterX; - private float mTouchCenterY; - private RectF mCrop = new RectF(); - private final Paint mPaint = new Paint(); - - public ImageStraighten(Context context) { - super(context); - } - - public ImageStraighten(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public void setFilterStraightenRepresentation(FilterStraightenRepresentation rep) { - mLocalRep = (rep == null) ? new FilterStraightenRepresentation() : rep; - mInitialAngle = mBaseAngle = mAngle = mLocalRep.getStraighten(); - } - - public Collection<FilterRepresentation> getFinalRepresentation() { - ArrayList<FilterRepresentation> reps = new ArrayList<FilterRepresentation>(2); - reps.add(mLocalRep); - if (mInitialAngle != mLocalRep.getStraighten()) { - reps.add(new FilterCropRepresentation(mCrop)); - } - return reps; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - - switch (event.getActionMasked()) { - case (MotionEvent.ACTION_DOWN): - if (mState == MODES.NONE) { - mTouchCenterX = x; - mTouchCenterY = y; - mCurrentX = x; - mCurrentY = y; - mState = MODES.MOVE; - mBaseAngle = mAngle; - } - break; - case (MotionEvent.ACTION_UP): - if (mState == MODES.MOVE) { - mState = MODES.NONE; - mCurrentX = x; - mCurrentY = y; - computeValue(); - mFirstDrawSinceUp = true; - } - break; - case (MotionEvent.ACTION_MOVE): - if (mState == MODES.MOVE) { - mCurrentX = x; - mCurrentY = y; - computeValue(); - } - break; - default: - break; - } - invalidate(); - return true; - } - - private static float angleFor(float dx, float dy) { - return (float) (Math.atan2(dx, dy) * 180 / Math.PI); - } - - private float getCurrentTouchAngle() { - float centerX = getWidth() / 2f; - float centerY = getHeight() / 2f; - if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) { - return 0; - } - float dX1 = mTouchCenterX - centerX; - float dY1 = mTouchCenterY - centerY; - float dX2 = mCurrentX - centerX; - float dY2 = mCurrentY - centerY; - float angleA = angleFor(dX1, dY1); - float angleB = angleFor(dX2, dY2); - return (angleB - angleA) % 360; - } - - private void computeValue() { - float angle = getCurrentTouchAngle(); - mAngle = (mBaseAngle - angle) % 360; - mAngle = Math.max(MIN_STRAIGHTEN_ANGLE, mAngle); - mAngle = Math.min(MAX_STRAIGHTEN_ANGLE, mAngle); - } - - private static void getUntranslatedStraightenCropBounds(RectF outRect, float straightenAngle) { - float deg = straightenAngle; - if (deg < 0) { - deg = -deg; - } - double a = Math.toRadians(deg); - double sina = Math.sin(a); - double cosa = Math.cos(a); - double rw = outRect.width(); - double rh = outRect.height(); - double h1 = rh * rh / (rw * sina + rh * cosa); - double h2 = rh * rw / (rw * cosa + rh * sina); - double hh = Math.min(h1, h2); - double ww = hh * rw / rh; - float left = (float) ((rw - ww) * 0.5f); - float top = (float) ((rh - hh) * 0.5f); - float right = (float) (left + ww); - float bottom = (float) (top + hh); - outRect.set(left, top, right, bottom); - } - - private void updateCurrentCrop(Matrix m, GeometryHolder h, RectF tmp, int imageWidth, - int imageHeight, int viewWidth, int viewHeight) { - if (GeometryMathUtils.needsDimensionSwap(h.rotation)) { - tmp.set(0, 0, imageHeight, imageWidth); - } else { - tmp.set(0, 0, imageWidth, imageHeight); - } - float scale = GeometryMathUtils.scale(imageWidth, imageHeight, viewWidth, viewHeight); - GeometryMathUtils.scaleRect(tmp, scale); - getUntranslatedStraightenCropBounds(tmp, mAngle); - tmp.offset(viewWidth / 2f - tmp.centerX(), viewHeight / 2f - tmp.centerY()); - h.straighten = 0; - Matrix m1 = GeometryMathUtils.getFullGeometryToScreenMatrix(h, imageWidth, - imageHeight, viewWidth, viewHeight); - m.reset(); - m1.invert(m); - mCrop.set(tmp); - m.mapRect(mCrop); - FilterCropRepresentation.findNormalizedCrop(mCrop, imageWidth, imageHeight); - } - - - @Override - public void onDraw(Canvas canvas) { - MasterImage master = MasterImage.getImage(); - Bitmap image = master.getFiltersOnlyImage(); - if (image == null) { - return; - } - GeometryMathUtils.initializeHolder(mDrawHolder, mLocalRep); - mDrawHolder.straighten = mAngle; - int imageWidth = image.getWidth(); - int imageHeight = image.getHeight(); - int viewWidth = canvas.getWidth(); - int viewHeight = canvas.getHeight(); - - // Get matrix for drawing bitmap - Matrix m = GeometryMathUtils.getFullGeometryToScreenMatrix(mDrawHolder, imageWidth, - imageHeight, viewWidth, viewHeight); - mPaint.reset(); - mPaint.setAntiAlias(true); - mPaint.setFilterBitmap(true); - canvas.drawBitmap(image, m, mPaint); - - mPaint.setFilterBitmap(false); - mPaint.setColor(Color.WHITE); - mPaint.setStrokeWidth(2); - mPaint.setStyle(Paint.Style.FILL_AND_STROKE); - updateCurrentCrop(m, mDrawHolder, mDrawRect, imageWidth, - imageHeight, viewWidth, viewHeight); - if (mFirstDrawSinceUp) { - mPriorCropAtUp.set(mCrop); - mLocalRep.setStraighten(mAngle); - mFirstDrawSinceUp = false; - } - - // Draw the grid - if (mState == MODES.MOVE) { - canvas.save(); - canvas.clipRect(mDrawRect); - int n = 16; - float step = viewWidth / n; - float p = 0; - for (int i = 1; i < n; i++) { - p = i * step; - mPaint.setAlpha(60); - canvas.drawLine(p, 0, p, viewHeight, mPaint); - canvas.drawLine(0, p, viewHeight, p, mPaint); - } - canvas.restore(); - } - mPaint.reset(); - mPaint.setColor(Color.WHITE); - mPaint.setStyle(Style.STROKE); - mPaint.setStrokeWidth(3); - mDrawPath.reset(); - mDrawPath.addRect(mDrawRect, Path.Direction.CW); - canvas.drawPath(mDrawPath, mPaint); - } - - public void setEditor(EditorStraighten editorStraighten) { - mEditorStraighten = editorStraighten; - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java b/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java deleted file mode 100644 index 25a0a9073..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageTinyPlanet.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.RectF; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; -import android.view.ScaleGestureDetector.OnScaleGestureListener; - -import com.android.gallery3d.filtershow.editors.BasicEditor; -import com.android.gallery3d.filtershow.editors.EditorTinyPlanet; -import com.android.gallery3d.filtershow.filters.FilterTinyPlanetRepresentation; - -public class ImageTinyPlanet extends ImageShow { - private static final String LOGTAG = "ImageTinyPlanet"; - - private float mTouchCenterX = 0; - private float mTouchCenterY = 0; - private float mCurrentX = 0; - private float mCurrentY = 0; - private float mCenterX = 0; - private float mCenterY = 0; - private float mStartAngle = 0; - private FilterTinyPlanetRepresentation mTinyPlanetRep; - private EditorTinyPlanet mEditorTinyPlanet; - private ScaleGestureDetector mScaleGestureDetector = null; - boolean mInScale = false; - RectF mDestRect = new RectF(); - - OnScaleGestureListener mScaleGestureListener = new OnScaleGestureListener() { - private float mScale = 100; - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - mInScale = false; - } - - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - mInScale = true; - mScale = mTinyPlanetRep.getValue(); - return true; - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - int value = mTinyPlanetRep.getValue(); - mScale *= detector.getScaleFactor(); - value = (int) (mScale); - value = Math.min(mTinyPlanetRep.getMaximum(), value); - value = Math.max(mTinyPlanetRep.getMinimum(), value); - mTinyPlanetRep.setValue(value); - invalidate(); - mEditorTinyPlanet.commitLocalRepresentation(); - mEditorTinyPlanet.updateUI(); - return true; - } - }; - - public ImageTinyPlanet(Context context) { - super(context); - mScaleGestureDetector = new ScaleGestureDetector(context, mScaleGestureListener); - } - - public ImageTinyPlanet(Context context, AttributeSet attrs) { - super(context, attrs); - mScaleGestureDetector = new ScaleGestureDetector(context,mScaleGestureListener ); - } - - protected static float angleFor(float dx, float dy) { - return (float) (Math.atan2(dx, dy) * 180 / Math.PI); - } - - protected float getCurrentTouchAngle() { - if (mCurrentX == mTouchCenterX && mCurrentY == mTouchCenterY) { - return 0; - } - float dX1 = mTouchCenterX - mCenterX; - float dY1 = mTouchCenterY - mCenterY; - float dX2 = mCurrentX - mCenterX; - float dY2 = mCurrentY - mCenterY; - - float angleA = angleFor(dX1, dY1); - float angleB = angleFor(dX2, dY2); - return (float) (((angleB - angleA) % 360) * Math.PI / 180); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - mCurrentX = x; - mCurrentY = y; - mCenterX = getWidth() / 2; - mCenterY = getHeight() / 2; - mScaleGestureDetector.onTouchEvent(event); - if (mInScale) { - return true; - } - switch (event.getActionMasked()) { - case (MotionEvent.ACTION_DOWN): - mTouchCenterX = x; - mTouchCenterY = y; - mStartAngle = mTinyPlanetRep.getAngle(); - break; - - case (MotionEvent.ACTION_MOVE): - mTinyPlanetRep.setAngle(mStartAngle + getCurrentTouchAngle()); - break; - } - invalidate(); - mEditorTinyPlanet.commitLocalRepresentation(); - return true; - } - - public void setRepresentation(FilterTinyPlanetRepresentation tinyPlanetRep) { - mTinyPlanetRep = tinyPlanetRep; - } - - public void setEditor(BasicEditor editorTinyPlanet) { - mEditorTinyPlanet = (EditorTinyPlanet) editorTinyPlanet; - } - - @Override - public void onDraw(Canvas canvas) { - Bitmap bitmap = MasterImage.getImage().getHighresImage(); - if (bitmap == null) { - bitmap = MasterImage.getImage().getFilteredImage(); - } - - if (bitmap != null) { - display(canvas, bitmap); - } - } - - private void display(Canvas canvas, Bitmap bitmap) { - float sw = canvas.getWidth(); - float sh = canvas.getHeight(); - float iw = bitmap.getWidth(); - float ih = bitmap.getHeight(); - float nsw = sw; - float nsh = sh; - - if (sw * ih > sh * iw) { - nsw = sh * iw / ih; - } else { - nsh = sw * ih / iw; - } - - mDestRect.left = (sw - nsw) / 2; - mDestRect.top = (sh - nsh) / 2; - mDestRect.right = sw - mDestRect.left; - mDestRect.bottom = sh - mDestRect.top; - - canvas.drawBitmap(bitmap, null, mDestRect, mPaint); - } -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java b/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java deleted file mode 100644 index 518969ee1..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/ImageVignette.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; - -import com.android.gallery3d.filtershow.editors.EditorVignette; -import com.android.gallery3d.filtershow.filters.FilterVignetteRepresentation; - -public class ImageVignette extends ImageShow { - private static final String LOGTAG = "ImageVignette"; - - private FilterVignetteRepresentation mVignetteRep; - private EditorVignette mEditorVignette; - - private int mActiveHandle = -1; - - EclipseControl mElipse; - - public ImageVignette(Context context) { - super(context); - mElipse = new EclipseControl(context); - } - - public ImageVignette(Context context, AttributeSet attrs) { - super(context, attrs); - mElipse = new EclipseControl(context); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - int mask = event.getActionMasked(); - if (mActiveHandle == -1) { - if (MotionEvent.ACTION_DOWN != mask) { - return super.onTouchEvent(event); - } - if (event.getPointerCount() == 1) { - mActiveHandle = mElipse.getCloseHandle(event.getX(), event.getY()); - } - if (mActiveHandle == -1) { - return super.onTouchEvent(event); - } - } else { - switch (mask) { - case MotionEvent.ACTION_UP: - mActiveHandle = -1; - break; - case MotionEvent.ACTION_DOWN: - break; - } - } - float x = event.getX(); - float y = event.getY(); - - mElipse.setScrToImageMatrix(getScreenToImageMatrix(true)); - - boolean didComputeEllipses = false; - switch (mask) { - case (MotionEvent.ACTION_DOWN): - mElipse.actionDown(x, y, mVignetteRep); - break; - case (MotionEvent.ACTION_UP): - case (MotionEvent.ACTION_MOVE): - mElipse.actionMove(mActiveHandle, x, y, mVignetteRep); - setRepresentation(mVignetteRep); - didComputeEllipses = true; - break; - } - if (!didComputeEllipses) { - computeEllipses(); - } - invalidate(); - return true; - } - - public void setRepresentation(FilterVignetteRepresentation vignetteRep) { - mVignetteRep = vignetteRep; - computeEllipses(); - } - - public void computeEllipses() { - if (mVignetteRep == null) { - return; - } - Matrix toImg = getScreenToImageMatrix(false); - Matrix toScr = new Matrix(); - toImg.invert(toScr); - - float[] c = new float[] { - mVignetteRep.getCenterX(), mVignetteRep.getCenterY() }; - if (Float.isNaN(c[0])) { - float cx = MasterImage.getImage().getOriginalBounds().width() / 2; - float cy = MasterImage.getImage().getOriginalBounds().height() / 2; - float rx = Math.min(cx, cy) * .8f; - float ry = rx; - mVignetteRep.setCenter(cx, cy); - mVignetteRep.setRadius(rx, ry); - - c[0] = cx; - c[1] = cy; - toScr.mapPoints(c); - if (getWidth() != 0) { - mElipse.setCenter(c[0], c[1]); - mElipse.setRadius(c[0] * 0.8f, c[1] * 0.8f); - } - } else { - - toScr.mapPoints(c); - - mElipse.setCenter(c[0], c[1]); - mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX()), - toScr.mapRadius(mVignetteRep.getRadiusY())); - } - mEditorVignette.commitLocalRepresentation(); - } - - public void setEditor(EditorVignette editorVignette) { - mEditorVignette = editorVignette; - } - - @Override - public void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - computeEllipses(); - } - - @Override - public void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (mVignetteRep == null) { - return; - } - Matrix toImg = getScreenToImageMatrix(false); - Matrix toScr = new Matrix(); - toImg.invert(toScr); - float[] c = new float[] { - mVignetteRep.getCenterX(), mVignetteRep.getCenterY() }; - toScr.mapPoints(c); - mElipse.setCenter(c[0], c[1]); - mElipse.setRadius(toScr.mapRadius(mVignetteRep.getRadiusX()), - toScr.mapRadius(mVignetteRep.getRadiusY())); - - mElipse.draw(canvas); - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/Line.java b/src/com/android/gallery3d/filtershow/imageshow/Line.java deleted file mode 100644 index a767bd809..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/Line.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -public interface Line { - void setPoint1(float x, float y); - void setPoint2(float x, float y); - float getPoint1X(); - float getPoint1Y(); - float getPoint2X(); - float getPoint2Y(); -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java b/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java deleted file mode 100644 index 92e57bfc1..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/MasterImage.java +++ /dev/null @@ -1,581 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.graphics.Bitmap; -import android.graphics.Matrix; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.RectF; -import android.net.Uri; -import android.os.Handler; -import android.os.Message; - -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.ImageFilter; -import com.android.gallery3d.filtershow.history.HistoryItem; -import com.android.gallery3d.filtershow.history.HistoryManager; -import com.android.gallery3d.filtershow.pipeline.Buffer; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.filtershow.pipeline.RenderingRequest; -import com.android.gallery3d.filtershow.pipeline.RenderingRequestCaller; -import com.android.gallery3d.filtershow.pipeline.SharedBuffer; -import com.android.gallery3d.filtershow.pipeline.SharedPreset; -import com.android.gallery3d.filtershow.state.StateAdapter; - -import java.util.Vector; - -public class MasterImage implements RenderingRequestCaller { - - private static final String LOGTAG = "MasterImage"; - private boolean DEBUG = false; - private static final boolean DISABLEZOOM = false; - public static final int SMALL_BITMAP_DIM = 160; - public static final int MAX_BITMAP_DIM = 900; - private static MasterImage sMasterImage = null; - - private boolean mSupportsHighRes = false; - - private ImageFilter mCurrentFilter = null; - private ImagePreset mPreset = null; - private ImagePreset mLoadedPreset = null; - private ImagePreset mGeometryOnlyPreset = null; - private ImagePreset mFiltersOnlyPreset = null; - - private SharedBuffer mPreviewBuffer = new SharedBuffer(); - private SharedPreset mPreviewPreset = new SharedPreset(); - - private Bitmap mOriginalBitmapSmall = null; - private Bitmap mOriginalBitmapLarge = null; - private Bitmap mOriginalBitmapHighres = null; - private int mOrientation; - private Rect mOriginalBounds; - private final Vector<ImageShow> mLoadListeners = new Vector<ImageShow>(); - private Uri mUri = null; - private int mZoomOrientation = ImageLoader.ORI_NORMAL; - - private Bitmap mGeometryOnlyBitmap = null; - private Bitmap mFiltersOnlyBitmap = null; - private Bitmap mPartialBitmap = null; - private Bitmap mHighresBitmap = null; - - private HistoryManager mHistory = null; - private StateAdapter mState = null; - - private FilterShowActivity mActivity = null; - - private Vector<ImageShow> mObservers = new Vector<ImageShow>(); - private FilterRepresentation mCurrentFilterRepresentation; - - private float mScaleFactor = 1.0f; - private float mMaxScaleFactor = 3.0f; // TODO: base this on the current view / image - private Point mTranslation = new Point(); - private Point mOriginalTranslation = new Point(); - - private Point mImageShowSize = new Point(); - - private boolean mShowsOriginal; - - private MasterImage() { - } - - // TODO: remove singleton - public static void setMaster(MasterImage master) { - sMasterImage = master; - } - - public static MasterImage getImage() { - if (sMasterImage == null) { - sMasterImage = new MasterImage(); - } - return sMasterImage; - } - - public Bitmap getOriginalBitmapSmall() { - return mOriginalBitmapSmall; - } - - public Bitmap getOriginalBitmapLarge() { - return mOriginalBitmapLarge; - } - - public Bitmap getOriginalBitmapHighres() { - return mOriginalBitmapHighres; - } - - public void setOriginalBitmapHighres(Bitmap mOriginalBitmapHighres) { - this.mOriginalBitmapHighres = mOriginalBitmapHighres; - } - - public int getOrientation() { - return mOrientation; - } - - public Rect getOriginalBounds() { - return mOriginalBounds; - } - - public void setOriginalBounds(Rect r) { - mOriginalBounds = r; - } - - public Uri getUri() { - return mUri; - } - - public void setUri(Uri uri) { - mUri = uri; - } - - public int getZoomOrientation() { - return mZoomOrientation; - } - - public void addListener(ImageShow imageShow) { - if (!mLoadListeners.contains(imageShow)) { - mLoadListeners.add(imageShow); - } - } - - public void warnListeners() { - mActivity.runOnUiThread(mWarnListenersRunnable); - } - - private Runnable mWarnListenersRunnable = new Runnable() { - @Override - public void run() { - for (int i = 0; i < mLoadListeners.size(); i++) { - ImageShow imageShow = mLoadListeners.elementAt(i); - imageShow.imageLoaded(); - } - invalidatePreview(); - } - }; - - public boolean loadBitmap(Uri uri, int size) { - setUri(uri); - mOrientation = ImageLoader.getMetadataOrientation(mActivity, uri); - Rect originalBounds = new Rect(); - mOriginalBitmapLarge = ImageLoader.loadOrientedConstrainedBitmap(uri, mActivity, - Math.min(MAX_BITMAP_DIM, size), - mOrientation, originalBounds); - setOriginalBounds(originalBounds); - if (mOriginalBitmapLarge == null) { - return false; - } - int sw = SMALL_BITMAP_DIM; - int sh = (int) (sw * (float) mOriginalBitmapLarge.getHeight() / mOriginalBitmapLarge - .getWidth()); - mOriginalBitmapSmall = Bitmap.createScaledBitmap(mOriginalBitmapLarge, sw, sh, true); - mZoomOrientation = mOrientation; - warnListeners(); - return true; - } - - public void setSupportsHighRes(boolean value) { - mSupportsHighRes = value; - } - - public void addObserver(ImageShow observer) { - if (mObservers.contains(observer)) { - return; - } - mObservers.add(observer); - } - - public void setActivity(FilterShowActivity activity) { - mActivity = activity; - } - - public FilterShowActivity getActivity() { - return mActivity; - } - - public synchronized ImagePreset getPreset() { - return mPreset; - } - - public synchronized ImagePreset getGeometryPreset() { - return mGeometryOnlyPreset; - } - - public synchronized ImagePreset getFiltersOnlyPreset() { - return mFiltersOnlyPreset; - } - - public synchronized void setPreset(ImagePreset preset, - FilterRepresentation change, - boolean addToHistory) { - if (DEBUG) { - preset.showFilters(); - } - mPreset = preset; - mPreset.fillImageStateAdapter(mState); - if (addToHistory) { - HistoryItem historyItem = new HistoryItem(mPreset, change); - mHistory.addHistoryItem(historyItem); - } - updatePresets(true); - mActivity.updateCategories(); - } - - public void onHistoryItemClick(int position) { - HistoryItem historyItem = mHistory.getItem(position); - // We need a copy from the history - ImagePreset newPreset = new ImagePreset(historyItem.getImagePreset()); - // don't need to add it to the history - setPreset(newPreset, historyItem.getFilterRepresentation(), false); - mHistory.setCurrentPreset(position); - } - - public HistoryManager getHistory() { - return mHistory; - } - - public StateAdapter getState() { - return mState; - } - - public void setHistoryManager(HistoryManager adapter) { - mHistory = adapter; - } - - public void setStateAdapter(StateAdapter adapter) { - mState = adapter; - } - - public void setCurrentFilter(ImageFilter filter) { - mCurrentFilter = filter; - } - - public ImageFilter getCurrentFilter() { - return mCurrentFilter; - } - - public synchronized boolean hasModifications() { - // TODO: We need to have a better same effects check to see if two - // presets are functionally the same. Right now, we are relying on a - // stricter check as equals(). - ImagePreset loadedPreset = getLoadedPreset(); - if (mPreset == null) { - if (loadedPreset == null) { - return false; - } else { - return loadedPreset.hasModifications(); - } - } else { - if (loadedPreset == null) { - return mPreset.hasModifications(); - } else { - return !mPreset.equals(loadedPreset); - } - } - } - - public SharedBuffer getPreviewBuffer() { - return mPreviewBuffer; - } - - public SharedPreset getPreviewPreset() { - return mPreviewPreset; - } - - public Bitmap getFilteredImage() { - mPreviewBuffer.swapConsumerIfNeeded(); // get latest bitmap - Buffer consumer = mPreviewBuffer.getConsumer(); - if (consumer != null) { - return consumer.getBitmap(); - } - return null; - } - - public Bitmap getFiltersOnlyImage() { - return mFiltersOnlyBitmap; - } - - public Bitmap getGeometryOnlyImage() { - return mGeometryOnlyBitmap; - } - - public Bitmap getPartialImage() { - return mPartialBitmap; - } - - public Bitmap getHighresImage() { - return mHighresBitmap; - } - - public void notifyObservers() { - for (ImageShow observer : mObservers) { - observer.invalidate(); - } - } - - public void updatePresets(boolean force) { - if (force || mGeometryOnlyPreset == null) { - ImagePreset newPreset = new ImagePreset(mPreset); - newPreset.setDoApplyFilters(false); - newPreset.setDoApplyGeometry(true); - if (force || mGeometryOnlyPreset == null - || !newPreset.same(mGeometryOnlyPreset)) { - mGeometryOnlyPreset = newPreset; - RenderingRequest.post(mActivity, getOriginalBitmapLarge(), - mGeometryOnlyPreset, RenderingRequest.GEOMETRY_RENDERING, this); - } - } - if (force || mFiltersOnlyPreset == null) { - ImagePreset newPreset = new ImagePreset(mPreset); - newPreset.setDoApplyFilters(true); - newPreset.setDoApplyGeometry(false); - if (force || mFiltersOnlyPreset == null - || !newPreset.same(mFiltersOnlyPreset)) { - mFiltersOnlyPreset = newPreset; - RenderingRequest.post(mActivity, MasterImage.getImage().getOriginalBitmapLarge(), - mFiltersOnlyPreset, RenderingRequest.FILTERS_RENDERING, this); - } - } - invalidatePreview(); - } - - public FilterRepresentation getCurrentFilterRepresentation() { - return mCurrentFilterRepresentation; - } - - public void setCurrentFilterRepresentation(FilterRepresentation currentFilterRepresentation) { - mCurrentFilterRepresentation = currentFilterRepresentation; - } - - public void invalidateFiltersOnly() { - mFiltersOnlyPreset = null; - updatePresets(false); - } - - public void invalidatePartialPreview() { - if (mPartialBitmap != null) { - mPartialBitmap = null; - notifyObservers(); - } - } - - public void invalidateHighresPreview() { - if (mHighresBitmap != null) { - mHighresBitmap = null; - notifyObservers(); - } - } - - public void invalidatePreview() { - mPreviewPreset.enqueuePreset(mPreset); - mPreviewBuffer.invalidate(); - invalidatePartialPreview(); - invalidateHighresPreview(); - needsUpdatePartialPreview(); - needsUpdateHighResPreview(); - mActivity.getProcessingService().updatePreviewBuffer(); - } - - public void setImageShowSize(int w, int h) { - if (mImageShowSize.x != w || mImageShowSize.y != h) { - mImageShowSize.set(w, h); - needsUpdatePartialPreview(); - needsUpdateHighResPreview(); - } - } - - private Matrix getImageToScreenMatrix(boolean reflectRotation) { - if (getOriginalBounds() == null || mImageShowSize.x == 0 || mImageShowSize.y == 0) { - return new Matrix(); - } - Matrix m = GeometryMathUtils.getImageToScreenMatrix(mPreset.getGeometryFilters(), - reflectRotation, getOriginalBounds(), mImageShowSize.x, mImageShowSize.y); - if (m == null) { - m = new Matrix(); - m.reset(); - return m; - } - Point translate = getTranslation(); - float scaleFactor = getScaleFactor(); - m.postTranslate(translate.x, translate.y); - m.postScale(scaleFactor, scaleFactor, mImageShowSize.x / 2.0f, mImageShowSize.y / 2.0f); - return m; - } - - private Matrix getScreenToImageMatrix(boolean reflectRotation) { - Matrix m = getImageToScreenMatrix(reflectRotation); - Matrix invert = new Matrix(); - m.invert(invert); - return invert; - } - - public void needsUpdateHighResPreview() { - if (!mSupportsHighRes) { - return; - } - if (mActivity.getProcessingService() == null) { - return; - } - mActivity.getProcessingService().postHighresRenderingRequest(mPreset, - getScaleFactor(), this); - invalidateHighresPreview(); - } - - public void needsUpdatePartialPreview() { - if (mPreset == null) { - return; - } - if (!mPreset.canDoPartialRendering()) { - invalidatePartialPreview(); - return; - } - Matrix m = getScreenToImageMatrix(true); - RectF r = new RectF(0, 0, mImageShowSize.x, mImageShowSize.y); - RectF dest = new RectF(); - m.mapRect(dest, r); - Rect bounds = new Rect(); - dest.roundOut(bounds); - RenderingRequest.post(mActivity, null, mPreset, RenderingRequest.PARTIAL_RENDERING, - this, bounds, new Rect(0, 0, mImageShowSize.x, mImageShowSize.y)); - invalidatePartialPreview(); - } - - @Override - public void available(RenderingRequest request) { - if (request.getBitmap() == null) { - return; - } - - boolean needsCheckModification = false; - if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) { - mGeometryOnlyBitmap = request.getBitmap(); - needsCheckModification = true; - } - if (request.getType() == RenderingRequest.FILTERS_RENDERING) { - mFiltersOnlyBitmap = request.getBitmap(); - notifyObservers(); - needsCheckModification = true; - } - if (request.getType() == RenderingRequest.PARTIAL_RENDERING - && request.getScaleFactor() == getScaleFactor()) { - mPartialBitmap = request.getBitmap(); - notifyObservers(); - needsCheckModification = true; - } - if (request.getType() == RenderingRequest.HIGHRES_RENDERING) { - mHighresBitmap = request.getBitmap(); - notifyObservers(); - needsCheckModification = true; - } - if (needsCheckModification) { - mActivity.enableSave(hasModifications()); - } - } - - public static void reset() { - sMasterImage = null; - } - - public float getScaleFactor() { - return mScaleFactor; - } - - public void setScaleFactor(float scaleFactor) { - if (DISABLEZOOM) { - return; - } - if (scaleFactor == mScaleFactor) { - return; - } - mScaleFactor = scaleFactor; - invalidatePartialPreview(); - } - - public Point getTranslation() { - return mTranslation; - } - - public void setTranslation(Point translation) { - if (DISABLEZOOM) { - mTranslation.x = 0; - mTranslation.y = 0; - return; - } - mTranslation.x = translation.x; - mTranslation.y = translation.y; - needsUpdatePartialPreview(); - } - - public Point getOriginalTranslation() { - return mOriginalTranslation; - } - - public void setOriginalTranslation(Point originalTranslation) { - if (DISABLEZOOM) { - return; - } - mOriginalTranslation.x = originalTranslation.x; - mOriginalTranslation.y = originalTranslation.y; - } - - public void resetTranslation() { - mTranslation.x = 0; - mTranslation.y = 0; - needsUpdatePartialPreview(); - } - - public Bitmap getThumbnailBitmap() { - return getOriginalBitmapSmall(); - } - - public Bitmap getLargeThumbnailBitmap() { - return getOriginalBitmapLarge(); - } - - public float getMaxScaleFactor() { - if (DISABLEZOOM) { - return 1; - } - return mMaxScaleFactor; - } - - public void setMaxScaleFactor(float maxScaleFactor) { - mMaxScaleFactor = maxScaleFactor; - } - - public boolean supportsHighRes() { - return mSupportsHighRes; - } - - public void setShowsOriginal(boolean value) { - mShowsOriginal = value; - notifyObservers(); - } - - public boolean showsOriginal() { - return mShowsOriginal; - } - - public void setLoadedPreset(ImagePreset preset) { - mLoadedPreset = preset; - } - - public ImagePreset getLoadedPreset() { - return mLoadedPreset; - } - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/Oval.java b/src/com/android/gallery3d/filtershow/imageshow/Oval.java deleted file mode 100644 index 28f278f1c..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/Oval.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -public interface Oval { - void setCenter(float x, float y); - void setRadius(float w, float h); - float getCenterX(); - float getCenterY(); - float getRadiusX(); - float getRadiusY(); - void setRadiusY(float y); - void setRadiusX(float x); - -} diff --git a/src/com/android/gallery3d/filtershow/imageshow/Spline.java b/src/com/android/gallery3d/filtershow/imageshow/Spline.java deleted file mode 100644 index 3c27a4d0f..000000000 --- a/src/com/android/gallery3d/filtershow/imageshow/Spline.java +++ /dev/null @@ -1,450 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.imageshow; - -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.drawable.Drawable; -import android.util.Log; - -import java.util.Collections; -import java.util.Vector; - -public class Spline { - private final Vector<ControlPoint> mPoints; - private static Drawable mCurveHandle; - private static int mCurveHandleSize; - private static int mCurveWidth; - - public static final int RGB = 0; - public static final int RED = 1; - public static final int GREEN = 2; - public static final int BLUE = 3; - private static final String LOGTAG = "Spline"; - - private final Paint gPaint = new Paint(); - private ControlPoint mCurrentControlPoint = null; - - public Spline() { - mPoints = new Vector<ControlPoint>(); - } - - public Spline(Spline spline) { - mPoints = new Vector<ControlPoint>(); - for (int i = 0; i < spline.mPoints.size(); i++) { - ControlPoint p = spline.mPoints.elementAt(i); - ControlPoint newPoint = new ControlPoint(p); - mPoints.add(newPoint); - if (spline.mCurrentControlPoint == p) { - mCurrentControlPoint = newPoint; - } - } - Collections.sort(mPoints); - } - - public static void setCurveHandle(Drawable drawable, int size) { - mCurveHandle = drawable; - mCurveHandleSize = size; - } - - public static void setCurveWidth(int width) { - mCurveWidth = width; - } - - public static int curveHandleSize() { - return mCurveHandleSize; - } - - public static int colorForCurve(int curveIndex) { - switch (curveIndex) { - case Spline.RED: - return Color.RED; - case GREEN: - return Color.GREEN; - case BLUE: - return Color.BLUE; - } - return Color.WHITE; - } - - public boolean sameValues(Spline other) { - if (this == other) { - return true; - } - if (other == null) { - return false; - } - - if (getNbPoints() != other.getNbPoints()) { - return false; - } - - for (int i = 0; i < getNbPoints(); i++) { - ControlPoint p = mPoints.elementAt(i); - ControlPoint otherPoint = other.mPoints.elementAt(i); - if (!p.sameValues(otherPoint)) { - return false; - } - } - return true; - } - - private void didMovePoint(ControlPoint point) { - mCurrentControlPoint = point; - } - - public void movePoint(int pick, float x, float y) { - if (pick < 0 || pick > mPoints.size() - 1) { - return; - } - ControlPoint point = mPoints.elementAt(pick); - point.x = x; - point.y = y; - didMovePoint(point); - } - - public boolean isOriginal() { - if (this.getNbPoints() != 2) { - return false; - } - if (mPoints.elementAt(0).x != 0 || mPoints.elementAt(0).y != 1) { - return false; - } - if (mPoints.elementAt(1).x != 1 || mPoints.elementAt(1).y != 0) { - return false; - } - return true; - } - - public void reset() { - mPoints.clear(); - addPoint(0.0f, 1.0f); - addPoint(1.0f, 0.0f); - } - - private void drawHandles(Canvas canvas, Drawable indicator, float centerX, float centerY) { - int left = (int) centerX - mCurveHandleSize / 2; - int top = (int) centerY - mCurveHandleSize / 2; - indicator.setBounds(left, top, left + mCurveHandleSize, top + mCurveHandleSize); - indicator.draw(canvas); - } - - public float[] getAppliedCurve() { - float[] curve = new float[256]; - ControlPoint[] points = new ControlPoint[mPoints.size()]; - for (int i = 0; i < mPoints.size(); i++) { - ControlPoint p = mPoints.get(i); - points[i] = new ControlPoint(p.x, p.y); - } - 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 = 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; - int pivot = 0; - for (int j = 0; j < points.length - 1; j++) { - if (x >= points[j].x && x <= points[j + 1].x) { - pivot = j; - } - } - cur = points[pivot]; - next = points[pivot + 1]; - if (x <= next.x) { - double x1 = cur.x; - double x2 = next.x; - double y1 = cur.y; - double y2 = next.y; - - // Use the second derivatives to apply the cubic spline - // equation: - double delta = (x2 - x1); - double delta2 = delta * delta; - double b = (x - x1) / delta; - double a = 1 - b; - double ta = a * y1; - double tb = b * y2; - double tc = (a * a * a - a) * derivatives[pivot]; - double td = (b * b * b - b) * derivatives[pivot + 1]; - double y = ta + tb + (delta2 / 6) * (tc + td); - if (y > 1.0f) { - y = 1.0f; - } - if (y < 0) { - y = 0; - } - curve[i] = (float) (1.0f - y); - } else { - curve[i] = 1.0f - next.y; - } - } - return curve; - } - - private void drawGrid(Canvas canvas, float w, float h) { - // Grid - gPaint.setARGB(128, 150, 150, 150); - gPaint.setStrokeWidth(1); - - float stepH = h / 9; - float stepW = w / 9; - - // central diagonal - gPaint.setARGB(255, 100, 100, 100); - gPaint.setStrokeWidth(2); - canvas.drawLine(0, h, w, 0, gPaint); - - gPaint.setARGB(128, 200, 200, 200); - gPaint.setStrokeWidth(4); - stepH = h / 3; - stepW = w / 3; - for (int j = 1; j < 3; j++) { - canvas.drawLine(0, j * stepH, w, j * stepH, gPaint); - canvas.drawLine(j * stepW, 0, j * stepW, h, gPaint); - } - canvas.drawLine(0, 0, 0, h, gPaint); - canvas.drawLine(w, 0, w, h, gPaint); - canvas.drawLine(0, 0, w, 0, gPaint); - canvas.drawLine(0, h, w, h, gPaint); - } - - public void draw(Canvas canvas, int color, int canvasWidth, int canvasHeight, - boolean showHandles, boolean moving) { - float w = canvasWidth - mCurveHandleSize; - float h = canvasHeight - mCurveHandleSize; - float dx = mCurveHandleSize / 2; - float dy = mCurveHandleSize / 2; - - // The cubic spline equation is (from numerical recipes in C): - // y = a(y_i) + b(y_i+1) + c(y"_i) + d(y"_i+1) - // - // with c(y"_i) and d(y"_i+1): - // c(y"_i) = 1/6 (a^3 - a) delta^2 (y"_i) - // d(y"_i_+1) = 1/6 (b^3 - b) delta^2 (y"_i+1) - // - // and delta: - // delta = x_i+1 - x_i - // - // To find the second derivatives y", we can rearrange the equation as: - // A(y"_i-1) + B(y"_i) + C(y"_i+1) = D - // - // With the coefficients A, B, C, D: - // A = 1/6 (x_i - x_i-1) - // B = 1/3 (x_i+1 - x_i-1) - // C = 1/6 (x_i+1 - x_i) - // D = (y_i+1 - y_i)/(x_i+1 - x_i) - (y_i - y_i-1)/(x_i - x_i-1) - // - // We can now easily solve the equation to find the second derivatives: - ControlPoint[] points = new ControlPoint[mPoints.size()]; - for (int i = 0; i < mPoints.size(); i++) { - ControlPoint p = mPoints.get(i); - points[i] = new ControlPoint(p.x * w, p.y * h); - } - double[] derivatives = solveSystem(points); - - Path path = new Path(); - path.moveTo(0, points[0].y); - for (int i = 0; i < points.length - 1; i++) { - double x1 = points[i].x; - double x2 = points[i + 1].x; - double y1 = points[i].y; - double y2 = points[i + 1].y; - - for (double x = x1; x < x2; x += 20) { - // Use the second derivatives to apply the cubic spline - // equation: - double delta = (x2 - x1); - double delta2 = delta * delta; - double b = (x - x1) / delta; - double a = 1 - b; - double ta = a * y1; - double tb = b * y2; - double tc = (a * a * a - a) * derivatives[i]; - double td = (b * b * b - b) * derivatives[i + 1]; - double y = ta + tb + (delta2 / 6) * (tc + td); - if (y > h) { - y = h; - } - if (y < 0) { - y = 0; - } - path.lineTo((float) x, (float) y); - } - } - canvas.save(); - canvas.translate(dx, dy); - drawGrid(canvas, w, h); - ControlPoint lastPoint = points[points.length - 1]; - path.lineTo(lastPoint.x, lastPoint.y); - path.lineTo(w, lastPoint.y); - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setFilterBitmap(true); - paint.setDither(true); - paint.setStyle(Paint.Style.STROKE); - int curveWidth = mCurveWidth; - if (showHandles) { - curveWidth *= 1.5; - } - paint.setStrokeWidth(curveWidth + 2); - paint.setColor(Color.BLACK); - canvas.drawPath(path, paint); - - if (moving && mCurrentControlPoint != null) { - float px = mCurrentControlPoint.x * w; - float py = mCurrentControlPoint.y * h; - paint.setStrokeWidth(3); - paint.setColor(Color.BLACK); - canvas.drawLine(px, py, px, h, paint); - canvas.drawLine(0, py, px, py, paint); - paint.setStrokeWidth(1); - paint.setColor(color); - canvas.drawLine(px, py, px, h, paint); - canvas.drawLine(0, py, px, py, paint); - } - - paint.setStrokeWidth(curveWidth); - paint.setColor(color); - canvas.drawPath(path, paint); - if (showHandles) { - for (int i = 0; i < points.length; i++) { - float x = points[i].x; - float y = points[i].y; - drawHandles(canvas, mCurveHandle, x, y); - } - } - canvas.restore(); - } - - double[] solveSystem(ControlPoint[] points) { - int n = points.length; - double[][] system = new double[n][3]; - double[] result = new double[n]; // d - double[] solution = new double[n]; // returned coefficients - system[0][1] = 1; - system[n - 1][1] = 1; - double d6 = 1.0 / 6.0; - double d3 = 1.0 / 3.0; - - // let's create a tridiagonal matrix representing the - // system, and apply the TDMA algorithm to solve it - // (see http://en.wikipedia.org/wiki/Tridiagonal_matrix_algorithm) - for (int i = 1; i < n - 1; i++) { - double deltaPrevX = points[i].x - points[i - 1].x; - double deltaX = points[i + 1].x - points[i - 1].x; - double deltaNextX = points[i + 1].x - points[i].x; - double deltaNextY = points[i + 1].y - points[i].y; - double deltaPrevY = points[i].y - points[i - 1].y; - system[i][0] = d6 * deltaPrevX; // a_i - system[i][1] = d3 * deltaX; // b_i - system[i][2] = d6 * deltaNextX; // c_i - result[i] = (deltaNextY / deltaNextX) - (deltaPrevY / deltaPrevX); // d_i - } - - // Forward sweep - for (int i = 1; i < n; i++) { - // m = a_i/b_i-1 - double m = system[i][0] / system[i - 1][1]; - // b_i = b_i - m(c_i-1) - system[i][1] = system[i][1] - m * system[i - 1][2]; - // d_i = d_i - m(d_i-1) - result[i] = result[i] - m * result[i - 1]; - } - - // Back substitution - solution[n - 1] = result[n - 1] / system[n - 1][1]; - for (int i = n - 2; i >= 0; --i) { - solution[i] = (result[i] - system[i][2] * solution[i + 1]) / system[i][1]; - } - return solution; - } - - public int addPoint(float x, float y) { - return addPoint(new ControlPoint(x, y)); - } - - public int addPoint(ControlPoint v) { - mPoints.add(v); - Collections.sort(mPoints); - return mPoints.indexOf(v); - } - - public void deletePoint(int n) { - mPoints.remove(n); - if (mPoints.size() < 2) { - reset(); - } - Collections.sort(mPoints); - } - - public int getNbPoints() { - return mPoints.size(); - } - - public ControlPoint getPoint(int n) { - return mPoints.elementAt(n); - } - - public boolean isPointContained(float x, int n) { - for (int i = 0; i < n; i++) { - ControlPoint point = mPoints.elementAt(i); - if (point.x > x) { - return false; - } - } - for (int i = n + 1; i < mPoints.size(); i++) { - ControlPoint point = mPoints.elementAt(i); - if (point.x < x) { - return false; - } - } - return true; - } - - public Spline copy() { - Spline spline = new Spline(); - for (int i = 0; i < mPoints.size(); i++) { - ControlPoint point = mPoints.elementAt(i); - spline.addPoint(point.copy()); - } - return spline; - } - - public void show() { - Log.v(LOGTAG, "show curve " + this); - for (int i = 0; i < mPoints.size(); i++) { - ControlPoint point = mPoints.elementAt(i); - Log.v(LOGTAG, "point " + i + " is (" + point.x + ", " + point.y + ")"); - } - } - -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java b/src/com/android/gallery3d/filtershow/pipeline/Buffer.java deleted file mode 100644 index 744451229..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/Buffer.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; -import android.support.v8.renderscript.Allocation; -import android.support.v8.renderscript.RenderScript; - -public class Buffer { - private static final String LOGTAG = "Buffer"; - private Bitmap mBitmap; - private Allocation mAllocation; - private boolean mUseAllocation = false; - private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; - private ImagePreset mPreset; - - public Buffer(Bitmap bitmap) { - RenderScript rs = CachingPipeline.getRenderScriptContext(); - if (bitmap != null) { - mBitmap = bitmap.copy(BITMAP_CONFIG, true); - } - if (mUseAllocation) { - // TODO: recreate the allocation when the RS context changes - mAllocation = Allocation.createFromBitmap(rs, mBitmap, - Allocation.MipmapControl.MIPMAP_NONE, - Allocation.USAGE_SHARED | Allocation.USAGE_SCRIPT); - } - } - - public void setBitmap(Bitmap bitmap) { - mBitmap = bitmap.copy(BITMAP_CONFIG, true); - } - - public Bitmap getBitmap() { - return mBitmap; - } - - public Allocation getAllocation() { - return mAllocation; - } - - public void sync() { - if (mUseAllocation) { - mAllocation.copyTo(mBitmap); - } - } - - public ImagePreset getPreset() { - return mPreset; - } - - public void setPreset(ImagePreset preset) { - if ((mPreset == null) || (!mPreset.same(preset))) { - mPreset = new ImagePreset(preset); - } else { - mPreset.updateWith(preset); - } - } -} - diff --git a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java b/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java deleted file mode 100644 index e0269e9bb..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/CacheProcessing.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; -import android.util.Log; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; - -import java.util.Vector; - -public class CacheProcessing { - private static final String LOGTAG = "CacheProcessing"; - private static final boolean DEBUG = false; - private Vector<CacheStep> mSteps = new Vector<CacheStep>(); - - static class CacheStep { - FilterRepresentation representation; - Bitmap cache; - } - - public Bitmap process(Bitmap originalBitmap, - Vector<FilterRepresentation> filters, - FilterEnvironment environment) { - - if (filters.size() == 0) { - return originalBitmap; - } - - // New set of filters, let's clear the cache and rebuild it. - if (filters.size() != mSteps.size()) { - mSteps.clear(); - for (int i = 0; i < filters.size(); i++) { - FilterRepresentation representation = filters.elementAt(i); - CacheStep step = new CacheStep(); - step.representation = representation.copy(); - mSteps.add(step); - } - } - - if (DEBUG) { - displayFilters(filters); - } - - // First, let's find how similar we are in our cache - // compared to the current list of filters - int similarUpToIndex = -1; - for (int i = 0; i < filters.size(); i++) { - FilterRepresentation representation = filters.elementAt(i); - CacheStep step = mSteps.elementAt(i); - boolean similar = step.representation.equals(representation); - if (similar) { - similarUpToIndex = i; - } else { - break; - } - } - if (DEBUG) { - Log.v(LOGTAG, "similar up to index " + similarUpToIndex); - } - - // Now, let's get the earliest cached result in our pipeline - Bitmap cacheBitmap = null; - int findBaseImageIndex = similarUpToIndex; - if (findBaseImageIndex > -1) { - while (findBaseImageIndex > 0 - && mSteps.elementAt(findBaseImageIndex).cache == null) { - findBaseImageIndex--; - } - cacheBitmap = mSteps.elementAt(findBaseImageIndex).cache; - } - boolean emptyStack = false; - if (cacheBitmap == null) { - emptyStack = true; - // Damn, it's an empty stack, we have to start from scratch - // TODO: use a bitmap cache + RS allocation instead of Bitmap.copy() - cacheBitmap = originalBitmap.copy(Bitmap.Config.ARGB_8888, true); - if (findBaseImageIndex > -1) { - FilterRepresentation representation = filters.elementAt(findBaseImageIndex); - if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) { - cacheBitmap = environment.applyRepresentation(representation, cacheBitmap); - } - mSteps.elementAt(findBaseImageIndex).representation = representation.copy(); - mSteps.elementAt(findBaseImageIndex).cache = cacheBitmap; - } - if (DEBUG) { - Log.v(LOGTAG, "empty stack"); - } - } - - // Ok, so sadly the earliest cached result is before the index we want. - // We have to rebuild a new result for this position, and then cache it. - if (findBaseImageIndex != similarUpToIndex) { - if (DEBUG) { - Log.v(LOGTAG, "rebuild cacheBitmap from " + findBaseImageIndex - + " to " + similarUpToIndex); - } - // rebuild the cache image for this step - if (!emptyStack) { - cacheBitmap = cacheBitmap.copy(Bitmap.Config.ARGB_8888, true); - } else { - // if it was an empty stack, we already applied it - findBaseImageIndex ++; - } - for (int i = findBaseImageIndex; i <= similarUpToIndex; i++) { - FilterRepresentation representation = filters.elementAt(i); - if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) { - cacheBitmap = environment.applyRepresentation(representation, cacheBitmap); - } - if (DEBUG) { - Log.v(LOGTAG, " - " + i + " => apply " + representation.getName()); - } - } - // Let's cache it! - mSteps.elementAt(similarUpToIndex).cache = cacheBitmap; - } - - if (DEBUG) { - Log.v(LOGTAG, "process pipeline from " + similarUpToIndex - + " to " + (filters.size() - 1)); - } - - // Now we are good to go, let's use the cacheBitmap as a starting point - for (int i = similarUpToIndex + 1; i < filters.size(); i++) { - FilterRepresentation representation = filters.elementAt(i); - CacheStep currentStep = mSteps.elementAt(i); - cacheBitmap = cacheBitmap.copy(Bitmap.Config.ARGB_8888, true); - if (representation.getFilterType() != FilterRepresentation.TYPE_GEOMETRY) { - cacheBitmap = environment.applyRepresentation(representation, cacheBitmap); - } - currentStep.representation = representation.copy(); - currentStep.cache = cacheBitmap; - if (DEBUG) { - Log.v(LOGTAG, " - " + i + " => apply " + representation.getName()); - } - } - - if (DEBUG) { - Log.v(LOGTAG, "now let's cleanup the cache..."); - displayNbBitmapsInCache(); - } - - // Let's see if we can cleanup the cache for unused bitmaps - for (int i = 0; i < similarUpToIndex; i++) { - CacheStep currentStep = mSteps.elementAt(i); - currentStep.cache = null; - } - - if (DEBUG) { - Log.v(LOGTAG, "cleanup done..."); - displayNbBitmapsInCache(); - } - return cacheBitmap; - } - - private void displayFilters(Vector<FilterRepresentation> filters) { - Log.v(LOGTAG, "------>>>"); - for (int i = 0; i < filters.size(); i++) { - FilterRepresentation representation = filters.elementAt(i); - CacheStep step = mSteps.elementAt(i); - boolean similar = step.representation.equals(representation); - Log.v(LOGTAG, "[" + i + "] - " + representation.getName() - + " similar rep ? " + (similar ? "YES" : "NO") - + " -- bitmap: " + step.cache); - } - Log.v(LOGTAG, "<<<------"); - } - - private void displayNbBitmapsInCache() { - int nbBitmapsCached = 0; - for (int i = 0; i < mSteps.size(); i++) { - CacheStep step = mSteps.elementAt(i); - if (step.cache != null) { - nbBitmapsCached++; - } - } - Log.v(LOGTAG, "nb bitmaps in cache: " + nbBitmapsCached + " / " + mSteps.size()); - } - -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java b/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java deleted file mode 100644 index fc0d6ce49..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/CachingPipeline.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.support.v8.renderscript.Allocation; -import android.support.v8.renderscript.RenderScript; -import android.util.Log; - -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -import java.util.Vector; - -public class CachingPipeline implements PipelineInterface { - private static final String LOGTAG = "CachingPipeline"; - private boolean DEBUG = false; - - private static final Bitmap.Config BITMAP_CONFIG = Bitmap.Config.ARGB_8888; - - private static volatile RenderScript sRS = null; - - private FiltersManager mFiltersManager = null; - private volatile Bitmap mOriginalBitmap = null; - private volatile Bitmap mResizedOriginalBitmap = null; - - private FilterEnvironment mEnvironment = new FilterEnvironment(); - private CacheProcessing mCachedProcessing = new CacheProcessing(); - - - private volatile Allocation mOriginalAllocation = null; - private volatile Allocation mFiltersOnlyOriginalAllocation = null; - - protected volatile Allocation mInPixelsAllocation; - protected volatile Allocation mOutPixelsAllocation; - private volatile int mWidth = 0; - private volatile int mHeight = 0; - - private volatile float mPreviewScaleFactor = 1.0f; - private volatile float mHighResPreviewScaleFactor = 1.0f; - private volatile String mName = ""; - - public CachingPipeline(FiltersManager filtersManager, String name) { - mFiltersManager = filtersManager; - mName = name; - } - - public static synchronized RenderScript getRenderScriptContext() { - return sRS; - } - - public static synchronized void createRenderscriptContext(Context context) { - if (sRS != null) { - Log.w(LOGTAG, "A prior RS context exists when calling setRenderScriptContext"); - destroyRenderScriptContext(); - } - sRS = RenderScript.create(context); - } - - public static synchronized void destroyRenderScriptContext() { - if (sRS != null) { - sRS.destroy(); - } - sRS = null; - } - - public void stop() { - mEnvironment.setStop(true); - } - - public synchronized void reset() { - synchronized (CachingPipeline.class) { - if (getRenderScriptContext() == null) { - return; - } - mOriginalBitmap = null; // just a reference to the bitmap in ImageLoader - if (mResizedOriginalBitmap != null) { - mResizedOriginalBitmap.recycle(); - mResizedOriginalBitmap = null; - } - if (mOriginalAllocation != null) { - mOriginalAllocation.destroy(); - mOriginalAllocation = null; - } - if (mFiltersOnlyOriginalAllocation != null) { - mFiltersOnlyOriginalAllocation.destroy(); - mFiltersOnlyOriginalAllocation = null; - } - mPreviewScaleFactor = 1.0f; - mHighResPreviewScaleFactor = 1.0f; - - destroyPixelAllocations(); - } - } - - public Resources getResources() { - return sRS.getApplicationContext().getResources(); - } - - private synchronized void destroyPixelAllocations() { - if (DEBUG) { - Log.v(LOGTAG, "destroyPixelAllocations in " + getName()); - } - if (mInPixelsAllocation != null) { - mInPixelsAllocation.destroy(); - mInPixelsAllocation = null; - } - if (mOutPixelsAllocation != null) { - mOutPixelsAllocation.destroy(); - mOutPixelsAllocation = null; - } - mWidth = 0; - mHeight = 0; - } - - private String getType(RenderingRequest request) { - if (request.getType() == RenderingRequest.ICON_RENDERING) { - return "ICON_RENDERING"; - } - if (request.getType() == RenderingRequest.FILTERS_RENDERING) { - return "FILTERS_RENDERING"; - } - if (request.getType() == RenderingRequest.FULL_RENDERING) { - return "FULL_RENDERING"; - } - if (request.getType() == RenderingRequest.GEOMETRY_RENDERING) { - return "GEOMETRY_RENDERING"; - } - if (request.getType() == RenderingRequest.PARTIAL_RENDERING) { - return "PARTIAL_RENDERING"; - } - if (request.getType() == RenderingRequest.HIGHRES_RENDERING) { - return "HIGHRES_RENDERING"; - } - return "UNKNOWN TYPE!"; - } - - private void setupEnvironment(ImagePreset preset, boolean highResPreview) { - mEnvironment.setPipeline(this); - mEnvironment.setFiltersManager(mFiltersManager); - if (highResPreview) { - mEnvironment.setScaleFactor(mHighResPreviewScaleFactor); - } else { - mEnvironment.setScaleFactor(mPreviewScaleFactor); - } - mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); - mEnvironment.setImagePreset(preset); - mEnvironment.setStop(false); - } - - public void setOriginal(Bitmap bitmap) { - mOriginalBitmap = bitmap; - Log.v(LOGTAG,"setOriginal, size " + bitmap.getWidth() + " x " + bitmap.getHeight()); - ImagePreset preset = MasterImage.getImage().getPreset(); - setupEnvironment(preset, false); - updateOriginalAllocation(preset); - } - - private synchronized boolean updateOriginalAllocation(ImagePreset preset) { - Bitmap originalBitmap = mOriginalBitmap; - - if (originalBitmap == null) { - return false; - } - - RenderScript RS = getRenderScriptContext(); - - Allocation filtersOnlyOriginalAllocation = mFiltersOnlyOriginalAllocation; - mFiltersOnlyOriginalAllocation = Allocation.createFromBitmap(RS, originalBitmap, - Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); - if (filtersOnlyOriginalAllocation != null) { - filtersOnlyOriginalAllocation.destroy(); - } - - Allocation originalAllocation = mOriginalAllocation; - mResizedOriginalBitmap = preset.applyGeometry(originalBitmap, mEnvironment); - mOriginalAllocation = Allocation.createFromBitmap(RS, mResizedOriginalBitmap, - Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); - if (originalAllocation != null) { - originalAllocation.destroy(); - } - - return true; - } - - public void renderHighres(RenderingRequest request) { - synchronized (CachingPipeline.class) { - if (getRenderScriptContext() == null) { - return; - } - ImagePreset preset = request.getImagePreset(); - setupEnvironment(preset, false); - Bitmap bitmap = MasterImage.getImage().getOriginalBitmapHighres(); - if (bitmap == null) { - return; - } - // TODO: use a cache of bitmaps - bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true); - bitmap = preset.applyGeometry(bitmap, mEnvironment); - - mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); - Bitmap bmp = preset.apply(bitmap, mEnvironment); - if (!mEnvironment.needsStop()) { - request.setBitmap(bmp); - } - mFiltersManager.freeFilterResources(preset); - } - } - - public synchronized void render(RenderingRequest request) { - synchronized (CachingPipeline.class) { - if (getRenderScriptContext() == null) { - return; - } - if (((request.getType() != RenderingRequest.PARTIAL_RENDERING - && request.getType() != RenderingRequest.HIGHRES_RENDERING) - && request.getBitmap() == null) - || request.getImagePreset() == null) { - return; - } - - if (DEBUG) { - Log.v(LOGTAG, "render image of type " + getType(request)); - } - - Bitmap bitmap = request.getBitmap(); - ImagePreset preset = request.getImagePreset(); - setupEnvironment(preset, - request.getType() != RenderingRequest.HIGHRES_RENDERING); - mFiltersManager.freeFilterResources(preset); - - if (request.getType() == RenderingRequest.PARTIAL_RENDERING) { - MasterImage master = MasterImage.getImage(); - bitmap = ImageLoader.getScaleOneImageForPreset(master.getActivity(), - master.getUri(), request.getBounds(), - request.getDestination()); - if (bitmap == null) { - Log.w(LOGTAG, "could not get bitmap for: " + getType(request)); - return; - } - } - - if (request.getType() == RenderingRequest.HIGHRES_RENDERING) { - bitmap = MasterImage.getImage().getOriginalBitmapHighres(); - if (bitmap != null) { - bitmap = preset.applyGeometry(bitmap, mEnvironment); - } - } - - if (request.getType() == RenderingRequest.FULL_RENDERING - || request.getType() == RenderingRequest.GEOMETRY_RENDERING - || request.getType() == RenderingRequest.FILTERS_RENDERING) { - updateOriginalAllocation(preset); - } - - if (DEBUG) { - Log.v(LOGTAG, "after update, req bitmap (" + bitmap.getWidth() + "x" + bitmap.getHeight() - + " ? resizeOriginal (" + mResizedOriginalBitmap.getWidth() + "x" - + mResizedOriginalBitmap.getHeight()); - } - - if (request.getType() == RenderingRequest.FULL_RENDERING - || request.getType() == RenderingRequest.GEOMETRY_RENDERING) { - mOriginalAllocation.copyTo(bitmap); - } else if (request.getType() == RenderingRequest.FILTERS_RENDERING) { - mFiltersOnlyOriginalAllocation.copyTo(bitmap); - } - - if (request.getType() == RenderingRequest.FULL_RENDERING - || request.getType() == RenderingRequest.FILTERS_RENDERING - || request.getType() == RenderingRequest.ICON_RENDERING - || request.getType() == RenderingRequest.PARTIAL_RENDERING - || request.getType() == RenderingRequest.HIGHRES_RENDERING - || request.getType() == RenderingRequest.STYLE_ICON_RENDERING) { - - if (request.getType() == RenderingRequest.ICON_RENDERING) { - mEnvironment.setQuality(FilterEnvironment.QUALITY_ICON); - } else { - mEnvironment.setQuality(FilterEnvironment.QUALITY_PREVIEW); - } - - Bitmap bmp = preset.apply(bitmap, mEnvironment); - if (!mEnvironment.needsStop()) { - request.setBitmap(bmp); - } - mFiltersManager.freeFilterResources(preset); - } - } - } - - public synchronized void renderImage(ImagePreset preset, Allocation in, Allocation out) { - synchronized (CachingPipeline.class) { - if (getRenderScriptContext() == null) { - return; - } - setupEnvironment(preset, false); - mFiltersManager.freeFilterResources(preset); - preset.applyFilters(-1, -1, in, out, mEnvironment); - boolean copyOut = false; - if (preset.nbFilters() > 0) { - copyOut = true; - } - preset.applyBorder(in, out, copyOut, mEnvironment); - } - } - - public synchronized Bitmap renderFinalImage(Bitmap bitmap, ImagePreset preset) { - synchronized (CachingPipeline.class) { - if (getRenderScriptContext() == null) { - return bitmap; - } - setupEnvironment(preset, false); - mEnvironment.setQuality(FilterEnvironment.QUALITY_FINAL); - mEnvironment.setScaleFactor(1.0f); - mFiltersManager.freeFilterResources(preset); - bitmap = preset.applyGeometry(bitmap, mEnvironment); - bitmap = preset.apply(bitmap, mEnvironment); - return bitmap; - } - } - - public Bitmap renderGeometryIcon(Bitmap bitmap, ImagePreset preset) { - return GeometryMathUtils.applyGeometryRepresentations(preset.getGeometryFilters(), bitmap); - } - - public void compute(SharedBuffer buffer, ImagePreset preset, int type) { - if (getRenderScriptContext() == null) { - return; - } - setupEnvironment(preset, false); - Vector<FilterRepresentation> filters = preset.getFilters(); - Bitmap result = mCachedProcessing.process(mOriginalBitmap, filters, mEnvironment); - buffer.setProducer(result); - } - - public synchronized void computeOld(SharedBuffer buffer, ImagePreset preset, int type) { - synchronized (CachingPipeline.class) { - if (getRenderScriptContext() == null) { - return; - } - if (DEBUG) { - Log.v(LOGTAG, "compute preset " + preset); - preset.showFilters(); - } - - String thread = Thread.currentThread().getName(); - long time = System.currentTimeMillis(); - setupEnvironment(preset, false); - mFiltersManager.freeFilterResources(preset); - - Bitmap resizedOriginalBitmap = mResizedOriginalBitmap; - if (updateOriginalAllocation(preset) || buffer.getProducer() == null) { - resizedOriginalBitmap = mResizedOriginalBitmap; - buffer.setProducer(resizedOriginalBitmap); - mEnvironment.cache(buffer.getProducer()); - } - - Bitmap bitmap = buffer.getProducer().getBitmap(); - long time2 = System.currentTimeMillis(); - - if (bitmap == null || (bitmap.getWidth() != resizedOriginalBitmap.getWidth()) - || (bitmap.getHeight() != resizedOriginalBitmap.getHeight())) { - mEnvironment.cache(buffer.getProducer()); - buffer.setProducer(resizedOriginalBitmap); - bitmap = buffer.getProducer().getBitmap(); - } - mOriginalAllocation.copyTo(bitmap); - - Bitmap tmpbitmap = preset.apply(bitmap, mEnvironment); - if (tmpbitmap != bitmap) { - mEnvironment.cache(buffer.getProducer()); - buffer.setProducer(tmpbitmap); - } - - mFiltersManager.freeFilterResources(preset); - - time = System.currentTimeMillis() - time; - time2 = System.currentTimeMillis() - time2; - if (DEBUG) { - Log.v(LOGTAG, "Applying type " + type + " filters to bitmap " - + bitmap + " (" + bitmap.getWidth() + " x " + bitmap.getHeight() - + ") took " + time + " ms, " + time2 + " ms for the filter, on thread " + thread); - } - } - } - - public boolean needsRepaint() { - SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer(); - return buffer.checkRepaintNeeded(); - } - - public void setPreviewScaleFactor(float previewScaleFactor) { - mPreviewScaleFactor = previewScaleFactor; - } - - public void setHighResPreviewScaleFactor(float highResPreviewScaleFactor) { - mHighResPreviewScaleFactor = highResPreviewScaleFactor; - } - - public synchronized boolean isInitialized() { - return getRenderScriptContext() != null && mOriginalBitmap != null; - } - - public boolean prepareRenderscriptAllocations(Bitmap bitmap) { - RenderScript RS = getRenderScriptContext(); - boolean needsUpdate = false; - if (mOutPixelsAllocation == null || mInPixelsAllocation == null || - bitmap.getWidth() != mWidth || bitmap.getHeight() != mHeight) { - destroyPixelAllocations(); - Bitmap bitmapBuffer = bitmap; - if (bitmap.getConfig() == null || bitmap.getConfig() != BITMAP_CONFIG) { - bitmapBuffer = bitmap.copy(BITMAP_CONFIG, true); - } - mOutPixelsAllocation = Allocation.createFromBitmap(RS, bitmapBuffer, - Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT); - mInPixelsAllocation = Allocation.createTyped(RS, - mOutPixelsAllocation.getType()); - needsUpdate = true; - } - if (RS != null) { - mInPixelsAllocation.copyFrom(bitmap); - } - if (bitmap.getWidth() != mWidth - || bitmap.getHeight() != mHeight) { - mWidth = bitmap.getWidth(); - mHeight = bitmap.getHeight(); - needsUpdate = true; - } - if (DEBUG) { - Log.v(LOGTAG, "prepareRenderscriptAllocations: " + needsUpdate + " in " + getName()); - } - return needsUpdate; - } - - public synchronized Allocation getInPixelsAllocation() { - return mInPixelsAllocation; - } - - public synchronized Allocation getOutPixelsAllocation() { - return mOutPixelsAllocation; - } - - public String getName() { - return mName; - } - - public RenderScript getRSContext() { - return CachingPipeline.getRenderScriptContext(); - } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java b/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java deleted file mode 100644 index 4fac956be..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/FilterEnvironment.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.support.v8.renderscript.Allocation; - -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation.Rotation; -import com.android.gallery3d.filtershow.filters.FiltersManagerInterface; -import com.android.gallery3d.filtershow.filters.ImageFilter; - -import java.lang.ref.WeakReference; -import java.util.HashMap; - -public class FilterEnvironment { - private static final String LOGTAG = "FilterEnvironment"; - private ImagePreset mImagePreset; - private float mScaleFactor; - private int mQuality; - private FiltersManagerInterface mFiltersManager; - private PipelineInterface mPipeline; - private volatile boolean mStop = false; - - public static final int QUALITY_ICON = 0; - public static final int QUALITY_PREVIEW = 1; - public static final int QUALITY_FINAL = 2; - - public synchronized boolean needsStop() { - return mStop; - } - - public synchronized void setStop(boolean stop) { - this.mStop = stop; - } - - private HashMap<Long, WeakReference<Bitmap>> - bitmapCach = new HashMap<Long, WeakReference<Bitmap>>(); - - private HashMap<Integer, Integer> - generalParameters = new HashMap<Integer, Integer>(); - - public void cache(Buffer buffer) { - if (buffer == null) { - return; - } - Bitmap bitmap = buffer.getBitmap(); - if (bitmap == null) { - return; - } - Long key = calcKey(bitmap.getWidth(), bitmap.getHeight()); - bitmapCach.put(key, new WeakReference<Bitmap>(bitmap)); - } - - public Bitmap getBitmap(int w, int h) { - Long key = calcKey(w, h); - WeakReference<Bitmap> ref = bitmapCach.remove(key); - Bitmap bitmap = null; - if (ref != null) { - bitmap = ref.get(); - } - if (bitmap == null) { - bitmap = Bitmap.createBitmap( - w, h, Bitmap.Config.ARGB_8888); - } - return bitmap; - } - - private Long calcKey(long w, long h) { - return (w << 32) | (h << 32); - } - - public void setImagePreset(ImagePreset imagePreset) { - mImagePreset = imagePreset; - } - - public ImagePreset getImagePreset() { - return mImagePreset; - } - - public void setScaleFactor(float scaleFactor) { - mScaleFactor = scaleFactor; - } - - public float getScaleFactor() { - return mScaleFactor; - } - - public void setQuality(int quality) { - mQuality = quality; - } - - public int getQuality() { - return mQuality; - } - - public void setFiltersManager(FiltersManagerInterface filtersManager) { - mFiltersManager = filtersManager; - } - - public FiltersManagerInterface getFiltersManager() { - return mFiltersManager; - } - - public void applyRepresentation(FilterRepresentation representation, - Allocation in, Allocation out) { - ImageFilter filter = mFiltersManager.getFilterForRepresentation(representation); - filter.useRepresentation(representation); - filter.setEnvironment(this); - if (filter.supportsAllocationInput()) { - filter.apply(in, out); - } - filter.setGeneralParameters(); - filter.setEnvironment(null); - } - - public Bitmap applyRepresentation(FilterRepresentation representation, Bitmap bitmap) { - if (representation instanceof FilterUserPresetRepresentation) { - // we allow instances of FilterUserPresetRepresentation in a preset only to know if one - // has been applied (so we can show this in the UI). But as all the filters in them are - // applied directly they do not themselves need to do any kind of filtering. - return bitmap; - } - ImageFilter filter = mFiltersManager.getFilterForRepresentation(representation); - filter.useRepresentation(representation); - filter.setEnvironment(this); - Bitmap ret = filter.apply(bitmap, mScaleFactor, mQuality); - filter.setGeneralParameters(); - filter.setEnvironment(null); - return ret; - } - - public PipelineInterface getPipeline() { - return mPipeline; - } - - public void setPipeline(PipelineInterface cachingPipeline) { - mPipeline = cachingPipeline; - } - - public synchronized void clearGeneralParameters() { - generalParameters = null; - } - - public synchronized Integer getGeneralParameter(int id) { - if (generalParameters == null || !generalParameters.containsKey(id)) { - return null; - } - return generalParameters.get(id); - } - - public synchronized void setGeneralParameter(int id, int value) { - if (generalParameters == null) { - generalParameters = new HashMap<Integer, Integer>(); - } - - generalParameters.put(id, value); - } - -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/HighresRenderingRequestTask.java b/src/com/android/gallery3d/filtershow/pipeline/HighresRenderingRequestTask.java deleted file mode 100644 index 5a0eb4d45..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/HighresRenderingRequestTask.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; -import com.android.gallery3d.filtershow.filters.FiltersManager; - -public class HighresRenderingRequestTask extends ProcessingTask { - - private CachingPipeline mHighresPreviewPipeline = null; - private boolean mPipelineIsOn = false; - - public void setHighresPreviewScaleFactor(float highResPreviewScale) { - mHighresPreviewPipeline.setHighResPreviewScaleFactor(highResPreviewScale); - } - - public void setPreviewScaleFactor(float previewScale) { - mHighresPreviewPipeline.setPreviewScaleFactor(previewScale); - } - - static class Render implements Request { - RenderingRequest request; - } - - static class RenderResult implements Result { - RenderingRequest request; - } - - public HighresRenderingRequestTask() { - mHighresPreviewPipeline = new CachingPipeline( - FiltersManager.getHighresManager(), "Highres"); - } - - public void setOriginal(Bitmap bitmap) { - mHighresPreviewPipeline.setOriginal(bitmap); - } - - public void setOriginalBitmapHighres(Bitmap originalHires) { - mPipelineIsOn = true; - } - - public void stop() { - mHighresPreviewPipeline.stop(); - } - - public void postRenderingRequest(RenderingRequest request) { - if (!mPipelineIsOn) { - return; - } - Render render = new Render(); - render.request = request; - postRequest(render); - } - - @Override - public Result doInBackground(Request message) { - RenderingRequest request = ((Render) message).request; - RenderResult result = null; - mHighresPreviewPipeline.renderHighres(request); - result = new RenderResult(); - result.request = request; - return result; - } - - @Override - public void onResult(Result message) { - if (message == null) { - return; - } - RenderingRequest request = ((RenderResult) message).request; - request.markAvailable(); - } - - @Override - public boolean isDelayedTask() { return true; } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java b/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java deleted file mode 100644 index d34216ad6..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/ImagePreset.java +++ /dev/null @@ -1,694 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.support.v8.renderscript.Allocation; -import android.util.JsonReader; -import android.util.JsonWriter; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.filters.BaseFiltersManager; -import com.android.gallery3d.filtershow.filters.FilterCropRepresentation; -import com.android.gallery3d.filtershow.filters.FilterFxRepresentation; -import com.android.gallery3d.filtershow.filters.FilterImageBorderRepresentation; -import com.android.gallery3d.filtershow.filters.FilterMirrorRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRotateRepresentation; -import com.android.gallery3d.filtershow.filters.FilterStraightenRepresentation; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.filters.ImageFilter; -import com.android.gallery3d.filtershow.imageshow.GeometryMathUtils; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.state.State; -import com.android.gallery3d.filtershow.state.StateAdapter; -import com.android.gallery3d.util.UsageStatistics; - -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Vector; - -public class ImagePreset { - - private static final String LOGTAG = "ImagePreset"; - - private Vector<FilterRepresentation> mFilters = new Vector<FilterRepresentation>(); - - private boolean mDoApplyGeometry = true; - private boolean mDoApplyFilters = true; - - private boolean mPartialRendering = false; - private Rect mPartialRenderingBounds; - private static final boolean DEBUG = false; - - public ImagePreset() { - } - - public ImagePreset(ImagePreset source) { - for (int i = 0; i < source.mFilters.size(); i++) { - FilterRepresentation sourceRepresentation = source.mFilters.elementAt(i); - mFilters.add(sourceRepresentation.copy()); - } - } - - public Vector<FilterRepresentation> getFilters() { - return mFilters; - } - - public FilterRepresentation getFilterRepresentation(int position) { - FilterRepresentation representation = null; - - representation = mFilters.elementAt(position).copy(); - - return representation; - } - - private static boolean sameSerializationName(String a, String b) { - if (a != null && b != null) { - return a.equals(b); - } else { - return a == null && b == null; - } - } - - public static boolean sameSerializationName(FilterRepresentation a, FilterRepresentation b) { - if (a == null || b == null) { - return false; - } - return sameSerializationName(a.getSerializationName(), b.getSerializationName()); - } - - public int getPositionForRepresentation(FilterRepresentation representation) { - for (int i = 0; i < mFilters.size(); i++) { - if (sameSerializationName(mFilters.elementAt(i), representation)) { - return i; - } - } - return -1; - } - - private FilterRepresentation getFilterRepresentationForType(int type) { - for (int i = 0; i < mFilters.size(); i++) { - if (mFilters.elementAt(i).getFilterType() == type) { - return mFilters.elementAt(i); - } - } - return null; - } - - public int getPositionForType(int type) { - for (int i = 0; i < mFilters.size(); i++) { - if (mFilters.elementAt(i).getFilterType() == type) { - return i; - } - } - return -1; - } - - public FilterRepresentation getFilterRepresentationCopyFrom( - FilterRepresentation filterRepresentation) { - // TODO: add concept of position in the filters (to allow multiple instances) - if (filterRepresentation == null) { - return null; - } - int position = getPositionForRepresentation(filterRepresentation); - if (position == -1) { - return null; - } - FilterRepresentation representation = mFilters.elementAt(position); - if (representation != null) { - representation = representation.copy(); - } - return representation; - } - - public void updateFilterRepresentations(Collection<FilterRepresentation> reps) { - for (FilterRepresentation r : reps) { - updateOrAddFilterRepresentation(r); - } - } - - public void updateOrAddFilterRepresentation(FilterRepresentation rep) { - int pos = getPositionForRepresentation(rep); - if (pos != -1) { - mFilters.elementAt(pos).useParametersFrom(rep); - } else { - addFilter(rep.copy()); - } - } - - public void setDoApplyGeometry(boolean value) { - mDoApplyGeometry = value; - } - - public void setDoApplyFilters(boolean value) { - mDoApplyFilters = value; - } - - public boolean getDoApplyFilters() { - return mDoApplyFilters; - } - - public boolean hasModifications() { - for (int i = 0; i < mFilters.size(); i++) { - FilterRepresentation filter = mFilters.elementAt(i); - if (!filter.isNil()) { - return true; - } - } - return false; - } - - public boolean isPanoramaSafe() { - for (FilterRepresentation representation : mFilters) { - if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY - && !representation.isNil()) { - return false; - } - if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER - && !representation.isNil()) { - return false; - } - if (representation.getFilterType() == FilterRepresentation.TYPE_VIGNETTE - && !representation.isNil()) { - return false; - } - if (representation.getFilterType() == FilterRepresentation.TYPE_TINYPLANET - && !representation.isNil()) { - return false; - } - } - return true; - } - - public boolean same(ImagePreset preset) { - if (preset == null) { - return false; - } - - if (preset.mFilters.size() != mFilters.size()) { - return false; - } - - if (mDoApplyGeometry != preset.mDoApplyGeometry) { - return false; - } - - if (mDoApplyFilters != preset.mDoApplyFilters) { - if (mFilters.size() > 0 || preset.mFilters.size() > 0) { - return false; - } - } - - if (mDoApplyFilters && preset.mDoApplyFilters) { - for (int i = 0; i < preset.mFilters.size(); i++) { - FilterRepresentation a = preset.mFilters.elementAt(i); - FilterRepresentation b = mFilters.elementAt(i); - - if (!a.same(b)) { - return false; - } - } - } - - return true; - } - - public int similarUpTo(ImagePreset preset) { - for (int i = 0; i < preset.mFilters.size(); i++) { - FilterRepresentation a = preset.mFilters.elementAt(i); - if (i < mFilters.size()) { - FilterRepresentation b = mFilters.elementAt(i); - if (!a.same(b)) { - return i; - } - if (!a.equals(b)) { - return i; - } - } else { - return i; - } - } - return preset.mFilters.size(); - } - - public void showFilters() { - Log.v(LOGTAG, "\\\\\\ showFilters -- " + mFilters.size() + " filters"); - int n = 0; - for (FilterRepresentation representation : mFilters) { - Log.v(LOGTAG, " filter " + n + " : " + representation.toString()); - n++; - } - Log.v(LOGTAG, "/// showFilters -- " + mFilters.size() + " filters"); - } - - public FilterRepresentation getLastRepresentation() { - if (mFilters.size() > 0) { - return mFilters.lastElement(); - } - return null; - } - - public void removeFilter(FilterRepresentation filterRepresentation) { - if (filterRepresentation.getFilterType() == FilterRepresentation.TYPE_BORDER) { - for (int i = 0; i < mFilters.size(); i++) { - if (mFilters.elementAt(i).getFilterType() - == filterRepresentation.getFilterType()) { - mFilters.remove(i); - break; - } - } - } else { - for (int i = 0; i < mFilters.size(); i++) { - if (sameSerializationName(mFilters.elementAt(i), filterRepresentation)) { - mFilters.remove(i); - break; - } - } - } - } - - // If the filter is an "None" effect or border, then just don't add this filter. - public void addFilter(FilterRepresentation representation) { - if (representation instanceof FilterUserPresetRepresentation) { - ImagePreset preset = ((FilterUserPresetRepresentation) representation).getImagePreset(); - // user preset replace everything but geometry - mFilters.clear(); - for (int i = 0; i < preset.nbFilters(); i++) { - addFilter(preset.getFilterRepresentation(i)); - } - mFilters.add(representation); - } else if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) { - // Add geometry filter, removing duplicates and do-nothing operations. - for (int i = 0; i < mFilters.size(); i++) { - if (sameSerializationName(representation, mFilters.elementAt(i))) { - mFilters.remove(i); - } - } - if (!representation.isNil()) { - mFilters.add(representation); - } - } else if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) { - removeFilter(representation); - if (!isNoneBorderFilter(representation)) { - mFilters.add(representation); - } - } else if (representation.getFilterType() == FilterRepresentation.TYPE_FX) { - boolean found = false; - for (int i = 0; i < mFilters.size(); i++) { - FilterRepresentation current = mFilters.elementAt(i); - int type = current.getFilterType(); - if (found) { - if (type != FilterRepresentation.TYPE_VIGNETTE) { - mFilters.remove(i); - continue; - } - } - if (type == FilterRepresentation.TYPE_FX) { - if (current instanceof FilterUserPresetRepresentation) { - ImagePreset preset = ((FilterUserPresetRepresentation) current) - .getImagePreset(); - // If we had an existing user preset, let's remove all the presets that - // were added by it - for (int j = 0; j < preset.nbFilters(); j++) { - FilterRepresentation rep = preset.getFilterRepresentation(j); - int pos = getPositionForRepresentation(rep); - if (pos != -1) { - mFilters.remove(pos); - } - } - int pos = getPositionForRepresentation(current); - if (pos != -1) { - mFilters.remove(pos); - } else { - pos = 0; - } - if (!isNoneFxFilter(representation)) { - mFilters.add(pos, representation); - } - - } else { - mFilters.remove(i); - if (!isNoneFxFilter(representation)) { - mFilters.add(i, representation); - } - } - found = true; - } - } - if (!found) { - if (!isNoneFxFilter(representation)) { - mFilters.add(representation); - } - } - } else { - mFilters.add(representation); - } - } - - private boolean isNoneBorderFilter(FilterRepresentation representation) { - return representation instanceof FilterImageBorderRepresentation && - ((FilterImageBorderRepresentation) representation).getDrawableResource() == 0; - } - - private boolean isNoneFxFilter(FilterRepresentation representation) { - return representation instanceof FilterFxRepresentation && - ((FilterFxRepresentation) representation).getNameResource() == R.string.none; - } - - public FilterRepresentation getRepresentation(FilterRepresentation filterRepresentation) { - for (int i = 0; i < mFilters.size(); i++) { - FilterRepresentation representation = mFilters.elementAt(i); - if (sameSerializationName(representation, filterRepresentation)) { - return representation; - } - } - return null; - } - - public Bitmap apply(Bitmap original, FilterEnvironment environment) { - Bitmap bitmap = original; - bitmap = applyFilters(bitmap, -1, -1, environment); - return applyBorder(bitmap, environment); - } - - public Collection<FilterRepresentation> getGeometryFilters() { - ArrayList<FilterRepresentation> geometry = new ArrayList<FilterRepresentation>(); - for (FilterRepresentation r : mFilters) { - if (r.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) { - geometry.add(r); - } - } - return geometry; - } - - public FilterRepresentation getFilterWithSerializationName(String serializationName) { - for (FilterRepresentation r : mFilters) { - if (r != null) { - if (sameSerializationName(r.getSerializationName(), serializationName)) { - return r.copy(); - } - } - } - return null; - } - - public Bitmap applyGeometry(Bitmap bitmap, FilterEnvironment environment) { - // Apply any transform -- 90 rotate, flip, straighten, crop - // Returns a new bitmap. - if (mDoApplyGeometry) { - bitmap = GeometryMathUtils.applyGeometryRepresentations(getGeometryFilters(), bitmap); - } - return bitmap; - } - - public Bitmap applyBorder(Bitmap bitmap, FilterEnvironment environment) { - // get the border from the list of filters. - FilterRepresentation border = getFilterRepresentationForType( - FilterRepresentation.TYPE_BORDER); - if (border != null && mDoApplyGeometry) { - bitmap = environment.applyRepresentation(border, bitmap); - if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) { - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - "SaveBorder", border.getSerializationName(), 1); - } - } - return bitmap; - } - - public int nbFilters() { - return mFilters.size(); - } - - public Bitmap applyFilters(Bitmap bitmap, int from, int to, FilterEnvironment environment) { - if (mDoApplyFilters) { - if (from < 0) { - from = 0; - } - if (to == -1) { - to = mFilters.size(); - } - if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) { - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - "SaveFilters", "Total", to - from + 1); - } - for (int i = from; i < to; i++) { - FilterRepresentation representation = mFilters.elementAt(i); - if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) { - // skip the geometry as it's already applied. - continue; - } - if (representation.getFilterType() == FilterRepresentation.TYPE_BORDER) { - // for now, let's skip the border as it will be applied in - // applyBorder() - // TODO: might be worth getting rid of applyBorder. - continue; - } - bitmap = environment.applyRepresentation(representation, bitmap); - if (environment.getQuality() == FilterEnvironment.QUALITY_FINAL) { - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - "SaveFilter", representation.getSerializationName(), 1); - } - if (environment.needsStop()) { - return bitmap; - } - } - } - - return bitmap; - } - - public void applyBorder(Allocation in, Allocation out, - boolean copyOut, FilterEnvironment environment) { - FilterRepresentation border = getFilterRepresentationForType( - FilterRepresentation.TYPE_BORDER); - if (border != null && mDoApplyGeometry) { - // TODO: should keep the bitmap around - Allocation bitmapIn = in; - if (copyOut) { - bitmapIn = Allocation.createTyped( - CachingPipeline.getRenderScriptContext(), in.getType()); - bitmapIn.copyFrom(out); - } - environment.applyRepresentation(border, bitmapIn, out); - } - } - - public void applyFilters(int from, int to, Allocation in, Allocation out, - FilterEnvironment environment) { - if (mDoApplyFilters) { - if (from < 0) { - from = 0; - } - if (to == -1) { - to = mFilters.size(); - } - for (int i = from; i < to; i++) { - FilterRepresentation representation = mFilters.elementAt(i); - if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY - || representation.getFilterType() == FilterRepresentation.TYPE_BORDER) { - continue; - } - if (i > from) { - in.copyFrom(out); - } - environment.applyRepresentation(representation, in, out); - } - } - } - - public boolean canDoPartialRendering() { - if (MasterImage.getImage().getZoomOrientation() != ImageLoader.ORI_NORMAL) { - return false; - } - for (int i = 0; i < mFilters.size(); i++) { - FilterRepresentation representation = mFilters.elementAt(i); - if (representation.getFilterType() == FilterRepresentation.TYPE_GEOMETRY - && !representation.isNil()) { - return false; - } - if (!representation.supportsPartialRendering()) { - return false; - } - } - return true; - } - - public void fillImageStateAdapter(StateAdapter imageStateAdapter) { - if (imageStateAdapter == null) { - return; - } - Vector<State> states = new Vector<State>(); - for (FilterRepresentation filter : mFilters) { - if (filter.getFilterType() == FilterRepresentation.TYPE_GEOMETRY) { - // TODO: supports Geometry representations in the state panel. - continue; - } - if (filter instanceof FilterUserPresetRepresentation) { - // do not show the user preset itself in the state panel - continue; - } - State state = new State(filter.getName()); - state.setFilterRepresentation(filter); - states.add(state); - } - imageStateAdapter.fill(states); - } - - public void setPartialRendering(boolean partialRendering, Rect bounds) { - mPartialRendering = partialRendering; - mPartialRenderingBounds = bounds; - } - - public boolean isPartialRendering() { - return mPartialRendering; - } - - public Rect getPartialRenderingBounds() { - return mPartialRenderingBounds; - } - - public Vector<ImageFilter> getUsedFilters(BaseFiltersManager filtersManager) { - Vector<ImageFilter> usedFilters = new Vector<ImageFilter>(); - for (int i = 0; i < mFilters.size(); i++) { - FilterRepresentation representation = mFilters.elementAt(i); - ImageFilter filter = filtersManager.getFilterForRepresentation(representation); - usedFilters.add(filter); - } - return usedFilters; - } - - public String getJsonString(String name) { - StringWriter swriter = new StringWriter(); - try { - JsonWriter writer = new JsonWriter(swriter); - writeJson(writer, name); - writer.close(); - } catch (IOException e) { - return null; - } - return swriter.toString(); - } - - public void writeJson(JsonWriter writer, String name) { - int numFilters = mFilters.size(); - try { - writer.beginObject(); - for (int i = 0; i < numFilters; i++) { - FilterRepresentation filter = mFilters.get(i); - if (filter instanceof FilterUserPresetRepresentation) { - continue; - } - String sname = filter.getSerializationName(); - if (DEBUG) { - Log.v(LOGTAG, "Serialization: " + sname); - if (sname == null) { - Log.v(LOGTAG, "Serialization name null for filter: " + filter); - } - } - writer.name(sname); - filter.serializeRepresentation(writer); - } - writer.endObject(); - - } catch (IOException e) { - Log.e(LOGTAG,"Error encoding JASON",e); - } - } - - /** - * populates preset from JSON string - * - * @param filterString a JSON string - * @return true on success if false ImagePreset is undefined - */ - public boolean readJsonFromString(String filterString) { - if (DEBUG) { - Log.v(LOGTAG, "reading preset: \"" + filterString + "\""); - } - StringReader sreader = new StringReader(filterString); - try { - JsonReader reader = new JsonReader(sreader); - boolean ok = readJson(reader); - if (!ok) { - reader.close(); - return false; - } - reader.close(); - } catch (Exception e) { - Log.e(LOGTAG, "parsing the filter parameters:", e); - return false; - } - return true; - } - - /** - * populates preset from JSON stream - * - * @param sreader a JSON string - * @return true on success if false ImagePreset is undefined - */ - public boolean readJson(JsonReader sreader) throws IOException { - sreader.beginObject(); - - while (sreader.hasNext()) { - String name = sreader.nextName(); - FilterRepresentation filter = creatFilterFromName(name); - if (filter == null) { - Log.w(LOGTAG, "UNKNOWN FILTER! " + name); - return false; - } - filter.deSerializeRepresentation(sreader); - addFilter(filter); - } - sreader.endObject(); - return true; - } - - FilterRepresentation creatFilterFromName(String name) { - if (FilterRotateRepresentation.SERIALIZATION_NAME.equals(name)) { - return new FilterRotateRepresentation(); - } else if (FilterMirrorRepresentation.SERIALIZATION_NAME.equals(name)) { - return new FilterMirrorRepresentation(); - } else if (FilterStraightenRepresentation.SERIALIZATION_NAME.equals(name)) { - return new FilterStraightenRepresentation(); - } else if (FilterCropRepresentation.SERIALIZATION_NAME.equals(name)) { - return new FilterCropRepresentation(); - } - FiltersManager filtersManager = FiltersManager.getManager(); - return filtersManager.createFilterFromName(name); - } - - public void updateWith(ImagePreset preset) { - if (preset.mFilters.size() != mFilters.size()) { - Log.e(LOGTAG, "Updating a preset with an incompatible one"); - return; - } - for (int i = 0; i < mFilters.size(); i++) { - FilterRepresentation destRepresentation = mFilters.elementAt(i); - FilterRepresentation sourceRepresentation = preset.mFilters.elementAt(i); - destRepresentation.useParametersFrom(sourceRepresentation); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java b/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java deleted file mode 100644 index b760edd5a..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/ImageSavingTask.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.net.Uri; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.tools.SaveImage; - -import java.io.File; - -public class ImageSavingTask extends ProcessingTask { - private ProcessingService mProcessingService; - - static class SaveRequest implements Request { - Uri sourceUri; - Uri selectedUri; - File destinationFile; - ImagePreset preset; - boolean flatten; - int quality; - } - - static class UpdateBitmap implements Update { - Bitmap bitmap; - } - - static class UpdateProgress implements Update { - int max; - int current; - } - - static class URIResult implements Result { - Uri uri; - } - - public ImageSavingTask(ProcessingService service) { - mProcessingService = service; - } - - public void saveImage(Uri sourceUri, Uri selectedUri, - File destinationFile, ImagePreset preset, boolean flatten, int quality) { - SaveRequest request = new SaveRequest(); - request.sourceUri = sourceUri; - request.selectedUri = selectedUri; - request.destinationFile = destinationFile; - request.preset = preset; - request.flatten = flatten; - request.quality = quality; - postRequest(request); - } - - public Result doInBackground(Request message) { - SaveRequest request = (SaveRequest) message; - Uri sourceUri = request.sourceUri; - Uri selectedUri = request.selectedUri; - File destinationFile = request.destinationFile; - ImagePreset preset = request.preset; - boolean flatten = request.flatten; - // We create a small bitmap showing the result that we can - // give to the notification - UpdateBitmap updateBitmap = new UpdateBitmap(); - updateBitmap.bitmap = createNotificationBitmap(sourceUri, preset); - postUpdate(updateBitmap); - SaveImage saveImage = new SaveImage(mProcessingService, sourceUri, - selectedUri, destinationFile, - new SaveImage.Callback() { - @Override - public void onProgress(int max, int current) { - UpdateProgress updateProgress = new UpdateProgress(); - updateProgress.max = max; - updateProgress.current = current; - postUpdate(updateProgress); - } - }); - Uri uri = saveImage.processAndSaveImage(preset, !flatten, request.quality); - URIResult result = new URIResult(); - result.uri = uri; - return result; - } - - @Override - public void onResult(Result message) { - URIResult result = (URIResult) message; - mProcessingService.completeSaveImage(result.uri); - } - - @Override - public void onUpdate(Update message) { - if (message instanceof UpdateBitmap) { - Bitmap bitmap = ((UpdateBitmap) message).bitmap; - mProcessingService.updateNotificationWithBitmap(bitmap); - } - if (message instanceof UpdateProgress) { - UpdateProgress progress = (UpdateProgress) message; - mProcessingService.updateProgress(progress.max, progress.current); - } - } - - private Bitmap createNotificationBitmap(Uri sourceUri, ImagePreset preset) { - int notificationBitmapSize = Resources.getSystem().getDimensionPixelSize( - android.R.dimen.notification_large_icon_width); - Bitmap bitmap = ImageLoader.loadConstrainedBitmap(sourceUri, getContext(), - notificationBitmapSize, null, true); - CachingPipeline pipeline = new CachingPipeline(FiltersManager.getManager(), "Thumb"); - return pipeline.renderFinalImage(bitmap, preset); - } - -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/PipelineInterface.java b/src/com/android/gallery3d/filtershow/pipeline/PipelineInterface.java deleted file mode 100644 index d53768c95..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/PipelineInterface.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.support.v8.renderscript.Allocation; -import android.support.v8.renderscript.RenderScript; - -public interface PipelineInterface { - public String getName(); - public Resources getResources(); - public Allocation getInPixelsAllocation(); - public Allocation getOutPixelsAllocation(); - public boolean prepareRenderscriptAllocations(Bitmap bitmap); - public RenderScript getRSContext(); -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java deleted file mode 100644 index d0504d11f..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingService.java +++ /dev/null @@ -1,283 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.app.Notification; -import android.app.NotificationManager; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Binder; -import android.os.IBinder; -import android.util.Log; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.filters.ImageFilter; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.tools.SaveImage; - -import java.io.File; - -public class ProcessingService extends Service { - private static final String LOGTAG = "ProcessingService"; - private static final boolean SHOW_IMAGE = false; - private int mNotificationId; - private NotificationManager mNotifyMgr = null; - private Notification.Builder mBuilder = null; - - private static final String PRESET = "preset"; - private static final String QUALITY = "quality"; - private static final String SOURCE_URI = "sourceUri"; - private static final String SELECTED_URI = "selectedUri"; - private static final String DESTINATION_FILE = "destinationFile"; - private static final String SAVING = "saving"; - private static final String FLATTEN = "flatten"; - - private ProcessingTaskController mProcessingTaskController; - private ImageSavingTask mImageSavingTask; - private UpdatePreviewTask mUpdatePreviewTask; - private HighresRenderingRequestTask mHighresRenderingRequestTask; - private RenderingRequestTask mRenderingRequestTask; - - private final IBinder mBinder = new LocalBinder(); - private FilterShowActivity mFiltershowActivity; - - private boolean mSaving = false; - private boolean mNeedsAlive = false; - - public void setFiltershowActivity(FilterShowActivity filtershowActivity) { - mFiltershowActivity = filtershowActivity; - } - - public void setOriginalBitmap(Bitmap originalBitmap) { - if (mUpdatePreviewTask == null) { - return; - } - mUpdatePreviewTask.setOriginal(originalBitmap); - mHighresRenderingRequestTask.setOriginal(originalBitmap); - mRenderingRequestTask.setOriginal(originalBitmap); - } - - public void updatePreviewBuffer() { - mHighresRenderingRequestTask.stop(); - mUpdatePreviewTask.updatePreview(); - } - - public void postRenderingRequest(RenderingRequest request) { - mRenderingRequestTask.postRenderingRequest(request); - } - - public void postHighresRenderingRequest(ImagePreset preset, float scaleFactor, - RenderingRequestCaller caller) { - RenderingRequest request = new RenderingRequest(); - // TODO: use the triple buffer preset as UpdatePreviewTask does instead of creating a copy - ImagePreset passedPreset = new ImagePreset(preset); - request.setOriginalImagePreset(preset); - request.setScaleFactor(scaleFactor); - request.setImagePreset(passedPreset); - request.setType(RenderingRequest.HIGHRES_RENDERING); - request.setCaller(caller); - mHighresRenderingRequestTask.postRenderingRequest(request); - } - - public void setHighresPreviewScaleFactor(float highResPreviewScale) { - mHighresRenderingRequestTask.setHighresPreviewScaleFactor(highResPreviewScale); - } - - public void setPreviewScaleFactor(float previewScale) { - mHighresRenderingRequestTask.setPreviewScaleFactor(previewScale); - mRenderingRequestTask.setPreviewScaleFactor(previewScale); - } - - public void setOriginalBitmapHighres(Bitmap originalHires) { - mHighresRenderingRequestTask.setOriginalBitmapHighres(originalHires); - } - - public class LocalBinder extends Binder { - public ProcessingService getService() { - return ProcessingService.this; - } - } - - public static Intent getSaveIntent(Context context, ImagePreset preset, File destination, - Uri selectedImageUri, Uri sourceImageUri, boolean doFlatten, int quality) { - Intent processIntent = new Intent(context, ProcessingService.class); - processIntent.putExtra(ProcessingService.SOURCE_URI, - sourceImageUri.toString()); - processIntent.putExtra(ProcessingService.SELECTED_URI, - selectedImageUri.toString()); - processIntent.putExtra(ProcessingService.QUALITY, quality); - if (destination != null) { - processIntent.putExtra(ProcessingService.DESTINATION_FILE, destination.toString()); - } - processIntent.putExtra(ProcessingService.PRESET, - preset.getJsonString(context.getString(R.string.saved))); - processIntent.putExtra(ProcessingService.SAVING, true); - if (doFlatten) { - processIntent.putExtra(ProcessingService.FLATTEN, true); - } - return processIntent; - } - - - @Override - public void onCreate() { - mProcessingTaskController = new ProcessingTaskController(this); - mImageSavingTask = new ImageSavingTask(this); - mUpdatePreviewTask = new UpdatePreviewTask(); - mHighresRenderingRequestTask = new HighresRenderingRequestTask(); - mRenderingRequestTask = new RenderingRequestTask(); - mProcessingTaskController.add(mImageSavingTask); - mProcessingTaskController.add(mUpdatePreviewTask); - mProcessingTaskController.add(mHighresRenderingRequestTask); - mProcessingTaskController.add(mRenderingRequestTask); - setupPipeline(); - } - - @Override - public void onDestroy() { - tearDownPipeline(); - mProcessingTaskController.quit(); - } - - @Override - public int onStartCommand(Intent intent, int flags, int startId) { - mNeedsAlive = true; - if (intent != null && intent.getBooleanExtra(SAVING, false)) { - // we save using an intent to keep the service around after the - // activity has been destroyed. - String presetJson = intent.getStringExtra(PRESET); - String source = intent.getStringExtra(SOURCE_URI); - String selected = intent.getStringExtra(SELECTED_URI); - String destination = intent.getStringExtra(DESTINATION_FILE); - int quality = intent.getIntExtra(QUALITY, 100); - boolean flatten = intent.getBooleanExtra(FLATTEN, false); - Uri sourceUri = Uri.parse(source); - Uri selectedUri = null; - if (selected != null) { - selectedUri = Uri.parse(selected); - } - File destinationFile = null; - if (destination != null) { - destinationFile = new File(destination); - } - ImagePreset preset = new ImagePreset(); - preset.readJsonFromString(presetJson); - mNeedsAlive = false; - mSaving = true; - handleSaveRequest(sourceUri, selectedUri, destinationFile, preset, flatten, quality); - } - return START_REDELIVER_INTENT; - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - public void onStart() { - mNeedsAlive = true; - if (!mSaving && mFiltershowActivity != null) { - mFiltershowActivity.updateUIAfterServiceStarted(); - } - } - - public void handleSaveRequest(Uri sourceUri, Uri selectedUri, - File destinationFile, ImagePreset preset, boolean flatten, int quality) { - mNotifyMgr = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - - mNotificationId++; - - mBuilder = - new Notification.Builder(this) - .setSmallIcon(R.drawable.filtershow_button_fx) - .setContentTitle(getString(R.string.filtershow_notification_label)) - .setContentText(getString(R.string.filtershow_notification_message)); - - startForeground(mNotificationId, mBuilder.build()); - - updateProgress(SaveImage.MAX_PROCESSING_STEPS, 0); - - // Process the image - - mImageSavingTask.saveImage(sourceUri, selectedUri, destinationFile, - preset, flatten, quality); - } - - public void updateNotificationWithBitmap(Bitmap bitmap) { - mBuilder.setLargeIcon(bitmap); - mNotifyMgr.notify(mNotificationId, mBuilder.build()); - } - - public void updateProgress(int max, int current) { - mBuilder.setProgress(max, current, false); - mNotifyMgr.notify(mNotificationId, mBuilder.build()); - } - - public void completeSaveImage(Uri result) { - if (SHOW_IMAGE) { - // TODO: we should update the existing image in Gallery instead - Intent viewImage = new Intent(Intent.ACTION_VIEW, result); - viewImage.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(viewImage); - } - stopForeground(true); - stopSelf(); - if (mNeedsAlive) { - // If the app has been restarted while we were saving... - mFiltershowActivity.updateUIAfterServiceStarted(); - } else if (mFiltershowActivity.isSimpleEditAction()) { - // terminate now - mFiltershowActivity.completeSaveImage(result); - } - } - - private void setupPipeline() { - Resources res = getResources(); - FiltersManager.setResources(res); - CachingPipeline.createRenderscriptContext(this); - - FiltersManager filtersManager = FiltersManager.getManager(); - filtersManager.addLooks(this); - filtersManager.addBorders(this); - filtersManager.addTools(this); - filtersManager.addEffects(); - - FiltersManager highresFiltersManager = FiltersManager.getHighresManager(); - highresFiltersManager.addLooks(this); - highresFiltersManager.addBorders(this); - highresFiltersManager.addTools(this); - highresFiltersManager.addEffects(); - } - - private void tearDownPipeline() { - ImageFilter.resetStatics(); - FiltersManager.getPreviewManager().freeRSFilterScripts(); - FiltersManager.getManager().freeRSFilterScripts(); - FiltersManager.getHighresManager().freeRSFilterScripts(); - FiltersManager.reset(); - CachingPipeline.destroyRenderScriptContext(); - } - - static { - System.loadLibrary("jni_filtershow_filters"); - } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTask.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingTask.java deleted file mode 100644 index 8d3e8110f..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTask.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.content.Context; -import android.os.Handler; -import android.os.Message; - -public abstract class ProcessingTask { - private ProcessingTaskController mTaskController; - private Handler mProcessingHandler; - private Handler mResultHandler; - private int mType; - private static final int DELAY = 300; - - static interface Request {} - static interface Update {} - static interface Result {} - - public boolean postRequest(Request message) { - Message msg = mProcessingHandler.obtainMessage(mType); - msg.obj = message; - if (isPriorityTask()) { - if (mProcessingHandler.hasMessages(getType())) { - return false; - } - mProcessingHandler.sendMessageAtFrontOfQueue(msg); - } else if (isDelayedTask()) { - if (mProcessingHandler.hasMessages(getType())) { - mProcessingHandler.removeMessages(getType()); - } - mProcessingHandler.sendMessageDelayed(msg, DELAY); - } else { - mProcessingHandler.sendMessage(msg); - } - return true; - } - - public void postUpdate(Update message) { - Message msg = mResultHandler.obtainMessage(mType); - msg.obj = message; - msg.arg1 = ProcessingTaskController.UPDATE; - mResultHandler.sendMessage(msg); - } - - public void processRequest(Request message) { - Object result = doInBackground(message); - Message msg = mResultHandler.obtainMessage(mType); - msg.obj = result; - msg.arg1 = ProcessingTaskController.RESULT; - mResultHandler.sendMessage(msg); - } - - public void added(ProcessingTaskController taskController) { - mTaskController = taskController; - mResultHandler = taskController.getResultHandler(); - mProcessingHandler = taskController.getProcessingHandler(); - mType = taskController.getReservedType(); - } - - public int getType() { - return mType; - } - - public Context getContext() { - return mTaskController.getContext(); - } - - public abstract Result doInBackground(Request message); - public abstract void onResult(Result message); - public void onUpdate(Update message) {} - public boolean isPriorityTask() { return false; } - public boolean isDelayedTask() { return false; } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTaskController.java b/src/com/android/gallery3d/filtershow/pipeline/ProcessingTaskController.java deleted file mode 100644 index b54bbb044..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/ProcessingTaskController.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.content.Context; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Message; -import android.util.Log; - -import java.util.HashMap; - -public class ProcessingTaskController implements Handler.Callback { - private static final String LOGTAG = "ProcessingTaskController"; - - private Context mContext; - private HandlerThread mHandlerThread = null; - private Handler mProcessingHandler = null; - private int mCurrentType; - private HashMap<Integer, ProcessingTask> mTasks = new HashMap<Integer, ProcessingTask>(); - - public final static int RESULT = 1; - public final static int UPDATE = 2; - - private final Handler mResultHandler = new Handler() { - @Override - public void handleMessage(Message msg) { - ProcessingTask task = mTasks.get(msg.what); - if (task != null) { - if (msg.arg1 == RESULT) { - task.onResult((ProcessingTask.Result) msg.obj); - } else if (msg.arg1 == UPDATE) { - task.onUpdate((ProcessingTask.Update) msg.obj); - } else { - Log.w(LOGTAG, "received unknown message! " + msg.arg1); - } - } - } - }; - - @Override - public boolean handleMessage(Message msg) { - ProcessingTask task = mTasks.get(msg.what); - if (task != null) { - task.processRequest((ProcessingTask.Request) msg.obj); - return true; - } - return false; - } - - public ProcessingTaskController(Context context) { - mContext = context; - mHandlerThread = new HandlerThread("ProcessingTaskController", - android.os.Process.THREAD_PRIORITY_FOREGROUND); - mHandlerThread.start(); - mProcessingHandler = new Handler(mHandlerThread.getLooper(), this); - } - - public Handler getProcessingHandler() { - return mProcessingHandler; - } - - public Handler getResultHandler() { - return mResultHandler; - } - - public int getReservedType() { - return mCurrentType++; - } - - public Context getContext() { - return mContext; - } - - public void add(ProcessingTask task) { - task.added(this); - mTasks.put(task.getType(), task); - } - - public void quit() { - mHandlerThread.quit(); - } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java deleted file mode 100644 index ef4bb9bc0..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequest.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Rect; -import com.android.gallery3d.app.Log; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class RenderingRequest { - private static final String LOGTAG = "RenderingRequest"; - private boolean mIsDirect = false; - private Bitmap mBitmap = null; - private ImagePreset mImagePreset = null; - private ImagePreset mOriginalImagePreset = null; - private RenderingRequestCaller mCaller = null; - private float mScaleFactor = 1.0f; - private Rect mBounds = null; - private Rect mDestination = null; - private int mType = FULL_RENDERING; - public static final int FULL_RENDERING = 0; - public static final int FILTERS_RENDERING = 1; - public static final int GEOMETRY_RENDERING = 2; - public static final int ICON_RENDERING = 3; - public static final int PARTIAL_RENDERING = 4; - public static final int HIGHRES_RENDERING = 5; - public static final int STYLE_ICON_RENDERING = 6; - - private static final Bitmap.Config mConfig = Bitmap.Config.ARGB_8888; - - public static void post(Context context, Bitmap source, ImagePreset preset, - int type, RenderingRequestCaller caller) { - RenderingRequest.post(context, source, preset, type, caller, null, null); - } - - public static void post(Context context, Bitmap source, ImagePreset preset, int type, - RenderingRequestCaller caller, Rect bounds, Rect destination) { - if (((type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) && source == null) - || preset == null || caller == null) { - Log.v(LOGTAG, "something null: source: " + source - + " or preset: " + preset + " or caller: " + caller); - return; - } - RenderingRequest request = new RenderingRequest(); - Bitmap bitmap = null; - if (type == FULL_RENDERING - || type == GEOMETRY_RENDERING - || type == ICON_RENDERING - || type == STYLE_ICON_RENDERING) { - CachingPipeline pipeline = new CachingPipeline( - FiltersManager.getManager(), "Icon"); - bitmap = pipeline.renderGeometryIcon(source, preset); - } else if (type != PARTIAL_RENDERING && type != HIGHRES_RENDERING) { - bitmap = Bitmap.createBitmap(source.getWidth(), source.getHeight(), mConfig); - } - - request.setBitmap(bitmap); - ImagePreset passedPreset = new ImagePreset(preset); - request.setOriginalImagePreset(preset); - request.setScaleFactor(MasterImage.getImage().getScaleFactor()); - - if (type == PARTIAL_RENDERING) { - request.setBounds(bounds); - request.setDestination(destination); - passedPreset.setPartialRendering(true, bounds); - } - - request.setImagePreset(passedPreset); - request.setType(type); - request.setCaller(caller); - request.post(context); - } - - public void post(Context context) { - if (context instanceof FilterShowActivity) { - FilterShowActivity activity = (FilterShowActivity) context; - ProcessingService service = activity.getProcessingService(); - service.postRenderingRequest(this); - } - } - - public void markAvailable() { - if (mBitmap == null || mImagePreset == null - || mCaller == null) { - return; - } - mCaller.available(this); - } - - public boolean isDirect() { - return mIsDirect; - } - - public void setDirect(boolean isDirect) { - mIsDirect = isDirect; - } - - public Bitmap getBitmap() { - return mBitmap; - } - - public void setBitmap(Bitmap bitmap) { - mBitmap = bitmap; - } - - public ImagePreset getImagePreset() { - return mImagePreset; - } - - public void setImagePreset(ImagePreset imagePreset) { - mImagePreset = imagePreset; - } - - public int getType() { - return mType; - } - - public void setType(int type) { - mType = type; - } - - public void setCaller(RenderingRequestCaller caller) { - mCaller = caller; - } - - public Rect getBounds() { - return mBounds; - } - - public void setBounds(Rect bounds) { - mBounds = bounds; - } - - public void setScaleFactor(float scaleFactor) { - mScaleFactor = scaleFactor; - } - - public float getScaleFactor() { - return mScaleFactor; - } - - public Rect getDestination() { - return mDestination; - } - - public void setDestination(Rect destination) { - mDestination = destination; - } - - public ImagePreset getOriginalImagePreset() { - return mOriginalImagePreset; - } - - public void setOriginalImagePreset(ImagePreset originalImagePreset) { - mOriginalImagePreset = originalImagePreset; - } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestCaller.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestCaller.java deleted file mode 100644 index b978e7040..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestCaller.java +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -public interface RenderingRequestCaller { - public void available(RenderingRequest request); -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java b/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java deleted file mode 100644 index 7a83f7072..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/RenderingRequestTask.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; -import com.android.gallery3d.filtershow.filters.FiltersManager; - -public class RenderingRequestTask extends ProcessingTask { - - private CachingPipeline mPreviewPipeline = null; - private boolean mPipelineIsOn = false; - - public void setPreviewScaleFactor(float previewScale) { - mPreviewPipeline.setPreviewScaleFactor(previewScale); - } - - static class Render implements Request { - RenderingRequest request; - } - - static class RenderResult implements Result { - RenderingRequest request; - } - - public RenderingRequestTask() { - mPreviewPipeline = new CachingPipeline( - FiltersManager.getManager(), "Normal"); - } - - public void setOriginal(Bitmap bitmap) { - mPreviewPipeline.setOriginal(bitmap); - mPipelineIsOn = true; - } - - public void stop() { - mPreviewPipeline.stop(); - } - - public void postRenderingRequest(RenderingRequest request) { - if (!mPipelineIsOn) { - return; - } - Render render = new Render(); - render.request = request; - postRequest(render); - } - - @Override - public Result doInBackground(Request message) { - RenderingRequest request = ((Render) message).request; - RenderResult result = null; - mPreviewPipeline.render(request); - result = new RenderResult(); - result.request = request; - return result; - } - - @Override - public void onResult(Result message) { - if (message == null) { - return; - } - RenderingRequest request = ((RenderResult) message).request; - request.markAvailable(); - } - -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java b/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java deleted file mode 100644 index 98e69f60e..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/SharedBuffer.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; - -public class SharedBuffer { - - private static final String LOGTAG = "SharedBuffer"; - - private volatile Buffer mProducer = null; - private volatile Buffer mConsumer = null; - private volatile Buffer mIntermediate = null; - - private volatile boolean mNeedsSwap = false; - private volatile boolean mNeedsRepaint = true; - - public void setProducer(Bitmap producer) { - Buffer buffer = new Buffer(producer); - synchronized (this) { - mProducer = buffer; - } - } - - public synchronized Buffer getProducer() { - return mProducer; - } - - public synchronized Buffer getConsumer() { - return mConsumer; - } - - public synchronized void swapProducer() { - Buffer intermediate = mIntermediate; - mIntermediate = mProducer; - mProducer = intermediate; - mNeedsSwap = true; - } - - public synchronized void swapConsumerIfNeeded() { - if (!mNeedsSwap) { - return; - } - Buffer intermediate = mIntermediate; - mIntermediate = mConsumer; - mConsumer = intermediate; - mNeedsSwap = false; - } - - public synchronized void invalidate() { - mNeedsRepaint = true; - } - - public synchronized boolean checkRepaintNeeded() { - if (mNeedsRepaint) { - mNeedsRepaint = false; - return true; - } - return false; - } - -} - diff --git a/src/com/android/gallery3d/filtershow/pipeline/SharedPreset.java b/src/com/android/gallery3d/filtershow/pipeline/SharedPreset.java deleted file mode 100644 index 3f850fed2..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/SharedPreset.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -public class SharedPreset { - - private volatile ImagePreset mProducerPreset = null; - private volatile ImagePreset mConsumerPreset = null; - private volatile ImagePreset mIntermediatePreset = null; - - public synchronized void enqueuePreset(ImagePreset preset) { - if (mProducerPreset == null || (!mProducerPreset.same(preset))) { - mProducerPreset = new ImagePreset(preset); - } else { - mProducerPreset.updateWith(preset); - } - ImagePreset temp = mIntermediatePreset; - mIntermediatePreset = mProducerPreset; - mProducerPreset = temp; - } - - public synchronized ImagePreset dequeuePreset() { - ImagePreset temp = mConsumerPreset; - mConsumerPreset = mIntermediatePreset; - mIntermediatePreset = temp; - return mConsumerPreset; - } -} diff --git a/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java b/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java deleted file mode 100644 index 406cc9bf5..000000000 --- a/src/com/android/gallery3d/filtershow/pipeline/UpdatePreviewTask.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.pipeline; - -import android.graphics.Bitmap; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class UpdatePreviewTask extends ProcessingTask { - private CachingPipeline mPreviewPipeline = null; - private boolean mHasUnhandledPreviewRequest = false; - private boolean mPipelineIsOn = false; - - public UpdatePreviewTask() { - mPreviewPipeline = new CachingPipeline( - FiltersManager.getPreviewManager(), "Preview"); - } - - public void setOriginal(Bitmap bitmap) { - mPreviewPipeline.setOriginal(bitmap); - mPipelineIsOn = true; - } - - public void updatePreview() { - if (!mPipelineIsOn) { - return; - } - mHasUnhandledPreviewRequest = true; - if (postRequest(null)) { - mHasUnhandledPreviewRequest = false; - } - } - - @Override - public boolean isPriorityTask() { - return true; - } - - @Override - public Result doInBackground(Request message) { - SharedBuffer buffer = MasterImage.getImage().getPreviewBuffer(); - SharedPreset preset = MasterImage.getImage().getPreviewPreset(); - ImagePreset renderingPreset = preset.dequeuePreset(); - if (renderingPreset != null) { - mPreviewPipeline.compute(buffer, renderingPreset, 0); - // set the preset we used in the buffer for later inspection UI-side - buffer.getProducer().setPreset(renderingPreset); - buffer.getProducer().sync(); - buffer.swapProducer(); // push back the result - } - return null; - } - - @Override - public void onResult(Result message) { - MasterImage.getImage().notifyObservers(); - if (mHasUnhandledPreviewRequest) { - updatePreview(); - } - } - - public void setPipelineIsOn(boolean pipelineIsOn) { - mPipelineIsOn = pipelineIsOn; - } -} diff --git a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java b/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java deleted file mode 100644 index 7ab61fcc9..000000000 --- a/src/com/android/gallery3d/filtershow/presets/PresetManagementDialog.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.presets; - -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ListView; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; - -public class PresetManagementDialog extends DialogFragment implements View.OnClickListener { - private UserPresetsAdapter mAdapter; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.filtershow_presets_management_dialog, container); - - FilterShowActivity activity = (FilterShowActivity) getActivity(); - mAdapter = activity.getUserPresetsAdapter(); - ListView panel = (ListView) view.findViewById(R.id.listItems); - panel.setAdapter(mAdapter); - - view.findViewById(R.id.cancel).setOnClickListener(this); - view.findViewById(R.id.addpreset).setOnClickListener(this); - view.findViewById(R.id.ok).setOnClickListener(this); - getDialog().setTitle(getString(R.string.filtershow_manage_preset)); - return view; - } - - @Override - public void onClick(View v) { - FilterShowActivity activity = (FilterShowActivity) getActivity(); - switch (v.getId()) { - case R.id.cancel: - mAdapter.clearChangedRepresentations(); - mAdapter.clearDeletedRepresentations(); - activity.updateUserPresetsFromAdapter(mAdapter); - dismiss(); - break; - case R.id.addpreset: - activity.saveCurrentImagePreset(); - dismiss(); - break; - case R.id.ok: - mAdapter.updateCurrent(); - activity.updateUserPresetsFromAdapter(mAdapter); - dismiss(); - break; - } - } -} diff --git a/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java b/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java deleted file mode 100644 index dab9ea454..000000000 --- a/src/com/android/gallery3d/filtershow/presets/UserPresetsAdapter.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.presets; - -import android.content.Context; -import android.graphics.Rect; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.ImageView; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.category.Action; -import com.android.gallery3d.filtershow.category.CategoryView; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.filters.FilterUserPresetRepresentation; - -import java.util.ArrayList; - -public class UserPresetsAdapter extends ArrayAdapter<Action> - implements View.OnClickListener, View.OnFocusChangeListener { - private static final String LOGTAG = "UserPresetsAdapter"; - private LayoutInflater mInflater; - private int mIconSize = 160; - private ArrayList<FilterUserPresetRepresentation> mDeletedRepresentations = - new ArrayList<FilterUserPresetRepresentation>(); - private ArrayList<FilterUserPresetRepresentation> mChangedRepresentations = - new ArrayList<FilterUserPresetRepresentation>(); - private EditText mCurrentEditText; - - public UserPresetsAdapter(Context context, int textViewResourceId) { - super(context, textViewResourceId); - mInflater = LayoutInflater.from(context); - mIconSize = context.getResources().getDimensionPixelSize(R.dimen.category_panel_icon_size); - } - - public UserPresetsAdapter(Context context) { - this(context, 0); - } - - @Override - public void add(Action action) { - super.add(action); - action.setAdapter(this); - } - - private void deletePreset(Action action) { - FilterRepresentation rep = action.getRepresentation(); - if (rep instanceof FilterUserPresetRepresentation) { - mDeletedRepresentations.add((FilterUserPresetRepresentation) rep); - } - remove(action); - notifyDataSetChanged(); - } - - private void changePreset(Action action) { - FilterRepresentation rep = action.getRepresentation(); - rep.setName(action.getName()); - if (rep instanceof FilterUserPresetRepresentation) { - mChangedRepresentations.add((FilterUserPresetRepresentation) rep); - } - } - - public void updateCurrent() { - if (mCurrentEditText != null) { - updateActionFromEditText(mCurrentEditText); - } - } - - static class UserPresetViewHolder { - ImageView imageView; - EditText editText; - ImageButton deleteButton; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - UserPresetViewHolder viewHolder; - if (convertView == null) { - convertView = mInflater.inflate(R.layout.filtershow_presets_management_row, null); - viewHolder = new UserPresetViewHolder(); - viewHolder.imageView = (ImageView) convertView.findViewById(R.id.imageView); - viewHolder.editText = (EditText) convertView.findViewById(R.id.editView); - viewHolder.deleteButton = (ImageButton) convertView.findViewById(R.id.deleteUserPreset); - viewHolder.editText.setOnClickListener(this); - viewHolder.editText.setOnFocusChangeListener(this); - viewHolder.deleteButton.setOnClickListener(this); - convertView.setTag(viewHolder); - } else { - viewHolder = (UserPresetViewHolder) convertView.getTag(); - } - Action action = getItem(position); - viewHolder.imageView.setImageBitmap(action.getImage()); - if (action.getImage() == null) { - // queue image rendering for this action - action.setImageFrame(new Rect(0, 0, mIconSize, mIconSize), CategoryView.VERTICAL); - } - viewHolder.deleteButton.setTag(action); - viewHolder.editText.setTag(action); - viewHolder.editText.setHint(action.getName()); - - return convertView; - } - - public ArrayList<FilterUserPresetRepresentation> getDeletedRepresentations() { - return mDeletedRepresentations; - } - - public void clearDeletedRepresentations() { - mDeletedRepresentations.clear(); - } - - public ArrayList<FilterUserPresetRepresentation> getChangedRepresentations() { - return mChangedRepresentations; - } - - public void clearChangedRepresentations() { - mChangedRepresentations.clear(); - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.editView: - v.requestFocus(); - break; - case R.id.deleteUserPreset: - Action action = (Action) v.getTag(); - deletePreset(action); - break; - } - } - - @Override - public void onFocusChange(View v, boolean hasFocus) { - if (v.getId() != R.id.editView) { - return; - } - EditText editText = (EditText) v; - if (!hasFocus) { - updateActionFromEditText(editText); - } else { - mCurrentEditText = editText; - } - } - - private void updateActionFromEditText(EditText editText) { - Action action = (Action) editText.getTag(); - String newName = editText.getText().toString(); - if (newName.length() > 0) { - action.setName(editText.getText().toString()); - changePreset(action); - } - } -} diff --git a/src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java b/src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java deleted file mode 100644 index bc17a6e03..000000000 --- a/src/com/android/gallery3d/filtershow/provider/SharedImageProvider.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.provider; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.net.Uri; -import android.os.ConditionVariable; -import android.os.ParcelFileDescriptor; -import android.provider.BaseColumns; -import android.provider.MediaStore; -import android.provider.OpenableColumns; - -import java.io.File; -import java.io.FileNotFoundException; - -public class SharedImageProvider extends ContentProvider { - - private static final String LOGTAG = "SharedImageProvider"; - - public static final String MIME_TYPE = "image/jpeg"; - public static final String AUTHORITY = "com.android.gallery3d.filtershow.provider.SharedImageProvider"; - public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/image"); - public static final String PREPARE = "prepare"; - - private final String[] mMimeStreamType = { - MIME_TYPE - }; - - private static ConditionVariable mImageReadyCond = new ConditionVariable(false); - - @Override - public int delete(Uri arg0, String arg1, String[] arg2) { - return 0; - } - - @Override - public String getType(Uri arg0) { - return MIME_TYPE; - } - - @Override - public String[] getStreamTypes(Uri arg0, String mimeTypeFilter) { - return mMimeStreamType; - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - if (values.containsKey(PREPARE)) { - if (values.getAsBoolean(PREPARE)) { - mImageReadyCond.close(); - } else { - mImageReadyCond.open(); - } - } - return null; - } - - @Override - public int update(Uri arg0, ContentValues arg1, String arg2, String[] arg3) { - return 0; - } - - @Override - public boolean onCreate() { - return true; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { - String uriPath = uri.getLastPathSegment(); - if (uriPath == null) { - return null; - } - if (projection == null) { - projection = new String[] { - BaseColumns._ID, - MediaStore.MediaColumns.DATA, - OpenableColumns.DISPLAY_NAME, - OpenableColumns.SIZE - }; - } - // If we receive a query on display name or size, - // we should block until the image is ready - mImageReadyCond.block(); - - File path = new File(uriPath); - - MatrixCursor cursor = new MatrixCursor(projection); - Object[] columns = new Object[projection.length]; - for (int i = 0; i < projection.length; i++) { - if (projection[i].equalsIgnoreCase(BaseColumns._ID)) { - columns[i] = 0; - } else if (projection[i].equalsIgnoreCase(MediaStore.MediaColumns.DATA)) { - columns[i] = uri; - } else if (projection[i].equalsIgnoreCase(OpenableColumns.DISPLAY_NAME)) { - columns[i] = path.getName(); - } else if (projection[i].equalsIgnoreCase(OpenableColumns.SIZE)) { - columns[i] = path.length(); - } - } - cursor.addRow(columns); - - return cursor; - } - - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - String uriPath = uri.getLastPathSegment(); - if (uriPath == null) { - return null; - } - // Here we need to block until the image is ready - mImageReadyCond.block(); - File path = new File(uriPath); - int imode = 0; - imode |= ParcelFileDescriptor.MODE_READ_ONLY; - return ParcelFileDescriptor.open(path, imode); - } -} diff --git a/src/com/android/gallery3d/filtershow/state/DragListener.java b/src/com/android/gallery3d/filtershow/state/DragListener.java deleted file mode 100644 index 1aa81ed69..000000000 --- a/src/com/android/gallery3d/filtershow/state/DragListener.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.state; - -import android.view.DragEvent; -import android.view.View; -import android.widget.ArrayAdapter; -import android.widget.LinearLayout; - -class DragListener implements View.OnDragListener { - - private static final String LOGTAG = "DragListener"; - private PanelTrack mStatePanelTrack; - private static float sSlope = 0.2f; - - public DragListener(PanelTrack statePanelTrack) { - mStatePanelTrack = statePanelTrack; - } - - private void setState(DragEvent event) { - float translation = event.getY() - mStatePanelTrack.getTouchPoint().y; - float alpha = 1.0f - (Math.abs(translation) - / mStatePanelTrack.getCurrentView().getHeight()); - if (mStatePanelTrack.getOrientation() == LinearLayout.VERTICAL) { - translation = event.getX() - mStatePanelTrack.getTouchPoint().x; - alpha = 1.0f - (Math.abs(translation) - / mStatePanelTrack.getCurrentView().getWidth()); - mStatePanelTrack.getCurrentView().setTranslationX(translation); - } else { - mStatePanelTrack.getCurrentView().setTranslationY(translation); - } - mStatePanelTrack.getCurrentView().setBackgroundAlpha(alpha); - } - - @Override - public boolean onDrag(View v, DragEvent event) { - switch (event.getAction()) { - case DragEvent.ACTION_DRAG_STARTED: { - break; - } - case DragEvent.ACTION_DRAG_LOCATION: { - if (mStatePanelTrack.getCurrentView() != null) { - setState(event); - View over = mStatePanelTrack.findChildAt((int) event.getX(), - (int) event.getY()); - if (over != null && over != mStatePanelTrack.getCurrentView()) { - StateView stateView = (StateView) over; - if (stateView != mStatePanelTrack.getCurrentView()) { - int pos = mStatePanelTrack.findChild(over); - int origin = mStatePanelTrack.findChild( - mStatePanelTrack.getCurrentView()); - ArrayAdapter array = (ArrayAdapter) mStatePanelTrack.getAdapter(); - if (origin != -1 && pos != -1) { - State current = (State) array.getItem(origin); - array.remove(current); - array.insert(current, pos); - mStatePanelTrack.fillContent(false); - mStatePanelTrack.setCurrentView(mStatePanelTrack.getChildAt(pos)); - } - } - } - } - break; - } - case DragEvent.ACTION_DRAG_ENTERED: { - mStatePanelTrack.setExited(false); - if (mStatePanelTrack.getCurrentView() != null) { - mStatePanelTrack.getCurrentView().setVisibility(View.VISIBLE); - } - return true; - } - case DragEvent.ACTION_DRAG_EXITED: { - if (mStatePanelTrack.getCurrentView() != null) { - setState(event); - mStatePanelTrack.getCurrentView().setVisibility(View.INVISIBLE); - } - mStatePanelTrack.setExited(true); - break; - } - case DragEvent.ACTION_DROP: { - break; - } - case DragEvent.ACTION_DRAG_ENDED: { - if (mStatePanelTrack.getCurrentView() != null - && mStatePanelTrack.getCurrentView().getAlpha() > sSlope) { - setState(event); - } - mStatePanelTrack.checkEndState(); - break; - } - default: - break; - } - return true; - } -} diff --git a/src/com/android/gallery3d/filtershow/state/PanelTrack.java b/src/com/android/gallery3d/filtershow/state/PanelTrack.java deleted file mode 100644 index d02207d9b..000000000 --- a/src/com/android/gallery3d/filtershow/state/PanelTrack.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.state; - -import android.graphics.Point; -import android.view.MotionEvent; -import android.view.View; -import android.widget.Adapter; - -public interface PanelTrack { - public int getOrientation(); - public void onTouch(MotionEvent event, StateView view); - public StateView getCurrentView(); - public void setCurrentView(View view); - public Point getTouchPoint(); - public View findChildAt(int x, int y); - public int findChild(View view); - public Adapter getAdapter(); - public void fillContent(boolean value); - public View getChildAt(int pos); - public void setExited(boolean value); - public void checkEndState(); -} diff --git a/src/com/android/gallery3d/filtershow/state/State.java b/src/com/android/gallery3d/filtershow/state/State.java deleted file mode 100644 index e7dedd6a2..000000000 --- a/src/com/android/gallery3d/filtershow/state/State.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.state; - -import com.android.gallery3d.filtershow.filters.FilterFxRepresentation; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; - -public class State { - private String mText; - private int mType; - private FilterRepresentation mFilterRepresentation; - - public State(State state) { - this(state.getText(), state.getType()); - } - - public State(String text) { - this(text, StateView.DEFAULT); - } - - public State(String text, int type) { - mText = text; - mType = type; - } - - public boolean equals(State state) { - if (mFilterRepresentation.getFilterClass() - != state.mFilterRepresentation.getFilterClass()) { - return false; - } - if (mFilterRepresentation instanceof FilterFxRepresentation) { - return mFilterRepresentation.equals(state.getFilterRepresentation()); - } - return true; - } - - public boolean isDraggable() { - return mFilterRepresentation != null; - } - - String getText() { - return mText; - } - - void setText(String text) { - mText = text; - } - - int getType() { - return mType; - } - - void setType(int type) { - mType = type; - } - - public FilterRepresentation getFilterRepresentation() { - return mFilterRepresentation; - } - - public void setFilterRepresentation(FilterRepresentation filterRepresentation) { - mFilterRepresentation = filterRepresentation; - } -} diff --git a/src/com/android/gallery3d/filtershow/state/StateAdapter.java b/src/com/android/gallery3d/filtershow/state/StateAdapter.java deleted file mode 100644 index 522585280..000000000 --- a/src/com/android/gallery3d/filtershow/state/StateAdapter.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.state; - -import android.content.Context; -import android.util.Log; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -import java.util.Vector; - -public class StateAdapter extends ArrayAdapter<State> { - - private static final String LOGTAG = "StateAdapter"; - private int mOrientation; - private String mOriginalText; - private String mResultText; - - public StateAdapter(Context context, int textViewResourceId) { - super(context, textViewResourceId); - mOriginalText = context.getString(R.string.state_panel_original); - mResultText = context.getString(R.string.state_panel_result); - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - StateView view = null; - if (convertView == null) { - convertView = new StateView(getContext()); - } - view = (StateView) convertView; - State state = getItem(position); - view.setState(state); - view.setOrientation(mOrientation); - FilterRepresentation currentRep = MasterImage.getImage().getCurrentFilterRepresentation(); - FilterRepresentation stateRep = state.getFilterRepresentation(); - if (currentRep != null && stateRep != null - && currentRep.getFilterClass() == stateRep.getFilterClass() - && currentRep.getEditorId() != ImageOnlyEditor.ID) { - view.setSelected(true); - } else { - view.setSelected(false); - } - return view; - } - - public boolean contains(State state) { - for (int i = 0; i < getCount(); i++) { - if (state == getItem(i)) { - return true; - } - } - return false; - } - - public void setOrientation(int orientation) { - mOrientation = orientation; - } - - public void addOriginal() { - add(new State(mOriginalText)); - } - - public boolean same(Vector<State> states) { - // we have the original state in addition - if (states.size() + 1 != getCount()) { - return false; - } - for (int i = 1; i < getCount(); i++) { - State state = getItem(i); - if (!state.equals(states.elementAt(i-1))) { - return false; - } - } - return true; - } - - public void fill(Vector<State> states) { - if (same(states)) { - return; - } - clear(); - addOriginal(); - addAll(states); - notifyDataSetChanged(); - } - - @Override - public void remove(State state) { - super.remove(state); - FilterRepresentation filterRepresentation = state.getFilterRepresentation(); - FilterShowActivity activity = (FilterShowActivity) getContext(); - activity.removeFilterRepresentation(filterRepresentation); - } -} diff --git a/src/com/android/gallery3d/filtershow/state/StatePanel.java b/src/com/android/gallery3d/filtershow/state/StatePanel.java deleted file mode 100644 index df470f23e..000000000 --- a/src/com/android/gallery3d/filtershow/state/StatePanel.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.state; - -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.util.Log; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.LinearLayout; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class StatePanel extends Fragment { - private static final String LOGTAG = "StatePanel"; - private StatePanelTrack track; - private LinearLayout mMainView; - public static final String FRAGMENT_TAG = "StatePanel"; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - mMainView = (LinearLayout) inflater.inflate(R.layout.filtershow_state_panel_new, null); - View panel = mMainView.findViewById(R.id.listStates); - track = (StatePanelTrack) panel; - track.setAdapter(MasterImage.getImage().getState()); - return mMainView; - } -} diff --git a/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java b/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java deleted file mode 100644 index fff7e7f5f..000000000 --- a/src/com/android/gallery3d/filtershow/state/StatePanelTrack.java +++ /dev/null @@ -1,351 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.state; - -import android.animation.LayoutTransition; -import android.content.Context; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.graphics.Canvas; -import android.graphics.Point; -import android.graphics.Rect; -import android.util.AttributeSet; -import android.util.Log; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Adapter; -import android.widget.LinearLayout; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.editors.ImageOnlyEditor; -import com.android.gallery3d.filtershow.filters.FilterRepresentation; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class StatePanelTrack extends LinearLayout implements PanelTrack { - - private static final String LOGTAG = "StatePanelTrack"; - private Point mTouchPoint; - private StateView mCurrentView; - private StateView mCurrentSelectedView; - private boolean mExited = false; - private boolean mStartedDrag = false; - private StateAdapter mAdapter; - private DragListener mDragListener = new DragListener(this); - private float mDeleteSlope = 0.2f; - private GestureDetector mGestureDetector; - private int mElemWidth; - private int mElemHeight; - private int mElemSize; - private int mElemEndSize; - private int mEndElemWidth; - private int mEndElemHeight; - private long mTouchTime; - private int mMaxTouchDelay = 300; // 300ms delay for touch - private static final boolean ALLOWS_DRAG = false; - private DataSetObserver mObserver = new DataSetObserver() { - @Override - public void onChanged() { - super.onChanged(); - fillContent(false); - } - - @Override - public void onInvalidated() { - super.onInvalidated(); - fillContent(false); - } - }; - - public StatePanelTrack(Context context, AttributeSet attrs) { - super(context, attrs); - TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.StatePanelTrack); - mElemSize = a.getDimensionPixelSize(R.styleable.StatePanelTrack_elemSize, 0); - mElemEndSize = a.getDimensionPixelSize(R.styleable.StatePanelTrack_elemEndSize, 0); - if (getOrientation() == LinearLayout.HORIZONTAL) { - mElemWidth = mElemSize; - mElemHeight = LayoutParams.MATCH_PARENT; - mEndElemWidth = mElemEndSize; - mEndElemHeight = LayoutParams.MATCH_PARENT; - } else { - mElemWidth = LayoutParams.MATCH_PARENT; - mElemHeight = mElemSize; - mEndElemWidth = LayoutParams.MATCH_PARENT; - mEndElemHeight = mElemEndSize; - } - GestureDetector.SimpleOnGestureListener simpleOnGestureListener - = new GestureDetector.SimpleOnGestureListener(){ - @Override - public void onLongPress(MotionEvent e) { - longPress(e); - } - @Override - public boolean onDoubleTap(MotionEvent e) { - addDuplicate(e); - return true; - } - }; - mGestureDetector = new GestureDetector(context, simpleOnGestureListener); - } - - private void addDuplicate(MotionEvent e) { - if (mCurrentSelectedView == null) { - return; - } - int pos = findChild(mCurrentSelectedView); - if (pos != -1) { - mAdapter.insert(new State(mCurrentSelectedView.getState()), pos); - fillContent(true); - } - } - - private void longPress(MotionEvent e) { - View view = findChildAt((int) e.getX(), (int) e.getY()); - if (view == null) { - return; - } - if (view instanceof StateView) { - StateView stateView = (StateView) view; - stateView.setDuplicateButton(true); - } - } - - public void setAdapter(StateAdapter adapter) { - mAdapter = adapter; - mAdapter.registerDataSetObserver(mObserver); - mAdapter.setOrientation(getOrientation()); - fillContent(false); - requestLayout(); - } - - public StateView findChildWithState(State state) { - for (int i = 0; i < getChildCount(); i++) { - StateView view = (StateView) getChildAt(i); - if (view.getState() == state) { - return view; - } - } - return null; - } - - public void fillContent(boolean animate) { - if (!animate) { - this.setLayoutTransition(null); - } - int n = mAdapter.getCount(); - for (int i = 0; i < getChildCount(); i++) { - StateView child = (StateView) getChildAt(i); - child.resetPosition(); - if (!mAdapter.contains(child.getState())) { - removeView(child); - } - } - LayoutParams params = new LayoutParams(mElemWidth, mElemHeight); - for (int i = 0; i < n; i++) { - State s = mAdapter.getItem(i); - if (findChildWithState(s) == null) { - View view = mAdapter.getView(i, null, this); - addView(view, i, params); - } - } - - for (int i = 0; i < n; i++) { - State state = mAdapter.getItem(i); - StateView view = (StateView) getChildAt(i); - view.setState(state); - if (i == 0) { - view.setType(StateView.BEGIN); - } else if (i == n - 1) { - view.setType(StateView.END); - } else { - view.setType(StateView.DEFAULT); - } - view.resetPosition(); - } - - if (!animate) { - this.setLayoutTransition(new LayoutTransition()); - } - } - - public void onTouch(MotionEvent event, StateView view) { - if (!view.isDraggable()) { - return; - } - mCurrentView = view; - if (mCurrentSelectedView == mCurrentView) { - return; - } - if (mCurrentSelectedView != null) { - mCurrentSelectedView.setSelected(false); - } - // We changed the current view -- let's reset the - // gesture detector. - MotionEvent cancelEvent = MotionEvent.obtain(event); - cancelEvent.setAction(MotionEvent.ACTION_CANCEL); - mGestureDetector.onTouchEvent(cancelEvent); - mCurrentSelectedView = mCurrentView; - // We have to send the event to the gesture detector - mGestureDetector.onTouchEvent(event); - mTouchTime = System.currentTimeMillis(); - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent event) { - if (mCurrentView != null) { - return true; - } - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (mCurrentView == null) { - return false; - } - if (mTouchTime == 0) { - mTouchTime = System.currentTimeMillis(); - } - mGestureDetector.onTouchEvent(event); - if (mTouchPoint == null) { - mTouchPoint = new Point(); - mTouchPoint.x = (int) event.getX(); - mTouchPoint.y = (int) event.getY(); - } - - if (event.getActionMasked() == MotionEvent.ACTION_MOVE) { - float translation = event.getY() - mTouchPoint.y; - float alpha = 1.0f - (Math.abs(translation) / mCurrentView.getHeight()); - if (getOrientation() == LinearLayout.VERTICAL) { - translation = event.getX() - mTouchPoint.x; - alpha = 1.0f - (Math.abs(translation) / mCurrentView.getWidth()); - mCurrentView.setTranslationX(translation); - } else { - mCurrentView.setTranslationY(translation); - } - mCurrentView.setBackgroundAlpha(alpha); - if (ALLOWS_DRAG && alpha < 0.7) { - setOnDragListener(mDragListener); - DragShadowBuilder shadowBuilder = new DragShadowBuilder(mCurrentView); - mCurrentView.startDrag(null, shadowBuilder, mCurrentView, 0); - mStartedDrag = true; - } - } - if (!mExited && mCurrentView != null - && mCurrentView.getBackgroundAlpha() > mDeleteSlope - && event.getActionMasked() == MotionEvent.ACTION_UP - && System.currentTimeMillis() - mTouchTime < mMaxTouchDelay) { - FilterRepresentation representation = mCurrentView.getState().getFilterRepresentation(); - mCurrentView.setSelected(true); - if (representation != MasterImage.getImage().getCurrentFilterRepresentation()) { - FilterShowActivity activity = (FilterShowActivity) getContext(); - activity.showRepresentation(representation); - mCurrentView.setSelected(false); - } - } - if (event.getActionMasked() == MotionEvent.ACTION_UP - || (!mStartedDrag && event.getActionMasked() == MotionEvent.ACTION_CANCEL)) { - checkEndState(); - if (mCurrentView != null) { - FilterRepresentation representation = mCurrentView.getState().getFilterRepresentation(); - if (representation.getEditorId() == ImageOnlyEditor.ID) { - mCurrentView.setSelected(false); - } - } - } - return true; - } - - public void checkEndState() { - mTouchPoint = null; - mTouchTime = 0; - if (mExited || mCurrentView.getBackgroundAlpha() < mDeleteSlope) { - int origin = findChild(mCurrentView); - if (origin != -1) { - State current = mAdapter.getItem(origin); - FilterRepresentation currentRep = MasterImage.getImage().getCurrentFilterRepresentation(); - FilterRepresentation removedRep = current.getFilterRepresentation(); - mAdapter.remove(current); - fillContent(true); - if (currentRep != null && removedRep != null - && currentRep.getFilterClass() == removedRep.getFilterClass()) { - FilterShowActivity activity = (FilterShowActivity) getContext(); - activity.backToMain(); - return; - } - } - } else { - mCurrentView.setBackgroundAlpha(1.0f); - mCurrentView.setTranslationX(0); - mCurrentView.setTranslationY(0); - } - if (mCurrentSelectedView != null) { - mCurrentSelectedView.invalidate(); - } - if (mCurrentView != null) { - mCurrentView.invalidate(); - } - mCurrentView = null; - mExited = false; - mStartedDrag = false; - } - - public View findChildAt(int x, int y) { - Rect frame = new Rect(); - int scrolledXInt = getScrollX() + x; - int scrolledYInt = getScrollY() + y; - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - child.getHitRect(frame); - if (frame.contains(scrolledXInt, scrolledYInt)) { - return child; - } - } - return null; - } - - public int findChild(View view) { - for (int i = 0; i < getChildCount(); i++) { - View child = getChildAt(i); - if (child == view) { - return i; - } - } - return -1; - } - - public StateView getCurrentView() { - return mCurrentView; - } - - public void setCurrentView(View currentView) { - mCurrentView = (StateView) currentView; - } - - public void setExited(boolean value) { - mExited = value; - } - - public Point getTouchPoint() { - return mTouchPoint; - } - - public Adapter getAdapter() { - return mAdapter; - } -} diff --git a/src/com/android/gallery3d/filtershow/state/StateView.java b/src/com/android/gallery3d/filtershow/state/StateView.java deleted file mode 100644 index 73d57846a..000000000 --- a/src/com/android/gallery3d/filtershow/state/StateView.java +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.state; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.*; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewParent; -import android.widget.LinearLayout; -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.imageshow.MasterImage; - -public class StateView extends View { - - private static final String LOGTAG = "StateView"; - private Path mPath = new Path(); - private Paint mPaint = new Paint(); - - public static int DEFAULT = 0; - public static int BEGIN = 1; - public static int END = 2; - - public static int UP = 1; - public static int DOWN = 2; - public static int LEFT = 3; - public static int RIGHT = 4; - - private int mType = DEFAULT; - private float mAlpha = 1.0f; - private String mText = "Default"; - private float mTextSize = 32; - private static int sMargin = 16; - private static int sArrowHeight = 16; - private static int sArrowWidth = 8; - private int mOrientation = LinearLayout.VERTICAL; - private int mDirection = DOWN; - private boolean mDuplicateButton; - private State mState; - - private int mEndsBackgroundColor; - private int mEndsTextColor; - private int mBackgroundColor; - private int mTextColor; - private int mSelectedBackgroundColor; - private int mSelectedTextColor; - private Rect mTextBounds = new Rect(); - - public StateView(Context context) { - this(context, DEFAULT); - } - - public StateView(Context context, int type) { - super(context); - mType = type; - Resources res = getResources(); - mEndsBackgroundColor = res.getColor(R.color.filtershow_stateview_end_background); - mEndsTextColor = res.getColor(R.color.filtershow_stateview_end_text); - mBackgroundColor = res.getColor(R.color.filtershow_stateview_background); - mTextColor = res.getColor(R.color.filtershow_stateview_text); - mSelectedBackgroundColor = res.getColor(R.color.filtershow_stateview_selected_background); - mSelectedTextColor = res.getColor(R.color.filtershow_stateview_selected_text); - mTextSize = res.getDimensionPixelSize(R.dimen.state_panel_text_size); - } - - public String getText() { - return mText; - } - - public void setText(String text) { - mText = text; - invalidate(); - } - - public void setType(int type) { - mType = type; - invalidate(); - } - - @Override - public void setSelected(boolean value) { - super.setSelected(value); - if (!value) { - mDuplicateButton = false; - } - invalidate(); - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { - ViewParent parent = getParent(); - if (parent instanceof PanelTrack) { - ((PanelTrack) getParent()).onTouch(event, this); - } - if (mType == BEGIN) { - MasterImage.getImage().setShowsOriginal(true); - } - } - if (event.getActionMasked() == MotionEvent.ACTION_UP - || event.getActionMasked() == MotionEvent.ACTION_CANCEL) { - MasterImage.getImage().setShowsOriginal(false); - } - return true; - } - - public void drawText(Canvas canvas) { - if (mText == null) { - return; - } - mPaint.reset(); - if (isSelected()) { - mPaint.setColor(mSelectedTextColor); - } else { - mPaint.setColor(mTextColor); - } - if (mType == BEGIN) { - mPaint.setColor(mEndsTextColor); - } - mPaint.setTypeface(Typeface.DEFAULT_BOLD); - mPaint.setAntiAlias(true); - mPaint.setTextSize(mTextSize); - mPaint.getTextBounds(mText, 0, mText.length(), mTextBounds); - int x = (canvas.getWidth() - mTextBounds.width()) / 2; - int y = mTextBounds.height() + (canvas.getHeight() - mTextBounds.height()) / 2; - canvas.drawText(mText, x, y, mPaint); - } - - public void onDraw(Canvas canvas) { - canvas.drawARGB(0, 0, 0, 0); - mPaint.reset(); - mPath.reset(); - - float w = canvas.getWidth(); - float h = canvas.getHeight(); - float r = sArrowHeight; - float d = sArrowWidth; - - if (mOrientation == LinearLayout.HORIZONTAL) { - drawHorizontalPath(w, h, r, d); - } else { - if (mDirection == DOWN) { - drawVerticalDownPath(w, h, r, d); - } else { - drawVerticalPath(w, h, r, d); - } - } - - if (mType == DEFAULT || mType == END) { - if (mDuplicateButton) { - mPaint.setARGB(255, 200, 0, 0); - } else if (isSelected()) { - mPaint.setColor(mSelectedBackgroundColor); - } else { - mPaint.setColor(mBackgroundColor); - } - } else { - mPaint.setColor(mEndsBackgroundColor); - } - canvas.drawPath(mPath, mPaint); - drawText(canvas); - } - - private void drawHorizontalPath(float w, float h, float r, float d) { - mPath.moveTo(0, 0); - if (mType == END) { - mPath.lineTo(w, 0); - mPath.lineTo(w, h); - } else { - mPath.lineTo(w - d, 0); - mPath.lineTo(w - d, r); - mPath.lineTo(w, r + d); - mPath.lineTo(w - d, r + d + r); - mPath.lineTo(w - d, h); - } - mPath.lineTo(0, h); - if (mType != BEGIN) { - mPath.lineTo(0, r + d + r); - mPath.lineTo(d, r + d); - mPath.lineTo(0, r); - } - mPath.close(); - } - - private void drawVerticalPath(float w, float h, float r, float d) { - if (mType == BEGIN) { - mPath.moveTo(0, 0); - mPath.lineTo(w, 0); - } else { - mPath.moveTo(0, d); - mPath.lineTo(r, d); - mPath.lineTo(r + d, 0); - mPath.lineTo(r + d + r, d); - mPath.lineTo(w, d); - } - mPath.lineTo(w, h); - if (mType != END) { - mPath.lineTo(r + d + r, h); - mPath.lineTo(r + d, h - d); - mPath.lineTo(r, h); - } - mPath.lineTo(0, h); - mPath.close(); - } - - private void drawVerticalDownPath(float w, float h, float r, float d) { - mPath.moveTo(0, 0); - if (mType != BEGIN) { - mPath.lineTo(r, 0); - mPath.lineTo(r + d, d); - mPath.lineTo(r + d + r, 0); - } - mPath.lineTo(w, 0); - - if (mType != END) { - mPath.lineTo(w, h - d); - - mPath.lineTo(r + d + r, h - d); - mPath.lineTo(r + d, h); - mPath.lineTo(r, h - d); - - mPath.lineTo(0, h - d); - } else { - mPath.lineTo(w, h); - mPath.lineTo(0, h); - } - - mPath.close(); - } - - public void setBackgroundAlpha(float alpha) { - if (mType == BEGIN) { - return; - } - mAlpha = alpha; - setAlpha(alpha); - invalidate(); - } - - public float getBackgroundAlpha() { - return mAlpha; - } - - public void setOrientation(int orientation) { - mOrientation = orientation; - } - - public void setDuplicateButton(boolean b) { - mDuplicateButton = b; - invalidate(); - } - - public State getState() { - return mState; - } - - public void setState(State state) { - mState = state; - mText = mState.getText().toUpperCase(); - mType = mState.getType(); - invalidate(); - } - - public void resetPosition() { - setTranslationX(0); - setTranslationY(0); - setBackgroundAlpha(1.0f); - } - - public boolean isDraggable() { - return mState.isDraggable(); - } -} diff --git a/src/com/android/gallery3d/filtershow/tools/IconFactory.java b/src/com/android/gallery3d/filtershow/tools/IconFactory.java deleted file mode 100644 index 9e39f27fc..000000000 --- a/src/com/android/gallery3d/filtershow/tools/IconFactory.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Rect; -import android.graphics.RectF; - -/** - * A factory class for producing bitmaps to use as UI icons. - */ -public class IconFactory { - - /** - * Builds an icon with the dimensions iconWidth:iconHeight. If scale is set - * the source image is stretched to fit within the given dimensions; - * otherwise, the source image is cropped to the proper aspect ratio. - * - * @param sourceImage image to create an icon from. - * @param iconWidth width of the icon bitmap. - * @param iconHeight height of the icon bitmap. - * @param scale if true, stretch sourceImage to fit the icon dimensions. - * @return an icon bitmap with the dimensions iconWidth:iconHeight. - */ - public static Bitmap createIcon(Bitmap sourceImage, int iconWidth, int iconHeight, - boolean scale) { - if (sourceImage == null) { - throw new IllegalArgumentException("Null argument to buildIcon"); - } - - int sourceWidth = sourceImage.getWidth(); - int sourceHeight = sourceImage.getHeight(); - - if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) { - throw new IllegalArgumentException("Bitmap with dimension 0 used as input"); - } - - Bitmap icon = Bitmap.createBitmap(iconWidth, iconHeight, - Bitmap.Config.ARGB_8888); - drawIcon(icon, sourceImage, scale); - return icon; - } - - /** - * Draws an icon in the destination bitmap. If scale is set the source image - * is stretched to fit within the destination dimensions; otherwise, the - * source image is cropped to the proper aspect ratio. - * - * @param dest bitmap into which to draw the icon. - * @param sourceImage image to create an icon from. - * @param scale if true, stretch sourceImage to fit the destination. - */ - public static void drawIcon(Bitmap dest, Bitmap sourceImage, boolean scale) { - if (dest == null || sourceImage == null) { - throw new IllegalArgumentException("Null argument to buildIcon"); - } - - int sourceWidth = sourceImage.getWidth(); - int sourceHeight = sourceImage.getHeight(); - int iconWidth = dest.getWidth(); - int iconHeight = dest.getHeight(); - - if (sourceWidth == 0 || sourceHeight == 0 || iconWidth == 0 || iconHeight == 0) { - throw new IllegalArgumentException("Bitmap with dimension 0 used as input"); - } - - Rect destRect = new Rect(0, 0, iconWidth, iconHeight); - Canvas canvas = new Canvas(dest); - - Rect srcRect = null; - if (scale) { - // scale image to fit in icon (stretches if aspect isn't the same) - srcRect = new Rect(0, 0, sourceWidth, sourceHeight); - } else { - // crop image to aspect ratio iconWidth:iconHeight - float wScale = sourceWidth / (float) iconWidth; - float hScale = sourceHeight / (float) iconHeight; - float s = Math.min(hScale, wScale); - - float iw = iconWidth * s; - float ih = iconHeight * s; - - float borderW = (sourceWidth - iw) / 2.0f; - float borderH = (sourceHeight - ih) / 2.0f; - RectF rec = new RectF(borderW, borderH, borderW + iw, borderH + ih); - srcRect = new Rect(); - rec.roundOut(srcRect); - } - - canvas.drawBitmap(sourceImage, srcRect, destRect, new Paint(Paint.FILTER_BITMAP_FLAG)); - } -} diff --git a/src/com/android/gallery3d/filtershow/tools/MatrixFit.java b/src/com/android/gallery3d/filtershow/tools/MatrixFit.java deleted file mode 100644 index 3b815673c..000000000 --- a/src/com/android/gallery3d/filtershow/tools/MatrixFit.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.util.Log; - -public class MatrixFit { - // Simple implementation of a matrix fit in N dimensions. - - private static final String LOGTAG = "MatrixFit"; - - private double[][] mMatrix; - private int mDimension; - private boolean mValid = false; - private static double sEPS = 1.0f/10000000000.0f; - - public MatrixFit(double[][] from, double[][] to) { - mValid = fit(from, to); - } - - public int getDimension() { - return mDimension; - } - - public boolean isValid() { - return mValid; - } - - public double[][] getMatrix() { - return mMatrix; - } - - public boolean fit(double[][] from, double[][] to) { - if ((from.length != to.length) || (from.length < 1)) { - Log.e(LOGTAG, "from and to must be of same size"); - return false; - } - - mDimension = from[0].length; - mMatrix = new double[mDimension +1][mDimension + mDimension +1]; - - if (from.length < mDimension) { - Log.e(LOGTAG, "Too few points => under-determined system"); - return false; - } - - double[][] q = new double[from.length][mDimension]; - for (int i = 0; i < from.length; i++) { - for (int j = 0; j < mDimension; j++) { - q[i][j] = from[i][j]; - } - } - - double[][] p = new double[to.length][mDimension]; - for (int i = 0; i < to.length; i++) { - for (int j = 0; j < mDimension; j++) { - p[i][j] = to[i][j]; - } - } - - // Make an empty (dim) x (dim + 1) matrix and fill it - double[][] c = new double[mDimension+1][mDimension]; - for (int j = 0; j < mDimension; j++) { - for (int k = 0; k < mDimension + 1; k++) { - for (int i = 0; i < q.length; i++) { - double qt = 1; - if (k < mDimension) { - qt = q[i][k]; - } - c[k][j] += qt * p[i][j]; - } - } - } - - // Make an empty (dim+1) x (dim+1) matrix and fill it - double[][] Q = new double[mDimension+1][mDimension+1]; - for (int qi = 0; qi < q.length; qi++) { - double[] qt = new double[mDimension + 1]; - for (int i = 0; i < mDimension; i++) { - qt[i] = q[qi][i]; - } - qt[mDimension] = 1; - for (int i = 0; i < mDimension + 1; i++) { - for (int j = 0; j < mDimension + 1; j++) { - Q[i][j] += qt[i] * qt[j]; - } - } - } - - // Use a gaussian elimination to solve the linear system - for (int i = 0; i < mDimension + 1; i++) { - for (int j = 0; j < mDimension + 1; j++) { - mMatrix[i][j] = Q[i][j]; - } - for (int j = 0; j < mDimension; j++) { - mMatrix[i][mDimension + 1 + j] = c[i][j]; - } - } - if (!gaussianElimination(mMatrix)) { - return false; - } - return true; - } - - public double[] apply(double[] point) { - if (mDimension != point.length) { - return null; - } - double[] res = new double[mDimension]; - for (int j = 0; j < mDimension; j++) { - for (int i = 0; i < mDimension; i++) { - res[j] += point[i] * mMatrix[i][j+ mDimension +1]; - } - res[j] += mMatrix[mDimension][j+ mDimension +1]; - } - return res; - } - - public void printEquation() { - for (int j = 0; j < mDimension; j++) { - String str = "x" + j + "' = "; - for (int i = 0; i < mDimension; i++) { - str += "x" + i + " * " + mMatrix[i][j+mDimension+1] + " + "; - } - str += mMatrix[mDimension][j+mDimension+1]; - Log.v(LOGTAG, str); - } - } - - private void printMatrix(String name, double[][] matrix) { - Log.v(LOGTAG, "name: " + name); - for (int i = 0; i < matrix.length; i++) { - String str = ""; - for (int j = 0; j < matrix[0].length; j++) { - str += "" + matrix[i][j] + " "; - } - Log.v(LOGTAG, str); - } - } - - /* - * Transforms the given matrix into a row echelon matrix - */ - private boolean gaussianElimination(double[][] m) { - int h = m.length; - int w = m[0].length; - - for (int y = 0; y < h; y++) { - int maxrow = y; - for (int y2 = y + 1; y2 < h; y2++) { // Find max pivot - if (Math.abs(m[y2][y]) > Math.abs(m[maxrow][y])) { - maxrow = y2; - } - } - // swap - for (int i = 0; i < mDimension; i++) { - double t = m[y][i]; - m[y][i] = m[maxrow][i]; - m[maxrow][i] = t; - } - - if (Math.abs(m[y][y]) <= sEPS) { // Singular Matrix - return false; - } - for (int y2 = y + 1; y2 < h; y2++) { // Eliminate column y - double c = m[y2][y] / m[y][y]; - for (int x = y; x < w; x++) { - m[y2][x] -= m[y][x] * c; - } - } - } - for (int y = h -1; y > -1; y--) { // Back substitution - double c = m[y][y]; - for (int y2 = 0; y2 < y; y2++) { - for (int x = w - 1; x > y - 1; x--) { - m[y2][x] -= m[y][x] * m[y2][y] / c; - } - } - m[y][y] /= c; - for (int x = h; x < w; x++) { // Normalize row y - m[y][x] /= c; - } - } - return true; - } -} diff --git a/src/com/android/gallery3d/filtershow/tools/SaveImage.java b/src/com/android/gallery3d/filtershow/tools/SaveImage.java deleted file mode 100644 index 83cbd0136..000000000 --- a/src/com/android/gallery3d/filtershow/tools/SaveImage.java +++ /dev/null @@ -1,632 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.Intent; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore; -import android.provider.MediaStore.Images; -import android.provider.MediaStore.Images.ImageColumns; -import android.util.Log; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.exif.ExifInterface; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.cache.ImageLoader; -import com.android.gallery3d.filtershow.filters.FiltersManager; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.CachingPipeline; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.filtershow.pipeline.ProcessingService; -import com.android.gallery3d.util.UsageStatistics; -import com.android.gallery3d.util.XmpUtilHelper; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.sql.Date; -import java.text.SimpleDateFormat; -import java.util.TimeZone; - -/** - * Handles saving edited photo - */ -public class SaveImage { - private static final String LOGTAG = "SaveImage"; - - /** - * Callback for updates - */ - public interface Callback { - void onProgress(int max, int current); - } - - public interface ContentResolverQueryCallback { - void onCursorResult(Cursor cursor); - } - - private static final String TIME_STAMP_NAME = "_yyyyMMdd_HHmmss"; - private static final String PREFIX_PANO = "PANO"; - private static final String PREFIX_IMG = "IMG"; - private static final String POSTFIX_JPG = ".jpg"; - private static final String AUX_DIR_NAME = ".aux"; - - private final Context mContext; - private final Uri mSourceUri; - private final Callback mCallback; - private final File mDestinationFile; - private final Uri mSelectedImageUri; - - private int mCurrentProcessingStep = 1; - - public static final int MAX_PROCESSING_STEPS = 6; - public static final String DEFAULT_SAVE_DIRECTORY = "EditedOnlinePhotos"; - - // In order to support the new edit-save behavior such that user won't see - // the edited image together with the original image, we are adding a new - // auxiliary directory for the edited image. Basically, the original image - // will be hidden in that directory after edit and user will see the edited - // image only. - // Note that deletion on the edited image will also cause the deletion of - // the original image under auxiliary directory. - // - // There are several situations we need to consider: - // 1. User edit local image local01.jpg. A local02.jpg will be created in the - // same directory, and original image will be moved to auxiliary directory as - // ./.aux/local02.jpg. - // If user edit the local02.jpg, local03.jpg will be created in the local - // directory and ./.aux/local02.jpg will be renamed to ./.aux/local03.jpg - // - // 2. User edit remote image remote01.jpg from picassa or other server. - // remoteSavedLocal01.jpg will be saved under proper local directory. - // In remoteSavedLocal01.jpg, there will be a reference pointing to the - // remote01.jpg. There will be no local copy of remote01.jpg. - // If user edit remoteSavedLocal01.jpg, then a new remoteSavedLocal02.jpg - // will be generated and still pointing to the remote01.jpg - // - // 3. User delete any local image local.jpg. - // Since the filenames are kept consistent in auxiliary directory, every - // time a local.jpg get deleted, the files in auxiliary directory whose - // names starting with "local." will be deleted. - // This pattern will facilitate the multiple images deletion in the auxiliary - // directory. - - /** - * @param context - * @param sourceUri The Uri for the original image, which can be the hidden - * image under the auxiliary directory or the same as selectedImageUri. - * @param selectedImageUri The Uri for the image selected by the user. - * In most cases, it is a content Uri for local image or remote image. - * @param destination Destinaton File, if this is null, a new file will be - * created under the same directory as selectedImageUri. - * @param callback Let the caller know the saving has completed. - * @return the newSourceUri - */ - public SaveImage(Context context, Uri sourceUri, Uri selectedImageUri, - File destination, Callback callback) { - mContext = context; - mSourceUri = sourceUri; - mCallback = callback; - if (destination == null) { - mDestinationFile = getNewFile(context, selectedImageUri); - } else { - mDestinationFile = destination; - } - - mSelectedImageUri = selectedImageUri; - } - - public static File getFinalSaveDirectory(Context context, Uri sourceUri) { - File saveDirectory = SaveImage.getSaveDirectory(context, sourceUri); - if ((saveDirectory == null) || !saveDirectory.canWrite()) { - saveDirectory = new File(Environment.getExternalStorageDirectory(), - SaveImage.DEFAULT_SAVE_DIRECTORY); - } - // Create the directory if it doesn't exist - if (!saveDirectory.exists()) - saveDirectory.mkdirs(); - return saveDirectory; - } - - public static File getNewFile(Context context, Uri sourceUri) { - File saveDirectory = getFinalSaveDirectory(context, sourceUri); - String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date( - System.currentTimeMillis())); - if (hasPanoPrefix(context, sourceUri)) { - return new File(saveDirectory, PREFIX_PANO + filename + POSTFIX_JPG); - } - return new File(saveDirectory, PREFIX_IMG + filename + POSTFIX_JPG); - } - - /** - * Remove the files in the auxiliary directory whose names are the same as - * the source image. - * @param contentResolver The application's contentResolver - * @param srcContentUri The content Uri for the source image. - */ - public static void deleteAuxFiles(ContentResolver contentResolver, - Uri srcContentUri) { - final String[] fullPath = new String[1]; - String[] queryProjection = new String[] { ImageColumns.DATA }; - querySourceFromContentResolver(contentResolver, - srcContentUri, queryProjection, - new ContentResolverQueryCallback() { - @Override - public void onCursorResult(Cursor cursor) { - fullPath[0] = cursor.getString(0); - } - } - ); - if (fullPath[0] != null) { - // Construct the auxiliary directory given the source file's path. - // Then select and delete all the files starting with the same name - // under the auxiliary directory. - File currentFile = new File(fullPath[0]); - - String filename = currentFile.getName(); - int firstDotPos = filename.indexOf("."); - final String filenameNoExt = (firstDotPos == -1) ? filename : - filename.substring(0, firstDotPos); - File auxDir = getLocalAuxDirectory(currentFile); - if (auxDir.exists()) { - FilenameFilter filter = new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - if (name.startsWith(filenameNoExt + ".")) { - return true; - } else { - return false; - } - } - }; - - // Delete all auxiliary files whose name is matching the - // current local image. - File[] auxFiles = auxDir.listFiles(filter); - for (File file : auxFiles) { - file.delete(); - } - } - } - } - - public Object getPanoramaXMPData(Uri source, ImagePreset preset) { - Object xmp = null; - if (preset.isPanoramaSafe()) { - InputStream is = null; - try { - is = mContext.getContentResolver().openInputStream(source); - xmp = XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "Failed to get XMP data from image: ", e); - } finally { - Utils.closeSilently(is); - } - } - return xmp; - } - - public boolean putPanoramaXMPData(File file, Object xmp) { - if (xmp != null) { - return XmpUtilHelper.writeXMPMeta(file.getAbsolutePath(), xmp); - } - return false; - } - - public ExifInterface getExifData(Uri source) { - ExifInterface exif = new ExifInterface(); - String mimeType = mContext.getContentResolver().getType(mSelectedImageUri); - if (mimeType == null) { - mimeType = ImageLoader.getMimeType(mSelectedImageUri); - } - if (mimeType.equals(ImageLoader.JPEG_MIME_TYPE)) { - InputStream inStream = null; - try { - inStream = mContext.getContentResolver().openInputStream(source); - exif.readExif(inStream); - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "Cannot find file: " + source, e); - } catch (IOException e) { - Log.w(LOGTAG, "Cannot read exif for: " + source, e); - } finally { - Utils.closeSilently(inStream); - } - } - return exif; - } - - public boolean putExifData(File file, ExifInterface exif, Bitmap image, - int jpegCompressQuality) { - boolean ret = false; - OutputStream s = null; - try { - s = exif.getExifWriterStream(file.getAbsolutePath()); - image.compress(Bitmap.CompressFormat.JPEG, - (jpegCompressQuality > 0) ? jpegCompressQuality : 1, s); - s.flush(); - s.close(); - s = null; - ret = true; - } catch (FileNotFoundException e) { - Log.w(LOGTAG, "File not found: " + file.getAbsolutePath(), e); - } catch (IOException e) { - Log.w(LOGTAG, "Could not write exif: ", e); - } finally { - Utils.closeSilently(s); - } - return ret; - } - - private Uri resetToOriginalImageIfNeeded(ImagePreset preset, boolean doAuxBackup) { - Uri uri = null; - if (!preset.hasModifications()) { - // This can happen only when preset has no modification but save - // button is enabled, it means the file is loaded with filters in - // the XMP, then all the filters are removed or restore to default. - // In this case, when mSourceUri exists, rename it to the - // destination file. - File srcFile = getLocalFileFromUri(mContext, mSourceUri); - // If the source is not a local file, then skip this renaming and - // create a local copy as usual. - if (srcFile != null) { - srcFile.renameTo(mDestinationFile); - uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri, - mDestinationFile, System.currentTimeMillis(), doAuxBackup); - } - } - return uri; - } - - private void resetProgress() { - mCurrentProcessingStep = 0; - } - - private void updateProgress() { - if (mCallback != null) { - mCallback.onProgress(MAX_PROCESSING_STEPS, ++mCurrentProcessingStep); - } - } - - public Uri processAndSaveImage(ImagePreset preset, boolean doAuxBackup, int quality) { - - Uri uri = resetToOriginalImageIfNeeded(preset, doAuxBackup); - if (uri != null) { - return null; - } - - resetProgress(); - - boolean noBitmap = true; - int num_tries = 0; - int sampleSize = 1; - - // If necessary, move the source file into the auxiliary directory, - // newSourceUri is then pointing to the new location. - // If no file is moved, newSourceUri will be the same as mSourceUri. - Uri newSourceUri = mSourceUri; - if (doAuxBackup) { - newSourceUri = moveSrcToAuxIfNeeded(mSourceUri, mDestinationFile); - } - - // Stopgap fix for low-memory devices. - while (noBitmap) { - try { - updateProgress(); - // Try to do bitmap operations, downsample if low-memory - Bitmap bitmap = ImageLoader.loadOrientedBitmapWithBackouts(mContext, newSourceUri, - sampleSize); - if (bitmap == null) { - return null; - } - updateProgress(); - CachingPipeline pipeline = new CachingPipeline(FiltersManager.getManager(), - "Saving"); - - bitmap = pipeline.renderFinalImage(bitmap, preset); - updateProgress(); - - Object xmp = getPanoramaXMPData(newSourceUri, preset); - ExifInterface exif = getExifData(newSourceUri); - - updateProgress(); - // Set tags - long time = System.currentTimeMillis(); - exif.addDateTimeStampTag(ExifInterface.TAG_DATE_TIME, time, - TimeZone.getDefault()); - exif.setTag(exif.buildTag(ExifInterface.TAG_ORIENTATION, - ExifInterface.Orientation.TOP_LEFT)); - // Remove old thumbnail - exif.removeCompressedThumbnail(); - - updateProgress(); - - // If we succeed in writing the bitmap as a jpeg, return a uri. - if (putExifData(mDestinationFile, exif, bitmap, quality)) { - putPanoramaXMPData(mDestinationFile, xmp); - // mDestinationFile will save the newSourceUri info in the XMP. - XmpPresets.writeFilterXMP(mContext, newSourceUri, - mDestinationFile, preset); - - // After this call, mSelectedImageUri will be actually - // pointing at the new file mDestinationFile. - uri = SaveImage.linkNewFileToUri(mContext, mSelectedImageUri, - mDestinationFile, time, doAuxBackup); - } - updateProgress(); - - noBitmap = false; - UsageStatistics.onEvent(UsageStatistics.COMPONENT_EDITOR, - "SaveComplete", null); - } catch (OutOfMemoryError e) { - // Try 5 times before failing for good. - if (++num_tries >= 5) { - throw e; - } - System.gc(); - sampleSize *= 2; - resetProgress(); - } - } - return uri; - } - - /** - * Move the source file to auxiliary directory if needed and return the Uri - * pointing to this new source file. - * @param srcUri Uri to the source image. - * @param dstFile Providing the destination file info to help to build the - * auxiliary directory and new source file's name. - * @return the newSourceUri pointing to the new source image. - */ - private Uri moveSrcToAuxIfNeeded(Uri srcUri, File dstFile) { - File srcFile = getLocalFileFromUri(mContext, srcUri); - if (srcFile == null) { - Log.d(LOGTAG, "Source file is not a local file, no update."); - return srcUri; - } - - // Get the destination directory and create the auxilliary directory - // if necessary. - File auxDiretory = getLocalAuxDirectory(dstFile); - if (!auxDiretory.exists()) { - auxDiretory.mkdirs(); - } - - // Make sure there is a .nomedia file in the auxiliary directory, such - // that MediaScanner will not report those files under this directory. - File noMedia = new File(auxDiretory, ".nomedia"); - if (!noMedia.exists()) { - try { - noMedia.createNewFile(); - } catch (IOException e) { - Log.e(LOGTAG, "Can't create the nomedia"); - return srcUri; - } - } - // We are using the destination file name such that photos sitting in - // the auxiliary directory are matching the parent directory. - File newSrcFile = new File(auxDiretory, dstFile.getName()); - - if (!newSrcFile.exists()) { - srcFile.renameTo(newSrcFile); - } - - return Uri.fromFile(newSrcFile); - - } - - private static File getLocalAuxDirectory(File dstFile) { - File dstDirectory = dstFile.getParentFile(); - File auxDiretory = new File(dstDirectory + "/" + AUX_DIR_NAME); - return auxDiretory; - } - - public static Uri makeAndInsertUri(Context context, Uri sourceUri) { - long time = System.currentTimeMillis(); - String filename = new SimpleDateFormat(TIME_STAMP_NAME).format(new Date(time)); - File saveDirectory = getFinalSaveDirectory(context, sourceUri); - File file = new File(saveDirectory, filename + ".JPG"); - return linkNewFileToUri(context, sourceUri, file, time, false); - } - - public static void saveImage(ImagePreset preset, final FilterShowActivity filterShowActivity, - File destination) { - Uri selectedImageUri = filterShowActivity.getSelectedImageUri(); - Uri sourceImageUri = MasterImage.getImage().getUri(); - - Intent processIntent = ProcessingService.getSaveIntent(filterShowActivity, preset, - destination, selectedImageUri, sourceImageUri, false, 90); - - filterShowActivity.startService(processIntent); - - if (!filterShowActivity.isSimpleEditAction()) { - // terminate for now - filterShowActivity.completeSaveImage(selectedImageUri); - } - } - - public static void querySource(Context context, Uri sourceUri, String[] projection, - ContentResolverQueryCallback callback) { - ContentResolver contentResolver = context.getContentResolver(); - querySourceFromContentResolver(contentResolver, sourceUri, projection, callback); - } - - private static void querySourceFromContentResolver( - ContentResolver contentResolver, Uri sourceUri, String[] projection, - ContentResolverQueryCallback callback) { - Cursor cursor = null; - try { - cursor = contentResolver.query(sourceUri, projection, null, null, - null); - if ((cursor != null) && cursor.moveToNext()) { - callback.onCursorResult(cursor); - } - } catch (Exception e) { - // Ignore error for lacking the data column from the source. - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - private static File getSaveDirectory(Context context, Uri sourceUri) { - File file = getLocalFileFromUri(context, sourceUri); - if (file != null) { - return file.getParentFile(); - } else { - return null; - } - } - - /** - * Construct a File object based on the srcUri. - * @return The file object. Return null if srcUri is invalid or not a local - * file. - */ - private static File getLocalFileFromUri(Context context, Uri srcUri) { - if (srcUri == null) { - Log.e(LOGTAG, "srcUri is null."); - return null; - } - - String scheme = srcUri.getScheme(); - if (scheme == null) { - Log.e(LOGTAG, "scheme is null."); - return null; - } - - final File[] file = new File[1]; - // sourceUri can be a file path or a content Uri, it need to be handled - // differently. - if (scheme.equals(ContentResolver.SCHEME_CONTENT)) { - if (srcUri.getAuthority().equals(MediaStore.AUTHORITY)) { - querySource(context, srcUri, new String[] { - ImageColumns.DATA - }, - new ContentResolverQueryCallback() { - - @Override - public void onCursorResult(Cursor cursor) { - file[0] = new File(cursor.getString(0)); - } - }); - } - } else if (scheme.equals(ContentResolver.SCHEME_FILE)) { - file[0] = new File(srcUri.getPath()); - } - return file[0]; - } - - /** - * Gets the actual filename for a Uri from Gallery's ContentProvider. - */ - private static String getTrueFilename(Context context, Uri src) { - if (context == null || src == null) { - return null; - } - final String[] trueName = new String[1]; - querySource(context, src, new String[] { - ImageColumns.DATA - }, new ContentResolverQueryCallback() { - @Override - public void onCursorResult(Cursor cursor) { - trueName[0] = new File(cursor.getString(0)).getName(); - } - }); - return trueName[0]; - } - - /** - * Checks whether the true filename has the panorama image prefix. - */ - private static boolean hasPanoPrefix(Context context, Uri src) { - String name = getTrueFilename(context, src); - return name != null && name.startsWith(PREFIX_PANO); - } - - /** - * If the <code>sourceUri</code> is a local content Uri, update the - * <code>sourceUri</code> to point to the <code>file</code>. - * At the same time, the old file <code>sourceUri</code> used to point to - * will be removed if it is local. - * If the <code>sourceUri</code> is not a local content Uri, then the - * <code>file</code> will be inserted as a new content Uri. - * @return the final Uri referring to the <code>file</code>. - */ - public static Uri linkNewFileToUri(Context context, Uri sourceUri, - File file, long time, boolean deleteOriginal) { - File oldSelectedFile = getLocalFileFromUri(context, sourceUri); - final ContentValues values = new ContentValues(); - - time /= 1000; - values.put(Images.Media.TITLE, file.getName()); - values.put(Images.Media.DISPLAY_NAME, file.getName()); - values.put(Images.Media.MIME_TYPE, "image/jpeg"); - values.put(Images.Media.DATE_TAKEN, time); - values.put(Images.Media.DATE_MODIFIED, time); - values.put(Images.Media.DATE_ADDED, time); - values.put(Images.Media.ORIENTATION, 0); - values.put(Images.Media.DATA, file.getAbsolutePath()); - values.put(Images.Media.SIZE, file.length()); - - final String[] projection = new String[] { - ImageColumns.DATE_TAKEN, - ImageColumns.LATITUDE, ImageColumns.LONGITUDE, - }; - SaveImage.querySource(context, sourceUri, projection, - new SaveImage.ContentResolverQueryCallback() { - - @Override - public void onCursorResult(Cursor cursor) { - values.put(Images.Media.DATE_TAKEN, cursor.getLong(0)); - - double latitude = cursor.getDouble(1); - double longitude = cursor.getDouble(2); - // TODO: Change || to && after the default location - // issue is fixed. - if ((latitude != 0f) || (longitude != 0f)) { - values.put(Images.Media.LATITUDE, latitude); - values.put(Images.Media.LONGITUDE, longitude); - } - } - }); - - Uri result = sourceUri; - if (oldSelectedFile == null || !deleteOriginal) { - result = context.getContentResolver().insert( - Images.Media.EXTERNAL_CONTENT_URI, values); - } else { - context.getContentResolver().update(sourceUri, values, null, null); - if (oldSelectedFile.exists()) { - oldSelectedFile.delete(); - } - } - - return result; - } - -} diff --git a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java b/src/com/android/gallery3d/filtershow/tools/XmpPresets.java deleted file mode 100644 index 3995eeb85..000000000 --- a/src/com/android/gallery3d/filtershow/tools/XmpPresets.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.tools; - -import android.content.Context; -import android.net.Uri; -import android.util.Log; - -import com.adobe.xmp.XMPException; -import com.adobe.xmp.XMPMeta; -import com.adobe.xmp.XMPMetaFactory; -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ImagePreset; -import com.android.gallery3d.util.XmpUtilHelper; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.InputStream; - -public class XmpPresets { - public static final String - XMP_GOOGLE_FILTER_NAMESPACE = "http://ns.google.com/photos/1.0/filter/"; - public static final String XMP_GOOGLE_FILTER_PREFIX = "AFltr"; - public static final String XMP_SRC_FILE_URI = "SourceFileUri"; - public static final String XMP_FILTERSTACK = "filterstack"; - private static final String LOGTAG = "XmpPresets"; - - public static class XMresults { - public String presetString; - public ImagePreset preset; - public Uri originalimage; - } - - static { - try { - XMPMetaFactory.getSchemaRegistry().registerNamespace( - XMP_GOOGLE_FILTER_NAMESPACE, XMP_GOOGLE_FILTER_PREFIX); - } catch (XMPException e) { - Log.e(LOGTAG, "Register XMP name space failed", e); - } - } - - public static void writeFilterXMP( - Context context, Uri srcUri, File dstFile, ImagePreset preset) { - InputStream is = null; - XMPMeta xmpMeta = null; - try { - is = context.getContentResolver().openInputStream(srcUri); - xmpMeta = XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - - } finally { - Utils.closeSilently(is); - } - - if (xmpMeta == null) { - xmpMeta = XMPMetaFactory.create(); - } - try { - xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_SRC_FILE_URI, srcUri.toString()); - xmpMeta.setProperty(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_FILTERSTACK, preset.getJsonString(context.getString(R.string.saved))); - } catch (XMPException e) { - Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath()); - return; - } - - if (!XmpUtilHelper.writeXMPMeta(dstFile.getAbsolutePath(), xmpMeta)) { - Log.v(LOGTAG, "Write XMP meta to file failed:" + dstFile.getAbsolutePath()); - } - } - - public static XMresults extractXMPData( - Context context, MasterImage mMasterImage, Uri uriToEdit) { - XMresults ret = new XMresults(); - - InputStream is = null; - XMPMeta xmpMeta = null; - try { - is = context.getContentResolver().openInputStream(uriToEdit); - xmpMeta = XmpUtilHelper.extractXMPMeta(is); - } catch (FileNotFoundException e) { - } finally { - Utils.closeSilently(is); - } - - if (xmpMeta == null) { - return null; - } - - try { - String strSrcUri = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_SRC_FILE_URI); - - if (strSrcUri != null) { - String filterString = xmpMeta.getPropertyString(XMP_GOOGLE_FILTER_NAMESPACE, - XMP_FILTERSTACK); - - Uri srcUri = Uri.parse(strSrcUri); - ret.originalimage = srcUri; - - ret.preset = new ImagePreset(mMasterImage.getPreset()); - ret.presetString = filterString; - boolean ok = ret.preset.readJsonFromString(filterString); - if (!ok) { - return null; - } - return ret; - } - } catch (XMPException e) { - e.printStackTrace(); - } - - return null; - } -} diff --git a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java b/src/com/android/gallery3d/filtershow/ui/ExportDialog.java deleted file mode 100644 index 4b30e7b18..000000000 --- a/src/com/android/gallery3d/filtershow/ui/ExportDialog.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.ui; - -import android.content.Intent; -import android.net.Uri; -import android.os.Bundle; -import android.support.v4.app.DialogFragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.SeekBar; -import android.widget.TextView; - -import com.android.gallery3d.R; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.imageshow.MasterImage; -import com.android.gallery3d.filtershow.pipeline.ProcessingService; -import com.android.gallery3d.filtershow.tools.SaveImage; - -import java.io.File; - -public class ExportDialog extends DialogFragment implements View.OnClickListener, SeekBar.OnSeekBarChangeListener{ - SeekBar mSeekBar; - TextView mSeekVal; - String mSliderLabel; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.filtershow_export_dialog, container); - mSeekBar = (SeekBar) view.findViewById(R.id.qualitySeekBar); - mSeekVal = (TextView) view.findViewById(R.id.qualityTextView); - mSliderLabel = getString(R.string.quality) + ": "; - mSeekVal.setText(mSliderLabel + mSeekBar.getProgress()); - mSeekBar.setOnSeekBarChangeListener(this); - view.findViewById(R.id.cancel).setOnClickListener(this); - view.findViewById(R.id.done).setOnClickListener(this); - getDialog().setTitle(R.string.export_flattened); - return view; - } - - @Override - public void onStopTrackingTouch(SeekBar arg0) { - // Do nothing - } - - @Override - public void onStartTrackingTouch(SeekBar arg0) { - // Do nothing - } - - @Override - public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) { - mSeekVal.setText(mSliderLabel + arg1); - } - - @Override - public void onClick(View v) { - switch (v.getId()) { - case R.id.cancel: - dismiss(); - break; - case R.id.done: - FilterShowActivity activity = (FilterShowActivity) getActivity(); - Uri sourceUri = MasterImage.getImage().getUri(); - File dest = SaveImage.getNewFile(activity, sourceUri); - Intent processIntent = ProcessingService.getSaveIntent(activity, MasterImage - .getImage().getPreset(), dest, activity.getSelectedImageUri(), sourceUri, - true, mSeekBar.getProgress()); - activity.startService(processIntent); - dismiss(); - break; - } - } -} diff --git a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java b/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java deleted file mode 100644 index c1e4109d2..000000000 --- a/src/com/android/gallery3d/filtershow/ui/FramedTextButton.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.ui; - -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; - -import com.android.gallery3d.R; - -public class FramedTextButton extends ImageButton { - private static final String LOGTAG = "FramedTextButton"; - private String mText = null; - 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; - - public static void setTextSize(int value) { - mTextSize = value; - } - - public static void setTextPadding(int value) { - 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(); - } - - public void setTextFrom(int itemId) { - switch (itemId) { - case R.id.curve_menu_rgb: { - setText(getContext().getString(R.string.curves_channel_rgb)); - break; - } - case R.id.curve_menu_red: { - setText(getContext().getString(R.string.curves_channel_red)); - break; - } - case R.id.curve_menu_green: { - setText(getContext().getString(R.string.curves_channel_green)); - break; - } - case R.id.curve_menu_blue: { - setText(getContext().getString(R.string.curves_channel_blue)); - break; - } - } - invalidate(); - } - - public FramedTextButton(Context context) { - this(context, null); - } - - public FramedTextButton(Context context, AttributeSet attrs) { - super(context, attrs); - if (attrs == null) { - return; - } - TypedArray a = getContext().obtainStyledAttributes( - attrs, R.styleable.ImageButtonTitle); - - mText = a.getString(R.styleable.ImageButtonTitle_android_text); - } - - public String getText(){ - return mText; - } - - @Override - public void onDraw(Canvas canvas) { - gPaint.setARGB(96, 255, 255, 255); - gPaint.setStrokeWidth(2); - gPaint.setStyle(Paint.Style.STROKE); - 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); - gPaint.setTextSize(mTextSize); - float textWidth = gPaint.measureText(mText); - Rect bounds = new Rect(); - gPaint.getTextBounds(mText, 0, mText.length(), bounds); - 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/SelectionRenderer.java b/src/com/android/gallery3d/filtershow/ui/SelectionRenderer.java deleted file mode 100644 index ef40c5e44..000000000 --- a/src/com/android/gallery3d/filtershow/ui/SelectionRenderer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.filtershow.ui; - -import android.graphics.Canvas; -import android.graphics.Paint; - -public class SelectionRenderer { - - public static void drawSelection(Canvas canvas, int left, int top, int right, int bottom, - int stroke, Paint paint) { - canvas.drawRect(left, top, right, top + stroke, paint); - canvas.drawRect(left, bottom - stroke, right, bottom, paint); - canvas.drawRect(left, top, left + stroke, bottom, paint); - canvas.drawRect(right - stroke, top, right, bottom, paint); - } - - public static void drawSelection(Canvas canvas, int left, int top, int right, int bottom, - int stroke, Paint selectPaint, int border, Paint borderPaint) { - canvas.drawRect(left, top, right, top + stroke, selectPaint); - canvas.drawRect(left, bottom - stroke, right, bottom, selectPaint); - canvas.drawRect(left, top, left + stroke, bottom, selectPaint); - canvas.drawRect(right - stroke, top, right, bottom, selectPaint); - canvas.drawRect(left + stroke, top + stroke, right - stroke, - top + stroke + border, borderPaint); - canvas.drawRect(left + stroke, bottom - stroke - border, right - stroke, - bottom - stroke, borderPaint); - canvas.drawRect(left + stroke, top + stroke, left + stroke + border, - bottom - stroke, borderPaint); - canvas.drawRect(right - stroke - border, top + stroke, right - stroke, - bottom - stroke, borderPaint); - } - -} diff --git a/src/com/android/gallery3d/gadget/LocalPhotoSource.java b/src/com/android/gallery3d/gadget/LocalPhotoSource.java deleted file mode 100644 index 4e94e8d75..000000000 --- a/src/com/android/gallery3d/gadget/LocalPhotoSource.java +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.content.ContentResolver; -import android.content.Context; -import android.database.ContentObserver; -import android.database.Cursor; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Environment; -import android.os.Handler; -import android.provider.MediaStore.Images.Media; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.util.GalleryUtils; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Random; - -public class LocalPhotoSource implements WidgetSource { - - @SuppressWarnings("unused") - private static final String TAG = "LocalPhotoSource"; - - private static final int MAX_PHOTO_COUNT = 128; - - /* Static fields used to query for the correct set of images */ - private static final Uri CONTENT_URI = Media.EXTERNAL_CONTENT_URI; - private static final String DATE_TAKEN = Media.DATE_TAKEN; - private static final String[] PROJECTION = {Media._ID}; - private static final String[] COUNT_PROJECTION = {"count(*)"}; - /* We don't want to include the download directory */ - private static final String SELECTION = - String.format("%s != %s", Media.BUCKET_ID, getDownloadBucketId()); - private static final String ORDER = String.format("%s DESC", DATE_TAKEN); - - private Context mContext; - private ArrayList<Long> mPhotos = new ArrayList<Long>(); - private ContentListener mContentListener; - private ContentObserver mContentObserver; - private boolean mContentDirty = true; - private DataManager mDataManager; - private static final Path LOCAL_IMAGE_ROOT = Path.fromString("/local/image/item"); - - public LocalPhotoSource(Context context) { - mContext = context; - mDataManager = ((GalleryApp) context.getApplicationContext()).getDataManager(); - mContentObserver = new ContentObserver(new Handler()) { - @Override - public void onChange(boolean selfChange) { - mContentDirty = true; - if (mContentListener != null) mContentListener.onContentDirty(); - } - }; - mContext.getContentResolver() - .registerContentObserver(CONTENT_URI, true, mContentObserver); - } - - @Override - public void close() { - mContext.getContentResolver().unregisterContentObserver(mContentObserver); - } - - @Override - public Uri getContentUri(int index) { - if (index < mPhotos.size()) { - return CONTENT_URI.buildUpon() - .appendPath(String.valueOf(mPhotos.get(index))) - .build(); - } - return null; - } - - @Override - public Bitmap getImage(int index) { - if (index >= mPhotos.size()) return null; - long id = mPhotos.get(index); - MediaItem image = (MediaItem) - mDataManager.getMediaObject(LOCAL_IMAGE_ROOT.getChild(id)); - if (image == null) return null; - - return WidgetUtils.createWidgetBitmap(image); - } - - private int[] getExponentialIndice(int total, int count) { - Random random = new Random(); - if (count > total) count = total; - HashSet<Integer> selected = new HashSet<Integer>(count); - while (selected.size() < count) { - int row = (int)(-Math.log(random.nextDouble()) * total / 2); - if (row < total) selected.add(row); - } - int values[] = new int[count]; - int index = 0; - for (int value : selected) { - values[index++] = value; - } - return values; - } - - private int getPhotoCount(ContentResolver resolver) { - Cursor cursor = resolver.query( - CONTENT_URI, COUNT_PROJECTION, SELECTION, null, null); - if (cursor == null) return 0; - try { - Utils.assertTrue(cursor.moveToNext()); - return cursor.getInt(0); - } finally { - cursor.close(); - } - } - - private boolean isContentSound(int totalCount) { - if (mPhotos.size() < Math.min(totalCount, MAX_PHOTO_COUNT)) return false; - if (mPhotos.size() == 0) return true; // totalCount is also 0 - - StringBuilder builder = new StringBuilder(); - for (Long imageId : mPhotos) { - if (builder.length() > 0) builder.append(","); - builder.append(imageId); - } - Cursor cursor = mContext.getContentResolver().query( - CONTENT_URI, COUNT_PROJECTION, - String.format("%s in (%s)", Media._ID, builder.toString()), - null, null); - if (cursor == null) return false; - try { - Utils.assertTrue(cursor.moveToNext()); - return cursor.getInt(0) == mPhotos.size(); - } finally { - cursor.close(); - } - } - - @Override - public void reload() { - if (!mContentDirty) return; - mContentDirty = false; - - ContentResolver resolver = mContext.getContentResolver(); - int photoCount = getPhotoCount(resolver); - if (isContentSound(photoCount)) return; - - int choosedIds[] = getExponentialIndice(photoCount, MAX_PHOTO_COUNT); - Arrays.sort(choosedIds); - - mPhotos.clear(); - Cursor cursor = mContext.getContentResolver().query( - CONTENT_URI, PROJECTION, SELECTION, null, ORDER); - if (cursor == null) return; - try { - for (int index : choosedIds) { - if (cursor.moveToPosition(index)) { - mPhotos.add(cursor.getLong(0)); - } - } - } finally { - cursor.close(); - } - } - - @Override - public int size() { - reload(); - return mPhotos.size(); - } - - /** - * Builds the bucket ID for the public external storage Downloads directory - * @return the bucket ID - */ - private static int getDownloadBucketId() { - String downloadsPath = Environment - .getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) - .getAbsolutePath(); - return GalleryUtils.getBucketId(downloadsPath); - } - - @Override - public void setContentListener(ContentListener listener) { - mContentListener = listener; - } -} diff --git a/src/com/android/gallery3d/gadget/MediaSetSource.java b/src/com/android/gallery3d/gadget/MediaSetSource.java deleted file mode 100644 index 458651c98..000000000 --- a/src/com/android/gallery3d/gadget/MediaSetSource.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Binder; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; - -import java.util.ArrayList; -import java.util.Arrays; - -public class MediaSetSource implements WidgetSource, ContentListener { - private static final String TAG = "MediaSetSource"; - - private DataManager mDataManager; - private Path mAlbumPath; - - private WidgetSource mSource; - - private MediaSet mRootSet; - private ContentListener mListener; - - public MediaSetSource(DataManager manager, String albumPath) { - MediaSet mediaSet = (MediaSet) manager.getMediaObject(albumPath); - if (mediaSet != null) { - mSource = new CheckedMediaSetSource(mediaSet); - return; - } - - // Initialize source to an empty source until the album path can be resolved - mDataManager = Utils.checkNotNull(manager); - mAlbumPath = Path.fromString(albumPath); - mSource = new EmptySource(); - monitorRootPath(); - } - - @Override - public int size() { - return mSource.size(); - } - - @Override - public Bitmap getImage(int index) { - return mSource.getImage(index); - } - - @Override - public Uri getContentUri(int index) { - return mSource.getContentUri(index); - } - - @Override - public synchronized void setContentListener(ContentListener listener) { - if (mRootSet != null) { - mListener = listener; - } else { - mSource.setContentListener(listener); - } - } - - @Override - public void reload() { - mSource.reload(); - } - - @Override - public void close() { - mSource.close(); - } - - @Override - public void onContentDirty() { - resolveAlbumPath(); - } - - private void monitorRootPath() { - String rootPath = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL); - mRootSet = (MediaSet) mDataManager.getMediaObject(rootPath); - mRootSet.addContentListener(this); - } - - private synchronized void resolveAlbumPath() { - if (mDataManager == null) return; - MediaSet mediaSet = (MediaSet) mDataManager.getMediaObject(mAlbumPath); - if (mediaSet != null) { - // Clear the reference instead of removing the listener - // to get around a concurrent modification exception. - mRootSet = null; - - mSource = new CheckedMediaSetSource(mediaSet); - if (mListener != null) { - mListener.onContentDirty(); - mSource.setContentListener(mListener); - mListener = null; - } - mDataManager = null; - mAlbumPath = null; - } - } - - private static class CheckedMediaSetSource implements WidgetSource, ContentListener { - private static final int CACHE_SIZE = 32; - - @SuppressWarnings("unused") - private static final String TAG = "CheckedMediaSetSource"; - - private MediaSet mSource; - private MediaItem mCache[] = new MediaItem[CACHE_SIZE]; - private int mCacheStart; - private int mCacheEnd; - private long mSourceVersion = MediaObject.INVALID_DATA_VERSION; - - private ContentListener mContentListener; - - public CheckedMediaSetSource(MediaSet source) { - mSource = Utils.checkNotNull(source); - mSource.addContentListener(this); - } - - @Override - public void close() { - mSource.removeContentListener(this); - } - - private void ensureCacheRange(int index) { - if (index >= mCacheStart && index < mCacheEnd) return; - - long token = Binder.clearCallingIdentity(); - try { - mCacheStart = index; - ArrayList<MediaItem> items = mSource.getMediaItem(mCacheStart, CACHE_SIZE); - mCacheEnd = mCacheStart + items.size(); - items.toArray(mCache); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public synchronized Uri getContentUri(int index) { - ensureCacheRange(index); - if (index < mCacheStart || index >= mCacheEnd) return null; - return mCache[index - mCacheStart].getContentUri(); - } - - @Override - public synchronized Bitmap getImage(int index) { - ensureCacheRange(index); - if (index < mCacheStart || index >= mCacheEnd) return null; - return WidgetUtils.createWidgetBitmap(mCache[index - mCacheStart]); - } - - @Override - public void reload() { - long version = mSource.reload(); - if (mSourceVersion != version) { - mSourceVersion = version; - mCacheStart = 0; - mCacheEnd = 0; - Arrays.fill(mCache, null); - } - } - - @Override - public void setContentListener(ContentListener listener) { - mContentListener = listener; - } - - @Override - public int size() { - long token = Binder.clearCallingIdentity(); - try { - return mSource.getMediaItemCount(); - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public void onContentDirty() { - if (mContentListener != null) mContentListener.onContentDirty(); - } - } - - private static class EmptySource implements WidgetSource { - - @Override - public int size() { - return 0; - } - - @Override - public Bitmap getImage(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public Uri getContentUri(int index) { - throw new UnsupportedOperationException(); - } - - @Override - public void setContentListener(ContentListener listener) {} - - @Override - public void reload() {} - - @Override - public void close() {} - } -} diff --git a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java b/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java deleted file mode 100644 index 58466bf01..000000000 --- a/src/com/android/gallery3d/gadget/PhotoAppWidgetProvider.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.annotation.TargetApi; -import android.app.PendingIntent; -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProvider; -import android.content.Context; -import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.net.Uri; -import android.util.Log; -import android.widget.RemoteViews; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry; -import com.android.gallery3d.onetimeinitializer.GalleryWidgetMigrator; - -public class PhotoAppWidgetProvider extends AppWidgetProvider { - - private static final String TAG = "WidgetProvider"; - - static RemoteViews buildWidget(Context context, int id, Entry entry) { - - switch (entry.type) { - case WidgetDatabaseHelper.TYPE_ALBUM: - case WidgetDatabaseHelper.TYPE_SHUFFLE: - return buildStackWidget(context, id, entry); - case WidgetDatabaseHelper.TYPE_SINGLE_PHOTO: - return buildFrameWidget(context, id, entry); - } - throw new RuntimeException("invalid type - " + entry.type); - } - - @Override - public void onUpdate(Context context, - AppWidgetManager appWidgetManager, int[] appWidgetIds) { - - if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) { - // migrate gallery widgets from pre-JB releases to JB due to bucket ID change - GalleryWidgetMigrator.migrateGalleryWidgets(context); - } - - WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context); - try { - for (int id : appWidgetIds) { - Entry entry = helper.getEntry(id); - if (entry != null) { - RemoteViews views = buildWidget(context, id, entry); - appWidgetManager.updateAppWidget(id, views); - } else { - Log.e(TAG, "cannot load widget: " + id); - } - } - } finally { - helper.close(); - } - super.onUpdate(context, appWidgetManager, appWidgetIds); - } - - @SuppressWarnings("deprecation") - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - private static RemoteViews buildStackWidget(Context context, int widgetId, Entry entry) { - RemoteViews views = new RemoteViews( - context.getPackageName(), R.layout.appwidget_main); - - Intent intent = new Intent(context, WidgetService.class); - intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId); - intent.putExtra(WidgetService.EXTRA_WIDGET_TYPE, entry.type); - intent.putExtra(WidgetService.EXTRA_ALBUM_PATH, entry.albumPath); - intent.setData(Uri.parse("widget://gallery/" + widgetId)); - - // We use the deprecated API for backward compatibility - // The new API is available in ICE_CREAM_SANDWICH (15) - views.setRemoteAdapter(widgetId, R.id.appwidget_stack_view, intent); - - views.setEmptyView(R.id.appwidget_stack_view, R.id.appwidget_empty_view); - - Intent clickIntent = new Intent(context, WidgetClickHandler.class); - PendingIntent pendingIntent = PendingIntent.getActivity( - context, 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT); - views.setPendingIntentTemplate(R.id.appwidget_stack_view, pendingIntent); - - return views; - } - - static RemoteViews buildFrameWidget(Context context, int appWidgetId, Entry entry) { - RemoteViews views = new RemoteViews( - context.getPackageName(), R.layout.photo_frame); - try { - byte[] data = entry.imageData; - Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length); - views.setImageViewBitmap(R.id.photo, bitmap); - } catch (Throwable t) { - Log.w(TAG, "cannot load widget image: " + appWidgetId, t); - } - - if (entry.imageUri != null) { - try { - Uri uri = Uri.parse(entry.imageUri); - Intent clickIntent = new Intent(context, WidgetClickHandler.class) - .setData(uri); - PendingIntent pendingClickIntent = PendingIntent.getActivity(context, 0, - clickIntent, PendingIntent.FLAG_CANCEL_CURRENT); - views.setOnClickPendingIntent(R.id.photo, pendingClickIntent); - } catch (Throwable t) { - Log.w(TAG, "cannot load widget uri: " + appWidgetId, t); - } - } - return views; - } - - @Override - public void onDeleted(Context context, int[] appWidgetIds) { - // Clean deleted photos out of our database - WidgetDatabaseHelper helper = new WidgetDatabaseHelper(context); - for (int appWidgetId : appWidgetIds) { - helper.deleteEntry(appWidgetId); - } - helper.close(); - } -} diff --git a/src/com/android/gallery3d/gadget/WidgetClickHandler.java b/src/com/android/gallery3d/gadget/WidgetClickHandler.java deleted file mode 100644 index 37ee1a651..000000000 --- a/src/com/android/gallery3d/gadget/WidgetClickHandler.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Intent; -import android.content.res.AssetFileDescriptor; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.util.Log; -import android.widget.Toast; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.Gallery; -import com.android.gallery3d.app.PhotoPage; -import com.android.gallery3d.common.ApiHelper; - -public class WidgetClickHandler extends Activity { - private static final String TAG = "PhotoAppWidgetClickHandler"; - - private boolean isValidDataUri(Uri dataUri) { - if (dataUri == null) return false; - try { - AssetFileDescriptor f = getContentResolver() - .openAssetFileDescriptor(dataUri, "r"); - f.close(); - return true; - } catch (Throwable e) { - Log.w(TAG, "cannot open uri: " + dataUri, e); - return false; - } - } - - @Override - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - protected void onCreate(Bundle savedState) { - super.onCreate(savedState); - // The behavior is changed in JB, refer to b/6384492 for more details - boolean tediousBack = Build.VERSION.SDK_INT >= ApiHelper.VERSION_CODES.JELLY_BEAN; - Uri uri = getIntent().getData(); - Intent intent; - if (isValidDataUri(uri)) { - intent = new Intent(Intent.ACTION_VIEW, uri); - if (tediousBack) { - intent.putExtra(PhotoPage.KEY_TREAT_BACK_AS_UP, true); - } - } else { - Toast.makeText(this, - R.string.no_such_item, Toast.LENGTH_LONG).show(); - intent = new Intent(this, Gallery.class); - } - if (tediousBack) { - intent.setFlags( - Intent.FLAG_ACTIVITY_NEW_TASK | - Intent.FLAG_ACTIVITY_CLEAR_TASK | - Intent.FLAG_ACTIVITY_TASK_ON_HOME); - } - startActivity(intent); - finish(); - } -} diff --git a/src/com/android/gallery3d/gadget/WidgetConfigure.java b/src/com/android/gallery3d/gadget/WidgetConfigure.java deleted file mode 100644 index 2a4c6cfe4..000000000 --- a/src/com/android/gallery3d/gadget/WidgetConfigure.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.app.Activity; -import android.appwidget.AppWidgetManager; -import android.content.Intent; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.net.Uri; -import android.os.Bundle; -import android.util.Log; -import android.widget.RemoteViews; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AlbumPicker; -import com.android.gallery3d.app.DialogPicker; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.LocalAlbum; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.filtershow.crop.CropExtras; - -public class WidgetConfigure extends Activity { - @SuppressWarnings("unused") - private static final String TAG = "WidgetConfigure"; - - public static final String KEY_WIDGET_TYPE = "widget-type"; - private static final String KEY_PICKED_ITEM = "picked-item"; - - private static final int REQUEST_WIDGET_TYPE = 1; - private static final int REQUEST_CHOOSE_ALBUM = 2; - private static final int REQUEST_CROP_IMAGE = 3; - private static final int REQUEST_GET_PHOTO = 4; - - public static final int RESULT_ERROR = RESULT_FIRST_USER; - - // Scale up the widget size since we only specified the minimized - // size of the gadget. The real size could be larger. - // Note: There is also a limit on the size of data that can be - // passed in Binder's transaction. - private static float WIDGET_SCALE_FACTOR = 1.5f; - private static int MAX_WIDGET_SIDE = 360; - - private int mAppWidgetId = -1; - private Uri mPickedItem; - - @Override - protected void onCreate(Bundle savedState) { - super.onCreate(savedState); - mAppWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1); - - if (mAppWidgetId == -1) { - setResult(Activity.RESULT_CANCELED); - finish(); - return; - } - - if (savedState == null) { - if (ApiHelper.HAS_REMOTE_VIEWS_SERVICE) { - Intent intent = new Intent(this, WidgetTypeChooser.class); - startActivityForResult(intent, REQUEST_WIDGET_TYPE); - } else { // Choose the photo type widget - setWidgetType(new Intent() - .putExtra(KEY_WIDGET_TYPE, R.id.widget_type_photo)); - } - } else { - mPickedItem = savedState.getParcelable(KEY_PICKED_ITEM); - } - } - - protected void onSaveInstanceStates(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putParcelable(KEY_PICKED_ITEM, mPickedItem); - } - - private void updateWidgetAndFinish(WidgetDatabaseHelper.Entry entry) { - AppWidgetManager manager = AppWidgetManager.getInstance(this); - RemoteViews views = PhotoAppWidgetProvider.buildWidget(this, mAppWidgetId, entry); - manager.updateAppWidget(mAppWidgetId, views); - setResult(RESULT_OK, new Intent().putExtra( - AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)); - finish(); - } - - @Override - protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (resultCode != RESULT_OK) { - setResult(resultCode, new Intent().putExtra( - AppWidgetManager.EXTRA_APPWIDGET_ID, mAppWidgetId)); - finish(); - return; - } - - if (requestCode == REQUEST_WIDGET_TYPE) { - setWidgetType(data); - } else if (requestCode == REQUEST_CHOOSE_ALBUM) { - setChoosenAlbum(data); - } else if (requestCode == REQUEST_GET_PHOTO) { - setChoosenPhoto(data); - } else if (requestCode == REQUEST_CROP_IMAGE) { - setPhotoWidget(data); - } else { - throw new AssertionError("unknown request: " + requestCode); - } - } - - private void setPhotoWidget(Intent data) { - // Store the cropped photo in our database - Bitmap bitmap = (Bitmap) data.getParcelableExtra("data"); - WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); - try { - helper.setPhoto(mAppWidgetId, mPickedItem, bitmap); - updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); - } finally { - helper.close(); - } - } - - private void setChoosenPhoto(Intent data) { - Resources res = getResources(); - - float width = res.getDimension(R.dimen.appwidget_width); - float height = res.getDimension(R.dimen.appwidget_height); - - // We try to crop a larger image (by scale factor), but there is still - // a bound on the binder limit. - float scale = Math.min(WIDGET_SCALE_FACTOR, - MAX_WIDGET_SIDE / Math.max(width, height)); - - int widgetWidth = Math.round(width * scale); - int widgetHeight = Math.round(height * scale); - - mPickedItem = data.getData(); - Intent request = new Intent(CropActivity.CROP_ACTION, mPickedItem) - .putExtra(CropExtras.KEY_OUTPUT_X, widgetWidth) - .putExtra(CropExtras.KEY_OUTPUT_Y, widgetHeight) - .putExtra(CropExtras.KEY_ASPECT_X, widgetWidth) - .putExtra(CropExtras.KEY_ASPECT_Y, widgetHeight) - .putExtra(CropExtras.KEY_SCALE_UP_IF_NEEDED, true) - .putExtra(CropExtras.KEY_SCALE, true) - .putExtra(CropExtras.KEY_RETURN_DATA, true); - startActivityForResult(request, REQUEST_CROP_IMAGE); - } - - private void setChoosenAlbum(Intent data) { - String albumPath = data.getStringExtra(AlbumPicker.KEY_ALBUM_PATH); - WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); - try { - String relativePath = null; - GalleryApp galleryApp = (GalleryApp) getApplicationContext(); - DataManager manager = galleryApp.getDataManager(); - Path path = Path.fromString(albumPath); - MediaSet mediaSet = (MediaSet) manager.getMediaObject(path); - if (mediaSet instanceof LocalAlbum) { - int bucketId = Integer.parseInt(path.getSuffix()); - // If the chosen album is a local album, find relative path - // Otherwise, leave the relative path field empty - relativePath = LocalAlbum.getRelativePath(bucketId); - Log.i(TAG, "Setting widget, album path: " + albumPath - + ", relative path: " + relativePath); - } - helper.setWidget(mAppWidgetId, - WidgetDatabaseHelper.TYPE_ALBUM, albumPath, relativePath); - updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); - } finally { - helper.close(); - } - } - - private void setWidgetType(Intent data) { - int widgetType = data.getIntExtra(KEY_WIDGET_TYPE, R.id.widget_type_shuffle); - if (widgetType == R.id.widget_type_album) { - Intent intent = new Intent(this, AlbumPicker.class); - startActivityForResult(intent, REQUEST_CHOOSE_ALBUM); - } else if (widgetType == R.id.widget_type_shuffle) { - WidgetDatabaseHelper helper = new WidgetDatabaseHelper(this); - try { - helper.setWidget(mAppWidgetId, WidgetDatabaseHelper.TYPE_SHUFFLE, null, null); - updateWidgetAndFinish(helper.getEntry(mAppWidgetId)); - } finally { - helper.close(); - } - } else { - // Explicitly send the intent to the DialogPhotoPicker - Intent request = new Intent(this, DialogPicker.class) - .setAction(Intent.ACTION_GET_CONTENT) - .setType("image/*"); - startActivityForResult(request, REQUEST_GET_PHOTO); - } - } -} diff --git a/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java b/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java deleted file mode 100644 index c0145843b..000000000 --- a/src/com/android/gallery3d/gadget/WidgetDatabaseHelper.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteException; -import android.database.sqlite.SQLiteOpenHelper; -import android.graphics.Bitmap; -import android.net.Uri; -import android.util.Log; - -import com.android.gallery3d.common.Utils; - -import java.io.ByteArrayOutputStream; -import java.util.ArrayList; -import java.util.List; - -public class WidgetDatabaseHelper extends SQLiteOpenHelper { - private static final String TAG = "PhotoDatabaseHelper"; - private static final String DATABASE_NAME = "launcher.db"; - - // Increment the database version to 5. In version 5, we - // add a column in widgets table to record relative paths. - private static final int DATABASE_VERSION = 5; - - private static final String TABLE_WIDGETS = "widgets"; - - private static final String FIELD_APPWIDGET_ID = "appWidgetId"; - private static final String FIELD_IMAGE_URI = "imageUri"; - private static final String FIELD_PHOTO_BLOB = "photoBlob"; - private static final String FIELD_WIDGET_TYPE = "widgetType"; - private static final String FIELD_ALBUM_PATH = "albumPath"; - private static final String FIELD_RELATIVE_PATH = "relativePath"; - - public static final int TYPE_SINGLE_PHOTO = 0; - public static final int TYPE_SHUFFLE = 1; - public static final int TYPE_ALBUM = 2; - - private static final String[] PROJECTION = { - FIELD_WIDGET_TYPE, FIELD_IMAGE_URI, FIELD_PHOTO_BLOB, FIELD_ALBUM_PATH, - FIELD_APPWIDGET_ID, FIELD_RELATIVE_PATH}; - private static final int INDEX_WIDGET_TYPE = 0; - private static final int INDEX_IMAGE_URI = 1; - private static final int INDEX_PHOTO_BLOB = 2; - private static final int INDEX_ALBUM_PATH = 3; - private static final int INDEX_APPWIDGET_ID = 4; - private static final int INDEX_RELATIVE_PATH = 5; - private static final String WHERE_APPWIDGET_ID = FIELD_APPWIDGET_ID + " = ?"; - private static final String WHERE_WIDGET_TYPE = FIELD_WIDGET_TYPE + " = ?"; - - public static class Entry { - public int widgetId; - public int type; - public String imageUri; - public byte imageData[]; - public String albumPath; - public String relativePath; - - private Entry() {} - - private Entry(int id, Cursor cursor) { - widgetId = id; - type = cursor.getInt(INDEX_WIDGET_TYPE); - if (type == TYPE_SINGLE_PHOTO) { - imageUri = cursor.getString(INDEX_IMAGE_URI); - imageData = cursor.getBlob(INDEX_PHOTO_BLOB); - } else if (type == TYPE_ALBUM) { - albumPath = cursor.getString(INDEX_ALBUM_PATH); - relativePath = cursor.getString(INDEX_RELATIVE_PATH); - } - } - - private Entry(Cursor cursor) { - this(cursor.getInt(INDEX_APPWIDGET_ID), cursor); - } - } - - public WidgetDatabaseHelper(Context context) { - super(context, DATABASE_NAME, null, DATABASE_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL("CREATE TABLE " + TABLE_WIDGETS + " (" - + FIELD_APPWIDGET_ID + " INTEGER PRIMARY KEY, " - + FIELD_WIDGET_TYPE + " INTEGER DEFAULT 0, " - + FIELD_IMAGE_URI + " TEXT, " - + FIELD_ALBUM_PATH + " TEXT, " - + FIELD_PHOTO_BLOB + " BLOB, " - + FIELD_RELATIVE_PATH + " TEXT)"); - } - - private void saveData(SQLiteDatabase db, int oldVersion, ArrayList<Entry> data) { - if (oldVersion <= 2) { - Cursor cursor = db.query("photos", - new String[] {FIELD_APPWIDGET_ID, FIELD_PHOTO_BLOB}, - null, null, null, null, null); - if (cursor == null) return; - try { - while (cursor.moveToNext()) { - Entry entry = new Entry(); - entry.type = TYPE_SINGLE_PHOTO; - entry.widgetId = cursor.getInt(0); - entry.imageData = cursor.getBlob(1); - data.add(entry); - } - } finally { - cursor.close(); - } - } else if (oldVersion == 3) { - Cursor cursor = db.query("photos", - new String[] {FIELD_APPWIDGET_ID, FIELD_PHOTO_BLOB, FIELD_IMAGE_URI}, - null, null, null, null, null); - if (cursor == null) return; - try { - while (cursor.moveToNext()) { - Entry entry = new Entry(); - entry.type = TYPE_SINGLE_PHOTO; - entry.widgetId = cursor.getInt(0); - entry.imageData = cursor.getBlob(1); - entry.imageUri = cursor.getString(2); - data.add(entry); - } - } finally { - cursor.close(); - } - } - } - - private void restoreData(SQLiteDatabase db, ArrayList<Entry> data) { - db.beginTransaction(); - try { - for (Entry entry : data) { - ContentValues values = new ContentValues(); - values.put(FIELD_APPWIDGET_ID, entry.widgetId); - values.put(FIELD_WIDGET_TYPE, entry.type); - values.put(FIELD_IMAGE_URI, entry.imageUri); - values.put(FIELD_PHOTO_BLOB, entry.imageData); - values.put(FIELD_ALBUM_PATH, entry.albumPath); - db.insert(TABLE_WIDGETS, null, values); - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - if (oldVersion < 4) { - // Table "photos" is renamed to "widget" in version 4 - ArrayList<Entry> data = new ArrayList<Entry>(); - saveData(db, oldVersion, data); - - Log.w(TAG, "destroying all old data."); - db.execSQL("DROP TABLE IF EXISTS photos"); - db.execSQL("DROP TABLE IF EXISTS " + TABLE_WIDGETS); - onCreate(db); - - restoreData(db, data); - } - // Add a column for relative path - if (oldVersion < DATABASE_VERSION) { - try { - db.execSQL("ALTER TABLE widgets ADD COLUMN relativePath TEXT"); - } catch (Throwable t) { - Log.e(TAG, "Failed to add the column for relative path."); - return; - } - } - } - - /** - * Store the given bitmap in this database for the given appWidgetId. - */ - public boolean setPhoto(int appWidgetId, Uri imageUri, Bitmap bitmap) { - try { - // Try go guesstimate how much space the icon will take when - // serialized to avoid unnecessary allocations/copies during - // the write. - int size = bitmap.getWidth() * bitmap.getHeight() * 4; - ByteArrayOutputStream out = new ByteArrayOutputStream(size); - bitmap.compress(Bitmap.CompressFormat.PNG, 100, out); - out.close(); - - ContentValues values = new ContentValues(); - values.put(FIELD_APPWIDGET_ID, appWidgetId); - values.put(FIELD_WIDGET_TYPE, TYPE_SINGLE_PHOTO); - values.put(FIELD_IMAGE_URI, imageUri.toString()); - values.put(FIELD_PHOTO_BLOB, out.toByteArray()); - - SQLiteDatabase db = getWritableDatabase(); - db.replaceOrThrow(TABLE_WIDGETS, null, values); - return true; - } catch (Throwable e) { - Log.e(TAG, "set widget photo fail", e); - return false; - } - } - - public boolean setWidget(int id, int type, String albumPath, String relativePath) { - try { - ContentValues values = new ContentValues(); - values.put(FIELD_APPWIDGET_ID, id); - values.put(FIELD_WIDGET_TYPE, type); - values.put(FIELD_ALBUM_PATH, Utils.ensureNotNull(albumPath)); - values.put(FIELD_RELATIVE_PATH, relativePath); - getWritableDatabase().replaceOrThrow(TABLE_WIDGETS, null, values); - return true; - } catch (Throwable e) { - Log.e(TAG, "set widget fail", e); - return false; - } - } - - public Entry getEntry(int appWidgetId) { - Cursor cursor = null; - try { - SQLiteDatabase db = getReadableDatabase(); - cursor = db.query(TABLE_WIDGETS, PROJECTION, - WHERE_APPWIDGET_ID, new String[] {String.valueOf(appWidgetId)}, - null, null, null); - if (cursor == null || !cursor.moveToNext()) { - Log.e(TAG, "query fail: empty cursor: " + cursor + " appWidgetId: " - + appWidgetId); - return null; - } - return new Entry(appWidgetId, cursor); - } catch (Throwable e) { - Log.e(TAG, "Could not load photo from database", e); - return null; - } finally { - Utils.closeSilently(cursor); - } - } - - public List<Entry> getEntries(int type) { - Cursor cursor = null; - try { - SQLiteDatabase db = getReadableDatabase(); - cursor = db.query(TABLE_WIDGETS, PROJECTION, - WHERE_WIDGET_TYPE, new String[] {String.valueOf(type)}, - null, null, null); - if (cursor == null) { - Log.e(TAG, "query fail: null cursor: " + cursor); - return null; - } - ArrayList<Entry> result = new ArrayList<Entry>(cursor.getCount()); - while (cursor.moveToNext()) { - result.add(new Entry(cursor)); - } - return result; - } catch (Throwable e) { - Log.e(TAG, "Could not load widget from database", e); - return null; - } finally { - Utils.closeSilently(cursor); - } - } - - /** - * Updates the entry in the widget database. - */ - public void updateEntry(Entry entry) { - deleteEntry(entry.widgetId); - try { - ContentValues values = new ContentValues(); - values.put(FIELD_APPWIDGET_ID, entry.widgetId); - values.put(FIELD_WIDGET_TYPE, entry.type); - values.put(FIELD_ALBUM_PATH, entry.albumPath); - values.put(FIELD_IMAGE_URI, entry.imageUri); - values.put(FIELD_PHOTO_BLOB, entry.imageData); - values.put(FIELD_RELATIVE_PATH, entry.relativePath); - getWritableDatabase().insert(TABLE_WIDGETS, null, values); - } catch (Throwable e) { - Log.e(TAG, "set widget fail", e); - } - } - - /** - * Remove any bitmap associated with the given appWidgetId. - */ - public void deleteEntry(int appWidgetId) { - try { - SQLiteDatabase db = getWritableDatabase(); - db.delete(TABLE_WIDGETS, WHERE_APPWIDGET_ID, - new String[] {String.valueOf(appWidgetId)}); - } catch (SQLiteException e) { - Log.e(TAG, "Could not delete photo from database", e); - } - } -} diff --git a/src/com/android/gallery3d/gadget/WidgetService.java b/src/com/android/gallery3d/gadget/WidgetService.java deleted file mode 100644 index 94dd16439..000000000 --- a/src/com/android/gallery3d/gadget/WidgetService.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.annotation.TargetApi; -import android.appwidget.AppWidgetManager; -import android.content.Intent; -import android.graphics.Bitmap; -import android.net.Uri; -import android.widget.RemoteViews; -import android.widget.RemoteViewsService; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.ContentListener; - -@TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) -public class WidgetService extends RemoteViewsService { - - @SuppressWarnings("unused") - private static final String TAG = "GalleryAppWidgetService"; - - public static final String EXTRA_WIDGET_TYPE = "widget-type"; - public static final String EXTRA_ALBUM_PATH = "album-path"; - - @Override - public RemoteViewsFactory onGetViewFactory(Intent intent) { - int id = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, - AppWidgetManager.INVALID_APPWIDGET_ID); - int type = intent.getIntExtra(EXTRA_WIDGET_TYPE, 0); - String albumPath = intent.getStringExtra(EXTRA_ALBUM_PATH); - - return new PhotoRVFactory((GalleryApp) getApplicationContext(), - id, type, albumPath); - } - - private static class PhotoRVFactory implements - RemoteViewsService.RemoteViewsFactory, ContentListener { - - private final int mAppWidgetId; - private final int mType; - private final String mAlbumPath; - private final GalleryApp mApp; - - private WidgetSource mSource; - - public PhotoRVFactory(GalleryApp app, int id, int type, String albumPath) { - mApp = app; - mAppWidgetId = id; - mType = type; - mAlbumPath = albumPath; - } - - @Override - public void onCreate() { - if (mType == WidgetDatabaseHelper.TYPE_ALBUM) { - mSource = new MediaSetSource(mApp.getDataManager(), mAlbumPath); - } else { - mSource = new LocalPhotoSource(mApp.getAndroidContext()); - } - mSource.setContentListener(this); - AppWidgetManager.getInstance(mApp.getAndroidContext()) - .notifyAppWidgetViewDataChanged( - mAppWidgetId, R.id.appwidget_stack_view); - } - - @Override - public void onDestroy() { - mSource.close(); - mSource = null; - } - - @Override - public int getCount() { - return mSource.size(); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public int getViewTypeCount() { - return 1; - } - - @Override - public boolean hasStableIds() { - return true; - } - - @Override - public RemoteViews getLoadingView() { - RemoteViews rv = new RemoteViews( - mApp.getAndroidContext().getPackageName(), - R.layout.appwidget_loading_item); - rv.setProgressBar(R.id.appwidget_loading_item, 0, 0, true); - return rv; - } - - @Override - public RemoteViews getViewAt(int position) { - Bitmap bitmap = mSource.getImage(position); - if (bitmap == null) return getLoadingView(); - RemoteViews views = new RemoteViews( - mApp.getAndroidContext().getPackageName(), - R.layout.appwidget_photo_item); - views.setImageViewBitmap(R.id.appwidget_photo_item, bitmap); - views.setOnClickFillInIntent(R.id.appwidget_photo_item, new Intent() - .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) - .setData(mSource.getContentUri(position))); - return views; - } - - @Override - public void onDataSetChanged() { - mSource.reload(); - } - - @Override - public void onContentDirty() { - AppWidgetManager.getInstance(mApp.getAndroidContext()) - .notifyAppWidgetViewDataChanged( - mAppWidgetId, R.id.appwidget_stack_view); - } - } -} diff --git a/src/com/android/gallery3d/gadget/WidgetSource.java b/src/com/android/gallery3d/gadget/WidgetSource.java deleted file mode 100644 index 92874c740..000000000 --- a/src/com/android/gallery3d/gadget/WidgetSource.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.graphics.Bitmap; -import android.net.Uri; - -import com.android.gallery3d.data.ContentListener; - -public interface WidgetSource { - public int size(); - public Bitmap getImage(int index); - public Uri getContentUri(int index); - public void setContentListener(ContentListener listener); - public void reload(); - public void close(); -} diff --git a/src/com/android/gallery3d/gadget/WidgetTypeChooser.java b/src/com/android/gallery3d/gadget/WidgetTypeChooser.java deleted file mode 100644 index 1694f1c04..000000000 --- a/src/com/android/gallery3d/gadget/WidgetTypeChooser.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.app.Activity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.RadioGroup; -import android.widget.RadioGroup.OnCheckedChangeListener; - -import com.android.gallery3d.R; - -public class WidgetTypeChooser extends Activity { - - private OnCheckedChangeListener mListener = new OnCheckedChangeListener() { - @Override - public void onCheckedChanged(RadioGroup group, int checkedId) { - Intent data = new Intent() - .putExtra(WidgetConfigure.KEY_WIDGET_TYPE, checkedId); - setResult(RESULT_OK, data); - finish(); - } - }; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setTitle(R.string.widget_type); - setContentView(R.layout.choose_widget_type); - RadioGroup rg = (RadioGroup) findViewById(R.id.widget_type); - rg.setOnCheckedChangeListener(mListener); - - Button cancel = (Button) findViewById(R.id.cancel); - cancel.setOnClickListener(new OnClickListener() { - @Override - public void onClick(View v) { - setResult(RESULT_CANCELED); - finish(); - } - }); - } -} diff --git a/src/com/android/gallery3d/gadget/WidgetUtils.java b/src/com/android/gallery3d/gadget/WidgetUtils.java deleted file mode 100644 index c20c186df..000000000 --- a/src/com/android/gallery3d/gadget/WidgetUtils.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.gadget; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.util.Log; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.util.ThreadPool; - -public class WidgetUtils { - - private static final String TAG = "WidgetUtils"; - - private static int sStackPhotoWidth = 220; - private static int sStackPhotoHeight = 170; - - private WidgetUtils() { - } - - public static void initialize(Context context) { - Resources r = context.getResources(); - sStackPhotoWidth = r.getDimensionPixelSize(R.dimen.stack_photo_width); - sStackPhotoHeight = r.getDimensionPixelSize(R.dimen.stack_photo_height); - } - - public static Bitmap createWidgetBitmap(MediaItem image) { - Bitmap bitmap = image.requestImage(MediaItem.TYPE_THUMBNAIL) - .run(ThreadPool.JOB_CONTEXT_STUB); - if (bitmap == null) { - Log.w(TAG, "fail to get image of " + image.toString()); - return null; - } - return createWidgetBitmap(bitmap, image.getRotation()); - } - - public static Bitmap createWidgetBitmap(Bitmap bitmap, int rotation) { - int w = bitmap.getWidth(); - int h = bitmap.getHeight(); - - float scale; - if (((rotation / 90) & 1) == 0) { - scale = Math.max((float) sStackPhotoWidth / w, - (float) sStackPhotoHeight / h); - } else { - scale = Math.max((float) sStackPhotoWidth / h, - (float) sStackPhotoHeight / w); - } - - Bitmap target = Bitmap.createBitmap( - sStackPhotoWidth, sStackPhotoHeight, Config.ARGB_8888); - Canvas canvas = new Canvas(target); - canvas.translate(sStackPhotoWidth / 2, sStackPhotoHeight / 2); - canvas.rotate(rotation); - canvas.scale(scale, scale); - Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG); - canvas.drawBitmap(bitmap, -w / 2, -h / 2, paint); - return target; - } -} diff --git a/src/com/android/gallery3d/glrenderer/CanvasTexture.java b/src/com/android/gallery3d/glrenderer/CanvasTexture.java deleted file mode 100644 index bff9d4baa..000000000 --- a/src/com/android/gallery3d/glrenderer/CanvasTexture.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; - -// CanvasTexture is a texture whose content is the drawing on a Canvas. -// The subclasses should override onDraw() to draw on the bitmap. -// By default CanvasTexture is not opaque. -abstract class CanvasTexture extends UploadedTexture { - protected Canvas mCanvas; - private final Config mConfig; - - public CanvasTexture(int width, int height) { - mConfig = Config.ARGB_8888; - setSize(width, height); - setOpaque(false); - } - - @Override - protected Bitmap onGetBitmap() { - Bitmap bitmap = Bitmap.createBitmap(mWidth, mHeight, mConfig); - mCanvas = new Canvas(bitmap); - onDraw(mCanvas, bitmap); - return bitmap; - } - - @Override - protected void onFreeBitmap(Bitmap bitmap) { - if (!inFinalizer()) { - bitmap.recycle(); - } - } - - abstract protected void onDraw(Canvas canvas, Bitmap backing); -} diff --git a/src/com/android/gallery3d/glrenderer/ColorTexture.java b/src/com/android/gallery3d/glrenderer/ColorTexture.java deleted file mode 100644 index 904c78e1b..000000000 --- a/src/com/android/gallery3d/glrenderer/ColorTexture.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import com.android.gallery3d.common.Utils; - -// ColorTexture is a texture which fills the rectangle with the specified color. -public class ColorTexture implements Texture { - - private final int mColor; - private int mWidth; - private int mHeight; - - public ColorTexture(int color) { - mColor = color; - mWidth = 1; - mHeight = 1; - } - - @Override - public void draw(GLCanvas canvas, int x, int y) { - draw(canvas, x, y, mWidth, mHeight); - } - - @Override - public void draw(GLCanvas canvas, int x, int y, int w, int h) { - canvas.fillRect(x, y, w, h, mColor); - } - - @Override - public boolean isOpaque() { - return Utils.isOpaque(mColor); - } - - public void setSize(int width, int height) { - mWidth = width; - mHeight = height; - } - - @Override - public int getWidth() { - return mWidth; - } - - @Override - public int getHeight() { - return mHeight; - } -} diff --git a/src/com/android/gallery3d/glrenderer/ExtTexture.java b/src/com/android/gallery3d/glrenderer/ExtTexture.java deleted file mode 100644 index af76300b1..000000000 --- a/src/com/android/gallery3d/glrenderer/ExtTexture.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -// ExtTexture is a texture whose content comes from a external texture. -// Before drawing, setSize() should be called. -public class ExtTexture extends BasicTexture { - - private int mTarget; - - public ExtTexture(GLCanvas canvas, int target) { - GLId glId = canvas.getGLId(); - mId = glId.generateTexture(); - mTarget = target; - } - - private void uploadToCanvas(GLCanvas canvas) { - canvas.setTextureParameters(this); - setAssociatedCanvas(canvas); - mState = STATE_LOADED; - } - - @Override - protected boolean onBind(GLCanvas canvas) { - if (!isLoaded()) { - uploadToCanvas(canvas); - } - - return true; - } - - @Override - public int getTarget() { - return mTarget; - } - - @Override - public boolean isOpaque() { - return true; - } - - @Override - public void yield() { - // we cannot free the texture because we have no backup. - } -} diff --git a/src/com/android/gallery3d/glrenderer/FadeInTexture.java b/src/com/android/gallery3d/glrenderer/FadeInTexture.java deleted file mode 100644 index 838d465f5..000000000 --- a/src/com/android/gallery3d/glrenderer/FadeInTexture.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - - -// FadeInTexture is a texture which begins with a color, then gradually animates -// into a given texture. -public class FadeInTexture extends FadeTexture implements Texture { - @SuppressWarnings("unused") - private static final String TAG = "FadeInTexture"; - - private final int mColor; - private final TiledTexture mTexture; - - public FadeInTexture(int color, TiledTexture texture) { - super(texture.getWidth(), texture.getHeight(), texture.isOpaque()); - mColor = color; - mTexture = texture; - } - - @Override - public void draw(GLCanvas canvas, int x, int y, int w, int h) { - if (isAnimating()) { - mTexture.drawMixed(canvas, mColor, getRatio(), x, y, w, h); - } else { - mTexture.draw(canvas, x, y, w, h); - } - } -} diff --git a/src/com/android/gallery3d/glrenderer/FadeOutTexture.java b/src/com/android/gallery3d/glrenderer/FadeOutTexture.java deleted file mode 100644 index b05f3b631..000000000 --- a/src/com/android/gallery3d/glrenderer/FadeOutTexture.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - - -// FadeOutTexture is a texture which begins with a given texture, then gradually animates -// into fading out totally. -public class FadeOutTexture extends FadeTexture { - @SuppressWarnings("unused") - private static final String TAG = "FadeOutTexture"; - - private final BasicTexture mTexture; - - public FadeOutTexture(BasicTexture texture) { - super(texture.getWidth(), texture.getHeight(), texture.isOpaque()); - mTexture = texture; - } - - @Override - public void draw(GLCanvas canvas, int x, int y, int w, int h) { - if (isAnimating()) { - canvas.save(GLCanvas.SAVE_FLAG_ALPHA); - canvas.setAlpha(getRatio()); - mTexture.draw(canvas, x, y, w, h); - canvas.restore(); - } - } -} diff --git a/src/com/android/gallery3d/glrenderer/FadeTexture.java b/src/com/android/gallery3d/glrenderer/FadeTexture.java deleted file mode 100644 index 002c90f5c..000000000 --- a/src/com/android/gallery3d/glrenderer/FadeTexture.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.ui.AnimationTime; - -// FadeTexture is a texture which fades the given texture along the time. -public abstract class FadeTexture implements Texture { - @SuppressWarnings("unused") - private static final String TAG = "FadeTexture"; - - // The duration of the fading animation in milliseconds - public static final int DURATION = 180; - - private final long mStartTime; - private final int mWidth; - private final int mHeight; - private final boolean mIsOpaque; - private boolean mIsAnimating; - - public FadeTexture(int width, int height, boolean opaque) { - mWidth = width; - mHeight = height; - mIsOpaque = opaque; - mStartTime = now(); - mIsAnimating = true; - } - - @Override - public void draw(GLCanvas canvas, int x, int y) { - draw(canvas, x, y, mWidth, mHeight); - } - - @Override - public boolean isOpaque() { - return mIsOpaque; - } - - @Override - public int getWidth() { - return mWidth; - } - - @Override - public int getHeight() { - return mHeight; - } - - public boolean isAnimating() { - if (mIsAnimating) { - if (now() - mStartTime >= DURATION) { - mIsAnimating = false; - } - } - return mIsAnimating; - } - - protected float getRatio() { - float r = (float)(now() - mStartTime) / DURATION; - return Utils.clamp(1.0f - r, 0.0f, 1.0f); - } - - private long now() { - return AnimationTime.get(); - } -} diff --git a/src/com/android/gallery3d/glrenderer/GLES11Canvas.java b/src/com/android/gallery3d/glrenderer/GLES11Canvas.java deleted file mode 100644 index 7013c3d1f..000000000 --- a/src/com/android/gallery3d/glrenderer/GLES11Canvas.java +++ /dev/null @@ -1,997 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.graphics.RectF; -import android.opengl.GLU; -import android.opengl.GLUtils; -import android.opengl.Matrix; -import android.util.Log; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.IntArray; - -import junit.framework.Assert; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import java.util.ArrayList; - -import javax.microedition.khronos.opengles.GL10; -import javax.microedition.khronos.opengles.GL11; -import javax.microedition.khronos.opengles.GL11Ext; -import javax.microedition.khronos.opengles.GL11ExtensionPack; - -public class GLES11Canvas implements GLCanvas { - @SuppressWarnings("unused") - private static final String TAG = "GLCanvasImp"; - - private static final float OPAQUE_ALPHA = 0.95f; - - private static final int OFFSET_FILL_RECT = 0; - private static final int OFFSET_DRAW_LINE = 4; - private static final int OFFSET_DRAW_RECT = 6; - private static final float[] BOX_COORDINATES = { - 0, 0, 1, 0, 0, 1, 1, 1, // used for filling a rectangle - 0, 0, 1, 1, // used for drawing a line - 0, 0, 0, 1, 1, 1, 1, 0}; // used for drawing the outline of a rectangle - - private GL11 mGL; - - private final float mMatrixValues[] = new float[16]; - private final float mTextureMatrixValues[] = new float[16]; - - // The results of mapPoints are stored in this buffer, and the order is - // x1, y1, x2, y2. - private final float mMapPointsBuffer[] = new float[4]; - - private final float mTextureColor[] = new float[4]; - - private int mBoxCoords; - - private GLState mGLState; - private final ArrayList<RawTexture> mTargetStack = new ArrayList<RawTexture>(); - - private float mAlpha; - private final ArrayList<ConfigState> mRestoreStack = new ArrayList<ConfigState>(); - private ConfigState mRecycledRestoreAction; - - private final RectF mDrawTextureSourceRect = new RectF(); - private final RectF mDrawTextureTargetRect = new RectF(); - private final float[] mTempMatrix = new float[32]; - private final IntArray mUnboundTextures = new IntArray(); - private final IntArray mDeleteBuffers = new IntArray(); - private int mScreenWidth; - private int mScreenHeight; - private boolean mBlendEnabled = true; - private int mFrameBuffer[] = new int[1]; - private static float[] sCropRect = new float[4]; - - private RawTexture mTargetTexture; - - // Drawing statistics - int mCountDrawLine; - int mCountFillRect; - int mCountDrawMesh; - int mCountTextureRect; - int mCountTextureOES; - - private static GLId mGLId = new GLES11IdImpl(); - - public GLES11Canvas(GL11 gl) { - mGL = gl; - mGLState = new GLState(gl); - // First create an nio buffer, then create a VBO from it. - int size = BOX_COORDINATES.length * Float.SIZE / Byte.SIZE; - FloatBuffer xyBuffer = allocateDirectNativeOrderBuffer(size).asFloatBuffer(); - xyBuffer.put(BOX_COORDINATES, 0, BOX_COORDINATES.length).position(0); - - int[] name = new int[1]; - mGLId.glGenBuffers(1, name, 0); - mBoxCoords = name[0]; - - gl.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords); - gl.glBufferData(GL11.GL_ARRAY_BUFFER, xyBuffer.capacity() * (Float.SIZE / Byte.SIZE), - xyBuffer, GL11.GL_STATIC_DRAW); - - gl.glVertexPointer(2, GL11.GL_FLOAT, 0, 0); - gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0); - - // Enable the texture coordinate array for Texture 1 - gl.glClientActiveTexture(GL11.GL_TEXTURE1); - gl.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0); - gl.glClientActiveTexture(GL11.GL_TEXTURE0); - gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); - - // mMatrixValues and mAlpha will be initialized in setSize() - } - - @Override - public void setSize(int width, int height) { - Assert.assertTrue(width >= 0 && height >= 0); - - if (mTargetTexture == null) { - mScreenWidth = width; - mScreenHeight = height; - } - mAlpha = 1.0f; - - GL11 gl = mGL; - gl.glViewport(0, 0, width, height); - gl.glMatrixMode(GL11.GL_PROJECTION); - gl.glLoadIdentity(); - GLU.gluOrtho2D(gl, 0, width, 0, height); - - gl.glMatrixMode(GL11.GL_MODELVIEW); - gl.glLoadIdentity(); - - float matrix[] = mMatrixValues; - Matrix.setIdentityM(matrix, 0); - // to match the graphic coordinate system in android, we flip it vertically. - if (mTargetTexture == null) { - Matrix.translateM(matrix, 0, 0, height, 0); - Matrix.scaleM(matrix, 0, 1, -1, 1); - } - } - - @Override - public void setAlpha(float alpha) { - Assert.assertTrue(alpha >= 0 && alpha <= 1); - mAlpha = alpha; - } - - @Override - public float getAlpha() { - return mAlpha; - } - - @Override - public void multiplyAlpha(float alpha) { - Assert.assertTrue(alpha >= 0 && alpha <= 1); - mAlpha *= alpha; - } - - private static ByteBuffer allocateDirectNativeOrderBuffer(int size) { - return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()); - } - - @Override - public void drawRect(float x, float y, float width, float height, GLPaint paint) { - GL11 gl = mGL; - - mGLState.setColorMode(paint.getColor(), mAlpha); - mGLState.setLineWidth(paint.getLineWidth()); - - saveTransform(); - translate(x, y); - scale(width, height, 1); - - gl.glLoadMatrixf(mMatrixValues, 0); - gl.glDrawArrays(GL11.GL_LINE_LOOP, OFFSET_DRAW_RECT, 4); - - restoreTransform(); - mCountDrawLine++; - } - - @Override - public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) { - GL11 gl = mGL; - - mGLState.setColorMode(paint.getColor(), mAlpha); - mGLState.setLineWidth(paint.getLineWidth()); - - saveTransform(); - translate(x1, y1); - scale(x2 - x1, y2 - y1, 1); - - gl.glLoadMatrixf(mMatrixValues, 0); - gl.glDrawArrays(GL11.GL_LINE_STRIP, OFFSET_DRAW_LINE, 2); - - restoreTransform(); - mCountDrawLine++; - } - - @Override - public void fillRect(float x, float y, float width, float height, int color) { - mGLState.setColorMode(color, mAlpha); - GL11 gl = mGL; - - saveTransform(); - translate(x, y); - scale(width, height, 1); - - gl.glLoadMatrixf(mMatrixValues, 0); - gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4); - - restoreTransform(); - mCountFillRect++; - } - - @Override - public void translate(float x, float y, float z) { - Matrix.translateM(mMatrixValues, 0, x, y, z); - } - - // This is a faster version of translate(x, y, z) because - // (1) we knows z = 0, (2) we inline the Matrix.translateM call, - // (3) we unroll the loop - @Override - public void translate(float x, float y) { - float[] m = mMatrixValues; - m[12] += m[0] * x + m[4] * y; - m[13] += m[1] * x + m[5] * y; - m[14] += m[2] * x + m[6] * y; - m[15] += m[3] * x + m[7] * y; - } - - @Override - public void scale(float sx, float sy, float sz) { - Matrix.scaleM(mMatrixValues, 0, sx, sy, sz); - } - - @Override - public void rotate(float angle, float x, float y, float z) { - if (angle == 0) return; - float[] temp = mTempMatrix; - Matrix.setRotateM(temp, 0, angle, x, y, z); - Matrix.multiplyMM(temp, 16, mMatrixValues, 0, temp, 0); - System.arraycopy(temp, 16, mMatrixValues, 0, 16); - } - - @Override - public void multiplyMatrix(float matrix[], int offset) { - float[] temp = mTempMatrix; - Matrix.multiplyMM(temp, 0, mMatrixValues, 0, matrix, offset); - System.arraycopy(temp, 0, mMatrixValues, 0, 16); - } - - private void textureRect(float x, float y, float width, float height) { - GL11 gl = mGL; - - saveTransform(); - translate(x, y); - scale(width, height, 1); - - gl.glLoadMatrixf(mMatrixValues, 0); - gl.glDrawArrays(GL11.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, 4); - - restoreTransform(); - mCountTextureRect++; - } - - @Override - public void drawMesh(BasicTexture tex, int x, int y, int xyBuffer, - int uvBuffer, int indexBuffer, int indexCount) { - float alpha = mAlpha; - if (!bindTexture(tex)) return; - - mGLState.setBlendEnabled(mBlendEnabled - && (!tex.isOpaque() || alpha < OPAQUE_ALPHA)); - mGLState.setTextureAlpha(alpha); - - // Reset the texture matrix. We will set our own texture coordinates - // below. - setTextureCoords(0, 0, 1, 1); - - saveTransform(); - translate(x, y); - - mGL.glLoadMatrixf(mMatrixValues, 0); - - mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, xyBuffer); - mGL.glVertexPointer(2, GL11.GL_FLOAT, 0, 0); - - mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, uvBuffer); - mGL.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0); - - mGL.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexBuffer); - mGL.glDrawElements(GL11.GL_TRIANGLE_STRIP, - indexCount, GL11.GL_UNSIGNED_BYTE, 0); - - mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, mBoxCoords); - mGL.glVertexPointer(2, GL11.GL_FLOAT, 0, 0); - mGL.glTexCoordPointer(2, GL11.GL_FLOAT, 0, 0); - - restoreTransform(); - mCountDrawMesh++; - } - - // Transforms two points by the given matrix m. The result - // {x1', y1', x2', y2'} are stored in mMapPointsBuffer and also returned. - private float[] mapPoints(float m[], int x1, int y1, int x2, int y2) { - float[] r = mMapPointsBuffer; - - // Multiply m and (x1 y1 0 1) to produce (x3 y3 z3 w3). z3 is unused. - float x3 = m[0] * x1 + m[4] * y1 + m[12]; - float y3 = m[1] * x1 + m[5] * y1 + m[13]; - float w3 = m[3] * x1 + m[7] * y1 + m[15]; - r[0] = x3 / w3; - r[1] = y3 / w3; - - // Same for x2 y2. - float x4 = m[0] * x2 + m[4] * y2 + m[12]; - float y4 = m[1] * x2 + m[5] * y2 + m[13]; - float w4 = m[3] * x2 + m[7] * y2 + m[15]; - r[2] = x4 / w4; - r[3] = y4 / w4; - - return r; - } - - private void drawBoundTexture( - BasicTexture texture, int x, int y, int width, int height) { - // Test whether it has been rotated or flipped, if so, glDrawTexiOES - // won't work - if (isMatrixRotatedOrFlipped(mMatrixValues)) { - if (texture.hasBorder()) { - setTextureCoords( - 1.0f / texture.getTextureWidth(), - 1.0f / texture.getTextureHeight(), - (texture.getWidth() - 1.0f) / texture.getTextureWidth(), - (texture.getHeight() - 1.0f) / texture.getTextureHeight()); - } else { - setTextureCoords(0, 0, - (float) texture.getWidth() / texture.getTextureWidth(), - (float) texture.getHeight() / texture.getTextureHeight()); - } - textureRect(x, y, width, height); - } else { - // draw the rect from bottom-left to top-right - float points[] = mapPoints( - mMatrixValues, x, y + height, x + width, y); - x = (int) (points[0] + 0.5f); - y = (int) (points[1] + 0.5f); - width = (int) (points[2] + 0.5f) - x; - height = (int) (points[3] + 0.5f) - y; - if (width > 0 && height > 0) { - ((GL11Ext) mGL).glDrawTexiOES(x, y, 0, width, height); - mCountTextureOES++; - } - } - } - - @Override - public void drawTexture( - BasicTexture texture, int x, int y, int width, int height) { - drawTexture(texture, x, y, width, height, mAlpha); - } - - private void drawTexture(BasicTexture texture, - int x, int y, int width, int height, float alpha) { - if (width <= 0 || height <= 0) return; - - mGLState.setBlendEnabled(mBlendEnabled - && (!texture.isOpaque() || alpha < OPAQUE_ALPHA)); - if (!bindTexture(texture)) return; - mGLState.setTextureAlpha(alpha); - drawBoundTexture(texture, x, y, width, height); - } - - @Override - public void drawTexture(BasicTexture texture, RectF source, RectF target) { - if (target.width() <= 0 || target.height() <= 0) return; - - // Copy the input to avoid changing it. - mDrawTextureSourceRect.set(source); - mDrawTextureTargetRect.set(target); - source = mDrawTextureSourceRect; - target = mDrawTextureTargetRect; - - mGLState.setBlendEnabled(mBlendEnabled - && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA)); - if (!bindTexture(texture)) return; - convertCoordinate(source, target, texture); - setTextureCoords(source); - mGLState.setTextureAlpha(mAlpha); - textureRect(target.left, target.top, target.width(), target.height()); - } - - @Override - public void drawTexture(BasicTexture texture, float[] mTextureTransform, - int x, int y, int w, int h) { - mGLState.setBlendEnabled(mBlendEnabled - && (!texture.isOpaque() || mAlpha < OPAQUE_ALPHA)); - if (!bindTexture(texture)) return; - setTextureCoords(mTextureTransform); - mGLState.setTextureAlpha(mAlpha); - textureRect(x, y, w, h); - } - - // This function changes the source coordinate to the texture coordinates. - // It also clips the source and target coordinates if it is beyond the - // bound of the texture. - private static void convertCoordinate(RectF source, RectF target, - BasicTexture texture) { - - int width = texture.getWidth(); - int height = texture.getHeight(); - int texWidth = texture.getTextureWidth(); - int texHeight = texture.getTextureHeight(); - // Convert to texture coordinates - source.left /= texWidth; - source.right /= texWidth; - source.top /= texHeight; - source.bottom /= texHeight; - - // Clip if the rendering range is beyond the bound of the texture. - float xBound = (float) width / texWidth; - if (source.right > xBound) { - target.right = target.left + target.width() * - (xBound - source.left) / source.width(); - source.right = xBound; - } - float yBound = (float) height / texHeight; - if (source.bottom > yBound) { - target.bottom = target.top + target.height() * - (yBound - source.top) / source.height(); - source.bottom = yBound; - } - } - - @Override - public void drawMixed(BasicTexture from, - int toColor, float ratio, int x, int y, int w, int h) { - drawMixed(from, toColor, ratio, x, y, w, h, mAlpha); - } - - private boolean bindTexture(BasicTexture texture) { - if (!texture.onBind(this)) return false; - int target = texture.getTarget(); - mGLState.setTextureTarget(target); - mGL.glBindTexture(target, texture.getId()); - return true; - } - - private void setTextureColor(float r, float g, float b, float alpha) { - float[] color = mTextureColor; - color[0] = r; - color[1] = g; - color[2] = b; - color[3] = alpha; - } - - private void setMixedColor(int toColor, float ratio, float alpha) { - // - // The formula we want: - // alpha * ((1 - ratio) * from + ratio * to) - // - // The formula that GL supports is in the form of: - // combo * from + (1 - combo) * to * scale - // - // So, we have combo = alpha * (1 - ratio) - // and scale = alpha * ratio / (1 - combo) - // - float combo = alpha * (1 - ratio); - float scale = alpha * ratio / (1 - combo); - - // Specify the interpolation factor via the alpha component of - // GL_TEXTURE_ENV_COLORs. - // RGB component are get from toColor and will used as SRC1 - float colorScale = scale * (toColor >>> 24) / (0xff * 0xff); - setTextureColor(((toColor >>> 16) & 0xff) * colorScale, - ((toColor >>> 8) & 0xff) * colorScale, - (toColor & 0xff) * colorScale, combo); - GL11 gl = mGL; - gl.glTexEnvfv(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_COLOR, mTextureColor, 0); - - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_RGB, GL11.GL_INTERPOLATE); - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_COMBINE_ALPHA, GL11.GL_INTERPOLATE); - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC1_RGB, GL11.GL_CONSTANT); - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND1_RGB, GL11.GL_SRC_COLOR); - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC1_ALPHA, GL11.GL_CONSTANT); - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND1_ALPHA, GL11.GL_SRC_ALPHA); - - // Wire up the interpolation factor for RGB. - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_RGB, GL11.GL_CONSTANT); - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_RGB, GL11.GL_SRC_ALPHA); - - // Wire up the interpolation factor for alpha. - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_SRC2_ALPHA, GL11.GL_CONSTANT); - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_OPERAND2_ALPHA, GL11.GL_SRC_ALPHA); - - } - - @Override - public void drawMixed(BasicTexture from, int toColor, float ratio, - RectF source, RectF target) { - if (target.width() <= 0 || target.height() <= 0) return; - - if (ratio <= 0.01f) { - drawTexture(from, source, target); - return; - } else if (ratio >= 1) { - fillRect(target.left, target.top, target.width(), target.height(), toColor); - return; - } - - float alpha = mAlpha; - - // Copy the input to avoid changing it. - mDrawTextureSourceRect.set(source); - mDrawTextureTargetRect.set(target); - source = mDrawTextureSourceRect; - target = mDrawTextureTargetRect; - - mGLState.setBlendEnabled(mBlendEnabled && (!from.isOpaque() - || !Utils.isOpaque(toColor) || alpha < OPAQUE_ALPHA)); - - if (!bindTexture(from)) return; - - // Interpolate the RGB and alpha values between both textures. - mGLState.setTexEnvMode(GL11.GL_COMBINE); - setMixedColor(toColor, ratio, alpha); - convertCoordinate(source, target, from); - setTextureCoords(source); - textureRect(target.left, target.top, target.width(), target.height()); - mGLState.setTexEnvMode(GL11.GL_REPLACE); - } - - private void drawMixed(BasicTexture from, int toColor, - float ratio, int x, int y, int width, int height, float alpha) { - // change from 0 to 0.01f to prevent getting divided by zero below - if (ratio <= 0.01f) { - drawTexture(from, x, y, width, height, alpha); - return; - } else if (ratio >= 1) { - fillRect(x, y, width, height, toColor); - return; - } - - mGLState.setBlendEnabled(mBlendEnabled && (!from.isOpaque() - || !Utils.isOpaque(toColor) || alpha < OPAQUE_ALPHA)); - - final GL11 gl = mGL; - if (!bindTexture(from)) return; - - // Interpolate the RGB and alpha values between both textures. - mGLState.setTexEnvMode(GL11.GL_COMBINE); - setMixedColor(toColor, ratio, alpha); - - drawBoundTexture(from, x, y, width, height); - mGLState.setTexEnvMode(GL11.GL_REPLACE); - } - - // TODO: the code only work for 2D should get fixed for 3D or removed - private static final int MSKEW_X = 4; - private static final int MSKEW_Y = 1; - private static final int MSCALE_X = 0; - private static final int MSCALE_Y = 5; - - private static boolean isMatrixRotatedOrFlipped(float matrix[]) { - final float eps = 1e-5f; - return Math.abs(matrix[MSKEW_X]) > eps - || Math.abs(matrix[MSKEW_Y]) > eps - || matrix[MSCALE_X] < -eps - || matrix[MSCALE_Y] > eps; - } - - private static class GLState { - - private final GL11 mGL; - - private int mTexEnvMode = GL11.GL_REPLACE; - private float mTextureAlpha = 1.0f; - private int mTextureTarget = GL11.GL_TEXTURE_2D; - private boolean mBlendEnabled = true; - private float mLineWidth = 1.0f; - private boolean mLineSmooth = false; - - public GLState(GL11 gl) { - mGL = gl; - - // Disable unused state - gl.glDisable(GL11.GL_LIGHTING); - - // Enable used features - gl.glEnable(GL11.GL_DITHER); - - gl.glEnableClientState(GL10.GL_VERTEX_ARRAY); - gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY); - gl.glEnable(GL11.GL_TEXTURE_2D); - - gl.glTexEnvf(GL11.GL_TEXTURE_ENV, - GL11.GL_TEXTURE_ENV_MODE, GL11.GL_REPLACE); - - // Set the background color - gl.glClearColor(0f, 0f, 0f, 0f); - - gl.glEnable(GL11.GL_BLEND); - gl.glBlendFunc(GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); - - // We use 565 or 8888 format, so set the alignment to 2 bytes/pixel. - gl.glPixelStorei(GL11.GL_UNPACK_ALIGNMENT, 2); - } - - public void setTexEnvMode(int mode) { - if (mTexEnvMode == mode) return; - mTexEnvMode = mode; - mGL.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, mode); - } - - public void setLineWidth(float width) { - if (mLineWidth == width) return; - mLineWidth = width; - mGL.glLineWidth(width); - } - - public void setTextureAlpha(float alpha) { - if (mTextureAlpha == alpha) return; - mTextureAlpha = alpha; - if (alpha >= OPAQUE_ALPHA) { - // The alpha is need for those texture without alpha channel - mGL.glColor4f(1, 1, 1, 1); - setTexEnvMode(GL11.GL_REPLACE); - } else { - mGL.glColor4f(alpha, alpha, alpha, alpha); - setTexEnvMode(GL11.GL_MODULATE); - } - } - - public void setColorMode(int color, float alpha) { - setBlendEnabled(!Utils.isOpaque(color) || alpha < OPAQUE_ALPHA); - - // Set mTextureAlpha to an invalid value, so that it will reset - // again in setTextureAlpha(float) later. - mTextureAlpha = -1.0f; - - setTextureTarget(0); - - float prealpha = (color >>> 24) * alpha * 65535f / 255f / 255f; - mGL.glColor4x( - Math.round(((color >> 16) & 0xFF) * prealpha), - Math.round(((color >> 8) & 0xFF) * prealpha), - Math.round((color & 0xFF) * prealpha), - Math.round(255 * prealpha)); - } - - // target is a value like GL_TEXTURE_2D. If target = 0, texturing is disabled. - public void setTextureTarget(int target) { - if (mTextureTarget == target) return; - if (mTextureTarget != 0) { - mGL.glDisable(mTextureTarget); - } - mTextureTarget = target; - if (mTextureTarget != 0) { - mGL.glEnable(mTextureTarget); - } - } - - public void setBlendEnabled(boolean enabled) { - if (mBlendEnabled == enabled) return; - mBlendEnabled = enabled; - if (enabled) { - mGL.glEnable(GL11.GL_BLEND); - } else { - mGL.glDisable(GL11.GL_BLEND); - } - } - } - - @Override - public void clearBuffer(float[] argb) { - if(argb != null && argb.length == 4) { - mGL.glClearColor(argb[1], argb[2], argb[3], argb[0]); - } else { - mGL.glClearColor(0, 0, 0, 1); - } - mGL.glClear(GL10.GL_COLOR_BUFFER_BIT); - } - - @Override - public void clearBuffer() { - clearBuffer(null); - } - - private void setTextureCoords(RectF source) { - setTextureCoords(source.left, source.top, source.right, source.bottom); - } - - private void setTextureCoords(float left, float top, - float right, float bottom) { - mGL.glMatrixMode(GL11.GL_TEXTURE); - mTextureMatrixValues[0] = right - left; - mTextureMatrixValues[5] = bottom - top; - mTextureMatrixValues[10] = 1; - mTextureMatrixValues[12] = left; - mTextureMatrixValues[13] = top; - mTextureMatrixValues[15] = 1; - mGL.glLoadMatrixf(mTextureMatrixValues, 0); - mGL.glMatrixMode(GL11.GL_MODELVIEW); - } - - private void setTextureCoords(float[] mTextureTransform) { - mGL.glMatrixMode(GL11.GL_TEXTURE); - mGL.glLoadMatrixf(mTextureTransform, 0); - mGL.glMatrixMode(GL11.GL_MODELVIEW); - } - - // unloadTexture and deleteBuffer can be called from the finalizer thread, - // so we synchronized on the mUnboundTextures object. - @Override - public boolean unloadTexture(BasicTexture t) { - synchronized (mUnboundTextures) { - if (!t.isLoaded()) return false; - mUnboundTextures.add(t.mId); - return true; - } - } - - @Override - public void deleteBuffer(int bufferId) { - synchronized (mUnboundTextures) { - mDeleteBuffers.add(bufferId); - } - } - - @Override - public void deleteRecycledResources() { - synchronized (mUnboundTextures) { - IntArray ids = mUnboundTextures; - if (ids.size() > 0) { - mGLId.glDeleteTextures(mGL, ids.size(), ids.getInternalArray(), 0); - ids.clear(); - } - - ids = mDeleteBuffers; - if (ids.size() > 0) { - mGLId.glDeleteBuffers(mGL, ids.size(), ids.getInternalArray(), 0); - ids.clear(); - } - } - } - - @Override - public void save() { - save(SAVE_FLAG_ALL); - } - - @Override - public void save(int saveFlags) { - ConfigState config = obtainRestoreConfig(); - - if ((saveFlags & SAVE_FLAG_ALPHA) != 0) { - config.mAlpha = mAlpha; - } else { - config.mAlpha = -1; - } - - if ((saveFlags & SAVE_FLAG_MATRIX) != 0) { - System.arraycopy(mMatrixValues, 0, config.mMatrix, 0, 16); - } else { - config.mMatrix[0] = Float.NEGATIVE_INFINITY; - } - - mRestoreStack.add(config); - } - - @Override - public void restore() { - if (mRestoreStack.isEmpty()) throw new IllegalStateException(); - ConfigState config = mRestoreStack.remove(mRestoreStack.size() - 1); - config.restore(this); - freeRestoreConfig(config); - } - - private void freeRestoreConfig(ConfigState action) { - action.mNextFree = mRecycledRestoreAction; - mRecycledRestoreAction = action; - } - - private ConfigState obtainRestoreConfig() { - if (mRecycledRestoreAction != null) { - ConfigState result = mRecycledRestoreAction; - mRecycledRestoreAction = result.mNextFree; - return result; - } - return new ConfigState(); - } - - private static class ConfigState { - float mAlpha; - float mMatrix[] = new float[16]; - ConfigState mNextFree; - - public void restore(GLES11Canvas canvas) { - if (mAlpha >= 0) canvas.setAlpha(mAlpha); - if (mMatrix[0] != Float.NEGATIVE_INFINITY) { - System.arraycopy(mMatrix, 0, canvas.mMatrixValues, 0, 16); - } - } - } - - @Override - public void dumpStatisticsAndClear() { - String line = String.format( - "MESH:%d, TEX_OES:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", - mCountDrawMesh, mCountTextureRect, mCountTextureOES, - mCountFillRect, mCountDrawLine); - mCountDrawMesh = 0; - mCountTextureRect = 0; - mCountTextureOES = 0; - mCountFillRect = 0; - mCountDrawLine = 0; - Log.d(TAG, line); - } - - private void saveTransform() { - System.arraycopy(mMatrixValues, 0, mTempMatrix, 0, 16); - } - - private void restoreTransform() { - System.arraycopy(mTempMatrix, 0, mMatrixValues, 0, 16); - } - - private void setRenderTarget(RawTexture texture) { - GL11ExtensionPack gl11ep = (GL11ExtensionPack) mGL; - - if (mTargetTexture == null && texture != null) { - mGLId.glGenBuffers(1, mFrameBuffer, 0); - gl11ep.glBindFramebufferOES( - GL11ExtensionPack.GL_FRAMEBUFFER_OES, mFrameBuffer[0]); - } - if (mTargetTexture != null && texture == null) { - gl11ep.glBindFramebufferOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES, 0); - gl11ep.glDeleteFramebuffersOES(1, mFrameBuffer, 0); - } - - mTargetTexture = texture; - if (texture == null) { - setSize(mScreenWidth, mScreenHeight); - } else { - setSize(texture.getWidth(), texture.getHeight()); - - if (!texture.isLoaded()) texture.prepare(this); - - gl11ep.glFramebufferTexture2DOES( - GL11ExtensionPack.GL_FRAMEBUFFER_OES, - GL11ExtensionPack.GL_COLOR_ATTACHMENT0_OES, - GL11.GL_TEXTURE_2D, texture.getId(), 0); - - checkFramebufferStatus(gl11ep); - } - } - - @Override - public void endRenderTarget() { - RawTexture texture = mTargetStack.remove(mTargetStack.size() - 1); - setRenderTarget(texture); - restore(); // restore matrix and alpha - } - - @Override - public void beginRenderTarget(RawTexture texture) { - save(); // save matrix and alpha - mTargetStack.add(mTargetTexture); - setRenderTarget(texture); - } - - private static void checkFramebufferStatus(GL11ExtensionPack gl11ep) { - int status = gl11ep.glCheckFramebufferStatusOES(GL11ExtensionPack.GL_FRAMEBUFFER_OES); - if (status != GL11ExtensionPack.GL_FRAMEBUFFER_COMPLETE_OES) { - String msg = ""; - switch (status) { - case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_FORMATS_OES: - msg = "FRAMEBUFFER_FORMATS"; - break; - case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_OES: - msg = "FRAMEBUFFER_ATTACHMENT"; - break; - case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES: - msg = "FRAMEBUFFER_MISSING_ATTACHMENT"; - break; - case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_OES: - msg = "FRAMEBUFFER_DRAW_BUFFER"; - break; - case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_OES: - msg = "FRAMEBUFFER_READ_BUFFER"; - break; - case GL11ExtensionPack.GL_FRAMEBUFFER_UNSUPPORTED_OES: - msg = "FRAMEBUFFER_UNSUPPORTED"; - break; - case GL11ExtensionPack.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_OES: - msg = "FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; - break; - } - throw new RuntimeException(msg + ":" + Integer.toHexString(status)); - } - } - - @Override - public void setTextureParameters(BasicTexture texture) { - int width = texture.getWidth(); - int height = texture.getHeight(); - // Define a vertically flipped crop rectangle for OES_draw_texture. - // The four values in sCropRect are: left, bottom, width, and - // height. Negative value of width or height means flip. - sCropRect[0] = 0; - sCropRect[1] = height; - sCropRect[2] = width; - sCropRect[3] = -height; - - // Set texture parameters. - int target = texture.getTarget(); - mGL.glBindTexture(target, texture.getId()); - mGL.glTexParameterfv(target, GL11Ext.GL_TEXTURE_CROP_RECT_OES, sCropRect, 0); - mGL.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP_TO_EDGE); - mGL.glTexParameteri(target, GL11.GL_TEXTURE_WRAP_T, GL11.GL_CLAMP_TO_EDGE); - mGL.glTexParameterf(target, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); - mGL.glTexParameterf(target, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); - } - - @Override - public void initializeTextureSize(BasicTexture texture, int format, int type) { - int target = texture.getTarget(); - mGL.glBindTexture(target, texture.getId()); - int width = texture.getTextureWidth(); - int height = texture.getTextureHeight(); - mGL.glTexImage2D(target, 0, format, width, height, 0, format, type, null); - } - - @Override - public void initializeTexture(BasicTexture texture, Bitmap bitmap) { - int target = texture.getTarget(); - mGL.glBindTexture(target, texture.getId()); - GLUtils.texImage2D(target, 0, bitmap, 0); - } - - @Override - public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap, - int format, int type) { - int target = texture.getTarget(); - mGL.glBindTexture(target, texture.getId()); - GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type); - } - - @Override - public int uploadBuffer(FloatBuffer buf) { - return uploadBuffer(buf, Float.SIZE / Byte.SIZE); - } - - @Override - public int uploadBuffer(ByteBuffer buf) { - return uploadBuffer(buf, 1); - } - - private int uploadBuffer(Buffer buf, int elementSize) { - int[] bufferIds = new int[1]; - mGLId.glGenBuffers(bufferIds.length, bufferIds, 0); - int bufferId = bufferIds[0]; - mGL.glBindBuffer(GL11.GL_ARRAY_BUFFER, bufferId); - mGL.glBufferData(GL11.GL_ARRAY_BUFFER, buf.capacity() * elementSize, buf, - GL11.GL_STATIC_DRAW); - return bufferId; - } - - @Override - public void recoverFromLightCycle() { - // This is only required for GLES20 - } - - @Override - public void getBounds(Rect bounds, int x, int y, int width, int height) { - // This is only required for GLES20 - } - - @Override - public GLId getGLId() { - return mGLId; - } -} diff --git a/src/com/android/gallery3d/glrenderer/GLES11IdImpl.java b/src/com/android/gallery3d/glrenderer/GLES11IdImpl.java deleted file mode 100644 index e4793730f..000000000 --- a/src/com/android/gallery3d/glrenderer/GLES11IdImpl.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.glrenderer; - -import javax.microedition.khronos.opengles.GL11; -import javax.microedition.khronos.opengles.GL11ExtensionPack; - -/** - * Open GL ES 1.1 implementation for generating and destroying texture IDs and - * buffer IDs - */ -public class GLES11IdImpl implements GLId { - private static int sNextId = 1; - // Mutex for sNextId - private static Object sLock = new Object(); - - @Override - public int generateTexture() { - synchronized (sLock) { - return sNextId++; - } - } - - @Override - public void glGenBuffers(int n, int[] buffers, int offset) { - synchronized (sLock) { - while (n-- > 0) { - buffers[offset + n] = sNextId++; - } - } - } - - @Override - public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) { - synchronized (sLock) { - gl.glDeleteTextures(n, textures, offset); - } - } - - @Override - public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) { - synchronized (sLock) { - gl.glDeleteBuffers(n, buffers, offset); - } - } - - @Override - public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) { - synchronized (sLock) { - gl11ep.glDeleteFramebuffersOES(n, buffers, offset); - } - } - - -} diff --git a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java b/src/com/android/gallery3d/glrenderer/GLES20Canvas.java deleted file mode 100644 index 4ead1315e..000000000 --- a/src/com/android/gallery3d/glrenderer/GLES20Canvas.java +++ /dev/null @@ -1,1009 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.glrenderer; - -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.graphics.RectF; -import android.opengl.GLES20; -import android.opengl.GLUtils; -import android.opengl.Matrix; -import android.util.Log; - -import com.android.gallery3d.util.IntArray; - -import java.nio.Buffer; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import java.util.ArrayList; -import java.util.Arrays; - -public class GLES20Canvas implements GLCanvas { - // ************** Constants ********************** - private static final String TAG = GLES20Canvas.class.getSimpleName(); - private static final int FLOAT_SIZE = Float.SIZE / Byte.SIZE; - private static final float OPAQUE_ALPHA = 0.95f; - - private static final int COORDS_PER_VERTEX = 2; - private static final int VERTEX_STRIDE = COORDS_PER_VERTEX * FLOAT_SIZE; - - private static final int COUNT_FILL_VERTEX = 4; - private static final int COUNT_LINE_VERTEX = 2; - private static final int COUNT_RECT_VERTEX = 4; - private static final int OFFSET_FILL_RECT = 0; - private static final int OFFSET_DRAW_LINE = OFFSET_FILL_RECT + COUNT_FILL_VERTEX; - private static final int OFFSET_DRAW_RECT = OFFSET_DRAW_LINE + COUNT_LINE_VERTEX; - - private static final float[] BOX_COORDINATES = { - 0, 0, // Fill rectangle - 1, 0, - 0, 1, - 1, 1, - 0, 0, // Draw line - 1, 1, - 0, 0, // Draw rectangle outline - 0, 1, - 1, 1, - 1, 0, - }; - - private static final float[] BOUNDS_COORDINATES = { - 0, 0, 0, 1, - 1, 1, 0, 1, - }; - - private static final String POSITION_ATTRIBUTE = "aPosition"; - private static final String COLOR_UNIFORM = "uColor"; - private static final String MATRIX_UNIFORM = "uMatrix"; - private static final String TEXTURE_MATRIX_UNIFORM = "uTextureMatrix"; - private static final String TEXTURE_SAMPLER_UNIFORM = "uTextureSampler"; - private static final String ALPHA_UNIFORM = "uAlpha"; - private static final String TEXTURE_COORD_ATTRIBUTE = "aTextureCoordinate"; - - private static final String DRAW_VERTEX_SHADER = "" - + "uniform mat4 " + MATRIX_UNIFORM + ";\n" - + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" - + "void main() {\n" - + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" - + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" - + "}\n"; - - private static final String DRAW_FRAGMENT_SHADER = "" - + "precision mediump float;\n" - + "uniform vec4 " + COLOR_UNIFORM + ";\n" - + "void main() {\n" - + " gl_FragColor = " + COLOR_UNIFORM + ";\n" - + "}\n"; - - private static final String TEXTURE_VERTEX_SHADER = "" - + "uniform mat4 " + MATRIX_UNIFORM + ";\n" - + "uniform mat4 " + TEXTURE_MATRIX_UNIFORM + ";\n" - + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" - + "varying vec2 vTextureCoord;\n" - + "void main() {\n" - + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" - + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" - + " vTextureCoord = (" + TEXTURE_MATRIX_UNIFORM + " * pos).xy;\n" - + "}\n"; - - private static final String MESH_VERTEX_SHADER = "" - + "uniform mat4 " + MATRIX_UNIFORM + ";\n" - + "attribute vec2 " + POSITION_ATTRIBUTE + ";\n" - + "attribute vec2 " + TEXTURE_COORD_ATTRIBUTE + ";\n" - + "varying vec2 vTextureCoord;\n" - + "void main() {\n" - + " vec4 pos = vec4(" + POSITION_ATTRIBUTE + ", 0.0, 1.0);\n" - + " gl_Position = " + MATRIX_UNIFORM + " * pos;\n" - + " vTextureCoord = " + TEXTURE_COORD_ATTRIBUTE + ";\n" - + "}\n"; - - private static final String TEXTURE_FRAGMENT_SHADER = "" - + "precision mediump float;\n" - + "varying vec2 vTextureCoord;\n" - + "uniform float " + ALPHA_UNIFORM + ";\n" - + "uniform sampler2D " + TEXTURE_SAMPLER_UNIFORM + ";\n" - + "void main() {\n" - + " gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n" - + " gl_FragColor *= " + ALPHA_UNIFORM + ";\n" - + "}\n"; - - private static final String OES_TEXTURE_FRAGMENT_SHADER = "" - + "#extension GL_OES_EGL_image_external : require\n" - + "precision mediump float;\n" - + "varying vec2 vTextureCoord;\n" - + "uniform float " + ALPHA_UNIFORM + ";\n" - + "uniform samplerExternalOES " + TEXTURE_SAMPLER_UNIFORM + ";\n" - + "void main() {\n" - + " gl_FragColor = texture2D(" + TEXTURE_SAMPLER_UNIFORM + ", vTextureCoord);\n" - + " gl_FragColor *= " + ALPHA_UNIFORM + ";\n" - + "}\n"; - - private static final int INITIAL_RESTORE_STATE_SIZE = 8; - private static final int MATRIX_SIZE = 16; - - // Keep track of restore state - private float[] mMatrices = new float[INITIAL_RESTORE_STATE_SIZE * MATRIX_SIZE]; - private float[] mAlphas = new float[INITIAL_RESTORE_STATE_SIZE]; - private IntArray mSaveFlags = new IntArray(); - - private int mCurrentAlphaIndex = 0; - private int mCurrentMatrixIndex = 0; - - // Viewport size - private int mWidth; - private int mHeight; - - // Projection matrix - private float[] mProjectionMatrix = new float[MATRIX_SIZE]; - - // Screen size for when we aren't bound to a texture - private int mScreenWidth; - private int mScreenHeight; - - // GL programs - private int mDrawProgram; - private int mTextureProgram; - private int mOesTextureProgram; - private int mMeshProgram; - - // GL buffer containing BOX_COORDINATES - private int mBoxCoordinates; - - // Handle indices -- common - private static final int INDEX_POSITION = 0; - private static final int INDEX_MATRIX = 1; - - // Handle indices -- draw - private static final int INDEX_COLOR = 2; - - // Handle indices -- texture - private static final int INDEX_TEXTURE_MATRIX = 2; - private static final int INDEX_TEXTURE_SAMPLER = 3; - private static final int INDEX_ALPHA = 4; - - // Handle indices -- mesh - private static final int INDEX_TEXTURE_COORD = 2; - - private abstract static class ShaderParameter { - public int handle; - protected final String mName; - - public ShaderParameter(String name) { - mName = name; - } - - public abstract void loadHandle(int program); - } - - private static class UniformShaderParameter extends ShaderParameter { - public UniformShaderParameter(String name) { - super(name); - } - - @Override - public void loadHandle(int program) { - handle = GLES20.glGetUniformLocation(program, mName); - checkError(); - } - } - - private static class AttributeShaderParameter extends ShaderParameter { - public AttributeShaderParameter(String name) { - super(name); - } - - @Override - public void loadHandle(int program) { - handle = GLES20.glGetAttribLocation(program, mName); - checkError(); - } - } - - ShaderParameter[] mDrawParameters = { - new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION - new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX - new UniformShaderParameter(COLOR_UNIFORM), // INDEX_COLOR - }; - ShaderParameter[] mTextureParameters = { - new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION - new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX - new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX - new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER - new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA - }; - ShaderParameter[] mOesTextureParameters = { - new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION - new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX - new UniformShaderParameter(TEXTURE_MATRIX_UNIFORM), // INDEX_TEXTURE_MATRIX - new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER - new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA - }; - ShaderParameter[] mMeshParameters = { - new AttributeShaderParameter(POSITION_ATTRIBUTE), // INDEX_POSITION - new UniformShaderParameter(MATRIX_UNIFORM), // INDEX_MATRIX - new AttributeShaderParameter(TEXTURE_COORD_ATTRIBUTE), // INDEX_TEXTURE_COORD - new UniformShaderParameter(TEXTURE_SAMPLER_UNIFORM), // INDEX_TEXTURE_SAMPLER - new UniformShaderParameter(ALPHA_UNIFORM), // INDEX_ALPHA - }; - - private final IntArray mUnboundTextures = new IntArray(); - private final IntArray mDeleteBuffers = new IntArray(); - - // Keep track of statistics for debugging - private int mCountDrawMesh = 0; - private int mCountTextureRect = 0; - private int mCountFillRect = 0; - private int mCountDrawLine = 0; - - // Buffer for framebuffer IDs -- we keep track so we can switch the attached - // texture. - private int[] mFrameBuffer = new int[1]; - - // Bound textures. - private ArrayList<RawTexture> mTargetTextures = new ArrayList<RawTexture>(); - - // Temporary variables used within calculations - private final float[] mTempMatrix = new float[32]; - private final float[] mTempColor = new float[4]; - private final RectF mTempSourceRect = new RectF(); - private final RectF mTempTargetRect = new RectF(); - private final float[] mTempTextureMatrix = new float[MATRIX_SIZE]; - private final int[] mTempIntArray = new int[1]; - - private static final GLId mGLId = new GLES20IdImpl(); - - public GLES20Canvas() { - Matrix.setIdentityM(mTempTextureMatrix, 0); - Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex); - mAlphas[mCurrentAlphaIndex] = 1f; - mTargetTextures.add(null); - - FloatBuffer boxBuffer = createBuffer(BOX_COORDINATES); - mBoxCoordinates = uploadBuffer(boxBuffer); - - int drawVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, DRAW_VERTEX_SHADER); - int textureVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, TEXTURE_VERTEX_SHADER); - int meshVertexShader = loadShader(GLES20.GL_VERTEX_SHADER, MESH_VERTEX_SHADER); - int drawFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, DRAW_FRAGMENT_SHADER); - int textureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, TEXTURE_FRAGMENT_SHADER); - int oesTextureFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, - OES_TEXTURE_FRAGMENT_SHADER); - - mDrawProgram = assembleProgram(drawVertexShader, drawFragmentShader, mDrawParameters); - mTextureProgram = assembleProgram(textureVertexShader, textureFragmentShader, - mTextureParameters); - mOesTextureProgram = assembleProgram(textureVertexShader, oesTextureFragmentShader, - mOesTextureParameters); - mMeshProgram = assembleProgram(meshVertexShader, textureFragmentShader, mMeshParameters); - GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); - checkError(); - } - - private static FloatBuffer createBuffer(float[] values) { - // First create an nio buffer, then create a VBO from it. - int size = values.length * FLOAT_SIZE; - FloatBuffer buffer = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()) - .asFloatBuffer(); - buffer.put(values, 0, values.length).position(0); - return buffer; - } - - private int assembleProgram(int vertexShader, int fragmentShader, ShaderParameter[] params) { - int program = GLES20.glCreateProgram(); - checkError(); - if (program == 0) { - throw new RuntimeException("Cannot create GL program: " + GLES20.glGetError()); - } - GLES20.glAttachShader(program, vertexShader); - checkError(); - GLES20.glAttachShader(program, fragmentShader); - checkError(); - GLES20.glLinkProgram(program); - checkError(); - int[] mLinkStatus = mTempIntArray; - GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, mLinkStatus, 0); - if (mLinkStatus[0] != GLES20.GL_TRUE) { - Log.e(TAG, "Could not link program: "); - Log.e(TAG, GLES20.glGetProgramInfoLog(program)); - GLES20.glDeleteProgram(program); - program = 0; - } - for (int i = 0; i < params.length; i++) { - params[i].loadHandle(program); - } - return program; - } - - private static int loadShader(int type, String shaderCode) { - // create a vertex shader type (GLES20.GL_VERTEX_SHADER) - // or a fragment shader type (GLES20.GL_FRAGMENT_SHADER) - int shader = GLES20.glCreateShader(type); - - // add the source code to the shader and compile it - GLES20.glShaderSource(shader, shaderCode); - checkError(); - GLES20.glCompileShader(shader); - checkError(); - - return shader; - } - - @Override - public void setSize(int width, int height) { - mWidth = width; - mHeight = height; - GLES20.glViewport(0, 0, mWidth, mHeight); - checkError(); - Matrix.setIdentityM(mMatrices, mCurrentMatrixIndex); - Matrix.orthoM(mProjectionMatrix, 0, 0, width, 0, height, -1, 1); - if (getTargetTexture() == null) { - mScreenWidth = width; - mScreenHeight = height; - Matrix.translateM(mMatrices, mCurrentMatrixIndex, 0, height, 0); - Matrix.scaleM(mMatrices, mCurrentMatrixIndex, 1, -1, 1); - } - } - - @Override - public void clearBuffer() { - GLES20.glClearColor(0f, 0f, 0f, 1f); - checkError(); - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); - checkError(); - } - - @Override - public void clearBuffer(float[] argb) { - GLES20.glClearColor(argb[1], argb[2], argb[3], argb[0]); - checkError(); - GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); - checkError(); - } - - @Override - public float getAlpha() { - return mAlphas[mCurrentAlphaIndex]; - } - - @Override - public void setAlpha(float alpha) { - mAlphas[mCurrentAlphaIndex] = alpha; - } - - @Override - public void multiplyAlpha(float alpha) { - setAlpha(getAlpha() * alpha); - } - - @Override - public void translate(float x, float y, float z) { - Matrix.translateM(mMatrices, mCurrentMatrixIndex, x, y, z); - } - - // This is a faster version of translate(x, y, z) because - // (1) we knows z = 0, (2) we inline the Matrix.translateM call, - // (3) we unroll the loop - @Override - public void translate(float x, float y) { - int index = mCurrentMatrixIndex; - float[] m = mMatrices; - m[index + 12] += m[index + 0] * x + m[index + 4] * y; - m[index + 13] += m[index + 1] * x + m[index + 5] * y; - m[index + 14] += m[index + 2] * x + m[index + 6] * y; - m[index + 15] += m[index + 3] * x + m[index + 7] * y; - } - - @Override - public void scale(float sx, float sy, float sz) { - Matrix.scaleM(mMatrices, mCurrentMatrixIndex, sx, sy, sz); - } - - @Override - public void rotate(float angle, float x, float y, float z) { - if (angle == 0f) { - return; - } - float[] temp = mTempMatrix; - Matrix.setRotateM(temp, 0, angle, x, y, z); - float[] matrix = mMatrices; - int index = mCurrentMatrixIndex; - Matrix.multiplyMM(temp, MATRIX_SIZE, matrix, index, temp, 0); - System.arraycopy(temp, MATRIX_SIZE, matrix, index, MATRIX_SIZE); - } - - @Override - public void multiplyMatrix(float[] matrix, int offset) { - float[] temp = mTempMatrix; - float[] currentMatrix = mMatrices; - int index = mCurrentMatrixIndex; - Matrix.multiplyMM(temp, 0, currentMatrix, index, matrix, offset); - System.arraycopy(temp, 0, currentMatrix, index, 16); - } - - @Override - public void save() { - save(SAVE_FLAG_ALL); - } - - @Override - public void save(int saveFlags) { - boolean saveAlpha = (saveFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA; - if (saveAlpha) { - float currentAlpha = getAlpha(); - mCurrentAlphaIndex++; - if (mAlphas.length <= mCurrentAlphaIndex) { - mAlphas = Arrays.copyOf(mAlphas, mAlphas.length * 2); - } - mAlphas[mCurrentAlphaIndex] = currentAlpha; - } - boolean saveMatrix = (saveFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX; - if (saveMatrix) { - int currentIndex = mCurrentMatrixIndex; - mCurrentMatrixIndex += MATRIX_SIZE; - if (mMatrices.length <= mCurrentMatrixIndex) { - mMatrices = Arrays.copyOf(mMatrices, mMatrices.length * 2); - } - System.arraycopy(mMatrices, currentIndex, mMatrices, mCurrentMatrixIndex, MATRIX_SIZE); - } - mSaveFlags.add(saveFlags); - } - - @Override - public void restore() { - int restoreFlags = mSaveFlags.removeLast(); - boolean restoreAlpha = (restoreFlags & SAVE_FLAG_ALPHA) == SAVE_FLAG_ALPHA; - if (restoreAlpha) { - mCurrentAlphaIndex--; - } - boolean restoreMatrix = (restoreFlags & SAVE_FLAG_MATRIX) == SAVE_FLAG_MATRIX; - if (restoreMatrix) { - mCurrentMatrixIndex -= MATRIX_SIZE; - } - } - - @Override - public void drawLine(float x1, float y1, float x2, float y2, GLPaint paint) { - draw(GLES20.GL_LINE_STRIP, OFFSET_DRAW_LINE, COUNT_LINE_VERTEX, x1, y1, x2 - x1, y2 - y1, - paint); - mCountDrawLine++; - } - - @Override - public void drawRect(float x, float y, float width, float height, GLPaint paint) { - draw(GLES20.GL_LINE_LOOP, OFFSET_DRAW_RECT, COUNT_RECT_VERTEX, x, y, width, height, paint); - mCountDrawLine++; - } - - private void draw(int type, int offset, int count, float x, float y, float width, float height, - GLPaint paint) { - draw(type, offset, count, x, y, width, height, paint.getColor(), paint.getLineWidth()); - } - - private void draw(int type, int offset, int count, float x, float y, float width, float height, - int color, float lineWidth) { - prepareDraw(offset, color, lineWidth); - draw(mDrawParameters, type, count, x, y, width, height); - } - - private void prepareDraw(int offset, int color, float lineWidth) { - GLES20.glUseProgram(mDrawProgram); - checkError(); - if (lineWidth > 0) { - GLES20.glLineWidth(lineWidth); - checkError(); - } - float[] colorArray = getColor(color); - boolean blendingEnabled = (colorArray[3] < 1f); - enableBlending(blendingEnabled); - if (blendingEnabled) { - GLES20.glBlendColor(colorArray[0], colorArray[1], colorArray[2], colorArray[3]); - checkError(); - } - - GLES20.glUniform4fv(mDrawParameters[INDEX_COLOR].handle, 1, colorArray, 0); - setPosition(mDrawParameters, offset); - checkError(); - } - - private float[] getColor(int color) { - float alpha = ((color >>> 24) & 0xFF) / 255f * getAlpha(); - float red = ((color >>> 16) & 0xFF) / 255f * alpha; - float green = ((color >>> 8) & 0xFF) / 255f * alpha; - float blue = (color & 0xFF) / 255f * alpha; - mTempColor[0] = red; - mTempColor[1] = green; - mTempColor[2] = blue; - mTempColor[3] = alpha; - return mTempColor; - } - - private void enableBlending(boolean enableBlending) { - if (enableBlending) { - GLES20.glEnable(GLES20.GL_BLEND); - checkError(); - } else { - GLES20.glDisable(GLES20.GL_BLEND); - checkError(); - } - } - - private void setPosition(ShaderParameter[] params, int offset) { - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, mBoxCoordinates); - checkError(); - GLES20.glVertexAttribPointer(params[INDEX_POSITION].handle, COORDS_PER_VERTEX, - GLES20.GL_FLOAT, false, VERTEX_STRIDE, offset * VERTEX_STRIDE); - checkError(); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - checkError(); - } - - private void draw(ShaderParameter[] params, int type, int count, float x, float y, float width, - float height) { - setMatrix(params, x, y, width, height); - int positionHandle = params[INDEX_POSITION].handle; - GLES20.glEnableVertexAttribArray(positionHandle); - checkError(); - GLES20.glDrawArrays(type, 0, count); - checkError(); - GLES20.glDisableVertexAttribArray(positionHandle); - checkError(); - } - - private void setMatrix(ShaderParameter[] params, float x, float y, float width, float height) { - Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f); - Matrix.scaleM(mTempMatrix, 0, width, height, 1f); - Matrix.multiplyMM(mTempMatrix, MATRIX_SIZE, mProjectionMatrix, 0, mTempMatrix, 0); - GLES20.glUniformMatrix4fv(params[INDEX_MATRIX].handle, 1, false, mTempMatrix, MATRIX_SIZE); - checkError(); - } - - @Override - public void fillRect(float x, float y, float width, float height, int color) { - draw(GLES20.GL_TRIANGLE_STRIP, OFFSET_FILL_RECT, COUNT_FILL_VERTEX, x, y, width, height, - color, 0f); - mCountFillRect++; - } - - @Override - public void drawTexture(BasicTexture texture, int x, int y, int width, int height) { - if (width <= 0 || height <= 0) { - return; - } - copyTextureCoordinates(texture, mTempSourceRect); - mTempTargetRect.set(x, y, x + width, y + height); - convertCoordinate(mTempSourceRect, mTempTargetRect, texture); - drawTextureRect(texture, mTempSourceRect, mTempTargetRect); - } - - private static void copyTextureCoordinates(BasicTexture texture, RectF outRect) { - int left = 0; - int top = 0; - int right = texture.getWidth(); - int bottom = texture.getHeight(); - if (texture.hasBorder()) { - left = 1; - top = 1; - right -= 1; - bottom -= 1; - } - outRect.set(left, top, right, bottom); - } - - @Override - public void drawTexture(BasicTexture texture, RectF source, RectF target) { - if (target.width() <= 0 || target.height() <= 0) { - return; - } - mTempSourceRect.set(source); - mTempTargetRect.set(target); - - convertCoordinate(mTempSourceRect, mTempTargetRect, texture); - drawTextureRect(texture, mTempSourceRect, mTempTargetRect); - } - - @Override - public void drawTexture(BasicTexture texture, float[] textureTransform, int x, int y, int w, - int h) { - if (w <= 0 || h <= 0) { - return; - } - mTempTargetRect.set(x, y, x + w, y + h); - drawTextureRect(texture, textureTransform, mTempTargetRect); - } - - private void drawTextureRect(BasicTexture texture, RectF source, RectF target) { - setTextureMatrix(source); - drawTextureRect(texture, mTempTextureMatrix, target); - } - - private void setTextureMatrix(RectF source) { - mTempTextureMatrix[0] = source.width(); - mTempTextureMatrix[5] = source.height(); - mTempTextureMatrix[12] = source.left; - mTempTextureMatrix[13] = source.top; - } - - // This function changes the source coordinate to the texture coordinates. - // It also clips the source and target coordinates if it is beyond the - // bound of the texture. - private static void convertCoordinate(RectF source, RectF target, BasicTexture texture) { - int width = texture.getWidth(); - int height = texture.getHeight(); - int texWidth = texture.getTextureWidth(); - int texHeight = texture.getTextureHeight(); - // Convert to texture coordinates - source.left /= texWidth; - source.right /= texWidth; - source.top /= texHeight; - source.bottom /= texHeight; - - // Clip if the rendering range is beyond the bound of the texture. - float xBound = (float) width / texWidth; - if (source.right > xBound) { - target.right = target.left + target.width() * (xBound - source.left) / source.width(); - source.right = xBound; - } - float yBound = (float) height / texHeight; - if (source.bottom > yBound) { - target.bottom = target.top + target.height() * (yBound - source.top) / source.height(); - source.bottom = yBound; - } - } - - private void drawTextureRect(BasicTexture texture, float[] textureMatrix, RectF target) { - ShaderParameter[] params = prepareTexture(texture); - setPosition(params, OFFSET_FILL_RECT); - GLES20.glUniformMatrix4fv(params[INDEX_TEXTURE_MATRIX].handle, 1, false, textureMatrix, 0); - checkError(); - if (texture.isFlippedVertically()) { - save(SAVE_FLAG_MATRIX); - translate(0, target.centerY()); - scale(1, -1, 1); - translate(0, -target.centerY()); - } - draw(params, GLES20.GL_TRIANGLE_STRIP, COUNT_FILL_VERTEX, target.left, target.top, - target.width(), target.height()); - if (texture.isFlippedVertically()) { - restore(); - } - mCountTextureRect++; - } - - private ShaderParameter[] prepareTexture(BasicTexture texture) { - ShaderParameter[] params; - int program; - if (texture.getTarget() == GLES20.GL_TEXTURE_2D) { - params = mTextureParameters; - program = mTextureProgram; - } else { - params = mOesTextureParameters; - program = mOesTextureProgram; - } - prepareTexture(texture, program, params); - return params; - } - - private void prepareTexture(BasicTexture texture, int program, ShaderParameter[] params) { - GLES20.glUseProgram(program); - checkError(); - enableBlending(!texture.isOpaque() || getAlpha() < OPAQUE_ALPHA); - GLES20.glActiveTexture(GLES20.GL_TEXTURE0); - checkError(); - texture.onBind(this); - GLES20.glBindTexture(texture.getTarget(), texture.getId()); - checkError(); - GLES20.glUniform1i(params[INDEX_TEXTURE_SAMPLER].handle, 0); - checkError(); - GLES20.glUniform1f(params[INDEX_ALPHA].handle, getAlpha()); - checkError(); - } - - @Override - public void drawMesh(BasicTexture texture, int x, int y, int xyBuffer, int uvBuffer, - int indexBuffer, int indexCount) { - prepareTexture(texture, mMeshProgram, mMeshParameters); - - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, indexBuffer); - checkError(); - - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, xyBuffer); - checkError(); - int positionHandle = mMeshParameters[INDEX_POSITION].handle; - GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, false, - VERTEX_STRIDE, 0); - checkError(); - - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, uvBuffer); - checkError(); - int texCoordHandle = mMeshParameters[INDEX_TEXTURE_COORD].handle; - GLES20.glVertexAttribPointer(texCoordHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT, - false, VERTEX_STRIDE, 0); - checkError(); - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0); - checkError(); - - GLES20.glEnableVertexAttribArray(positionHandle); - checkError(); - GLES20.glEnableVertexAttribArray(texCoordHandle); - checkError(); - - setMatrix(mMeshParameters, x, y, 1, 1); - GLES20.glDrawElements(GLES20.GL_TRIANGLE_STRIP, indexCount, GLES20.GL_UNSIGNED_BYTE, 0); - checkError(); - - GLES20.glDisableVertexAttribArray(positionHandle); - checkError(); - GLES20.glDisableVertexAttribArray(texCoordHandle); - checkError(); - GLES20.glBindBuffer(GLES20.GL_ELEMENT_ARRAY_BUFFER, 0); - checkError(); - mCountDrawMesh++; - } - - @Override - public void drawMixed(BasicTexture texture, int toColor, float ratio, int x, int y, int w, int h) { - copyTextureCoordinates(texture, mTempSourceRect); - mTempTargetRect.set(x, y, x + w, y + h); - drawMixed(texture, toColor, ratio, mTempSourceRect, mTempTargetRect); - } - - @Override - public void drawMixed(BasicTexture texture, int toColor, float ratio, RectF source, RectF target) { - if (target.width() <= 0 || target.height() <= 0) { - return; - } - save(SAVE_FLAG_ALPHA); - - float currentAlpha = getAlpha(); - float cappedRatio = Math.min(1f, Math.max(0f, ratio)); - - float textureAlpha = (1f - cappedRatio) * currentAlpha; - setAlpha(textureAlpha); - drawTexture(texture, source, target); - - float colorAlpha = cappedRatio * currentAlpha; - setAlpha(colorAlpha); - fillRect(target.left, target.top, target.width(), target.height(), toColor); - - restore(); - } - - @Override - public boolean unloadTexture(BasicTexture texture) { - boolean unload = texture.isLoaded(); - if (unload) { - synchronized (mUnboundTextures) { - mUnboundTextures.add(texture.getId()); - } - } - return unload; - } - - @Override - public void deleteBuffer(int bufferId) { - synchronized (mUnboundTextures) { - mDeleteBuffers.add(bufferId); - } - } - - @Override - public void deleteRecycledResources() { - synchronized (mUnboundTextures) { - IntArray ids = mUnboundTextures; - if (mUnboundTextures.size() > 0) { - mGLId.glDeleteTextures(null, ids.size(), ids.getInternalArray(), 0); - ids.clear(); - } - - ids = mDeleteBuffers; - if (ids.size() > 0) { - mGLId.glDeleteBuffers(null, ids.size(), ids.getInternalArray(), 0); - ids.clear(); - } - } - } - - @Override - public void dumpStatisticsAndClear() { - String line = String.format("MESH:%d, TEX_RECT:%d, FILL_RECT:%d, LINE:%d", mCountDrawMesh, - mCountTextureRect, mCountFillRect, mCountDrawLine); - mCountDrawMesh = 0; - mCountTextureRect = 0; - mCountFillRect = 0; - mCountDrawLine = 0; - Log.d(TAG, line); - } - - @Override - public void endRenderTarget() { - RawTexture oldTexture = mTargetTextures.remove(mTargetTextures.size() - 1); - RawTexture texture = getTargetTexture(); - setRenderTarget(oldTexture, texture); - restore(); // restore matrix and alpha - } - - @Override - public void beginRenderTarget(RawTexture texture) { - save(); // save matrix and alpha and blending - RawTexture oldTexture = getTargetTexture(); - mTargetTextures.add(texture); - setRenderTarget(oldTexture, texture); - } - - private RawTexture getTargetTexture() { - return mTargetTextures.get(mTargetTextures.size() - 1); - } - - private void setRenderTarget(BasicTexture oldTexture, RawTexture texture) { - if (oldTexture == null && texture != null) { - GLES20.glGenFramebuffers(1, mFrameBuffer, 0); - checkError(); - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFrameBuffer[0]); - checkError(); - } else if (oldTexture != null && texture == null) { - GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); - checkError(); - GLES20.glDeleteFramebuffers(1, mFrameBuffer, 0); - checkError(); - } - - if (texture == null) { - setSize(mScreenWidth, mScreenHeight); - } else { - setSize(texture.getWidth(), texture.getHeight()); - - if (!texture.isLoaded()) { - texture.prepare(this); - } - - GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, - texture.getTarget(), texture.getId(), 0); - checkError(); - - checkFramebufferStatus(); - } - } - - private static void checkFramebufferStatus() { - int status = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); - if (status != GLES20.GL_FRAMEBUFFER_COMPLETE) { - String msg = ""; - switch (status) { - case GLES20.GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - msg = "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT"; - break; - case GLES20.GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - msg = "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS"; - break; - case GLES20.GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - msg = "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT"; - break; - case GLES20.GL_FRAMEBUFFER_UNSUPPORTED: - msg = "GL_FRAMEBUFFER_UNSUPPORTED"; - break; - } - throw new RuntimeException(msg + ":" + Integer.toHexString(status)); - } - } - - @Override - public void setTextureParameters(BasicTexture texture) { - int target = texture.getTarget(); - GLES20.glBindTexture(target, texture.getId()); - checkError(); - GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameteri(target, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); - GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR); - GLES20.glTexParameterf(target, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR); - } - - @Override - public void initializeTextureSize(BasicTexture texture, int format, int type) { - int target = texture.getTarget(); - GLES20.glBindTexture(target, texture.getId()); - checkError(); - int width = texture.getTextureWidth(); - int height = texture.getTextureHeight(); - GLES20.glTexImage2D(target, 0, format, width, height, 0, format, type, null); - } - - @Override - public void initializeTexture(BasicTexture texture, Bitmap bitmap) { - int target = texture.getTarget(); - GLES20.glBindTexture(target, texture.getId()); - checkError(); - GLUtils.texImage2D(target, 0, bitmap, 0); - } - - @Override - public void texSubImage2D(BasicTexture texture, int xOffset, int yOffset, Bitmap bitmap, - int format, int type) { - int target = texture.getTarget(); - GLES20.glBindTexture(target, texture.getId()); - checkError(); - GLUtils.texSubImage2D(target, 0, xOffset, yOffset, bitmap, format, type); - } - - @Override - public int uploadBuffer(FloatBuffer buf) { - return uploadBuffer(buf, FLOAT_SIZE); - } - - @Override - public int uploadBuffer(ByteBuffer buf) { - return uploadBuffer(buf, 1); - } - - private int uploadBuffer(Buffer buffer, int elementSize) { - mGLId.glGenBuffers(1, mTempIntArray, 0); - checkError(); - int bufferId = mTempIntArray[0]; - GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, bufferId); - checkError(); - GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, buffer.capacity() * elementSize, buffer, - GLES20.GL_STATIC_DRAW); - checkError(); - return bufferId; - } - - public static void checkError() { - int error = GLES20.glGetError(); - if (error != 0) { - Throwable t = new Throwable(); - Log.e(TAG, "GL error: " + error, t); - } - } - - @SuppressWarnings("unused") - private static void printMatrix(String message, float[] m, int offset) { - StringBuilder b = new StringBuilder(message); - for (int i = 0; i < MATRIX_SIZE; i++) { - b.append(' '); - if (i % 4 == 0) { - b.append('\n'); - } - b.append(m[offset + i]); - } - Log.v(TAG, b.toString()); - } - - @Override - public void recoverFromLightCycle() { - GLES20.glViewport(0, 0, mWidth, mHeight); - GLES20.glDisable(GLES20.GL_DEPTH_TEST); - GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); - checkError(); - } - - @Override - public void getBounds(Rect bounds, int x, int y, int width, int height) { - Matrix.translateM(mTempMatrix, 0, mMatrices, mCurrentMatrixIndex, x, y, 0f); - Matrix.scaleM(mTempMatrix, 0, width, height, 1f); - Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE, mTempMatrix, 0, BOUNDS_COORDINATES, 0); - Matrix.multiplyMV(mTempMatrix, MATRIX_SIZE + 4, mTempMatrix, 0, BOUNDS_COORDINATES, 4); - bounds.left = Math.round(mTempMatrix[MATRIX_SIZE]); - bounds.right = Math.round(mTempMatrix[MATRIX_SIZE + 4]); - bounds.top = Math.round(mTempMatrix[MATRIX_SIZE + 1]); - bounds.bottom = Math.round(mTempMatrix[MATRIX_SIZE + 5]); - bounds.sort(); - } - - @Override - public GLId getGLId() { - return mGLId; - } -} diff --git a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java b/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java deleted file mode 100644 index 6cd7149cb..000000000 --- a/src/com/android/gallery3d/glrenderer/GLES20IdImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.android.gallery3d.glrenderer; - -import android.opengl.GLES20; - -import javax.microedition.khronos.opengles.GL11; -import javax.microedition.khronos.opengles.GL11ExtensionPack; - -public class GLES20IdImpl implements GLId { - private final int[] mTempIntArray = new int[1]; - - @Override - public int generateTexture() { - GLES20.glGenTextures(1, mTempIntArray, 0); - GLES20Canvas.checkError(); - return mTempIntArray[0]; - } - - @Override - public void glGenBuffers(int n, int[] buffers, int offset) { - GLES20.glGenBuffers(n, buffers, offset); - GLES20Canvas.checkError(); - } - - @Override - public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset) { - GLES20.glDeleteTextures(n, textures, offset); - GLES20Canvas.checkError(); - } - - - @Override - public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset) { - GLES20.glDeleteBuffers(n, buffers, offset); - GLES20Canvas.checkError(); - } - - @Override - public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset) { - GLES20.glDeleteFramebuffers(n, buffers, offset); - GLES20Canvas.checkError(); - } -} diff --git a/src/com/android/gallery3d/glrenderer/GLId.java b/src/com/android/gallery3d/glrenderer/GLId.java deleted file mode 100644 index 3cec558f6..000000000 --- a/src/com/android/gallery3d/glrenderer/GLId.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import javax.microedition.khronos.opengles.GL11; -import javax.microedition.khronos.opengles.GL11ExtensionPack; - -// This mimics corresponding GL functions. -public interface GLId { - public int generateTexture(); - - public void glGenBuffers(int n, int[] buffers, int offset); - - public void glDeleteTextures(GL11 gl, int n, int[] textures, int offset); - - public void glDeleteBuffers(GL11 gl, int n, int[] buffers, int offset); - - public void glDeleteFramebuffers(GL11ExtensionPack gl11ep, int n, int[] buffers, int offset); -} diff --git a/src/com/android/gallery3d/glrenderer/GLPaint.java b/src/com/android/gallery3d/glrenderer/GLPaint.java deleted file mode 100644 index 16b220690..000000000 --- a/src/com/android/gallery3d/glrenderer/GLPaint.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import junit.framework.Assert; - -public class GLPaint { - private float mLineWidth = 1f; - private int mColor = 0; - - public void setColor(int color) { - mColor = color; - } - - public int getColor() { - return mColor; - } - - public void setLineWidth(float width) { - Assert.assertTrue(width >= 0); - mLineWidth = width; - } - - public float getLineWidth() { - return mLineWidth; - } -} diff --git a/src/com/android/gallery3d/glrenderer/MultiLineTexture.java b/src/com/android/gallery3d/glrenderer/MultiLineTexture.java deleted file mode 100644 index 82839f107..000000000 --- a/src/com/android/gallery3d/glrenderer/MultiLineTexture.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.text.Layout; -import android.text.StaticLayout; -import android.text.TextPaint; - - -// MultiLineTexture is a texture shows the content of a specified String. -// -// To create a MultiLineTexture, use the newInstance() method and specify -// the String, the font size, and the color. -class MultiLineTexture extends CanvasTexture { - private final Layout mLayout; - - private MultiLineTexture(Layout layout) { - super(layout.getWidth(), layout.getHeight()); - mLayout = layout; - } - - public static MultiLineTexture newInstance( - String text, int maxWidth, float textSize, int color, - Layout.Alignment alignment) { - TextPaint paint = StringTexture.getDefaultPaint(textSize, color); - Layout layout = new StaticLayout(text, 0, text.length(), paint, - maxWidth, alignment, 1, 0, true, null, 0); - - return new MultiLineTexture(layout); - } - - @Override - protected void onDraw(Canvas canvas, Bitmap backing) { - mLayout.draw(canvas); - } -} diff --git a/src/com/android/gallery3d/glrenderer/StringTexture.java b/src/com/android/gallery3d/glrenderer/StringTexture.java deleted file mode 100644 index 56ca29753..000000000 --- a/src/com/android/gallery3d/glrenderer/StringTexture.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint.FontMetricsInt; -import android.graphics.Typeface; -import android.text.TextPaint; -import android.text.TextUtils; -import android.util.FloatMath; - -// StringTexture is a texture shows the content of a specified String. -// -// To create a StringTexture, use the newInstance() method and specify -// the String, the font size, and the color. -public class StringTexture extends CanvasTexture { - private final String mText; - private final TextPaint mPaint; - private final FontMetricsInt mMetrics; - - private StringTexture(String text, TextPaint paint, - FontMetricsInt metrics, int width, int height) { - super(width, height); - mText = text; - mPaint = paint; - mMetrics = metrics; - } - - public static TextPaint getDefaultPaint(float textSize, int color) { - TextPaint paint = new TextPaint(); - paint.setTextSize(textSize); - paint.setAntiAlias(true); - paint.setColor(color); - paint.setShadowLayer(2f, 0f, 0f, Color.BLACK); - return paint; - } - - public static StringTexture newInstance( - String text, float textSize, int color) { - return newInstance(text, getDefaultPaint(textSize, color)); - } - - public static StringTexture newInstance( - String text, float textSize, int color, - float lengthLimit, boolean isBold) { - TextPaint paint = getDefaultPaint(textSize, color); - if (isBold) { - paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); - } - if (lengthLimit > 0) { - text = TextUtils.ellipsize( - text, paint, lengthLimit, TextUtils.TruncateAt.END).toString(); - } - return newInstance(text, paint); - } - - private static StringTexture newInstance(String text, TextPaint paint) { - FontMetricsInt metrics = paint.getFontMetricsInt(); - int width = (int) FloatMath.ceil(paint.measureText(text)); - int height = metrics.bottom - metrics.top; - // The texture size needs to be at least 1x1. - if (width <= 0) width = 1; - if (height <= 0) height = 1; - return new StringTexture(text, paint, metrics, width, height); - } - - @Override - protected void onDraw(Canvas canvas, Bitmap backing) { - canvas.translate(0, -mMetrics.ascent); - canvas.drawText(mText, 0, 0, mPaint); - } -} diff --git a/src/com/android/gallery3d/glrenderer/Texture.java b/src/com/android/gallery3d/glrenderer/Texture.java deleted file mode 100644 index 3dcae4aec..000000000 --- a/src/com/android/gallery3d/glrenderer/Texture.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - - -// Texture is a rectangular image which can be drawn on GLCanvas. -// The isOpaque() function gives a hint about whether the texture is opaque, -// so the drawing can be done faster. -// -// This is the current texture hierarchy: -// -// Texture -// -- ColorTexture -// -- FadeInTexture -// -- BasicTexture -// -- UploadedTexture -// -- BitmapTexture -// -- Tile -// -- ResourceTexture -// -- NinePatchTexture -// -- CanvasTexture -// -- StringTexture -// -public interface Texture { - public int getWidth(); - public int getHeight(); - public void draw(GLCanvas canvas, int x, int y); - public void draw(GLCanvas canvas, int x, int y, int w, int h); - public boolean isOpaque(); -} diff --git a/src/com/android/gallery3d/glrenderer/TextureUploader.java b/src/com/android/gallery3d/glrenderer/TextureUploader.java deleted file mode 100644 index f17ab845c..000000000 --- a/src/com/android/gallery3d/glrenderer/TextureUploader.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLRoot.OnGLIdleListener; - -import java.util.ArrayDeque; - -public class TextureUploader implements OnGLIdleListener { - private static final int INIT_CAPACITY = 64; - private static final int QUOTA_PER_FRAME = 1; - - private final ArrayDeque<UploadedTexture> mFgTextures = - new ArrayDeque<UploadedTexture>(INIT_CAPACITY); - private final ArrayDeque<UploadedTexture> mBgTextures = - new ArrayDeque<UploadedTexture>(INIT_CAPACITY); - private final GLRoot mGLRoot; - private volatile boolean mIsQueued = false; - - public TextureUploader(GLRoot root) { - mGLRoot = root; - } - - public synchronized void clear() { - while (!mFgTextures.isEmpty()) { - mFgTextures.pop().setIsUploading(false); - } - while (!mBgTextures.isEmpty()) { - mBgTextures.pop().setIsUploading(false); - } - } - - // caller should hold synchronized on "this" - private void queueSelfIfNeed() { - if (mIsQueued) return; - mIsQueued = true; - mGLRoot.addOnGLIdleListener(this); - } - - public synchronized void addBgTexture(UploadedTexture t) { - if (t.isContentValid()) return; - mBgTextures.addLast(t); - t.setIsUploading(true); - queueSelfIfNeed(); - } - - public synchronized void addFgTexture(UploadedTexture t) { - if (t.isContentValid()) return; - mFgTextures.addLast(t); - t.setIsUploading(true); - queueSelfIfNeed(); - } - - private int upload(GLCanvas canvas, ArrayDeque<UploadedTexture> deque, - int uploadQuota, boolean isBackground) { - while (uploadQuota > 0) { - UploadedTexture t; - synchronized (this) { - if (deque.isEmpty()) break; - t = deque.removeFirst(); - t.setIsUploading(false); - if (t.isContentValid()) continue; - - // this has to be protected by the synchronized block - // to prevent the inner bitmap get recycled - t.updateContent(canvas); - } - - // It will took some more time for a texture to be drawn for - // the first time. - // Thus, when scrolling, if a new column appears on screen, - // it may cause a UI jank even these textures are uploaded. - if (isBackground) t.draw(canvas, 0, 0); - --uploadQuota; - } - return uploadQuota; - } - - @Override - public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) { - int uploadQuota = QUOTA_PER_FRAME; - uploadQuota = upload(canvas, mFgTextures, uploadQuota, false); - if (uploadQuota < QUOTA_PER_FRAME) mGLRoot.requestRender(); - upload(canvas, mBgTextures, uploadQuota, true); - synchronized (this) { - mIsQueued = !mFgTextures.isEmpty() || !mBgTextures.isEmpty(); - return mIsQueued; - } - } -} diff --git a/src/com/android/gallery3d/glrenderer/TiledTexture.java b/src/com/android/gallery3d/glrenderer/TiledTexture.java deleted file mode 100644 index 6ca1de088..000000000 --- a/src/com/android/gallery3d/glrenderer/TiledTexture.java +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.glrenderer; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PorterDuff.Mode; -import android.graphics.PorterDuffXfermode; -import android.graphics.RectF; -import android.os.SystemClock; - -import com.android.gallery3d.ui.GLRoot; -import com.android.gallery3d.ui.GLRoot.OnGLIdleListener; - -import java.util.ArrayDeque; -import java.util.ArrayList; - -// This class is similar to BitmapTexture, except the bitmap is -// split into tiles. By doing so, we may increase the time required to -// upload the whole bitmap but we reduce the time of uploading each tile -// so it make the animation more smooth and prevents jank. -public class TiledTexture implements Texture { - private static final int CONTENT_SIZE = 254; - private static final int BORDER_SIZE = 1; - private static final int TILE_SIZE = CONTENT_SIZE + 2 * BORDER_SIZE; - private static final int INIT_CAPACITY = 8; - - // We are targeting at 60fps, so we have 16ms for each frame. - // In this 16ms, we use about 4~8 ms to upload tiles. - private static final long UPLOAD_TILE_LIMIT = 4; // ms - - private static Tile sFreeTileHead = null; - private static final Object sFreeTileLock = new Object(); - - private static Bitmap sUploadBitmap; - private static Canvas sCanvas; - private static Paint sBitmapPaint; - private static Paint sPaint; - - private int mUploadIndex = 0; - - 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(); - private final RectF mDestRect = new RectF(); - - public static class Uploader implements OnGLIdleListener { - private final ArrayDeque<TiledTexture> mTextures = - new ArrayDeque<TiledTexture>(INIT_CAPACITY); - - private final GLRoot mGlRoot; - private boolean mIsQueued = false; - - public Uploader(GLRoot glRoot) { - mGlRoot = glRoot; - } - - public synchronized void clear() { - mTextures.clear(); - } - - public synchronized void addTexture(TiledTexture t) { - if (t.isReady()) return; - mTextures.addLast(t); - - if (mIsQueued) return; - mIsQueued = true; - mGlRoot.addOnGLIdleListener(this); - } - - @Override - public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) { - ArrayDeque<TiledTexture> deque = mTextures; - synchronized (this) { - long now = SystemClock.uptimeMillis(); - long dueTime = now + UPLOAD_TILE_LIMIT; - while (now < dueTime && !deque.isEmpty()) { - TiledTexture t = deque.peekFirst(); - if (t.uploadNextTile(canvas)) { - deque.removeFirst(); - mGlRoot.requestRender(); - } - now = SystemClock.uptimeMillis(); - } - mIsQueued = !mTextures.isEmpty(); - - // return true to keep this listener in the queue - return mIsQueued; - } - } - } - - private static class Tile extends UploadedTexture { - public int offsetX; - public int offsetY; - public Bitmap bitmap; - public Tile nextFreeTile; - public int contentWidth; - public int contentHeight; - - @Override - public void setSize(int width, int height) { - contentWidth = width; - contentHeight = height; - mWidth = width + 2 * BORDER_SIZE; - mHeight = height + 2 * BORDER_SIZE; - mTextureWidth = TILE_SIZE; - mTextureHeight = TILE_SIZE; - } - - @Override - protected Bitmap onGetBitmap() { - int x = BORDER_SIZE - offsetX; - int y = BORDER_SIZE - offsetY; - int r = bitmap.getWidth() + x; - int b = bitmap.getHeight() + y; - sCanvas.drawBitmap(bitmap, x, y, sBitmapPaint); - bitmap = null; - - // draw borders if need - if (x > 0) sCanvas.drawLine(x - 1, 0, x - 1, TILE_SIZE, sPaint); - if (y > 0) sCanvas.drawLine(0, y - 1, TILE_SIZE, y - 1, sPaint); - if (r < CONTENT_SIZE) sCanvas.drawLine(r, 0, r, TILE_SIZE, sPaint); - if (b < CONTENT_SIZE) sCanvas.drawLine(0, b, TILE_SIZE, b, sPaint); - - return sUploadBitmap; - } - - @Override - protected void onFreeBitmap(Bitmap bitmap) { - // do nothing - } - } - - private static void freeTile(Tile tile) { - tile.invalidateContent(); - tile.bitmap = null; - synchronized (sFreeTileLock) { - tile.nextFreeTile = sFreeTileHead; - sFreeTileHead = tile; - } - } - - private static Tile obtainTile() { - synchronized (sFreeTileLock) { - Tile result = sFreeTileHead; - if (result == null) return new Tile(); - sFreeTileHead = result.nextFreeTile; - result.nextFreeTile = null; - return result; - } - } - - private boolean uploadNextTile(GLCanvas canvas) { - if (mUploadIndex == mTiles.length) return true; - - 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); - - // 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; - } - - public TiledTexture(Bitmap bitmap) { - mWidth = bitmap.getWidth(); - mHeight = bitmap.getHeight(); - ArrayList<Tile> list = new ArrayList<Tile>(); - - for (int x = 0, w = mWidth; x < w; x += CONTENT_SIZE) { - for (int y = 0, h = mHeight; y < h; y += CONTENT_SIZE) { - Tile tile = obtainTile(); - tile.offsetX = x; - tile.offsetY = y; - tile.bitmap = bitmap; - tile.setSize( - Math.min(CONTENT_SIZE, mWidth - x), - Math.min(CONTENT_SIZE, mHeight - y)); - list.add(tile); - } - } - mTiles = list.toArray(new Tile[list.size()]); - } - - public boolean isReady() { - return mUploadIndex == mTiles.length; - } - - // Can be called in UI thread. - public void recycle() { - synchronized (mTiles) { - for (int i = 0, n = mTiles.length; i < n; ++i) { - freeTile(mTiles[i]); - } - } - } - - public static void freeResources() { - sUploadBitmap = null; - sCanvas = null; - sBitmapPaint = null; - sPaint = null; - } - - public static void prepareResources() { - sUploadBitmap = Bitmap.createBitmap(TILE_SIZE, TILE_SIZE, Config.ARGB_8888); - sCanvas = new Canvas(sUploadBitmap); - sBitmapPaint = new Paint(Paint.FILTER_BITMAP_FLAG); - sBitmapPaint.setXfermode(new PorterDuffXfermode(Mode.SRC)); - sPaint = new Paint(); - sPaint.setXfermode(new PorterDuffXfermode(Mode.SRC)); - sPaint.setColor(Color.TRANSPARENT); - } - - // We want to draw the "source" on the "target". - // This method is to find the "output" rectangle which is - // the corresponding area of the "src". - // (x,y) target - // (x0,y0) source +---------------+ - // +----------+ | | - // | src | | output | - // | +--+ | linear map | +----+ | - // | +--+ | ----------> | | | | - // | | by (scaleX, scaleY) | +----+ | - // +----------+ | | - // Texture +---------------+ - // Canvas - private static void mapRect(RectF output, - RectF src, float x0, float y0, float x, float y, float scaleX, - float scaleY) { - output.set(x + (src.left - x0) * scaleX, - y + (src.top - y0) * scaleY, - x + (src.right - x0) * scaleX, - y + (src.bottom - y0) * scaleY); - } - - // Draws a mixed color of this texture and a specified color onto the - // a rectangle. The used color is: from * (1 - ratio) + to * ratio. - public void drawMixed(GLCanvas canvas, int color, float ratio, - int x, int y, int width, int height) { - RectF src = mSrcRect; - RectF dest = mDestRect; - float scaleX = (float) width / mWidth; - float scaleY = (float) height / mHeight; - 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); - } - } - } - - // Draws the texture on to the specified rectangle. - @Override - 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 scaleY = (float) height / mHeight; - 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); - } - } - } - - // Draws a sub region of this texture on to the specified rectangle. - public void draw(GLCanvas canvas, RectF source, RectF target) { - RectF src = mSrcRect; - RectF dest = mDestRect; - float x0 = source.left; - float y0 = source.top; - float x = target.left; - float y = target.top; - float scaleX = target.width() / source.width(); - float scaleY = target.height() / source.height(); - - 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); - } - } - } - - @Override - public int getWidth() { - return mWidth; - } - - @Override - public int getHeight() { - return mHeight; - } - - @Override - public void draw(GLCanvas canvas, int x, int y) { - draw(canvas, x, y, mWidth, mHeight); - } - - @Override - public boolean isOpaque() { - return false; - } -} diff --git a/src/com/android/gallery3d/ingest/ImportTask.java b/src/com/android/gallery3d/ingest/ImportTask.java deleted file mode 100644 index 7d2d641a5..000000000 --- a/src/com/android/gallery3d/ingest/ImportTask.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest; - -import android.content.Context; -import android.mtp.MtpDevice; -import android.mtp.MtpObjectInfo; -import android.os.Environment; -import android.os.PowerManager; - -import com.android.gallery3d.util.GalleryUtils; - -import java.io.File; -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - -public class ImportTask implements Runnable { - - public interface Listener { - void onImportProgress(int visitedCount, int totalCount, String pathIfSuccessful); - - void onImportFinish(Collection<MtpObjectInfo> objectsNotImported, int visitedCount); - } - - static private final String WAKELOCK_LABEL = "MTP Import Task"; - - private Listener mListener; - private String mDestAlbumName; - private Collection<MtpObjectInfo> mObjectsToImport; - private MtpDevice mDevice; - private PowerManager.WakeLock mWakeLock; - - public ImportTask(MtpDevice device, Collection<MtpObjectInfo> objectsToImport, - String destAlbumName, Context context) { - mDestAlbumName = destAlbumName; - mObjectsToImport = objectsToImport; - mDevice = device; - PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); - mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, WAKELOCK_LABEL); - } - - public void setListener(Listener listener) { - mListener = listener; - } - - @Override - public void run() { - mWakeLock.acquire(); - try { - List<MtpObjectInfo> objectsNotImported = new LinkedList<MtpObjectInfo>(); - int visited = 0; - int total = mObjectsToImport.size(); - mListener.onImportProgress(visited, total, null); - File dest = new File(Environment.getExternalStorageDirectory(), mDestAlbumName); - dest.mkdirs(); - for (MtpObjectInfo object : mObjectsToImport) { - visited++; - String importedPath = null; - if (GalleryUtils.hasSpaceForSize(object.getCompressedSize())) { - importedPath = new File(dest, object.getName()).getAbsolutePath(); - if (!mDevice.importFile(object.getObjectHandle(), importedPath)) { - importedPath = null; - } - } - if (importedPath == null) { - objectsNotImported.add(object); - } - if (mListener != null) { - mListener.onImportProgress(visited, total, importedPath); - } - } - if (mListener != null) { - mListener.onImportFinish(objectsNotImported, visited); - } - } finally { - mListener = null; - mWakeLock.release(); - } - } -} diff --git a/src/com/android/gallery3d/ingest/IngestActivity.java b/src/com/android/gallery3d/ingest/IngestActivity.java deleted file mode 100644 index 687e9fd44..000000000 --- a/src/com/android/gallery3d/ingest/IngestActivity.java +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest; - -import android.app.Activity; -import android.app.ProgressDialog; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.ServiceConnection; -import android.content.res.Configuration; -import android.database.DataSetObserver; -import android.mtp.MtpObjectInfo; -import android.os.Bundle; -import android.os.Handler; -import android.os.IBinder; -import android.os.Message; -import android.support.v4.view.ViewPager; -import android.util.SparseBooleanArray; -import android.view.ActionMode; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.view.View; -import android.widget.AbsListView.MultiChoiceModeListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.TextView; - -import com.android.gallery3d.R; -import com.android.gallery3d.ingest.adapter.CheckBroker; -import com.android.gallery3d.ingest.adapter.MtpAdapter; -import com.android.gallery3d.ingest.adapter.MtpPagerAdapter; -import com.android.gallery3d.ingest.data.MtpBitmapFetch; -import com.android.gallery3d.ingest.ui.DateTileView; -import com.android.gallery3d.ingest.ui.IngestGridView; -import com.android.gallery3d.ingest.ui.IngestGridView.OnClearChoicesListener; - -import java.lang.ref.WeakReference; -import java.util.Collection; - -public class IngestActivity extends Activity implements - MtpDeviceIndex.ProgressListener, ImportTask.Listener { - - private IngestService mHelperService; - private boolean mActive = false; - private IngestGridView mGridView; - private MtpAdapter mAdapter; - private Handler mHandler; - private ProgressDialog mProgressDialog; - private ActionMode mActiveActionMode; - - private View mWarningView; - private TextView mWarningText; - private int mLastCheckedPosition = 0; - - private ViewPager mFullscreenPager; - private MtpPagerAdapter mPagerAdapter; - private boolean mFullscreenPagerVisible = false; - - private MenuItem mMenuSwitcherItem; - private MenuItem mActionMenuSwitcherItem; - - // The MTP framework components don't give us fine-grained file copy - // progress updates, so for large photos and videos, we will be stuck - // with a dialog not updating for a long time. To give the user feedback, - // we switch to the animated indeterminate progress bar after the timeout - // specified by INDETERMINATE_SWITCH_TIMEOUT_MS. On the next update from - // the framework, we switch back to the normal progress bar. - private static final int INDETERMINATE_SWITCH_TIMEOUT_MS = 3000; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - doBindHelperService(); - - setContentView(R.layout.ingest_activity_item_list); - mGridView = (IngestGridView) findViewById(R.id.ingest_gridview); - mAdapter = new MtpAdapter(this); - mAdapter.registerDataSetObserver(mMasterObserver); - mGridView.setAdapter(mAdapter); - mGridView.setMultiChoiceModeListener(mMultiChoiceModeListener); - mGridView.setOnItemClickListener(mOnItemClickListener); - mGridView.setOnClearChoicesListener(mPositionMappingCheckBroker); - - mFullscreenPager = (ViewPager) findViewById(R.id.ingest_view_pager); - - mHandler = new ItemListHandler(this); - - MtpBitmapFetch.configureForContext(this); - } - - private OnItemClickListener mOnItemClickListener = new OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> adapterView, View itemView, int position, long arg3) { - mLastCheckedPosition = position; - mGridView.setItemChecked(position, !mGridView.getCheckedItemPositions().get(position)); - } - }; - - private MultiChoiceModeListener mMultiChoiceModeListener = new MultiChoiceModeListener() { - private boolean mIgnoreItemCheckedStateChanges = false; - - private void updateSelectedTitle(ActionMode mode) { - int count = mGridView.getCheckedItemCount(); - mode.setTitle(getResources().getQuantityString( - R.plurals.number_of_items_selected, count, count)); - } - - @Override - public void onItemCheckedStateChanged(ActionMode mode, int position, long id, - boolean checked) { - if (mIgnoreItemCheckedStateChanges) return; - if (mAdapter.itemAtPositionIsBucket(position)) { - SparseBooleanArray checkedItems = mGridView.getCheckedItemPositions(); - mIgnoreItemCheckedStateChanges = true; - mGridView.setItemChecked(position, false); - - // Takes advantage of the fact that SectionIndexer imposes the - // need to clamp to the valid range - int nextSectionStart = mAdapter.getPositionForSection( - mAdapter.getSectionForPosition(position) + 1); - if (nextSectionStart == position) - nextSectionStart = mAdapter.getCount(); - - boolean rangeValue = false; // Value we want to set all of the bucket items to - - // Determine if all the items in the bucket are currently checked, so that we - // can uncheck them, otherwise we will check all items in the bucket. - for (int i = position + 1; i < nextSectionStart; i++) { - if (checkedItems.get(i) == false) { - rangeValue = true; - break; - } - } - - // Set all items in the bucket to the desired state - for (int i = position + 1; i < nextSectionStart; i++) { - if (checkedItems.get(i) != rangeValue) - mGridView.setItemChecked(i, rangeValue); - } - - mPositionMappingCheckBroker.onBulkCheckedChange(); - mIgnoreItemCheckedStateChanges = false; - } else { - mPositionMappingCheckBroker.onCheckedChange(position, checked); - } - mLastCheckedPosition = position; - updateSelectedTitle(mode); - } - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - return onOptionsItemSelected(item); - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - MenuInflater inflater = mode.getMenuInflater(); - inflater.inflate(R.menu.ingest_menu_item_list_selection, menu); - updateSelectedTitle(mode); - mActiveActionMode = mode; - mActionMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view); - setSwitcherMenuState(mActionMenuSwitcherItem, mFullscreenPagerVisible); - return true; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - mActiveActionMode = null; - mActionMenuSwitcherItem = null; - mHandler.sendEmptyMessage(ItemListHandler.MSG_BULK_CHECKED_CHANGE); - } - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - updateSelectedTitle(mode); - return false; - } - }; - - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.import_items: - if (mActiveActionMode != null) { - mHelperService.importSelectedItems( - mGridView.getCheckedItemPositions(), - mAdapter); - mActiveActionMode.finish(); - } - return true; - case R.id.ingest_switch_view: - setFullscreenPagerVisibility(!mFullscreenPagerVisible); - return true; - default: - return false; - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.ingest_menu_item_list_selection, menu); - mMenuSwitcherItem = menu.findItem(R.id.ingest_switch_view); - menu.findItem(R.id.import_items).setVisible(false); - setSwitcherMenuState(mMenuSwitcherItem, mFullscreenPagerVisible); - return true; - } - - @Override - protected void onDestroy() { - super.onDestroy(); - doUnbindHelperService(); - } - - @Override - protected void onResume() { - DateTileView.refreshLocale(); - mActive = true; - if (mHelperService != null) mHelperService.setClientActivity(this); - updateWarningView(); - super.onResume(); - } - - @Override - protected void onPause() { - if (mHelperService != null) mHelperService.setClientActivity(null); - mActive = false; - cleanupProgressDialog(); - super.onPause(); - } - - @Override - public void onConfigurationChanged(Configuration newConfig) { - super.onConfigurationChanged(newConfig); - MtpBitmapFetch.configureForContext(this); - } - - private void showWarningView(int textResId) { - if (mWarningView == null) { - mWarningView = findViewById(R.id.ingest_warning_view); - mWarningText = - (TextView)mWarningView.findViewById(R.id.ingest_warning_view_text); - } - mWarningText.setText(textResId); - mWarningView.setVisibility(View.VISIBLE); - setFullscreenPagerVisibility(false); - mGridView.setVisibility(View.GONE); - } - - private void hideWarningView() { - if (mWarningView != null) { - mWarningView.setVisibility(View.GONE); - setFullscreenPagerVisibility(false); - } - } - - private PositionMappingCheckBroker mPositionMappingCheckBroker = new PositionMappingCheckBroker(); - - private class PositionMappingCheckBroker extends CheckBroker - implements OnClearChoicesListener { - private int mLastMappingPager = -1; - private int mLastMappingGrid = -1; - - private int mapPagerToGridPosition(int position) { - if (position != mLastMappingPager) { - mLastMappingPager = position; - mLastMappingGrid = mAdapter.translatePositionWithoutLabels(position); - } - return mLastMappingGrid; - } - - private int mapGridToPagerPosition(int position) { - if (position != mLastMappingGrid) { - mLastMappingGrid = position; - mLastMappingPager = mPagerAdapter.translatePositionWithLabels(position); - } - return mLastMappingPager; - } - - @Override - public void setItemChecked(int position, boolean checked) { - mGridView.setItemChecked(mapPagerToGridPosition(position), checked); - } - - @Override - public void onCheckedChange(int position, boolean checked) { - if (mPagerAdapter != null) { - super.onCheckedChange(mapGridToPagerPosition(position), checked); - } - } - - @Override - public boolean isItemChecked(int position) { - return mGridView.getCheckedItemPositions().get(mapPagerToGridPosition(position)); - } - - @Override - public void onClearChoices() { - onBulkCheckedChange(); - } - }; - - private DataSetObserver mMasterObserver = new DataSetObserver() { - @Override - public void onChanged() { - if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged(); - } - - @Override - public void onInvalidated() { - if (mPagerAdapter != null) mPagerAdapter.notifyDataSetChanged(); - } - }; - - private int pickFullscreenStartingPosition() { - int firstVisiblePosition = mGridView.getFirstVisiblePosition(); - if (mLastCheckedPosition <= firstVisiblePosition - || mLastCheckedPosition > mGridView.getLastVisiblePosition()) { - return firstVisiblePosition; - } else { - return mLastCheckedPosition; - } - } - - private void setSwitcherMenuState(MenuItem menuItem, boolean inFullscreenMode) { - if (menuItem == null) return; - if (!inFullscreenMode) { - menuItem.setIcon(android.R.drawable.ic_menu_zoom); - menuItem.setTitle(R.string.switch_photo_fullscreen); - } else { - menuItem.setIcon(android.R.drawable.ic_dialog_dialer); - menuItem.setTitle(R.string.switch_photo_grid); - } - } - - private void setFullscreenPagerVisibility(boolean visible) { - mFullscreenPagerVisible = visible; - if (visible) { - if (mPagerAdapter == null) { - mPagerAdapter = new MtpPagerAdapter(this, mPositionMappingCheckBroker); - mPagerAdapter.setMtpDeviceIndex(mAdapter.getMtpDeviceIndex()); - } - mFullscreenPager.setAdapter(mPagerAdapter); - mFullscreenPager.setCurrentItem(mPagerAdapter.translatePositionWithLabels( - pickFullscreenStartingPosition()), false); - } else if (mPagerAdapter != null) { - mGridView.setSelection(mAdapter.translatePositionWithoutLabels( - mFullscreenPager.getCurrentItem())); - mFullscreenPager.setAdapter(null); - } - mGridView.setVisibility(visible ? View.INVISIBLE : View.VISIBLE); - mFullscreenPager.setVisibility(visible ? View.VISIBLE : View.INVISIBLE); - if (mActionMenuSwitcherItem != null) { - setSwitcherMenuState(mActionMenuSwitcherItem, visible); - } - setSwitcherMenuState(mMenuSwitcherItem, visible); - } - - private void updateWarningView() { - if (!mAdapter.deviceConnected()) { - showWarningView(R.string.ingest_no_device); - } else if (mAdapter.indexReady() && mAdapter.getCount() == 0) { - showWarningView(R.string.ingest_empty_device); - } else { - hideWarningView(); - } - } - - private void UiThreadNotifyIndexChanged() { - mAdapter.notifyDataSetChanged(); - if (mActiveActionMode != null) { - mActiveActionMode.finish(); - mActiveActionMode = null; - } - updateWarningView(); - } - - protected void notifyIndexChanged() { - mHandler.sendEmptyMessage(ItemListHandler.MSG_NOTIFY_CHANGED); - } - - private static class ProgressState { - String message; - String title; - int current; - int max; - - public void reset() { - title = null; - message = null; - current = 0; - max = 0; - } - } - - private ProgressState mProgressState = new ProgressState(); - - @Override - public void onObjectIndexed(MtpObjectInfo object, int numVisited) { - // Not guaranteed to be called on the UI thread - mProgressState.reset(); - mProgressState.max = 0; - mProgressState.message = getResources().getQuantityString( - R.plurals.ingest_number_of_items_scanned, numVisited, numVisited); - mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE); - } - - @Override - public void onSorting() { - // Not guaranteed to be called on the UI thread - mProgressState.reset(); - mProgressState.max = 0; - mProgressState.message = getResources().getString(R.string.ingest_sorting); - mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE); - } - - @Override - public void onIndexFinish() { - // Not guaranteed to be called on the UI thread - mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_HIDE); - mHandler.sendEmptyMessage(ItemListHandler.MSG_NOTIFY_CHANGED); - } - - @Override - public void onImportProgress(final int visitedCount, final int totalCount, - String pathIfSuccessful) { - // Not guaranteed to be called on the UI thread - mProgressState.reset(); - mProgressState.max = totalCount; - mProgressState.current = visitedCount; - mProgressState.title = getResources().getString(R.string.ingest_importing); - mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_UPDATE); - mHandler.removeMessages(ItemListHandler.MSG_PROGRESS_INDETERMINATE); - mHandler.sendEmptyMessageDelayed(ItemListHandler.MSG_PROGRESS_INDETERMINATE, - INDETERMINATE_SWITCH_TIMEOUT_MS); - } - - @Override - public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported, - int numVisited) { - // Not guaranteed to be called on the UI thread - mHandler.sendEmptyMessage(ItemListHandler.MSG_PROGRESS_HIDE); - mHandler.removeMessages(ItemListHandler.MSG_PROGRESS_INDETERMINATE); - // TODO: maybe show an extra dialog listing the ones that failed - // importing, if any? - } - - private ProgressDialog getProgressDialog() { - if (mProgressDialog == null || !mProgressDialog.isShowing()) { - mProgressDialog = new ProgressDialog(this); - mProgressDialog.setCancelable(false); - } - return mProgressDialog; - } - - private void updateProgressDialog() { - ProgressDialog dialog = getProgressDialog(); - boolean indeterminate = (mProgressState.max == 0); - dialog.setIndeterminate(indeterminate); - dialog.setProgressStyle(indeterminate ? ProgressDialog.STYLE_SPINNER - : ProgressDialog.STYLE_HORIZONTAL); - if (mProgressState.title != null) { - dialog.setTitle(mProgressState.title); - } - if (mProgressState.message != null) { - dialog.setMessage(mProgressState.message); - } - if (!indeterminate) { - dialog.setProgress(mProgressState.current); - dialog.setMax(mProgressState.max); - } - if (!dialog.isShowing()) { - dialog.show(); - } - } - - private void makeProgressDialogIndeterminate() { - ProgressDialog dialog = getProgressDialog(); - dialog.setIndeterminate(true); - } - - private void cleanupProgressDialog() { - if (mProgressDialog != null) { - mProgressDialog.hide(); - mProgressDialog = null; - } - } - - // This is static and uses a WeakReference in order to avoid leaking the Activity - private static class ItemListHandler extends Handler { - public static final int MSG_PROGRESS_UPDATE = 0; - public static final int MSG_PROGRESS_HIDE = 1; - public static final int MSG_NOTIFY_CHANGED = 2; - public static final int MSG_BULK_CHECKED_CHANGE = 3; - public static final int MSG_PROGRESS_INDETERMINATE = 4; - - WeakReference<IngestActivity> mParentReference; - - public ItemListHandler(IngestActivity parent) { - super(); - mParentReference = new WeakReference<IngestActivity>(parent); - } - - public void handleMessage(Message message) { - IngestActivity parent = mParentReference.get(); - if (parent == null || !parent.mActive) - return; - switch (message.what) { - case MSG_PROGRESS_HIDE: - parent.cleanupProgressDialog(); - break; - case MSG_PROGRESS_UPDATE: - parent.updateProgressDialog(); - break; - case MSG_NOTIFY_CHANGED: - parent.UiThreadNotifyIndexChanged(); - break; - case MSG_BULK_CHECKED_CHANGE: - parent.mPositionMappingCheckBroker.onBulkCheckedChange(); - break; - case MSG_PROGRESS_INDETERMINATE: - parent.makeProgressDialogIndeterminate(); - break; - default: - break; - } - } - } - - private ServiceConnection mHelperServiceConnection = new ServiceConnection() { - public void onServiceConnected(ComponentName className, IBinder service) { - mHelperService = ((IngestService.LocalBinder) service).getService(); - mHelperService.setClientActivity(IngestActivity.this); - MtpDeviceIndex index = mHelperService.getIndex(); - mAdapter.setMtpDeviceIndex(index); - if (mPagerAdapter != null) mPagerAdapter.setMtpDeviceIndex(index); - } - - public void onServiceDisconnected(ComponentName className) { - mHelperService = null; - } - }; - - private void doBindHelperService() { - bindService(new Intent(getApplicationContext(), IngestService.class), - mHelperServiceConnection, Context.BIND_AUTO_CREATE); - } - - private void doUnbindHelperService() { - if (mHelperService != null) { - mHelperService.setClientActivity(null); - unbindService(mHelperServiceConnection); - } - } -} diff --git a/src/com/android/gallery3d/ingest/IngestService.java b/src/com/android/gallery3d/ingest/IngestService.java deleted file mode 100644 index 0ce3ab6a9..000000000 --- a/src/com/android/gallery3d/ingest/IngestService.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest; - -import android.app.NotificationManager; -import android.app.PendingIntent; -import android.app.Service; -import android.content.Context; -import android.content.Intent; -import android.media.MediaScannerConnection; -import android.media.MediaScannerConnection.MediaScannerConnectionClient; -import android.mtp.MtpDevice; -import android.mtp.MtpDeviceInfo; -import android.mtp.MtpObjectInfo; -import android.net.Uri; -import android.os.Binder; -import android.os.IBinder; -import android.os.SystemClock; -import android.support.v4.app.NotificationCompat; -import android.util.SparseBooleanArray; -import android.widget.Adapter; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.NotificationIds; -import com.android.gallery3d.data.MtpClient; -import com.android.gallery3d.util.BucketNames; -import com.android.gallery3d.util.UsageStatistics; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -public class IngestService extends Service implements ImportTask.Listener, - MtpDeviceIndex.ProgressListener, MtpClient.Listener { - - public class LocalBinder extends Binder { - IngestService getService() { - return IngestService.this; - } - } - - private static final int PROGRESS_UPDATE_INTERVAL_MS = 180; - - private static MtpClient sClient; - - private final IBinder mBinder = new LocalBinder(); - private ScannerClient mScannerClient; - private MtpDevice mDevice; - private String mDevicePrettyName; - private MtpDeviceIndex mIndex; - private IngestActivity mClientActivity; - private boolean mRedeliverImportFinish = false; - private int mRedeliverImportFinishCount = 0; - private Collection<MtpObjectInfo> mRedeliverObjectsNotImported; - private boolean mRedeliverNotifyIndexChanged = false; - private boolean mRedeliverIndexFinish = false; - private NotificationManager mNotificationManager; - private NotificationCompat.Builder mNotificationBuilder; - private long mLastProgressIndexTime = 0; - private boolean mNeedRelaunchNotification = false; - - @Override - public void onCreate() { - super.onCreate(); - mScannerClient = new ScannerClient(this); - mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - mNotificationBuilder = new NotificationCompat.Builder(this); - mNotificationBuilder.setSmallIcon(android.R.drawable.stat_notify_sync) // TODO drawable - .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, IngestActivity.class), 0)); - mIndex = MtpDeviceIndex.getInstance(); - mIndex.setProgressListener(this); - - if (sClient == null) { - sClient = new MtpClient(getApplicationContext()); - } - List<MtpDevice> devices = sClient.getDeviceList(); - if (devices.size() > 0) { - setDevice(devices.get(0)); - } - sClient.addListener(this); - } - - @Override - public void onDestroy() { - sClient.removeListener(this); - mIndex.unsetProgressListener(this); - super.onDestroy(); - } - - @Override - public IBinder onBind(Intent intent) { - return mBinder; - } - - private void setDevice(MtpDevice device) { - if (mDevice == device) return; - mRedeliverImportFinish = false; - mRedeliverObjectsNotImported = null; - mRedeliverNotifyIndexChanged = false; - mRedeliverIndexFinish = false; - mDevice = device; - mIndex.setDevice(mDevice); - if (mDevice != null) { - MtpDeviceInfo deviceInfo = mDevice.getDeviceInfo(); - if (deviceInfo == null) { - setDevice(null); - return; - } else { - mDevicePrettyName = deviceInfo.getModel(); - mNotificationBuilder.setContentTitle(mDevicePrettyName); - new Thread(mIndex.getIndexRunnable()).start(); - } - } else { - mDevicePrettyName = null; - } - if (mClientActivity != null) { - mClientActivity.notifyIndexChanged(); - } else { - mRedeliverNotifyIndexChanged = true; - } - } - - protected MtpDeviceIndex getIndex() { - return mIndex; - } - - protected void setClientActivity(IngestActivity activity) { - if (mClientActivity == activity) return; - mClientActivity = activity; - if (mClientActivity == null) { - if (mNeedRelaunchNotification) { - mNotificationBuilder.setProgress(0, 0, false) - .setContentText(getResources().getText(R.string.ingest_scanning_done)); - mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING, - mNotificationBuilder.build()); - } - return; - } - mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_IMPORTING); - mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING); - if (mRedeliverImportFinish) { - mClientActivity.onImportFinish(mRedeliverObjectsNotImported, - mRedeliverImportFinishCount); - mRedeliverImportFinish = false; - mRedeliverObjectsNotImported = null; - } - if (mRedeliverNotifyIndexChanged) { - mClientActivity.notifyIndexChanged(); - mRedeliverNotifyIndexChanged = false; - } - if (mRedeliverIndexFinish) { - mClientActivity.onIndexFinish(); - mRedeliverIndexFinish = false; - } - } - - protected void importSelectedItems(SparseBooleanArray selected, Adapter adapter) { - List<MtpObjectInfo> importHandles = new ArrayList<MtpObjectInfo>(); - for (int i = 0; i < selected.size(); i++) { - if (selected.valueAt(i)) { - Object item = adapter.getItem(selected.keyAt(i)); - if (item instanceof MtpObjectInfo) { - importHandles.add(((MtpObjectInfo) item)); - } - } - } - ImportTask task = new ImportTask(mDevice, importHandles, BucketNames.IMPORTED, this); - task.setListener(this); - mNotificationBuilder.setProgress(0, 0, true) - .setContentText(getResources().getText(R.string.ingest_importing)); - startForeground(NotificationIds.INGEST_NOTIFICATION_IMPORTING, - mNotificationBuilder.build()); - new Thread(task).start(); - } - - @Override - public void deviceAdded(MtpDevice device) { - if (mDevice == null) { - setDevice(device); - UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER, - "DeviceConnected", null); - } - } - - @Override - public void deviceRemoved(MtpDevice device) { - if (device == mDevice) { - setDevice(null); - mNeedRelaunchNotification = false; - mNotificationManager.cancel(NotificationIds.INGEST_NOTIFICATION_SCANNING); - } - } - - @Override - public void onImportProgress(int visitedCount, int totalCount, - String pathIfSuccessful) { - if (pathIfSuccessful != null) { - mScannerClient.scanPath(pathIfSuccessful); - } - mNeedRelaunchNotification = false; - if (mClientActivity != null) { - mClientActivity.onImportProgress(visitedCount, totalCount, pathIfSuccessful); - } - mNotificationBuilder.setProgress(totalCount, visitedCount, false) - .setContentText(getResources().getText(R.string.ingest_importing)); - mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING, - mNotificationBuilder.build()); - } - - @Override - public void onImportFinish(Collection<MtpObjectInfo> objectsNotImported, - int visitedCount) { - stopForeground(true); - mNeedRelaunchNotification = true; - if (mClientActivity != null) { - mClientActivity.onImportFinish(objectsNotImported, visitedCount); - } else { - mRedeliverImportFinish = true; - mRedeliverObjectsNotImported = objectsNotImported; - mRedeliverImportFinishCount = visitedCount; - mNotificationBuilder.setProgress(0, 0, false) - .setContentText(getResources().getText(R.string.import_complete)); - mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_IMPORTING, - mNotificationBuilder.build()); - } - UsageStatistics.onEvent(UsageStatistics.COMPONENT_IMPORTER, - "ImportFinished", null, visitedCount); - } - - @Override - public void onObjectIndexed(MtpObjectInfo object, int numVisited) { - mNeedRelaunchNotification = false; - if (mClientActivity != null) { - mClientActivity.onObjectIndexed(object, numVisited); - } else { - // Throttle the updates to one every PROGRESS_UPDATE_INTERVAL_MS milliseconds - long currentTime = SystemClock.uptimeMillis(); - if (currentTime > mLastProgressIndexTime + PROGRESS_UPDATE_INTERVAL_MS) { - mLastProgressIndexTime = currentTime; - mNotificationBuilder.setProgress(0, numVisited, true) - .setContentText(getResources().getText(R.string.ingest_scanning)); - mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING, - mNotificationBuilder.build()); - } - } - } - - @Override - public void onSorting() { - if (mClientActivity != null) mClientActivity.onSorting(); - } - - @Override - public void onIndexFinish() { - mNeedRelaunchNotification = true; - if (mClientActivity != null) { - mClientActivity.onIndexFinish(); - } else { - mNotificationBuilder.setProgress(0, 0, false) - .setContentText(getResources().getText(R.string.ingest_scanning_done)); - mNotificationManager.notify(NotificationIds.INGEST_NOTIFICATION_SCANNING, - mNotificationBuilder.build()); - mRedeliverIndexFinish = true; - } - } - - // Copied from old Gallery3d code - private static final class ScannerClient implements MediaScannerConnectionClient { - ArrayList<String> mPaths = new ArrayList<String>(); - MediaScannerConnection mScannerConnection; - boolean mConnected; - Object mLock = new Object(); - - public ScannerClient(Context context) { - mScannerConnection = new MediaScannerConnection(context, this); - } - - public void scanPath(String path) { - synchronized (mLock) { - if (mConnected) { - mScannerConnection.scanFile(path, null); - } else { - mPaths.add(path); - mScannerConnection.connect(); - } - } - } - - @Override - public void onMediaScannerConnected() { - synchronized (mLock) { - mConnected = true; - if (!mPaths.isEmpty()) { - for (String path : mPaths) { - mScannerConnection.scanFile(path, null); - } - mPaths.clear(); - } - } - } - - @Override - public void onScanCompleted(String path, Uri uri) { - } - } -} diff --git a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java b/src/com/android/gallery3d/ingest/MtpDeviceIndex.java deleted file mode 100644 index d30f94a87..000000000 --- a/src/com/android/gallery3d/ingest/MtpDeviceIndex.java +++ /dev/null @@ -1,596 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest; - -import android.mtp.MtpConstants; -import android.mtp.MtpDevice; -import android.mtp.MtpObjectInfo; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Stack; - -/** - * MTP objects in the index are organized into "buckets," or groupings. - * At present, these buckets are based on the date an item was created. - * - * When the index is created, the buckets are sorted in their natural - * order, and the items within the buckets sorted by the date they are taken. - * - * The index enables the access of items and bucket labels as one unified list. - * For example, let's say we have the following data in the index: - * [Bucket A]: [photo 1], [photo 2] - * [Bucket B]: [photo 3] - * - * Then the items can be thought of as being organized as a 5 element list: - * [Bucket A], [photo 1], [photo 2], [Bucket B], [photo 3] - * - * The data can also be accessed in descending order, in which case the list - * would be a bit different from simply reversing the ascending list, since the - * bucket labels need to always be at the beginning: - * [Bucket B], [photo 3], [Bucket A], [photo 2], [photo 1] - * - * The index enables all the following operations in constant time, both for - * ascending and descending views of the data: - * - get/getAscending/getDescending: get an item at a specified list position - * - size: get the total number of items (bucket labels and MTP objects) - * - getFirstPositionForBucketNumber - * - getBucketNumberForPosition - * - isFirstInBucket - * - * See the comments in buildLookupIndex for implementation notes. - */ -public class MtpDeviceIndex { - - public static final int FORMAT_MOV = 0x300D; // For some reason this is not in MtpConstants - - public static final Set<Integer> SUPPORTED_IMAGE_FORMATS; - public static final Set<Integer> SUPPORTED_VIDEO_FORMATS; - - static { - SUPPORTED_IMAGE_FORMATS = new HashSet<Integer>(); - SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_JFIF); - SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_EXIF_JPEG); - SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_PNG); - SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_GIF); - SUPPORTED_IMAGE_FORMATS.add(MtpConstants.FORMAT_BMP); - - SUPPORTED_VIDEO_FORMATS = new HashSet<Integer>(); - SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_3GP_CONTAINER); - SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_AVI); - SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_MP4_CONTAINER); - SUPPORTED_VIDEO_FORMATS.add(MtpConstants.FORMAT_MPEG); - // TODO: add FORMAT_MOV once Media Scanner supports .mov files - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((mDevice == null) ? 0 : mDevice.getDeviceId()); - result = prime * result + mGeneration; - return result; - } - - public interface ProgressListener { - public void onObjectIndexed(MtpObjectInfo object, int numVisited); - - public void onSorting(); - - public void onIndexFinish(); - } - - public enum SortOrder { - Ascending, Descending - } - - private MtpDevice mDevice; - private int[] mUnifiedLookupIndex; - private MtpObjectInfo[] mMtpObjects; - private DateBucket[] mBuckets; - private int mGeneration = 0; - - public enum Progress { - Uninitialized, Initialized, Pending, Started, Sorting, Finished - } - - private Progress mProgress = Progress.Uninitialized; - private ProgressListener mProgressListener; - - private static final MtpDeviceIndex sInstance = new MtpDeviceIndex(); - private static final MtpObjectTimestampComparator sMtpObjectComparator = - new MtpObjectTimestampComparator(); - - public static MtpDeviceIndex getInstance() { - return sInstance; - } - - private MtpDeviceIndex() { - } - - synchronized public MtpDevice getDevice() { - return mDevice; - } - - /** - * Sets the MtpDevice that should be indexed and initializes state, but does - * not kick off the actual indexing task, which is instead done by using - * {@link #getIndexRunnable()} - * - * @param device The MtpDevice that should be indexed - */ - synchronized public void setDevice(MtpDevice device) { - if (device == mDevice) return; - mDevice = device; - resetState(); - } - - /** - * Provides a Runnable for the indexing task assuming the state has already - * been correctly initialized (by calling {@link #setDevice(MtpDevice)}) and - * has not already been run. - * - * @return Runnable for the main indexing task - */ - synchronized public Runnable getIndexRunnable() { - if (mProgress != Progress.Initialized) return null; - mProgress = Progress.Pending; - return new IndexRunnable(mDevice); - } - - synchronized public boolean indexReady() { - return mProgress == Progress.Finished; - } - - synchronized public Progress getProgress() { - return mProgress; - } - - /** - * @param listener Listener to change to - * @return Progress at the time the listener was added (useful for - * configuring initial UI state) - */ - synchronized public Progress setProgressListener(ProgressListener listener) { - mProgressListener = listener; - return mProgress; - } - - /** - * Make the listener null if it matches the argument - * - * @param listener Listener to unset, if currently registered - */ - synchronized public void unsetProgressListener(ProgressListener listener) { - if (mProgressListener == listener) - mProgressListener = null; - } - - /** - * @return The total number of elements in the index (labels and items) - */ - public int size() { - return mProgress == Progress.Finished ? mUnifiedLookupIndex.length : 0; - } - - /** - * @param position Index of item to fetch, where 0 is the first item in the - * specified order - * @param order - * @return the bucket label or MtpObjectInfo at the specified position and - * order - */ - public Object get(int position, SortOrder order) { - if (mProgress != Progress.Finished) return null; - if(order == SortOrder.Ascending) { - DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]]; - if (bucket.unifiedStartIndex == position) { - return bucket.bucket; - } else { - return mMtpObjects[bucket.itemsStartIndex + position - 1 - - bucket.unifiedStartIndex]; - } - } else { - int zeroIndex = mUnifiedLookupIndex.length - 1 - position; - DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]]; - if (bucket.unifiedEndIndex == zeroIndex) { - return bucket.bucket; - } else { - return mMtpObjects[bucket.itemsStartIndex + zeroIndex - - bucket.unifiedStartIndex]; - } - } - } - - /** - * @param position Index of item to fetch from a view of the data that doesn't - * include labels and is in the specified order - * @return position-th item in specified order, when not including labels - */ - public MtpObjectInfo getWithoutLabels(int position, SortOrder order) { - if (mProgress != Progress.Finished) return null; - if (order == SortOrder.Ascending) { - return mMtpObjects[position]; - } else { - return mMtpObjects[mMtpObjects.length - 1 - position]; - } - } - - /** - * Although this is O(log(number of buckets)), and thus should not be used - * in hotspots, even if the attached device has items for every day for - * a five-year timeframe, it would still only take 11 iterations at most, - * so shouldn't be a huge issue. - * @param position Index of item to map from a view of the data that doesn't - * include labels and is in the specified order - * @param order - * @return position in a view of the data that does include labels - */ - public int getPositionFromPositionWithoutLabels(int position, SortOrder order) { - if (mProgress != Progress.Finished) return -1; - if (order == SortOrder.Descending) { - position = mMtpObjects.length - 1 - position; - } - int bucketNumber = 0; - int iMin = 0; - int iMax = mBuckets.length - 1; - while (iMax >= iMin) { - int iMid = (iMax + iMin) / 2; - if (mBuckets[iMid].itemsStartIndex + mBuckets[iMid].numItems <= position) { - iMin = iMid + 1; - } else if (mBuckets[iMid].itemsStartIndex > position) { - iMax = iMid - 1; - } else { - bucketNumber = iMid; - break; - } - } - int mappedPos = mBuckets[bucketNumber].unifiedStartIndex - + position - mBuckets[bucketNumber].itemsStartIndex; - if (order == SortOrder.Descending) { - mappedPos = mUnifiedLookupIndex.length - 1 - mappedPos; - } - return mappedPos; - } - - public int getPositionWithoutLabelsFromPosition(int position, SortOrder order) { - if (mProgress != Progress.Finished) return -1; - if(order == SortOrder.Ascending) { - DateBucket bucket = mBuckets[mUnifiedLookupIndex[position]]; - if (bucket.unifiedStartIndex == position) position++; - return bucket.itemsStartIndex + position - 1 - bucket.unifiedStartIndex; - } else { - int zeroIndex = mUnifiedLookupIndex.length - 1 - position; - DateBucket bucket = mBuckets[mUnifiedLookupIndex[zeroIndex]]; - if (bucket.unifiedEndIndex == zeroIndex) zeroIndex--; - return mMtpObjects.length - 1 - bucket.itemsStartIndex - - zeroIndex + bucket.unifiedStartIndex; - } - } - - /** - * @return The number of MTP items in the index (without labels) - */ - public int sizeWithoutLabels() { - return mProgress == Progress.Finished ? mMtpObjects.length : 0; - } - - public int getFirstPositionForBucketNumber(int bucketNumber, SortOrder order) { - if (order == SortOrder.Ascending) { - return mBuckets[bucketNumber].unifiedStartIndex; - } else { - return mUnifiedLookupIndex.length - mBuckets[mBuckets.length - 1 - bucketNumber].unifiedEndIndex - 1; - } - } - - public int getBucketNumberForPosition(int position, SortOrder order) { - if (order == SortOrder.Ascending) { - return mUnifiedLookupIndex[position]; - } else { - return mBuckets.length - 1 - mUnifiedLookupIndex[mUnifiedLookupIndex.length - 1 - position]; - } - } - - public boolean isFirstInBucket(int position, SortOrder order) { - if (order == SortOrder.Ascending) { - return mBuckets[mUnifiedLookupIndex[position]].unifiedStartIndex == position; - } else { - position = mUnifiedLookupIndex.length - 1 - position; - return mBuckets[mUnifiedLookupIndex[position]].unifiedEndIndex == position; - } - } - - private Object[] mCachedReverseBuckets; - - public Object[] getBuckets(SortOrder order) { - if (mBuckets == null) return null; - if (order == SortOrder.Ascending) { - return mBuckets; - } else { - if (mCachedReverseBuckets == null) { - computeReversedBuckets(); - } - return mCachedReverseBuckets; - } - } - - /* - * See the comments for buildLookupIndex for notes on the specific fields of - * this class. - */ - private class DateBucket implements Comparable<DateBucket> { - SimpleDate bucket; - List<MtpObjectInfo> tempElementsList = new ArrayList<MtpObjectInfo>(); - int unifiedStartIndex; - int unifiedEndIndex; - int itemsStartIndex; - int numItems; - - public DateBucket(SimpleDate bucket) { - this.bucket = bucket; - } - - public DateBucket(SimpleDate bucket, MtpObjectInfo firstElement) { - this(bucket); - tempElementsList.add(firstElement); - } - - void sortElements(Comparator<MtpObjectInfo> comparator) { - Collections.sort(tempElementsList, comparator); - } - - @Override - public String toString() { - return bucket.toString(); - } - - @Override - public int hashCode() { - return bucket.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null) return false; - if (!(obj instanceof DateBucket)) return false; - DateBucket other = (DateBucket) obj; - if (bucket == null) { - if (other.bucket != null) return false; - } else if (!bucket.equals(other.bucket)) { - return false; - } - return true; - } - - @Override - public int compareTo(DateBucket another) { - return this.bucket.compareTo(another.bucket); - } - } - - /** - * Comparator to sort MtpObjectInfo objects by date created. - */ - private static class MtpObjectTimestampComparator implements Comparator<MtpObjectInfo> { - @Override - public int compare(MtpObjectInfo o1, MtpObjectInfo o2) { - long diff = o1.getDateCreated() - o2.getDateCreated(); - if (diff < 0) { - return -1; - } else if (diff == 0) { - return 0; - } else { - return 1; - } - } - } - - private void resetState() { - mGeneration++; - mUnifiedLookupIndex = null; - mMtpObjects = null; - mBuckets = null; - mCachedReverseBuckets = null; - mProgress = (mDevice == null) ? Progress.Uninitialized : Progress.Initialized; - } - - - private class IndexRunnable implements Runnable { - private int[] mUnifiedLookupIndex; - private MtpObjectInfo[] mMtpObjects; - private DateBucket[] mBuckets; - private Map<SimpleDate, DateBucket> mBucketsTemp; - private MtpDevice mDevice; - private int mNumObjects = 0; - - private class IndexingException extends Exception {}; - - public IndexRunnable(MtpDevice device) { - mDevice = device; - } - - /* - * Implementation note: this is the way the index supports a lot of its operations in - * constant time and respecting the need to have bucket names always come before items - * in that bucket when accessing the list sequentially, both in ascending and descending - * orders. - * - * Let's say the data we have in the index is the following: - * [Bucket A]: [photo 1], [photo 2] - * [Bucket B]: [photo 3] - * - * In this case, the lookup index array would be - * [0, 0, 0, 1, 1] - * - * Now, whether we access the list in ascending or descending order, we know which bucket - * to look in (0 corresponds to A and 1 to B), and can return the bucket label as the first - * item in a bucket as needed. The individual IndexBUckets have a startIndex and endIndex - * that correspond to indices in this lookup index array, allowing us to calculate the - * offset of the specific item we want from within a specific bucket. - */ - private void buildLookupIndex() { - int numBuckets = mBuckets.length; - mUnifiedLookupIndex = new int[mNumObjects + numBuckets]; - int currentUnifiedIndexEntry = 0; - int nextUnifiedEntry; - - mMtpObjects = new MtpObjectInfo[mNumObjects]; - int currentItemsEntry = 0; - for (int i = 0; i < numBuckets; i++) { - DateBucket bucket = mBuckets[i]; - nextUnifiedEntry = currentUnifiedIndexEntry + bucket.tempElementsList.size() + 1; - Arrays.fill(mUnifiedLookupIndex, currentUnifiedIndexEntry, nextUnifiedEntry, i); - bucket.unifiedStartIndex = currentUnifiedIndexEntry; - bucket.unifiedEndIndex = nextUnifiedEntry - 1; - currentUnifiedIndexEntry = nextUnifiedEntry; - - bucket.itemsStartIndex = currentItemsEntry; - bucket.numItems = bucket.tempElementsList.size(); - for (int j = 0; j < bucket.numItems; j++) { - mMtpObjects[currentItemsEntry] = bucket.tempElementsList.get(j); - currentItemsEntry++; - } - bucket.tempElementsList = null; - } - } - - private void copyResults() { - MtpDeviceIndex.this.mUnifiedLookupIndex = mUnifiedLookupIndex; - MtpDeviceIndex.this.mMtpObjects = mMtpObjects; - MtpDeviceIndex.this.mBuckets = mBuckets; - mUnifiedLookupIndex = null; - mMtpObjects = null; - mBuckets = null; - } - - @Override - public void run() { - try { - indexDevice(); - } catch (IndexingException e) { - synchronized (MtpDeviceIndex.this) { - resetState(); - if (mProgressListener != null) { - mProgressListener.onIndexFinish(); - } - } - } - } - - private void indexDevice() throws IndexingException { - synchronized (MtpDeviceIndex.this) { - mProgress = Progress.Started; - } - mBucketsTemp = new HashMap<SimpleDate, DateBucket>(); - for (int storageId : mDevice.getStorageIds()) { - if (mDevice != getDevice()) throw new IndexingException(); - Stack<Integer> pendingDirectories = new Stack<Integer>(); - pendingDirectories.add(0xFFFFFFFF); // start at the root of the device - while (!pendingDirectories.isEmpty()) { - if (mDevice != getDevice()) throw new IndexingException(); - int dirHandle = pendingDirectories.pop(); - for (int objectHandle : mDevice.getObjectHandles(storageId, 0, dirHandle)) { - MtpObjectInfo objectInfo = mDevice.getObjectInfo(objectHandle); - if (objectInfo == null) throw new IndexingException(); - int format = objectInfo.getFormat(); - if (format == MtpConstants.FORMAT_ASSOCIATION) { - pendingDirectories.add(objectHandle); - } else if (SUPPORTED_IMAGE_FORMATS.contains(format) - || SUPPORTED_VIDEO_FORMATS.contains(format)) { - addObject(objectInfo); - } - } - } - } - Collection<DateBucket> values = mBucketsTemp.values(); - mBucketsTemp = null; - mBuckets = values.toArray(new DateBucket[values.size()]); - values = null; - synchronized (MtpDeviceIndex.this) { - mProgress = Progress.Sorting; - if (mProgressListener != null) { - mProgressListener.onSorting(); - } - } - sortAll(); - buildLookupIndex(); - synchronized (MtpDeviceIndex.this) { - if (mDevice != getDevice()) throw new IndexingException(); - copyResults(); - - /* - * In order for getBuckets to operate in constant time for descending - * order, we must precompute a reversed array of the buckets, mainly - * because the android.widget.SectionIndexer interface which adapters - * that call getBuckets implement depends on section numbers to be - * ascending relative to the scroll position, so we must have this for - * descending order or the scrollbar goes crazy. - */ - computeReversedBuckets(); - - mProgress = Progress.Finished; - if (mProgressListener != null) { - mProgressListener.onIndexFinish(); - } - } - } - - private SimpleDate mDateInstance = new SimpleDate(); - - private void addObject(MtpObjectInfo objectInfo) { - mNumObjects++; - mDateInstance.setTimestamp(objectInfo.getDateCreated()); - DateBucket bucket = mBucketsTemp.get(mDateInstance); - if (bucket == null) { - bucket = new DateBucket(mDateInstance, objectInfo); - mBucketsTemp.put(mDateInstance, bucket); - mDateInstance = new SimpleDate(); // only create new date - // objects when they are used - return; - } else { - bucket.tempElementsList.add(objectInfo); - } - if (mProgressListener != null) { - mProgressListener.onObjectIndexed(objectInfo, mNumObjects); - } - } - - private void sortAll() { - Arrays.sort(mBuckets); - for (DateBucket bucket : mBuckets) { - bucket.sortElements(sMtpObjectComparator); - } - } - - } - - private void computeReversedBuckets() { - mCachedReverseBuckets = new Object[mBuckets.length]; - for (int i = 0; i < mCachedReverseBuckets.length; i++) { - mCachedReverseBuckets[i] = mBuckets[mBuckets.length - 1 - i]; - } - } -} diff --git a/src/com/android/gallery3d/ingest/SimpleDate.java b/src/com/android/gallery3d/ingest/SimpleDate.java deleted file mode 100644 index 05db2cde2..000000000 --- a/src/com/android/gallery3d/ingest/SimpleDate.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest; - -import java.text.DateFormat; -import java.util.Calendar; - -/** - * Represents a date (year, month, day) - */ -public class SimpleDate implements Comparable<SimpleDate> { - public int month; // MM - public int day; // DD - public int year; // YYYY - private long timestamp; - private String mCachedStringRepresentation; - - public SimpleDate() { - } - - public SimpleDate(long timestamp) { - setTimestamp(timestamp); - } - - private static Calendar sCalendarInstance = Calendar.getInstance(); - - public void setTimestamp(long timestamp) { - synchronized (sCalendarInstance) { - // TODO find a more efficient way to convert a timestamp to a date? - sCalendarInstance.setTimeInMillis(timestamp); - this.day = sCalendarInstance.get(Calendar.DATE); - this.month = sCalendarInstance.get(Calendar.MONTH); - this.year = sCalendarInstance.get(Calendar.YEAR); - this.timestamp = timestamp; - mCachedStringRepresentation = DateFormat.getDateInstance(DateFormat.SHORT).format(timestamp); - } - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + day; - result = prime * result + month; - result = prime * result + year; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (!(obj instanceof SimpleDate)) - return false; - SimpleDate other = (SimpleDate) obj; - if (year != other.year) - return false; - if (month != other.month) - return false; - if (day != other.day) - return false; - return true; - } - - @Override - public int compareTo(SimpleDate other) { - int yearDiff = this.year - other.getYear(); - if (yearDiff != 0) - return yearDiff; - else { - int monthDiff = this.month - other.getMonth(); - if (monthDiff != 0) - return monthDiff; - else - return this.day - other.getDay(); - } - } - - public int getDay() { - return day; - } - - public int getMonth() { - return month; - } - - public int getYear() { - return year; - } - - @Override - public String toString() { - if (mCachedStringRepresentation == null) { - mCachedStringRepresentation = DateFormat.getDateInstance(DateFormat.SHORT).format(timestamp); - } - return mCachedStringRepresentation; - } -} diff --git a/src/com/android/gallery3d/ingest/adapter/CheckBroker.java b/src/com/android/gallery3d/ingest/adapter/CheckBroker.java deleted file mode 100644 index 6783f23c5..000000000 --- a/src/com/android/gallery3d/ingest/adapter/CheckBroker.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.adapter; - -import java.util.ArrayList; -import java.util.Collection; - -public abstract class CheckBroker { - private Collection<OnCheckedChangedListener> mListeners = - new ArrayList<OnCheckedChangedListener>(); - - public interface OnCheckedChangedListener { - public void onCheckedChanged(int position, boolean isChecked); - public void onBulkCheckedChanged(); - } - - public abstract void setItemChecked(int position, boolean checked); - - public void onCheckedChange(int position, boolean checked) { - if (isItemChecked(position) != checked) { - for (OnCheckedChangedListener l : mListeners) { - l.onCheckedChanged(position, checked); - } - } - } - - public void onBulkCheckedChange() { - for (OnCheckedChangedListener l : mListeners) { - l.onBulkCheckedChanged(); - } - } - - public abstract boolean isItemChecked(int position); - - public void registerOnCheckedChangeListener(OnCheckedChangedListener l) { - mListeners.add(l); - } - - public void unregisterOnCheckedChangeListener(OnCheckedChangedListener l) { - mListeners.remove(l); - } -} diff --git a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java deleted file mode 100644 index e8dd69f8c..000000000 --- a/src/com/android/gallery3d/ingest/adapter/MtpAdapter.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.adapter; - -import android.app.Activity; -import android.content.Context; -import android.mtp.MtpObjectInfo; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.SectionIndexer; - -import com.android.gallery3d.R; -import com.android.gallery3d.ingest.MtpDeviceIndex; -import com.android.gallery3d.ingest.MtpDeviceIndex.SortOrder; -import com.android.gallery3d.ingest.SimpleDate; -import com.android.gallery3d.ingest.ui.DateTileView; -import com.android.gallery3d.ingest.ui.MtpThumbnailTileView; - -public class MtpAdapter extends BaseAdapter implements SectionIndexer { - public static final int ITEM_TYPE_MEDIA = 0; - public static final int ITEM_TYPE_BUCKET = 1; - - private Context mContext; - private MtpDeviceIndex mModel; - private SortOrder mSortOrder = SortOrder.Descending; - private LayoutInflater mInflater; - private int mGeneration = 0; - - public MtpAdapter(Activity context) { - super(); - mContext = context; - mInflater = LayoutInflater.from(context); - } - - public void setMtpDeviceIndex(MtpDeviceIndex index) { - mModel = index; - notifyDataSetChanged(); - } - - public MtpDeviceIndex getMtpDeviceIndex() { - return mModel; - } - - @Override - public void notifyDataSetChanged() { - mGeneration++; - super.notifyDataSetChanged(); - } - - @Override - public void notifyDataSetInvalidated() { - mGeneration++; - super.notifyDataSetInvalidated(); - } - - public boolean deviceConnected() { - return (mModel != null) && (mModel.getDevice() != null); - } - - public boolean indexReady() { - return (mModel != null) && mModel.indexReady(); - } - - @Override - public int getCount() { - return mModel != null ? mModel.size() : 0; - } - - @Override - public Object getItem(int position) { - return mModel.get(position, mSortOrder); - } - - @Override - public boolean areAllItemsEnabled() { - return true; - } - - @Override - public boolean isEnabled(int position) { - return true; - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public int getViewTypeCount() { - return 2; - } - - @Override - public int getItemViewType(int position) { - // If the position is the first in its section, then it corresponds to - // a title tile, if not it's a media tile - if (position == getPositionForSection(getSectionForPosition(position))) { - return ITEM_TYPE_BUCKET; - } else { - return ITEM_TYPE_MEDIA; - } - } - - public boolean itemAtPositionIsBucket(int position) { - return getItemViewType(position) == ITEM_TYPE_BUCKET; - } - - public boolean itemAtPositionIsMedia(int position) { - return getItemViewType(position) == ITEM_TYPE_MEDIA; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - int type = getItemViewType(position); - if (type == ITEM_TYPE_MEDIA) { - MtpThumbnailTileView imageView; - if (convertView == null) { - imageView = (MtpThumbnailTileView) mInflater.inflate( - R.layout.ingest_thumbnail, parent, false); - } else { - imageView = (MtpThumbnailTileView) convertView; - } - imageView.setMtpDeviceAndObjectInfo(mModel.getDevice(), (MtpObjectInfo)getItem(position), mGeneration); - return imageView; - } else { - DateTileView dateTile; - if (convertView == null) { - dateTile = (DateTileView) mInflater.inflate( - R.layout.ingest_date_tile, parent, false); - } else { - dateTile = (DateTileView) convertView; - } - dateTile.setDate((SimpleDate)getItem(position)); - return dateTile; - } - } - - @Override - public int getPositionForSection(int section) { - if (getCount() == 0) { - return 0; - } - int numSections = getSections().length; - if (section >= numSections) { - section = numSections - 1; - } - return mModel.getFirstPositionForBucketNumber(section, mSortOrder); - } - - @Override - public int getSectionForPosition(int position) { - int count = getCount(); - if (count == 0) { - return 0; - } - if (position >= count) { - position = count - 1; - } - return mModel.getBucketNumberForPosition(position, mSortOrder); - } - - @Override - public Object[] getSections() { - return getCount() > 0 ? mModel.getBuckets(mSortOrder) : null; - } - - public SortOrder getSortOrder() { - return mSortOrder; - } - - public int translatePositionWithoutLabels(int position) { - if (mModel == null) return -1; - return mModel.getPositionFromPositionWithoutLabels(position, mSortOrder); - } -} diff --git a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java b/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java deleted file mode 100644 index 9e7abc01d..000000000 --- a/src/com/android/gallery3d/ingest/adapter/MtpPagerAdapter.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.adapter; - -import android.content.Context; -import android.mtp.MtpObjectInfo; -import android.support.v4.view.PagerAdapter; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import com.android.gallery3d.R; -import com.android.gallery3d.ingest.MtpDeviceIndex; -import com.android.gallery3d.ingest.MtpDeviceIndex.SortOrder; -import com.android.gallery3d.ingest.ui.MtpFullscreenView; - -public class MtpPagerAdapter extends PagerAdapter { - - private LayoutInflater mInflater; - private int mGeneration = 0; - private CheckBroker mBroker; - private MtpDeviceIndex mModel; - private SortOrder mSortOrder = SortOrder.Descending; - - private MtpFullscreenView mReusableView = null; - - public MtpPagerAdapter(Context context, CheckBroker broker) { - super(); - mInflater = LayoutInflater.from(context); - mBroker = broker; - } - - public void setMtpDeviceIndex(MtpDeviceIndex index) { - mModel = index; - notifyDataSetChanged(); - } - - @Override - public int getCount() { - return mModel != null ? mModel.sizeWithoutLabels() : 0; - } - - @Override - public void notifyDataSetChanged() { - mGeneration++; - super.notifyDataSetChanged(); - } - - public int translatePositionWithLabels(int position) { - if (mModel == null) return -1; - return mModel.getPositionWithoutLabelsFromPosition(position, mSortOrder); - } - - @Override - public void finishUpdate(ViewGroup container) { - mReusableView = null; - super.finishUpdate(container); - } - - @Override - public boolean isViewFromObject(View view, Object object) { - return view == object; - } - - @Override - public void destroyItem(ViewGroup container, int position, Object object) { - MtpFullscreenView v = (MtpFullscreenView)object; - container.removeView(v); - mBroker.unregisterOnCheckedChangeListener(v); - mReusableView = v; - } - - @Override - public Object instantiateItem(ViewGroup container, int position) { - MtpFullscreenView v; - if (mReusableView != null) { - v = mReusableView; - mReusableView = null; - } else { - v = (MtpFullscreenView) mInflater.inflate(R.layout.ingest_fullsize, container, false); - } - MtpObjectInfo i = mModel.getWithoutLabels(position, mSortOrder); - v.getImageView().setMtpDeviceAndObjectInfo(mModel.getDevice(), i, mGeneration); - v.setPositionAndBroker(position, mBroker); - container.addView(v); - return v; - } -} diff --git a/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java b/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java deleted file mode 100644 index bbc90f670..000000000 --- a/src/com/android/gallery3d/ingest/data/BitmapWithMetadata.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.data; - -import android.graphics.Bitmap; - -public class BitmapWithMetadata { - public Bitmap bitmap; - public int rotationDegrees; - - public BitmapWithMetadata(Bitmap bitmap, int rotationDegrees) { - this.bitmap = bitmap; - this.rotationDegrees = rotationDegrees; - } -} diff --git a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java b/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java deleted file mode 100644 index 30868c22b..000000000 --- a/src/com/android/gallery3d/ingest/data/MtpBitmapFetch.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.data; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.mtp.MtpDevice; -import android.mtp.MtpObjectInfo; -import android.util.DisplayMetrics; -import android.view.WindowManager; - -import com.android.camera.Exif; -import com.android.photos.data.GalleryBitmapPool; - -public class MtpBitmapFetch { - private static int sMaxSize = 0; - - public static void recycleThumbnail(Bitmap b) { - if (b != null) { - GalleryBitmapPool.getInstance().put(b); - } - } - - public static Bitmap getThumbnail(MtpDevice device, MtpObjectInfo info) { - byte[] imageBytes = device.getThumbnail(info.getObjectHandle()); - if (imageBytes == null) { - return null; - } - BitmapFactory.Options o = new BitmapFactory.Options(); - o.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o); - if (o.outWidth == 0 || o.outHeight == 0) { - return null; - } - o.inBitmap = GalleryBitmapPool.getInstance().get(o.outWidth, o.outHeight); - o.inMutable = true; - o.inJustDecodeBounds = false; - o.inSampleSize = 1; - try { - return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o); - } catch (IllegalArgumentException e) { - // BitmapFactory throws an exception rather than returning null - // when image decoding fails and an existing bitmap was supplied - // for recycling, even if the failure was not caused by the use - // of that bitmap. - return BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); - } - } - - public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info) { - return getFullsize(device, info, sMaxSize); - } - - public static BitmapWithMetadata getFullsize(MtpDevice device, MtpObjectInfo info, int maxSide) { - byte[] imageBytes = device.getObject(info.getObjectHandle(), info.getCompressedSize()); - if (imageBytes == null) { - return null; - } - Bitmap created; - if (maxSide > 0) { - BitmapFactory.Options o = new BitmapFactory.Options(); - o.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o); - int w = o.outWidth; - int h = o.outHeight; - int comp = Math.max(h, w); - int sampleSize = 1; - while ((comp >> 1) >= maxSide) { - comp = comp >> 1; - sampleSize++; - } - o.inSampleSize = sampleSize; - o.inJustDecodeBounds = false; - created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length, o); - } else { - created = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length); - } - if (created == null) { - return null; - } - - return new BitmapWithMetadata(created, Exif.getOrientation(imageBytes)); - } - - public static void configureForContext(Context context) { - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(metrics); - sMaxSize = Math.max(metrics.heightPixels, metrics.widthPixels); - } -} diff --git a/src/com/android/gallery3d/ingest/ui/DateTileView.java b/src/com/android/gallery3d/ingest/ui/DateTileView.java deleted file mode 100644 index 52fe9b85b..000000000 --- a/src/com/android/gallery3d/ingest/ui/DateTileView.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.FrameLayout; -import android.widget.TextView; - -import com.android.gallery3d.R; -import com.android.gallery3d.ingest.SimpleDate; - -import java.text.DateFormatSymbols; -import java.util.Locale; - -public class DateTileView extends FrameLayout { - private static String[] sMonthNames = DateFormatSymbols.getInstance().getShortMonths(); - private static Locale sLocale; - - static { - refreshLocale(); - } - - public static boolean refreshLocale() { - Locale currentLocale = Locale.getDefault(); - if (!currentLocale.equals(sLocale)) { - sLocale = currentLocale; - sMonthNames = DateFormatSymbols.getInstance(sLocale).getShortMonths(); - return true; - } else { - return false; - } - } - - private TextView mDateTextView; - private TextView mMonthTextView; - private TextView mYearTextView; - private int mMonth = -1; - private int mYear = -1; - private int mDate = -1; - private String[] mMonthNames = sMonthNames; - - public DateTileView(Context context) { - super(context); - } - - public DateTileView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public DateTileView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // Force this to be square - super.onMeasure(widthMeasureSpec, widthMeasureSpec); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mDateTextView = (TextView) findViewById(R.id.date_tile_day); - mMonthTextView = (TextView) findViewById(R.id.date_tile_month); - mYearTextView = (TextView) findViewById(R.id.date_tile_year); - } - - public void setDate(SimpleDate date) { - setDate(date.getDay(), date.getMonth(), date.getYear()); - } - - public void setDate(int date, int month, int year) { - if (date != mDate) { - mDate = date; - mDateTextView.setText(mDate > 9 ? Integer.toString(mDate) : "0" + mDate); - } - if (mMonthNames != sMonthNames) { - mMonthNames = sMonthNames; - if (month == mMonth) { - mMonthTextView.setText(mMonthNames[mMonth]); - } - } - if (month != mMonth) { - mMonth = month; - mMonthTextView.setText(mMonthNames[mMonth]); - } - if (year != mYear) { - mYear = year; - mYearTextView.setText(Integer.toString(mYear)); - } - } -} diff --git a/src/com/android/gallery3d/ingest/ui/IngestGridView.java b/src/com/android/gallery3d/ingest/ui/IngestGridView.java deleted file mode 100644 index c821259fe..000000000 --- a/src/com/android/gallery3d/ingest/ui/IngestGridView.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.GridView; - -/** - * This just extends GridView with the ability to listen for calls - * to clearChoices() - */ -public class IngestGridView extends GridView { - - public interface OnClearChoicesListener { - public void onClearChoices(); - } - - private OnClearChoicesListener mOnClearChoicesListener = null; - - public IngestGridView(Context context) { - super(context); - } - - public IngestGridView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public IngestGridView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - public void setOnClearChoicesListener(OnClearChoicesListener l) { - mOnClearChoicesListener = l; - } - - @Override - public void clearChoices() { - super.clearChoices(); - if (mOnClearChoicesListener != null) { - mOnClearChoicesListener.onClearChoices(); - } - } -} diff --git a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java b/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java deleted file mode 100644 index 8d3884dc6..000000000 --- a/src/com/android/gallery3d/ingest/ui/MtpFullscreenView.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.ui; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.CheckBox; -import android.widget.Checkable; -import android.widget.CompoundButton; -import android.widget.CompoundButton.OnCheckedChangeListener; -import android.widget.RelativeLayout; - -import com.android.gallery3d.R; -import com.android.gallery3d.ingest.adapter.CheckBroker; - -public class MtpFullscreenView extends RelativeLayout implements Checkable, - CompoundButton.OnCheckedChangeListener, CheckBroker.OnCheckedChangedListener { - - private MtpImageView mImageView; - private CheckBox mCheckbox; - private int mPosition = -1; - private CheckBroker mBroker; - - public MtpFullscreenView(Context context) { - super(context); - } - - public MtpFullscreenView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public MtpFullscreenView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - mImageView = (MtpImageView) findViewById(R.id.ingest_fullsize_image); - mCheckbox = (CheckBox) findViewById(R.id.ingest_fullsize_image_checkbox); - mCheckbox.setOnCheckedChangeListener(this); - } - - @Override - public boolean isChecked() { - return mCheckbox.isChecked(); - } - - @Override - public void setChecked(boolean checked) { - mCheckbox.setChecked(checked); - } - - @Override - public void toggle() { - mCheckbox.toggle(); - } - - @Override - public void onDetachedFromWindow() { - setPositionAndBroker(-1, null); - super.onDetachedFromWindow(); - } - - public MtpImageView getImageView() { - return mImageView; - } - - public int getPosition() { - return mPosition; - } - - public void setPositionAndBroker(int position, CheckBroker b) { - if (mBroker != null) { - mBroker.unregisterOnCheckedChangeListener(this); - } - mPosition = position; - mBroker = b; - if (mBroker != null) { - setChecked(mBroker.isItemChecked(position)); - mBroker.registerOnCheckedChangeListener(this); - } - } - - @Override - public void onCheckedChanged(CompoundButton arg0, boolean isChecked) { - if (mBroker != null) mBroker.setItemChecked(mPosition, isChecked); - } - - @Override - public void onCheckedChanged(int position, boolean isChecked) { - if (position == mPosition) { - setChecked(isChecked); - } - } - - @Override - public void onBulkCheckedChanged() { - if(mBroker != null) setChecked(mBroker.isItemChecked(mPosition)); - } -} diff --git a/src/com/android/gallery3d/ingest/ui/MtpImageView.java b/src/com/android/gallery3d/ingest/ui/MtpImageView.java deleted file mode 100644 index 80c105126..000000000 --- a/src/com/android/gallery3d/ingest/ui/MtpImageView.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Matrix; -import android.graphics.drawable.Drawable; -import android.mtp.MtpDevice; -import android.mtp.MtpObjectInfo; -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Looper; -import android.os.Message; -import android.util.AttributeSet; -import android.widget.ImageView; - -import com.android.gallery3d.R; -import com.android.gallery3d.ingest.MtpDeviceIndex; -import com.android.gallery3d.ingest.data.BitmapWithMetadata; -import com.android.gallery3d.ingest.data.MtpBitmapFetch; - -import java.lang.ref.WeakReference; - -public class MtpImageView extends ImageView { - // We will use the thumbnail for images larger than this threshold - private static final int MAX_FULLSIZE_PREVIEW_SIZE = 8388608; // 8 megabytes - - private int mObjectHandle; - private int mGeneration; - - private WeakReference<MtpImageView> mWeakReference = new WeakReference<MtpImageView>(this); - private Object mFetchLock = new Object(); - private boolean mFetchPending = false; - private MtpObjectInfo mFetchObjectInfo; - private MtpDevice mFetchDevice; - private Object mFetchResult; - private Drawable mOverlayIcon; - private boolean mShowOverlayIcon; - - private static final FetchImageHandler sFetchHandler = FetchImageHandler.createOnNewThread(); - private static final ShowImageHandler sFetchCompleteHandler = new ShowImageHandler(); - - private void init() { - showPlaceholder(); - } - - public MtpImageView(Context context) { - super(context); - init(); - } - - public MtpImageView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public MtpImageView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - private void showPlaceholder() { - setImageResource(android.R.color.transparent); - } - - public void setMtpDeviceAndObjectInfo(MtpDevice device, MtpObjectInfo object, int gen) { - int handle = object.getObjectHandle(); - if (handle == mObjectHandle && gen == mGeneration) { - return; - } - cancelLoadingAndClear(); - showPlaceholder(); - mGeneration = gen; - mObjectHandle = handle; - mShowOverlayIcon = MtpDeviceIndex.SUPPORTED_VIDEO_FORMATS.contains(object.getFormat()); - if (mShowOverlayIcon && mOverlayIcon == null) { - mOverlayIcon = getResources().getDrawable(R.drawable.ic_control_play); - updateOverlayIconBounds(); - } - synchronized (mFetchLock) { - mFetchObjectInfo = object; - mFetchDevice = device; - if (mFetchPending) return; - mFetchPending = true; - sFetchHandler.sendMessage( - sFetchHandler.obtainMessage(0, mWeakReference)); - } - } - - protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) { - if (info.getCompressedSize() <= MAX_FULLSIZE_PREVIEW_SIZE - && MtpDeviceIndex.SUPPORTED_IMAGE_FORMATS.contains(info.getFormat())) { - return MtpBitmapFetch.getFullsize(device, info); - } else { - return new BitmapWithMetadata(MtpBitmapFetch.getThumbnail(device, info), 0); - } - } - - private float mLastBitmapWidth; - private float mLastBitmapHeight; - private int mLastRotationDegrees; - private Matrix mDrawMatrix = new Matrix(); - - private void updateDrawMatrix() { - mDrawMatrix.reset(); - float dwidth; - float dheight; - float vheight = getHeight(); - float vwidth = getWidth(); - float scale; - boolean rotated90 = (mLastRotationDegrees % 180 != 0); - if (rotated90) { - dwidth = mLastBitmapHeight; - dheight = mLastBitmapWidth; - } else { - dwidth = mLastBitmapWidth; - dheight = mLastBitmapHeight; - } - if (dwidth <= vwidth && dheight <= vheight) { - scale = 1.0f; - } else { - scale = Math.min(vwidth / dwidth, vheight / dheight); - } - mDrawMatrix.setScale(scale, scale); - if (rotated90) { - mDrawMatrix.postTranslate(-dheight * scale * 0.5f, - -dwidth * scale * 0.5f); - mDrawMatrix.postRotate(mLastRotationDegrees); - mDrawMatrix.postTranslate(dwidth * scale * 0.5f, - dheight * scale * 0.5f); - } - mDrawMatrix.postTranslate((vwidth - dwidth * scale) * 0.5f, - (vheight - dheight * scale) * 0.5f); - if (!rotated90 && mLastRotationDegrees > 0) { - // rotated by a multiple of 180 - mDrawMatrix.postRotate(mLastRotationDegrees, vwidth / 2, vheight / 2); - } - setImageMatrix(mDrawMatrix); - } - - private static final int OVERLAY_ICON_SIZE_DENOMINATOR = 4; - - private void updateOverlayIconBounds() { - int iheight = mOverlayIcon.getIntrinsicHeight(); - int iwidth = mOverlayIcon.getIntrinsicWidth(); - int vheight = getHeight(); - int vwidth = getWidth(); - float scale_height = ((float) vheight) / (iheight * OVERLAY_ICON_SIZE_DENOMINATOR); - float scale_width = ((float) vwidth) / (iwidth * OVERLAY_ICON_SIZE_DENOMINATOR); - if (scale_height >= 1f && scale_width >= 1f) { - mOverlayIcon.setBounds((vwidth - iwidth) / 2, - (vheight - iheight) / 2, - (vwidth + iwidth) / 2, - (vheight + iheight) / 2); - } else { - float scale = Math.min(scale_height, scale_width); - mOverlayIcon.setBounds((int) (vwidth - scale * iwidth) / 2, - (int) (vheight - scale * iheight) / 2, - (int) (vwidth + scale * iwidth) / 2, - (int) (vheight + scale * iheight) / 2); - } - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (changed && getScaleType() == ScaleType.MATRIX) { - updateDrawMatrix(); - } - if (mShowOverlayIcon && changed && mOverlayIcon != null) { - updateOverlayIconBounds(); - } - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - if (mShowOverlayIcon && mOverlayIcon != null) { - mOverlayIcon.draw(canvas); - } - } - - protected void onMtpImageDataFetchedFromDevice(Object result) { - BitmapWithMetadata bitmapWithMetadata = (BitmapWithMetadata)result; - if (getScaleType() == ScaleType.MATRIX) { - mLastBitmapHeight = bitmapWithMetadata.bitmap.getHeight(); - mLastBitmapWidth = bitmapWithMetadata.bitmap.getWidth(); - mLastRotationDegrees = bitmapWithMetadata.rotationDegrees; - updateDrawMatrix(); - } else { - setRotation(bitmapWithMetadata.rotationDegrees); - } - setAlpha(0f); - setImageBitmap(bitmapWithMetadata.bitmap); - animate().alpha(1f); - } - - protected void cancelLoadingAndClear() { - synchronized (mFetchLock) { - mFetchDevice = null; - mFetchObjectInfo = null; - mFetchResult = null; - } - animate().cancel(); - setImageResource(android.R.color.transparent); - } - - @Override - public void onDetachedFromWindow() { - cancelLoadingAndClear(); - super.onDetachedFromWindow(); - } - - private static class FetchImageHandler extends Handler { - public FetchImageHandler(Looper l) { - super(l); - } - - public static FetchImageHandler createOnNewThread() { - HandlerThread t = new HandlerThread("MtpImageView Fetch"); - t.start(); - return new FetchImageHandler(t.getLooper()); - } - - @Override - public void handleMessage(Message msg) { - @SuppressWarnings("unchecked") - MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get(); - if (parent == null) return; - MtpObjectInfo objectInfo; - MtpDevice device; - synchronized (parent.mFetchLock) { - parent.mFetchPending = false; - device = parent.mFetchDevice; - objectInfo = parent.mFetchObjectInfo; - } - if (device == null) return; - Object result = parent.fetchMtpImageDataFromDevice(device, objectInfo); - if (result == null) return; - synchronized (parent.mFetchLock) { - if (parent.mFetchObjectInfo != objectInfo) return; - parent.mFetchResult = result; - parent.mFetchDevice = null; - parent.mFetchObjectInfo = null; - sFetchCompleteHandler.sendMessage( - sFetchCompleteHandler.obtainMessage(0, parent.mWeakReference)); - } - } - } - - private static class ShowImageHandler extends Handler { - @Override - public void handleMessage(Message msg) { - @SuppressWarnings("unchecked") - MtpImageView parent = ((WeakReference<MtpImageView>) msg.obj).get(); - if (parent == null) return; - Object result; - synchronized (parent.mFetchLock) { - result = parent.mFetchResult; - } - if (result == null) return; - parent.onMtpImageDataFetchedFromDevice(result); - } - } -} diff --git a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java b/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java deleted file mode 100644 index 3307e78aa..000000000 --- a/src/com/android/gallery3d/ingest/ui/MtpThumbnailTileView.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ingest.ui; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.mtp.MtpDevice; -import android.mtp.MtpObjectInfo; -import android.util.AttributeSet; -import android.widget.Checkable; - -import com.android.gallery3d.R; -import com.android.gallery3d.ingest.data.MtpBitmapFetch; - - -public class MtpThumbnailTileView extends MtpImageView implements Checkable { - - private Paint mForegroundPaint; - private boolean mIsChecked; - private Bitmap mBitmap; - - private void init() { - mForegroundPaint = new Paint(); - mForegroundPaint.setColor(getResources().getColor(R.color.ingest_highlight_semitransparent)); - } - - public MtpThumbnailTileView(Context context) { - super(context); - init(); - } - - public MtpThumbnailTileView(Context context, AttributeSet attrs) { - super(context, attrs); - init(); - } - - public MtpThumbnailTileView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - init(); - } - - @Override - public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - // Force this to be square - super.onMeasure(widthMeasureSpec, widthMeasureSpec); - } - - @Override - protected Object fetchMtpImageDataFromDevice(MtpDevice device, MtpObjectInfo info) { - return MtpBitmapFetch.getThumbnail(device, info); - } - - @Override - protected void onMtpImageDataFetchedFromDevice(Object result) { - mBitmap = (Bitmap)result; - setImageBitmap(mBitmap); - } - - @Override - public void draw(Canvas canvas) { - super.draw(canvas); - if (isChecked()) { - canvas.drawRect(canvas.getClipBounds(), mForegroundPaint); - } - } - - @Override - public boolean isChecked() { - return mIsChecked; - } - - @Override - public void setChecked(boolean checked) { - mIsChecked = checked; - } - - @Override - public void toggle() { - setChecked(!mIsChecked); - } - - @Override - protected void cancelLoadingAndClear() { - super.cancelLoadingAndClear(); - if (mBitmap != null) { - MtpBitmapFetch.recycleThumbnail(mBitmap); - mBitmap = null; - } - } -} diff --git a/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java b/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java deleted file mode 100644 index ef26b1b97..000000000 --- a/src/com/android/gallery3d/onetimeinitializer/GalleryWidgetMigrator.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.onetimeinitializer; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Build; -import android.os.Environment; -import android.preference.PreferenceManager; -import android.util.Log; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.LocalAlbum; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.gadget.WidgetDatabaseHelper; -import com.android.gallery3d.gadget.WidgetDatabaseHelper.Entry; -import com.android.gallery3d.util.GalleryUtils; - -import java.io.File; -import java.util.HashMap; -import java.util.List; - -/** - * This one-timer migrates local-album gallery app widgets from old paths from prior releases - * to updated paths in the current build version. This migration is needed because of - * bucket ID (i.e., directory hash) change in JB and JB MR1 (The external storage path has changed - * from /mnt/sdcard in pre-JB releases, to /storage/sdcard0 in JB, then again - * to /external/storage/sdcard/0 in JB MR1). - */ -public class GalleryWidgetMigrator { - private static final String TAG = "GalleryWidgetMigrator"; - private static final String PRE_JB_EXT_PATH = "/mnt/sdcard"; - private static final String JB_EXT_PATH = "/storage/sdcard0"; - private static final String NEW_EXT_PATH = - Environment.getExternalStorageDirectory().getAbsolutePath(); - private static final int RELATIVE_PATH_START = NEW_EXT_PATH.length(); - private static final String KEY_EXT_PATH = "external_storage_path"; - - /** - * Migrates local-album gallery widgets from prior releases to current release - * due to bucket ID (i.e., directory hash) change. - */ - public static void migrateGalleryWidgets(Context context) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - // Migration is only needed when external storage path has changed - String extPath = prefs.getString(KEY_EXT_PATH, null); - boolean isDone = NEW_EXT_PATH.equals(extPath); - if (isDone) return; - - try { - migrateGalleryWidgetsInternal(context); - prefs.edit().putString(KEY_EXT_PATH, NEW_EXT_PATH).commit(); - } catch (Throwable t) { - // exception may be thrown if external storage is not available(?) - Log.w(TAG, "migrateGalleryWidgets", t); - } - } - - private static void migrateGalleryWidgetsInternal(Context context) { - GalleryApp galleryApp = (GalleryApp) context.getApplicationContext(); - DataManager manager = galleryApp.getDataManager(); - WidgetDatabaseHelper dbHelper = new WidgetDatabaseHelper(context); - - // only need to migrate local-album entries of type TYPE_ALBUM - List<Entry> entries = dbHelper.getEntries(WidgetDatabaseHelper.TYPE_ALBUM); - if (entries == null) return; - - // Check each entry's relativePath. If exists, update bucket id using relative - // path combined with external storage path. Otherwise, iterate through old external - // storage paths to find the relative path that matches the old bucket id, and then update - // bucket id and relative path - HashMap<Integer, Entry> localEntries = new HashMap<Integer, Entry>(entries.size()); - for (Entry entry : entries) { - Path path = Path.fromString(entry.albumPath); - MediaSet mediaSet = (MediaSet) manager.getMediaObject(path); - if (mediaSet instanceof LocalAlbum) { - if (entry.relativePath != null && entry.relativePath.length() > 0) { - // update entry using relative path + external storage path - updateEntryUsingRelativePath(entry, dbHelper); - } else { - int bucketId = Integer.parseInt(path.getSuffix()); - localEntries.put(bucketId, entry); - } - } - } - if (!localEntries.isEmpty()) migrateLocalEntries(context, localEntries, dbHelper); - } - - private static void migrateLocalEntries(Context context, - HashMap<Integer, Entry> entries, WidgetDatabaseHelper dbHelper) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - String oldExtPath = prefs.getString(KEY_EXT_PATH, null); - if (oldExtPath != null) { - migrateLocalEntries(entries, dbHelper, oldExtPath); - return; - } - // If old external storage path is unknown, it could be either Pre-JB or JB version - // we need to try both. - migrateLocalEntries(entries, dbHelper, PRE_JB_EXT_PATH); - if (!entries.isEmpty() && - Build.VERSION.SDK_INT > ApiHelper.VERSION_CODES.JELLY_BEAN) { - migrateLocalEntries(entries, dbHelper, JB_EXT_PATH); - } - } - - private static void migrateLocalEntries(HashMap<Integer, Entry> entries, - WidgetDatabaseHelper dbHelper, String oldExtPath) { - File root = Environment.getExternalStorageDirectory(); - // check the DCIM directory first; this should take care of 99% use cases - updatePath(new File(root, "DCIM"), entries, dbHelper, oldExtPath); - // check other directories if DCIM doesn't cut it - if (!entries.isEmpty()) updatePath(root, entries, dbHelper, oldExtPath); - } - private static void updatePath(File root, HashMap<Integer, Entry> entries, - WidgetDatabaseHelper dbHelper, String oldExtStorage) { - File[] files = root.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory() && !entries.isEmpty()) { - String path = file.getAbsolutePath(); - String oldPath = oldExtStorage + path.substring(RELATIVE_PATH_START); - int oldBucketId = GalleryUtils.getBucketId(oldPath); - Entry entry = entries.remove(oldBucketId); - if (entry != null) { - int newBucketId = GalleryUtils.getBucketId(path); - String newAlbumPath = Path.fromString(entry.albumPath) - .getParent() - .getChild(newBucketId) - .toString(); - Log.d(TAG, "migrate from " + entry.albumPath + " to " + newAlbumPath); - entry.albumPath = newAlbumPath; - // update entry's relative path - entry.relativePath = path.substring(RELATIVE_PATH_START); - dbHelper.updateEntry(entry); - } - updatePath(file, entries, dbHelper, oldExtStorage); // recursion - } - } - } - } - - private static void updateEntryUsingRelativePath(Entry entry, WidgetDatabaseHelper dbHelper) { - String newPath = NEW_EXT_PATH + entry.relativePath; - int newBucketId = GalleryUtils.getBucketId(newPath); - String newAlbumPath = Path.fromString(entry.albumPath) - .getParent() - .getChild(newBucketId) - .toString(); - entry.albumPath = newAlbumPath; - dbHelper.updateEntry(entry); - } -} diff --git a/src/com/android/gallery3d/provider/GalleryProvider.java b/src/com/android/gallery3d/provider/GalleryProvider.java deleted file mode 100644 index d6c7ccd4d..000000000 --- a/src/com/android/gallery3d/provider/GalleryProvider.java +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2009 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.provider; - -import android.content.ContentProvider; -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.net.Uri; -import android.os.AsyncTask; -import android.os.Binder; -import android.os.ParcelFileDescriptor; -import android.provider.MediaStore.Images.ImageColumns; -import android.util.Log; - -import com.android.gallery3d.app.GalleryApp; -import com.android.gallery3d.common.AsyncTaskUtil; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.picasasource.PicasaSource; -import com.android.gallery3d.util.GalleryUtils; - -import java.io.FileNotFoundException; -import java.io.IOException; - -public class GalleryProvider extends ContentProvider { - private static final String TAG = "GalleryProvider"; - - public static final String AUTHORITY = "com.android.gallery3d.provider"; - public static final Uri BASE_URI = Uri.parse("content://" + AUTHORITY); - - public static interface PicasaColumns { - public static final String USER_ACCOUNT = "user_account"; - public static final String PICASA_ID = "picasa_id"; - } - - private static final String[] SUPPORTED_PICASA_COLUMNS = { - PicasaColumns.USER_ACCOUNT, - PicasaColumns.PICASA_ID, - ImageColumns.DISPLAY_NAME, - ImageColumns.SIZE, - ImageColumns.MIME_TYPE, - ImageColumns.DATE_TAKEN, - ImageColumns.LATITUDE, - ImageColumns.LONGITUDE, - ImageColumns.ORIENTATION}; - - private DataManager mDataManager; - private static Uri sBaseUri; - - public static String getAuthority(Context context) { - return context.getPackageName() + ".provider"; - } - - public static Uri getUriFor(Context context, Path path) { - if (sBaseUri == null) { - sBaseUri = Uri.parse("content://" + context.getPackageName() + ".provider"); - } - return sBaseUri.buildUpon() - .appendEncodedPath(path.toString().substring(1)) // ignore the leading '/' - .build(); - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException(); - } - - // TODO: consider concurrent access - @Override - public String getType(Uri uri) { - long token = Binder.clearCallingIdentity(); - try { - Path path = Path.fromString(uri.getPath()); - MediaItem item = (MediaItem) mDataManager.getMediaObject(path); - return item != null ? item.getMimeType() : null; - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - throw new UnsupportedOperationException(); - } - - @Override - public boolean onCreate() { - GalleryApp app = (GalleryApp) getContext().getApplicationContext(); - mDataManager = app.getDataManager(); - return true; - } - - // TODO: consider concurrent access - @Override - public Cursor query(Uri uri, String[] projection, - String selection, String[] selectionArgs, String sortOrder) { - long token = Binder.clearCallingIdentity(); - try { - Path path = Path.fromString(uri.getPath()); - MediaObject object = mDataManager.getMediaObject(path); - if (object == null) { - Log.w(TAG, "cannot find: " + uri); - return null; - } - if (PicasaSource.isPicasaImage(object)) { - return queryPicasaItem(object, - projection, selection, selectionArgs, sortOrder); - } else { - return null; - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - private Cursor queryPicasaItem(MediaObject image, String[] projection, - String selection, String[] selectionArgs, String sortOrder) { - if (projection == null) projection = SUPPORTED_PICASA_COLUMNS; - Object[] columnValues = new Object[projection.length]; - double latitude = PicasaSource.getLatitude(image); - double longitude = PicasaSource.getLongitude(image); - boolean isValidLatlong = GalleryUtils.isValidLocation(latitude, longitude); - - for (int i = 0, n = projection.length; i < n; ++i) { - String column = projection[i]; - if (PicasaColumns.USER_ACCOUNT.equals(column)) { - columnValues[i] = PicasaSource.getUserAccount(getContext(), image); - } else if (PicasaColumns.PICASA_ID.equals(column)) { - columnValues[i] = PicasaSource.getPicasaId(image); - } else if (ImageColumns.DISPLAY_NAME.equals(column)) { - columnValues[i] = PicasaSource.getImageTitle(image); - } else if (ImageColumns.SIZE.equals(column)){ - columnValues[i] = PicasaSource.getImageSize(image); - } else if (ImageColumns.MIME_TYPE.equals(column)) { - columnValues[i] = PicasaSource.getContentType(image); - } else if (ImageColumns.DATE_TAKEN.equals(column)) { - columnValues[i] = PicasaSource.getDateTaken(image); - } else if (ImageColumns.LATITUDE.equals(column)) { - columnValues[i] = isValidLatlong ? latitude : null; - } else if (ImageColumns.LONGITUDE.equals(column)) { - columnValues[i] = isValidLatlong ? longitude : null; - } else if (ImageColumns.ORIENTATION.equals(column)) { - columnValues[i] = PicasaSource.getRotation(image); - } else { - Log.w(TAG, "unsupported column: " + column); - } - } - MatrixCursor cursor = new MatrixCursor(projection); - cursor.addRow(columnValues); - return cursor; - } - - @Override - public ParcelFileDescriptor openFile(Uri uri, String mode) - throws FileNotFoundException { - long token = Binder.clearCallingIdentity(); - try { - if (mode.contains("w")) { - throw new FileNotFoundException("cannot open file for write"); - } - Path path = Path.fromString(uri.getPath()); - MediaObject object = mDataManager.getMediaObject(path); - if (object == null) { - throw new FileNotFoundException(uri.toString()); - } - if (PicasaSource.isPicasaImage(object)) { - return PicasaSource.openFile(getContext(), object, mode); - } else { - throw new FileNotFoundException("unspported type: " + object); - } - } finally { - Binder.restoreCallingIdentity(token); - } - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - throw new UnsupportedOperationException(); - } - - private static interface PipeDataWriter<T> { - void writeDataToPipe(ParcelFileDescriptor output, T args); - } - - // Modified from ContentProvider.openPipeHelper. We are target at API LEVEL 10. - // But openPipeHelper is available in API LEVEL 11. - private static <T> ParcelFileDescriptor openPipeHelper( - final T args, final PipeDataWriter<T> func) throws FileNotFoundException { - try { - final ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); - AsyncTask<Object, Object, Object> task = new AsyncTask<Object, Object, Object>() { - @Override - protected Object doInBackground(Object... params) { - try { - func.writeDataToPipe(pipe[1], args); - return null; - } finally { - Utils.closeSilently(pipe[1]); - } - } - }; - AsyncTaskUtil.executeInParallel(task, (Object[]) null); - return pipe[0]; - } catch (IOException e) { - throw new FileNotFoundException("failure making pipe"); - } - } - -} diff --git a/src/com/android/gallery3d/ui/AbstractSlotRenderer.java b/src/com/android/gallery3d/ui/AbstractSlotRenderer.java deleted file mode 100644 index 729439dc3..000000000 --- a/src/com/android/gallery3d/ui/AbstractSlotRenderer.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Rect; - -import com.android.gallery3d.R; -import com.android.gallery3d.glrenderer.FadeOutTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.NinePatchTexture; -import com.android.gallery3d.glrenderer.ResourceTexture; -import com.android.gallery3d.glrenderer.Texture; - -public abstract class AbstractSlotRenderer implements SlotView.SlotRenderer { - - private final ResourceTexture mVideoOverlay; - private final ResourceTexture mVideoPlayIcon; - private final ResourceTexture mPanoramaIcon; - private final NinePatchTexture mFramePressed; - private final NinePatchTexture mFrameSelected; - private FadeOutTexture mFramePressedUp; - - protected AbstractSlotRenderer(Context context) { - mVideoOverlay = new ResourceTexture(context, R.drawable.ic_video_thumb); - mVideoPlayIcon = new ResourceTexture(context, R.drawable.ic_gallery_play); - mPanoramaIcon = new ResourceTexture(context, R.drawable.ic_360pano_holo_light); - mFramePressed = new NinePatchTexture(context, R.drawable.grid_pressed); - mFrameSelected = new NinePatchTexture(context, R.drawable.grid_selected); - } - - protected void drawContent(GLCanvas canvas, - Texture content, int width, int height, int rotation) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - - // The content is always rendered in to the largest square that fits - // inside the slot, aligned to the top of the slot. - width = height = Math.min(width, height); - if (rotation != 0) { - canvas.translate(width / 2, height / 2); - canvas.rotate(rotation, 0, 0, 1); - canvas.translate(-width / 2, -height / 2); - } - - // Fit the content into the box - float scale = Math.min( - (float) width / content.getWidth(), - (float) height / content.getHeight()); - canvas.scale(scale, scale, 1); - content.draw(canvas, 0, 0); - - canvas.restore(); - } - - protected void drawVideoOverlay(GLCanvas canvas, int width, int height) { - // Scale the video overlay to the height of the thumbnail and put it - // on the left side. - ResourceTexture v = mVideoOverlay; - float scale = (float) height / v.getHeight(); - int w = Math.round(scale * v.getWidth()); - int h = Math.round(scale * v.getHeight()); - v.draw(canvas, 0, 0, w, h); - - int s = Math.min(width, height) / 6; - mVideoPlayIcon.draw(canvas, (width - s) / 2, (height - s) / 2, s, s); - } - - protected void drawPanoramaIcon(GLCanvas canvas, int width, int height) { - int iconSize = Math.min(width, height) / 6; - mPanoramaIcon.draw(canvas, (width - iconSize) / 2, (height - iconSize) / 2, - iconSize, iconSize); - } - - protected boolean isPressedUpFrameFinished() { - if (mFramePressedUp != null) { - if (mFramePressedUp.isAnimating()) { - return false; - } else { - mFramePressedUp = null; - } - } - return true; - } - - protected void drawPressedUpFrame(GLCanvas canvas, int width, int height) { - if (mFramePressedUp == null) { - mFramePressedUp = new FadeOutTexture(mFramePressed); - } - drawFrame(canvas, mFramePressed.getPaddings(), mFramePressedUp, 0, 0, width, height); - } - - protected void drawPressedFrame(GLCanvas canvas, int width, int height) { - drawFrame(canvas, mFramePressed.getPaddings(), mFramePressed, 0, 0, width, height); - } - - protected void drawSelectedFrame(GLCanvas canvas, int width, int height) { - drawFrame(canvas, mFrameSelected.getPaddings(), mFrameSelected, 0, 0, width, height); - } - - protected static void drawFrame(GLCanvas canvas, Rect padding, Texture frame, - int x, int y, int width, int height) { - frame.draw(canvas, x - padding.left, y - padding.top, width + padding.left + padding.right, - height + padding.top + padding.bottom); - } -} diff --git a/src/com/android/gallery3d/ui/ActionModeHandler.java b/src/com/android/gallery3d/ui/ActionModeHandler.java deleted file mode 100644 index 6b4f10312..000000000 --- a/src/com/android/gallery3d/ui/ActionModeHandler.java +++ /dev/null @@ -1,501 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.annotation.TargetApi; -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.nfc.NfcAdapter; -import android.os.Handler; -import android.view.ActionMode; -import android.view.ActionMode.Callback; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.widget.Button; -import android.widget.ShareActionProvider; -import android.widget.ShareActionProvider.OnShareTargetSelectedListener; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.ui.MenuExecutor.ProgressListener; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; - -public class ActionModeHandler implements Callback, PopupList.OnPopupItemClickListener { - - @SuppressWarnings("unused") - private static final String TAG = "ActionModeHandler"; - - private static final int MAX_SELECTED_ITEMS_FOR_SHARE_INTENT = 300; - private static final int MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT = 10; - - private static final int SUPPORT_MULTIPLE_MASK = MediaObject.SUPPORT_DELETE - | MediaObject.SUPPORT_ROTATE | MediaObject.SUPPORT_SHARE - | MediaObject.SUPPORT_CACHE; - - public interface ActionModeListener { - public boolean onActionItemClicked(MenuItem item); - } - - private final AbstractGalleryActivity mActivity; - private final MenuExecutor mMenuExecutor; - private final SelectionManager mSelectionManager; - private final NfcAdapter mNfcAdapter; - private Menu mMenu; - private MenuItem mSharePanoramaMenuItem; - private MenuItem mShareMenuItem; - private ShareActionProvider mSharePanoramaActionProvider; - private ShareActionProvider mShareActionProvider; - private SelectionMenu mSelectionMenu; - private ActionModeListener mListener; - private Future<?> mMenuTask; - private final Handler mMainHandler; - private ActionMode mActionMode; - - private static class GetAllPanoramaSupports implements PanoramaSupportCallback { - private int mNumInfoRequired; - private JobContext mJobContext; - public boolean mAllPanoramas = true; - public boolean mAllPanorama360 = true; - public boolean mHasPanorama360 = false; - private Object mLock = new Object(); - - public GetAllPanoramaSupports(ArrayList<MediaObject> mediaObjects, JobContext jc) { - mJobContext = jc; - mNumInfoRequired = mediaObjects.size(); - for (MediaObject mediaObject : mediaObjects) { - mediaObject.getPanoramaSupport(this); - } - } - - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - synchronized (mLock) { - mNumInfoRequired--; - mAllPanoramas = isPanorama && mAllPanoramas; - mAllPanorama360 = isPanorama360 && mAllPanorama360; - mHasPanorama360 = mHasPanorama360 || isPanorama360; - if (mNumInfoRequired == 0 || mJobContext.isCancelled()) { - mLock.notifyAll(); - } - } - } - - public void waitForPanoramaSupport() { - synchronized (mLock) { - while (mNumInfoRequired != 0 && !mJobContext.isCancelled()) { - try { - mLock.wait(); - } catch (InterruptedException e) { - // May be a cancelled job context - } - } - } - } - } - - public ActionModeHandler( - AbstractGalleryActivity activity, SelectionManager selectionManager) { - mActivity = Utils.checkNotNull(activity); - mSelectionManager = Utils.checkNotNull(selectionManager); - mMenuExecutor = new MenuExecutor(activity, selectionManager); - mMainHandler = new Handler(activity.getMainLooper()); - mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity.getAndroidContext()); - } - - public void startActionMode() { - Activity a = mActivity; - mActionMode = a.startActionMode(this); - View customView = LayoutInflater.from(a).inflate( - R.layout.action_mode, null); - mActionMode.setCustomView(customView); - mSelectionMenu = new SelectionMenu(a, - (Button) customView.findViewById(R.id.selection_menu), this); - updateSelectionMenu(); - } - - public void finishActionMode() { - mActionMode.finish(); - } - - public void setTitle(String title) { - mSelectionMenu.setTitle(title); - } - - public void setActionModeListener(ActionModeListener listener) { - mListener = listener; - } - - private WakeLockHoldingProgressListener mDeleteProgressListener; - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - boolean result; - // Give listener a chance to process this command before it's routed to - // ActionModeHandler, which handles command only based on the action id. - // Sometimes the listener may have more background information to handle - // an action command. - if (mListener != null) { - result = mListener.onActionItemClicked(item); - if (result) { - mSelectionManager.leaveSelectionMode(); - return result; - } - } - ProgressListener listener = null; - String confirmMsg = null; - int action = item.getItemId(); - if (action == R.id.action_delete) { - confirmMsg = mActivity.getResources().getQuantityString( - R.plurals.delete_selection, mSelectionManager.getSelectedCount()); - if (mDeleteProgressListener == null) { - mDeleteProgressListener = new WakeLockHoldingProgressListener(mActivity, - "Gallery Delete Progress Listener"); - } - listener = mDeleteProgressListener; - } - mMenuExecutor.onMenuClicked(item, confirmMsg, listener); - } finally { - root.unlockRenderThread(); - } - return true; - } - - @Override - public boolean onPopupItemClick(int itemId) { - GLRoot root = mActivity.getGLRoot(); - root.lockRenderThread(); - try { - if (itemId == R.id.action_select_all) { - updateSupportedOperation(); - mMenuExecutor.onMenuClicked(itemId, null, false, true); - } - return true; - } finally { - root.unlockRenderThread(); - } - } - - private void updateSelectionMenu() { - // update title - int count = mSelectionManager.getSelectedCount(); - String format = mActivity.getResources().getQuantityString( - R.plurals.number_of_items_selected, count); - setTitle(String.format(format, count)); - - // For clients who call SelectionManager.selectAll() directly, we need to ensure the - // menu status is consistent with selection manager. - mSelectionMenu.updateSelectAllMode(mSelectionManager.inSelectAllMode()); - } - - private final OnShareTargetSelectedListener mShareTargetSelectedListener = - new OnShareTargetSelectedListener() { - @Override - public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) { - mSelectionManager.leaveSelectionMode(); - return false; - } - }; - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - return false; - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - mode.getMenuInflater().inflate(R.menu.operation, menu); - - mMenu = menu; - mSharePanoramaMenuItem = menu.findItem(R.id.action_share_panorama); - if (mSharePanoramaMenuItem != null) { - mSharePanoramaActionProvider = (ShareActionProvider) mSharePanoramaMenuItem - .getActionProvider(); - mSharePanoramaActionProvider.setOnShareTargetSelectedListener( - mShareTargetSelectedListener); - mSharePanoramaActionProvider.setShareHistoryFileName("panorama_share_history.xml"); - } - mShareMenuItem = menu.findItem(R.id.action_share); - if (mShareMenuItem != null) { - mShareActionProvider = (ShareActionProvider) mShareMenuItem - .getActionProvider(); - mShareActionProvider.setOnShareTargetSelectedListener( - mShareTargetSelectedListener); - mShareActionProvider.setShareHistoryFileName("share_history.xml"); - } - return true; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - mSelectionManager.leaveSelectionMode(); - } - - private ArrayList<MediaObject> getSelectedMediaObjects(JobContext jc) { - ArrayList<Path> unexpandedPaths = mSelectionManager.getSelected(false); - if (unexpandedPaths.isEmpty()) { - // This happens when starting selection mode from overflow menu - // (instead of long press a media object) - return null; - } - ArrayList<MediaObject> selected = new ArrayList<MediaObject>(); - DataManager manager = mActivity.getDataManager(); - for (Path path : unexpandedPaths) { - if (jc.isCancelled()) { - return null; - } - selected.add(manager.getMediaObject(path)); - } - - return selected; - } - // Menu options are determined by selection set itself. - // We cannot expand it because MenuExecuter executes it based on - // the selection set instead of the expanded result. - // e.g. LocalImage can be rotated but collections of them (LocalAlbum) can't. - private int computeMenuOptions(ArrayList<MediaObject> selected) { - int operation = MediaObject.SUPPORT_ALL; - int type = 0; - for (MediaObject mediaObject: selected) { - int support = mediaObject.getSupportedOperations(); - type |= mediaObject.getMediaType(); - operation &= support; - } - - switch (selected.size()) { - case 1: - final String mimeType = MenuExecutor.getMimeType(type); - if (!GalleryUtils.isEditorAvailable(mActivity, mimeType)) { - operation &= ~MediaObject.SUPPORT_EDIT; - } - break; - default: - operation &= SUPPORT_MULTIPLE_MASK; - } - - return operation; - } - - @TargetApi(ApiHelper.VERSION_CODES.JELLY_BEAN) - private void setNfcBeamPushUris(Uri[] uris) { - if (mNfcAdapter != null && ApiHelper.HAS_SET_BEAM_PUSH_URIS) { - mNfcAdapter.setBeamPushUrisCallback(null, mActivity); - mNfcAdapter.setBeamPushUris(uris, mActivity); - } - } - - // Share intent needs to expand the selection set so we can get URI of - // each media item - private Intent computePanoramaSharingIntent(JobContext jc, int maxItems) { - ArrayList<Path> expandedPaths = mSelectionManager.getSelected(true, maxItems); - if (expandedPaths == null || expandedPaths.size() == 0) { - return new Intent(); - } - final ArrayList<Uri> uris = new ArrayList<Uri>(); - DataManager manager = mActivity.getDataManager(); - final Intent intent = new Intent(); - for (Path path : expandedPaths) { - if (jc.isCancelled()) return null; - uris.add(manager.getContentUri(path)); - } - - final int size = uris.size(); - if (size > 0) { - if (size > 1) { - intent.setAction(Intent.ACTION_SEND_MULTIPLE); - intent.setType(GalleryUtils.MIME_TYPE_PANORAMA360); - intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); - } else { - intent.setAction(Intent.ACTION_SEND); - intent.setType(GalleryUtils.MIME_TYPE_PANORAMA360); - intent.putExtra(Intent.EXTRA_STREAM, uris.get(0)); - } - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - } - - return intent; - } - - private Intent computeSharingIntent(JobContext jc, int maxItems) { - ArrayList<Path> expandedPaths = mSelectionManager.getSelected(true, maxItems); - if (expandedPaths == null || expandedPaths.size() == 0) { - setNfcBeamPushUris(null); - return new Intent(); - } - final ArrayList<Uri> uris = new ArrayList<Uri>(); - DataManager manager = mActivity.getDataManager(); - int type = 0; - final Intent intent = new Intent(); - for (Path path : expandedPaths) { - if (jc.isCancelled()) return null; - int support = manager.getSupportedOperations(path); - type |= manager.getMediaType(path); - - if ((support & MediaObject.SUPPORT_SHARE) != 0) { - uris.add(manager.getContentUri(path)); - } - } - - final int size = uris.size(); - if (size > 0) { - final String mimeType = MenuExecutor.getMimeType(type); - if (size > 1) { - intent.setAction(Intent.ACTION_SEND_MULTIPLE).setType(mimeType); - intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris); - } else { - intent.setAction(Intent.ACTION_SEND).setType(mimeType); - intent.putExtra(Intent.EXTRA_STREAM, uris.get(0)); - } - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - setNfcBeamPushUris(uris.toArray(new Uri[uris.size()])); - } else { - setNfcBeamPushUris(null); - } - - return intent; - } - - public void updateSupportedOperation(Path path, boolean selected) { - // TODO: We need to improve the performance - updateSupportedOperation(); - } - - public void updateSupportedOperation() { - // Interrupt previous unfinished task, mMenuTask is only accessed in main thread - if (mMenuTask != null) mMenuTask.cancel(); - - updateSelectionMenu(); - - // Disable share actions until share intent is in good shape - if (mSharePanoramaMenuItem != null) mSharePanoramaMenuItem.setEnabled(false); - if (mShareMenuItem != null) mShareMenuItem.setEnabled(false); - - // Generate sharing intent and update supported operations in the background - // The task can take a long time and be canceled in the mean time. - mMenuTask = mActivity.getThreadPool().submit(new Job<Void>() { - @Override - public Void run(final JobContext jc) { - // Pass1: Deal with unexpanded media object list for menu operation. - ArrayList<MediaObject> selected = getSelectedMediaObjects(jc); - if (selected == null) { - mMainHandler.post(new Runnable() { - @Override - public void run() { - mMenuTask = null; - if (jc.isCancelled()) return; - // Disable all the operations when no item is selected - MenuExecutor.updateMenuOperation(mMenu, 0); - } - }); - return null; - } - final int operation = computeMenuOptions(selected); - if (jc.isCancelled()) { - return null; - } - int numSelected = selected.size(); - final boolean canSharePanoramas = - numSelected < MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT; - final boolean canShare = - numSelected < MAX_SELECTED_ITEMS_FOR_SHARE_INTENT; - - final GetAllPanoramaSupports supportCallback = canSharePanoramas ? - new GetAllPanoramaSupports(selected, jc) - : null; - - // Pass2: Deal with expanded media object list for sharing operation. - final Intent share_panorama_intent = canSharePanoramas ? - computePanoramaSharingIntent(jc, MAX_SELECTED_ITEMS_FOR_PANORAMA_SHARE_INTENT) - : new Intent(); - final Intent share_intent = canShare ? - computeSharingIntent(jc, MAX_SELECTED_ITEMS_FOR_SHARE_INTENT) - : new Intent(); - - if (canSharePanoramas) { - supportCallback.waitForPanoramaSupport(); - } - if (jc.isCancelled()) { - return null; - } - mMainHandler.post(new Runnable() { - @Override - public void run() { - mMenuTask = null; - if (jc.isCancelled()) return; - MenuExecutor.updateMenuOperation(mMenu, operation); - MenuExecutor.updateMenuForPanorama(mMenu, - canSharePanoramas && supportCallback.mAllPanorama360, - canSharePanoramas && supportCallback.mHasPanorama360); - if (mSharePanoramaMenuItem != null) { - mSharePanoramaMenuItem.setEnabled(true); - if (canSharePanoramas && supportCallback.mAllPanorama360) { - mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); - mShareMenuItem.setTitle( - mActivity.getResources().getString(R.string.share_as_photo)); - } else { - mSharePanoramaMenuItem.setVisible(false); - mShareMenuItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM); - mShareMenuItem.setTitle( - mActivity.getResources().getString(R.string.share)); - } - mSharePanoramaActionProvider.setShareIntent(share_panorama_intent); - } - if (mShareMenuItem != null) { - mShareMenuItem.setEnabled(canShare); - mShareActionProvider.setShareIntent(share_intent); - } - } - }); - return null; - } - }); - } - - public void pause() { - if (mMenuTask != null) { - mMenuTask.cancel(); - mMenuTask = null; - } - mMenuExecutor.pause(); - } - - public void destroy() { - mMenuExecutor.destroy(); - } - - public void resume() { - if (mSelectionManager.inSelectionMode()) updateSupportedOperation(); - mMenuExecutor.resume(); - } -} diff --git a/src/com/android/gallery3d/ui/AlbumLabelMaker.java b/src/com/android/gallery3d/ui/AlbumLabelMaker.java deleted file mode 100644 index da1cac0bd..000000000 --- a/src/com/android/gallery3d/ui/AlbumLabelMaker.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.PorterDuff; -import android.graphics.Typeface; -import android.text.TextPaint; -import android.text.TextUtils; - -import com.android.gallery3d.R; -import com.android.gallery3d.data.DataSourceType; -import com.android.photos.data.GalleryBitmapPool; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.JobContext; - -public class AlbumLabelMaker { - private static final int BORDER_SIZE = 0; - - private final AlbumSetSlotRenderer.LabelSpec mSpec; - private final TextPaint mTitlePaint; - private final TextPaint mCountPaint; - private final Context mContext; - - private int mLabelWidth; - private int mBitmapWidth; - private int mBitmapHeight; - - private final LazyLoadedBitmap mLocalSetIcon; - private final LazyLoadedBitmap mPicasaIcon; - private final LazyLoadedBitmap mCameraIcon; - - public AlbumLabelMaker(Context context, AlbumSetSlotRenderer.LabelSpec spec) { - mContext = context; - mSpec = spec; - mTitlePaint = getTextPaint(spec.titleFontSize, spec.titleColor, false); - mCountPaint = getTextPaint(spec.countFontSize, spec.countColor, false); - - mLocalSetIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_folder); - mPicasaIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_picasa); - mCameraIcon = new LazyLoadedBitmap(R.drawable.frame_overlay_gallery_camera); - } - - public static int getBorderSize() { - return BORDER_SIZE; - } - - private Bitmap getOverlayAlbumIcon(int sourceType) { - switch (sourceType) { - case DataSourceType.TYPE_CAMERA: - return mCameraIcon.get(); - case DataSourceType.TYPE_LOCAL: - return mLocalSetIcon.get(); - case DataSourceType.TYPE_PICASA: - return mPicasaIcon.get(); - } - return null; - } - - private static TextPaint getTextPaint(int textSize, int color, boolean isBold) { - TextPaint paint = new TextPaint(); - paint.setTextSize(textSize); - paint.setAntiAlias(true); - paint.setColor(color); - //paint.setShadowLayer(2f, 0f, 0f, Color.LTGRAY); - if (isBold) { - paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); - } - return paint; - } - - private class LazyLoadedBitmap { - private Bitmap mBitmap; - private int mResId; - - public LazyLoadedBitmap(int resId) { - mResId = resId; - } - - public synchronized Bitmap get() { - if (mBitmap == null) { - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - mBitmap = BitmapFactory.decodeResource( - mContext.getResources(), mResId, options); - } - return mBitmap; - } - } - - public synchronized void setLabelWidth(int width) { - if (mLabelWidth == width) return; - mLabelWidth = width; - int borders = 2 * BORDER_SIZE; - mBitmapWidth = width + borders; - mBitmapHeight = mSpec.labelBackgroundHeight + borders; - } - - public ThreadPool.Job<Bitmap> requestLabel( - String title, String count, int sourceType) { - return new AlbumLabelJob(title, count, sourceType); - } - - static void drawText(Canvas canvas, - int x, int y, String text, int lengthLimit, TextPaint p) { - // The TextPaint cannot be used concurrently - synchronized (p) { - text = TextUtils.ellipsize( - text, p, lengthLimit, TextUtils.TruncateAt.END).toString(); - canvas.drawText(text, x, y - p.getFontMetricsInt().ascent, p); - } - } - - private class AlbumLabelJob implements ThreadPool.Job<Bitmap> { - private final String mTitle; - private final String mCount; - private final int mSourceType; - - public AlbumLabelJob(String title, String count, int sourceType) { - mTitle = title; - mCount = count; - mSourceType = sourceType; - } - - @Override - public Bitmap run(JobContext jc) { - AlbumSetSlotRenderer.LabelSpec s = mSpec; - - String title = mTitle; - String count = mCount; - Bitmap icon = getOverlayAlbumIcon(mSourceType); - - Bitmap bitmap; - int labelWidth; - - synchronized (this) { - labelWidth = mLabelWidth; - bitmap = GalleryBitmapPool.getInstance().get(mBitmapWidth, mBitmapHeight); - } - - if (bitmap == null) { - int borders = 2 * BORDER_SIZE; - bitmap = Bitmap.createBitmap(labelWidth + borders, - s.labelBackgroundHeight + borders, Config.ARGB_8888); - } - - Canvas canvas = new Canvas(bitmap); - canvas.clipRect(BORDER_SIZE, BORDER_SIZE, - bitmap.getWidth() - BORDER_SIZE, - bitmap.getHeight() - BORDER_SIZE); - canvas.drawColor(mSpec.backgroundColor, PorterDuff.Mode.SRC); - - canvas.translate(BORDER_SIZE, BORDER_SIZE); - - // draw title - if (jc.isCancelled()) return null; - int x = s.leftMargin + s.iconSize; - // TODO: is the offset relevant in new reskin? - // int y = s.titleOffset; - int y = (s.labelBackgroundHeight - s.titleFontSize) / 2; - drawText(canvas, x, y, title, labelWidth - s.leftMargin - x - - s.titleRightMargin, mTitlePaint); - - // draw count - if (jc.isCancelled()) return null; - x = labelWidth - s.titleRightMargin; - y = (s.labelBackgroundHeight - s.countFontSize) / 2; - drawText(canvas, x, y, count, - labelWidth - x , mCountPaint); - - // draw the icon - if (icon != null) { - if (jc.isCancelled()) return null; - float scale = (float) s.iconSize / icon.getWidth(); - canvas.translate(s.leftMargin, (s.labelBackgroundHeight - - Math.round(scale * icon.getHeight()))/2f); - canvas.scale(scale, scale); - canvas.drawBitmap(icon, 0, 0, null); - } - - return bitmap; - } - } - - public void recycleLabel(Bitmap label) { - GalleryBitmapPool.getInstance().put(label); - } -} diff --git a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java deleted file mode 100644 index 8149df4b3..000000000 --- a/src/com/android/gallery3d/ui/AlbumSetSlidingWindow.java +++ /dev/null @@ -1,549 +0,0 @@ -/*T - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Bitmap; -import android.os.Message; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.app.AlbumSetDataLoader; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataSourceType; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.BitmapTexture; -import com.android.gallery3d.glrenderer.Texture; -import com.android.gallery3d.glrenderer.TextureUploader; -import com.android.gallery3d.glrenderer.TiledTexture; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; - -public class AlbumSetSlidingWindow implements AlbumSetDataLoader.DataListener { - private static final String TAG = "AlbumSetSlidingWindow"; - private static final int MSG_UPDATE_ALBUM_ENTRY = 1; - - public static interface Listener { - public void onSizeChanged(int size); - public void onContentChanged(); - } - - private final AlbumSetDataLoader mSource; - private int mSize; - - private int mContentStart = 0; - private int mContentEnd = 0; - - private int mActiveStart = 0; - private int mActiveEnd = 0; - - private Listener mListener; - - private final AlbumSetEntry mData[]; - private final SynchronizedHandler mHandler; - private final ThreadPool mThreadPool; - private final AlbumLabelMaker mLabelMaker; - private final String mLoadingText; - - private final TiledTexture.Uploader mContentUploader; - private final TextureUploader mLabelUploader; - - private int mActiveRequestCount = 0; - private boolean mIsActive = false; - private BitmapTexture mLoadingLabel; - - private int mSlotWidth; - - public static class AlbumSetEntry { - public MediaSet album; - public MediaItem coverItem; - public Texture content; - public BitmapTexture labelTexture; - public TiledTexture bitmapTexture; - public Path setPath; - public String title; - public int totalCount; - public int sourceType; - public int cacheFlag; - public int cacheStatus; - public int rotation; - public boolean isWaitLoadingDisplayed; - public long setDataVersion; - public long coverDataVersion; - private BitmapLoader labelLoader; - private BitmapLoader coverLoader; - } - - public AlbumSetSlidingWindow(AbstractGalleryActivity activity, - AlbumSetDataLoader source, AlbumSetSlotRenderer.LabelSpec labelSpec, int cacheSize) { - source.setModelListener(this); - mSource = source; - mData = new AlbumSetEntry[cacheSize]; - mSize = source.size(); - mThreadPool = activity.getThreadPool(); - - mLabelMaker = new AlbumLabelMaker(activity.getAndroidContext(), labelSpec); - mLoadingText = activity.getAndroidContext().getString(R.string.loading); - mContentUploader = new TiledTexture.Uploader(activity.getGLRoot()); - mLabelUploader = new TextureUploader(activity.getGLRoot()); - - mHandler = new SynchronizedHandler(activity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - Utils.assertTrue(message.what == MSG_UPDATE_ALBUM_ENTRY); - ((EntryUpdater) message.obj).updateEntry(); - } - }; - } - - public void setListener(Listener listener) { - mListener = listener; - } - - public AlbumSetEntry get(int slotIndex) { - if (!isActiveSlot(slotIndex)) { - Utils.fail("invalid slot: %s outsides (%s, %s)", - slotIndex, mActiveStart, mActiveEnd); - } - return mData[slotIndex % mData.length]; - } - - public int size() { - return mSize; - } - - public boolean isActiveSlot(int slotIndex) { - return slotIndex >= mActiveStart && slotIndex < mActiveEnd; - } - - private void setContentWindow(int contentStart, int contentEnd) { - if (contentStart == mContentStart && contentEnd == mContentEnd) return; - - if (contentStart >= mContentEnd || mContentStart >= contentEnd) { - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - freeSlotContent(i); - } - mSource.setActiveWindow(contentStart, contentEnd); - for (int i = contentStart; i < contentEnd; ++i) { - prepareSlotContent(i); - } - } else { - for (int i = mContentStart; i < contentStart; ++i) { - freeSlotContent(i); - } - for (int i = contentEnd, n = mContentEnd; i < n; ++i) { - freeSlotContent(i); - } - mSource.setActiveWindow(contentStart, contentEnd); - for (int i = contentStart, n = mContentStart; i < n; ++i) { - prepareSlotContent(i); - } - for (int i = mContentEnd; i < contentEnd; ++i) { - prepareSlotContent(i); - } - } - - mContentStart = contentStart; - mContentEnd = contentEnd; - } - - public void setActiveWindow(int start, int end) { - if (!(start <= end && end - start <= mData.length && end <= mSize)) { - Utils.fail("start = %s, end = %s, length = %s, size = %s", - start, end, mData.length, mSize); - } - - AlbumSetEntry data[] = mData; - mActiveStart = start; - mActiveEnd = end; - int contentStart = Utils.clamp((start + end) / 2 - data.length / 2, - 0, Math.max(0, mSize - data.length)); - int contentEnd = Math.min(contentStart + data.length, mSize); - setContentWindow(contentStart, contentEnd); - - if (mIsActive) { - updateTextureUploadQueue(); - updateAllImageRequests(); - } - } - - // We would like to request non active slots in the following order: - // Order: 8 6 4 2 1 3 5 7 - // |---------|---------------|---------| - // |<- active ->| - // |<-------- cached range ----------->| - private void requestNonactiveImages() { - int range = Math.max( - mContentEnd - mActiveEnd, mActiveStart - mContentStart); - for (int i = 0 ;i < range; ++i) { - requestImagesInSlot(mActiveEnd + i); - requestImagesInSlot(mActiveStart - 1 - i); - } - } - - private void cancelNonactiveImages() { - int range = Math.max( - mContentEnd - mActiveEnd, mActiveStart - mContentStart); - for (int i = 0 ;i < range; ++i) { - cancelImagesInSlot(mActiveEnd + i); - cancelImagesInSlot(mActiveStart - 1 - i); - } - } - - private void requestImagesInSlot(int slotIndex) { - if (slotIndex < mContentStart || slotIndex >= mContentEnd) return; - AlbumSetEntry entry = mData[slotIndex % mData.length]; - if (entry.coverLoader != null) entry.coverLoader.startLoad(); - if (entry.labelLoader != null) entry.labelLoader.startLoad(); - } - - private void cancelImagesInSlot(int slotIndex) { - if (slotIndex < mContentStart || slotIndex >= mContentEnd) return; - AlbumSetEntry entry = mData[slotIndex % mData.length]; - if (entry.coverLoader != null) entry.coverLoader.cancelLoad(); - if (entry.labelLoader != null) entry.labelLoader.cancelLoad(); - } - - private static long getDataVersion(MediaObject object) { - return object == null - ? MediaSet.INVALID_DATA_VERSION - : object.getDataVersion(); - } - - private void freeSlotContent(int slotIndex) { - AlbumSetEntry entry = mData[slotIndex % mData.length]; - if (entry.coverLoader != null) entry.coverLoader.recycle(); - if (entry.labelLoader != null) entry.labelLoader.recycle(); - if (entry.labelTexture != null) entry.labelTexture.recycle(); - if (entry.bitmapTexture != null) entry.bitmapTexture.recycle(); - mData[slotIndex % mData.length] = null; - } - - private boolean isLabelChanged( - AlbumSetEntry entry, String title, int totalCount, int sourceType) { - return !Utils.equals(entry.title, title) - || entry.totalCount != totalCount - || entry.sourceType != sourceType; - } - - private void updateAlbumSetEntry(AlbumSetEntry entry, int slotIndex) { - MediaSet album = mSource.getMediaSet(slotIndex); - MediaItem cover = mSource.getCoverItem(slotIndex); - int totalCount = mSource.getTotalCount(slotIndex); - - entry.album = album; - entry.setDataVersion = getDataVersion(album); - entry.cacheFlag = identifyCacheFlag(album); - entry.cacheStatus = identifyCacheStatus(album); - entry.setPath = (album == null) ? null : album.getPath(); - - String title = (album == null) ? "" : Utils.ensureNotNull(album.getName()); - int sourceType = DataSourceType.identifySourceType(album); - if (isLabelChanged(entry, title, totalCount, sourceType)) { - entry.title = title; - entry.totalCount = totalCount; - entry.sourceType = sourceType; - if (entry.labelLoader != null) { - entry.labelLoader.recycle(); - entry.labelLoader = null; - entry.labelTexture = null; - } - if (album != null) { - entry.labelLoader = new AlbumLabelLoader( - slotIndex, title, totalCount, sourceType); - } - } - - entry.coverItem = cover; - if (getDataVersion(cover) != entry.coverDataVersion) { - entry.coverDataVersion = getDataVersion(cover); - entry.rotation = (cover == null) ? 0 : cover.getRotation(); - if (entry.coverLoader != null) { - entry.coverLoader.recycle(); - entry.coverLoader = null; - entry.bitmapTexture = null; - entry.content = null; - } - if (cover != null) { - entry.coverLoader = new AlbumCoverLoader(slotIndex, cover); - } - } - } - - private void prepareSlotContent(int slotIndex) { - AlbumSetEntry entry = new AlbumSetEntry(); - updateAlbumSetEntry(entry, slotIndex); - mData[slotIndex % mData.length] = entry; - } - - private static boolean startLoadBitmap(BitmapLoader loader) { - if (loader == null) return false; - loader.startLoad(); - return loader.isRequestInProgress(); - } - - private void uploadBackgroundTextureInSlot(int index) { - if (index < mContentStart || index >= mContentEnd) return; - AlbumSetEntry entry = mData[index % mData.length]; - if (entry.bitmapTexture != null) { - mContentUploader.addTexture(entry.bitmapTexture); - } - if (entry.labelTexture != null) { - mLabelUploader.addBgTexture(entry.labelTexture); - } - } - - private void updateTextureUploadQueue() { - if (!mIsActive) return; - mContentUploader.clear(); - mLabelUploader.clear(); - - // Upload foreground texture - for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) { - AlbumSetEntry entry = mData[i % mData.length]; - if (entry.bitmapTexture != null) { - mContentUploader.addTexture(entry.bitmapTexture); - } - if (entry.labelTexture != null) { - mLabelUploader.addFgTexture(entry.labelTexture); - } - } - - // add background textures - int range = Math.max( - (mContentEnd - mActiveEnd), (mActiveStart - mContentStart)); - for (int i = 0; i < range; ++i) { - uploadBackgroundTextureInSlot(mActiveEnd + i); - uploadBackgroundTextureInSlot(mActiveStart - i - 1); - } - } - - private void updateAllImageRequests() { - mActiveRequestCount = 0; - for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) { - AlbumSetEntry entry = mData[i % mData.length]; - if (startLoadBitmap(entry.coverLoader)) ++mActiveRequestCount; - if (startLoadBitmap(entry.labelLoader)) ++mActiveRequestCount; - } - if (mActiveRequestCount == 0) { - requestNonactiveImages(); - } else { - cancelNonactiveImages(); - } - } - - @Override - public void onSizeChanged(int size) { - if (mIsActive && mSize != size) { - mSize = size; - if (mListener != null) mListener.onSizeChanged(mSize); - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - } - - @Override - public void onContentChanged(int index) { - if (!mIsActive) { - // paused, ignore slot changed event - return; - } - - // If the updated content is not cached, ignore it - if (index < mContentStart || index >= mContentEnd) { - Log.w(TAG, String.format( - "invalid update: %s is outside (%s, %s)", - index, mContentStart, mContentEnd) ); - return; - } - - AlbumSetEntry entry = mData[index % mData.length]; - updateAlbumSetEntry(entry, index); - updateAllImageRequests(); - updateTextureUploadQueue(); - if (mListener != null && isActiveSlot(index)) { - mListener.onContentChanged(); - } - } - - public BitmapTexture getLoadingTexture() { - if (mLoadingLabel == null) { - Bitmap bitmap = mLabelMaker.requestLabel( - mLoadingText, "", DataSourceType.TYPE_NOT_CATEGORIZED) - .run(ThreadPool.JOB_CONTEXT_STUB); - mLoadingLabel = new BitmapTexture(bitmap); - mLoadingLabel.setOpaque(false); - } - return mLoadingLabel; - } - - public void pause() { - mIsActive = false; - mLabelUploader.clear(); - mContentUploader.clear(); - TiledTexture.freeResources(); - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - freeSlotContent(i); - } - } - - public void resume() { - mIsActive = true; - TiledTexture.prepareResources(); - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - prepareSlotContent(i); - } - updateAllImageRequests(); - } - - private static interface EntryUpdater { - public void updateEntry(); - } - - private class AlbumCoverLoader extends BitmapLoader implements EntryUpdater { - private MediaItem mMediaItem; - private final int mSlotIndex; - - public AlbumCoverLoader(int slotIndex, MediaItem item) { - mSlotIndex = slotIndex; - mMediaItem = item; - } - - @Override - protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) { - return mThreadPool.submit(mMediaItem.requestImage( - MediaItem.TYPE_MICROTHUMBNAIL), l); - } - - @Override - protected void onLoadComplete(Bitmap bitmap) { - mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget(); - } - - @Override - public void updateEntry() { - Bitmap bitmap = getBitmap(); - if (bitmap == null) return; // error or recycled - - AlbumSetEntry entry = mData[mSlotIndex % mData.length]; - TiledTexture texture = new TiledTexture(bitmap); - entry.bitmapTexture = texture; - entry.content = texture; - - if (isActiveSlot(mSlotIndex)) { - mContentUploader.addTexture(texture); - --mActiveRequestCount; - if (mActiveRequestCount == 0) requestNonactiveImages(); - if (mListener != null) mListener.onContentChanged(); - } else { - mContentUploader.addTexture(texture); - } - } - } - - private static int identifyCacheFlag(MediaSet set) { - if (set == null || (set.getSupportedOperations() - & MediaSet.SUPPORT_CACHE) == 0) { - return MediaSet.CACHE_FLAG_NO; - } - - return set.getCacheFlag(); - } - - private static int identifyCacheStatus(MediaSet set) { - if (set == null || (set.getSupportedOperations() - & MediaSet.SUPPORT_CACHE) == 0) { - return MediaSet.CACHE_STATUS_NOT_CACHED; - } - - return set.getCacheStatus(); - } - - private class AlbumLabelLoader extends BitmapLoader implements EntryUpdater { - private final int mSlotIndex; - private final String mTitle; - private final int mTotalCount; - private final int mSourceType; - - public AlbumLabelLoader( - int slotIndex, String title, int totalCount, int sourceType) { - mSlotIndex = slotIndex; - mTitle = title; - mTotalCount = totalCount; - mSourceType = sourceType; - } - - @Override - protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) { - return mThreadPool.submit(mLabelMaker.requestLabel( - mTitle, String.valueOf(mTotalCount), mSourceType), l); - } - - @Override - protected void onLoadComplete(Bitmap bitmap) { - mHandler.obtainMessage(MSG_UPDATE_ALBUM_ENTRY, this).sendToTarget(); - } - - @Override - public void updateEntry() { - Bitmap bitmap = getBitmap(); - if (bitmap == null) return; // Error or recycled - - AlbumSetEntry entry = mData[mSlotIndex % mData.length]; - BitmapTexture texture = new BitmapTexture(bitmap); - texture.setOpaque(false); - entry.labelTexture = texture; - - if (isActiveSlot(mSlotIndex)) { - mLabelUploader.addFgTexture(texture); - --mActiveRequestCount; - if (mActiveRequestCount == 0) requestNonactiveImages(); - if (mListener != null) mListener.onContentChanged(); - } else { - mLabelUploader.addBgTexture(texture); - } - } - } - - public void onSlotSizeChanged(int width, int height) { - if (mSlotWidth == width) return; - - mSlotWidth = width; - mLoadingLabel = null; - mLabelMaker.setLabelWidth(mSlotWidth); - - if (!mIsActive) return; - - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - AlbumSetEntry entry = mData[i % mData.length]; - if (entry.labelLoader != null) { - entry.labelLoader.recycle(); - entry.labelLoader = null; - entry.labelTexture = null; - } - if (entry.album != null) { - entry.labelLoader = new AlbumLabelLoader(i, - entry.title, entry.totalCount, entry.sourceType); - } - } - updateAllImageRequests(); - updateTextureUploadQueue(); - } -} diff --git a/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java b/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java deleted file mode 100644 index 5332ef89a..000000000 --- a/src/com/android/gallery3d/ui/AlbumSetSlotRenderer.java +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.app.AlbumSetDataLoader; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.ColorTexture; -import com.android.gallery3d.glrenderer.FadeInTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.ResourceTexture; -import com.android.gallery3d.glrenderer.Texture; -import com.android.gallery3d.glrenderer.TiledTexture; -import com.android.gallery3d.glrenderer.UploadedTexture; -import com.android.gallery3d.ui.AlbumSetSlidingWindow.AlbumSetEntry; - -public class AlbumSetSlotRenderer extends AbstractSlotRenderer { - @SuppressWarnings("unused") - private static final String TAG = "AlbumSetView"; - private static final int CACHE_SIZE = 96; - private final int mPlaceholderColor; - - private final ColorTexture mWaitLoadingTexture; - private final ResourceTexture mCameraOverlay; - private final AbstractGalleryActivity mActivity; - private final SelectionManager mSelectionManager; - protected final LabelSpec mLabelSpec; - - protected AlbumSetSlidingWindow mDataWindow; - private SlotView mSlotView; - - private int mPressedIndex = -1; - private boolean mAnimatePressedUp; - private Path mHighlightItemPath = null; - private boolean mInSelectionMode; - - public static class LabelSpec { - public int labelBackgroundHeight; - public int titleOffset; - public int countOffset; - public int titleFontSize; - public int countFontSize; - public int leftMargin; - public int iconSize; - public int titleRightMargin; - public int backgroundColor; - public int titleColor; - public int countColor; - public int borderSize; - } - - public AlbumSetSlotRenderer(AbstractGalleryActivity activity, - SelectionManager selectionManager, - SlotView slotView, LabelSpec labelSpec, int placeholderColor) { - super (activity); - mActivity = activity; - mSelectionManager = selectionManager; - mSlotView = slotView; - mLabelSpec = labelSpec; - mPlaceholderColor = placeholderColor; - - mWaitLoadingTexture = new ColorTexture(mPlaceholderColor); - mWaitLoadingTexture.setSize(1, 1); - mCameraOverlay = new ResourceTexture(activity, - R.drawable.ic_cameraalbum_overlay); - } - - public void setPressedIndex(int index) { - if (mPressedIndex == index) return; - mPressedIndex = index; - mSlotView.invalidate(); - } - - public void setPressedUp() { - if (mPressedIndex == -1) return; - mAnimatePressedUp = true; - mSlotView.invalidate(); - } - - public void setHighlightItemPath(Path path) { - if (mHighlightItemPath == path) return; - mHighlightItemPath = path; - mSlotView.invalidate(); - } - - public void setModel(AlbumSetDataLoader model) { - if (mDataWindow != null) { - mDataWindow.setListener(null); - mDataWindow = null; - mSlotView.setSlotCount(0); - } - if (model != null) { - mDataWindow = new AlbumSetSlidingWindow( - mActivity, model, mLabelSpec, CACHE_SIZE); - mDataWindow.setListener(new MyCacheListener()); - mSlotView.setSlotCount(mDataWindow.size()); - } - } - - private static Texture checkLabelTexture(Texture texture) { - return ((texture instanceof UploadedTexture) - && ((UploadedTexture) texture).isUploading()) - ? null - : texture; - } - - private static Texture checkContentTexture(Texture texture) { - return ((texture instanceof TiledTexture) - && !((TiledTexture) texture).isReady()) - ? null - : texture; - } - - @Override - public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) { - AlbumSetEntry entry = mDataWindow.get(index); - int renderRequestFlags = 0; - renderRequestFlags |= renderContent(canvas, entry, width, height); - renderRequestFlags |= renderLabel(canvas, entry, width, height); - renderRequestFlags |= renderOverlay(canvas, index, entry, width, height); - return renderRequestFlags; - } - - protected int renderOverlay( - GLCanvas canvas, int index, AlbumSetEntry entry, int width, int height) { - int renderRequestFlags = 0; - if (entry.album != null && entry.album.isCameraRoll()) { - int uncoveredHeight = height - mLabelSpec.labelBackgroundHeight; - int dim = uncoveredHeight / 2; - mCameraOverlay.draw(canvas, (width - dim) / 2, - (uncoveredHeight - dim) / 2, dim, dim); - } - if (mPressedIndex == index) { - if (mAnimatePressedUp) { - drawPressedUpFrame(canvas, width, height); - renderRequestFlags |= SlotView.RENDER_MORE_FRAME; - if (isPressedUpFrameFinished()) { - mAnimatePressedUp = false; - mPressedIndex = -1; - } - } else { - drawPressedFrame(canvas, width, height); - } - } else if ((mHighlightItemPath != null) && (mHighlightItemPath == entry.setPath)) { - drawSelectedFrame(canvas, width, height); - } else if (mInSelectionMode && mSelectionManager.isItemSelected(entry.setPath)) { - drawSelectedFrame(canvas, width, height); - } - return renderRequestFlags; - } - - protected int renderContent( - GLCanvas canvas, AlbumSetEntry entry, int width, int height) { - int renderRequestFlags = 0; - - Texture content = checkContentTexture(entry.content); - if (content == null) { - content = mWaitLoadingTexture; - entry.isWaitLoadingDisplayed = true; - } else if (entry.isWaitLoadingDisplayed) { - entry.isWaitLoadingDisplayed = false; - content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture); - entry.content = content; - } - drawContent(canvas, content, width, height, entry.rotation); - if ((content instanceof FadeInTexture) && - ((FadeInTexture) content).isAnimating()) { - renderRequestFlags |= SlotView.RENDER_MORE_FRAME; - } - - return renderRequestFlags; - } - - protected int renderLabel( - GLCanvas canvas, AlbumSetEntry entry, int width, int height) { - Texture content = checkLabelTexture(entry.labelTexture); - if (content == null) { - content = mWaitLoadingTexture; - } - int b = AlbumLabelMaker.getBorderSize(); - int h = mLabelSpec.labelBackgroundHeight; - content.draw(canvas, -b, height - h + b, width + b + b, h); - - return 0; - } - - @Override - public void prepareDrawing() { - mInSelectionMode = mSelectionManager.inSelectionMode(); - } - - private class MyCacheListener implements AlbumSetSlidingWindow.Listener { - - @Override - public void onSizeChanged(int size) { - mSlotView.setSlotCount(size); - } - - @Override - public void onContentChanged() { - mSlotView.invalidate(); - } - } - - public void pause() { - mDataWindow.pause(); - } - - public void resume() { - mDataWindow.resume(); - } - - @Override - public void onVisibleRangeChanged(int visibleStart, int visibleEnd) { - if (mDataWindow != null) { - mDataWindow.setActiveWindow(visibleStart, visibleEnd); - } - } - - @Override - public void onSlotSizeChanged(int width, int height) { - if (mDataWindow != null) { - mDataWindow.onSlotSizeChanged(width, height); - } - } -} diff --git a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java b/src/com/android/gallery3d/ui/AlbumSlidingWindow.java deleted file mode 100644 index fec7d1e92..000000000 --- a/src/com/android/gallery3d/ui/AlbumSlidingWindow.java +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Bitmap; -import android.os.Message; - -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.app.AlbumDataLoader; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaObject.PanoramaSupportCallback; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.Texture; -import com.android.gallery3d.glrenderer.TiledTexture; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.JobLimiter; - -public class AlbumSlidingWindow implements AlbumDataLoader.DataListener { - @SuppressWarnings("unused") - private static final String TAG = "AlbumSlidingWindow"; - - private static final int MSG_UPDATE_ENTRY = 0; - private static final int JOB_LIMIT = 2; - - public static interface Listener { - public void onSizeChanged(int size); - public void onContentChanged(); - } - - public static class AlbumEntry { - public MediaItem item; - public Path path; - public boolean isPanorama; - public int rotation; - public int mediaType; - public boolean isWaitDisplayed; - public TiledTexture bitmapTexture; - public Texture content; - private BitmapLoader contentLoader; - private PanoSupportListener mPanoSupportListener; - } - - private final AlbumDataLoader mSource; - private final AlbumEntry mData[]; - private final SynchronizedHandler mHandler; - private final JobLimiter mThreadPool; - private final TiledTexture.Uploader mTileUploader; - - private int mSize; - - private int mContentStart = 0; - private int mContentEnd = 0; - - private int mActiveStart = 0; - private int mActiveEnd = 0; - - private Listener mListener; - - private int mActiveRequestCount = 0; - private boolean mIsActive = false; - - private class PanoSupportListener implements PanoramaSupportCallback { - public final AlbumEntry mEntry; - public PanoSupportListener (AlbumEntry entry) { - mEntry = entry; - } - @Override - public void panoramaInfoAvailable(MediaObject mediaObject, boolean isPanorama, - boolean isPanorama360) { - if (mEntry != null) mEntry.isPanorama = isPanorama; - } - } - - public AlbumSlidingWindow(AbstractGalleryActivity activity, - AlbumDataLoader source, int cacheSize) { - source.setDataListener(this); - mSource = source; - mData = new AlbumEntry[cacheSize]; - mSize = source.size(); - - mHandler = new SynchronizedHandler(activity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - Utils.assertTrue(message.what == MSG_UPDATE_ENTRY); - ((ThumbnailLoader) message.obj).updateEntry(); - } - }; - - mThreadPool = new JobLimiter(activity.getThreadPool(), JOB_LIMIT); - mTileUploader = new TiledTexture.Uploader(activity.getGLRoot()); - } - - public void setListener(Listener listener) { - mListener = listener; - } - - public AlbumEntry get(int slotIndex) { - if (!isActiveSlot(slotIndex)) { - Utils.fail("invalid slot: %s outsides (%s, %s)", - slotIndex, mActiveStart, mActiveEnd); - } - return mData[slotIndex % mData.length]; - } - - public boolean isActiveSlot(int slotIndex) { - return slotIndex >= mActiveStart && slotIndex < mActiveEnd; - } - - private void setContentWindow(int contentStart, int contentEnd) { - if (contentStart == mContentStart && contentEnd == mContentEnd) return; - - if (!mIsActive) { - mContentStart = contentStart; - mContentEnd = contentEnd; - mSource.setActiveWindow(contentStart, contentEnd); - return; - } - - if (contentStart >= mContentEnd || mContentStart >= contentEnd) { - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - freeSlotContent(i); - } - mSource.setActiveWindow(contentStart, contentEnd); - for (int i = contentStart; i < contentEnd; ++i) { - prepareSlotContent(i); - } - } else { - for (int i = mContentStart; i < contentStart; ++i) { - freeSlotContent(i); - } - for (int i = contentEnd, n = mContentEnd; i < n; ++i) { - freeSlotContent(i); - } - mSource.setActiveWindow(contentStart, contentEnd); - for (int i = contentStart, n = mContentStart; i < n; ++i) { - prepareSlotContent(i); - } - for (int i = mContentEnd; i < contentEnd; ++i) { - prepareSlotContent(i); - } - } - - mContentStart = contentStart; - mContentEnd = contentEnd; - } - - public void setActiveWindow(int start, int end) { - if (!(start <= end && end - start <= mData.length && end <= mSize)) { - Utils.fail("%s, %s, %s, %s", start, end, mData.length, mSize); - } - AlbumEntry data[] = mData; - - mActiveStart = start; - mActiveEnd = end; - - int contentStart = Utils.clamp((start + end) / 2 - data.length / 2, - 0, Math.max(0, mSize - data.length)); - int contentEnd = Math.min(contentStart + data.length, mSize); - setContentWindow(contentStart, contentEnd); - updateTextureUploadQueue(); - if (mIsActive) updateAllImageRequests(); - } - - private void uploadBgTextureInSlot(int index) { - if (index < mContentEnd && index >= mContentStart) { - AlbumEntry entry = mData[index % mData.length]; - if (entry.bitmapTexture != null) { - mTileUploader.addTexture(entry.bitmapTexture); - } - } - } - - private void updateTextureUploadQueue() { - if (!mIsActive) return; - mTileUploader.clear(); - - // add foreground textures - for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) { - AlbumEntry entry = mData[i % mData.length]; - if (entry.bitmapTexture != null) { - mTileUploader.addTexture(entry.bitmapTexture); - } - } - - // add background textures - int range = Math.max( - (mContentEnd - mActiveEnd), (mActiveStart - mContentStart)); - for (int i = 0; i < range; ++i) { - uploadBgTextureInSlot(mActiveEnd + i); - uploadBgTextureInSlot(mActiveStart - i - 1); - } - } - - // We would like to request non active slots in the following order: - // Order: 8 6 4 2 1 3 5 7 - // |---------|---------------|---------| - // |<- active ->| - // |<-------- cached range ----------->| - private void requestNonactiveImages() { - int range = Math.max( - (mContentEnd - mActiveEnd), (mActiveStart - mContentStart)); - for (int i = 0 ;i < range; ++i) { - requestSlotImage(mActiveEnd + i); - requestSlotImage(mActiveStart - 1 - i); - } - } - - // return whether the request is in progress or not - private boolean requestSlotImage(int slotIndex) { - if (slotIndex < mContentStart || slotIndex >= mContentEnd) return false; - AlbumEntry entry = mData[slotIndex % mData.length]; - if (entry.content != null || entry.item == null) return false; - - // Set up the panorama callback - entry.mPanoSupportListener = new PanoSupportListener(entry); - entry.item.getPanoramaSupport(entry.mPanoSupportListener); - - entry.contentLoader.startLoad(); - return entry.contentLoader.isRequestInProgress(); - } - - private void cancelNonactiveImages() { - int range = Math.max( - (mContentEnd - mActiveEnd), (mActiveStart - mContentStart)); - for (int i = 0 ;i < range; ++i) { - cancelSlotImage(mActiveEnd + i); - cancelSlotImage(mActiveStart - 1 - i); - } - } - - private void cancelSlotImage(int slotIndex) { - if (slotIndex < mContentStart || slotIndex >= mContentEnd) return; - AlbumEntry item = mData[slotIndex % mData.length]; - if (item.contentLoader != null) item.contentLoader.cancelLoad(); - } - - private void freeSlotContent(int slotIndex) { - AlbumEntry data[] = mData; - int index = slotIndex % data.length; - AlbumEntry entry = data[index]; - if (entry.contentLoader != null) entry.contentLoader.recycle(); - if (entry.bitmapTexture != null) entry.bitmapTexture.recycle(); - data[index] = null; - } - - private void prepareSlotContent(int slotIndex) { - AlbumEntry entry = new AlbumEntry(); - MediaItem item = mSource.get(slotIndex); // item could be null; - entry.item = item; - entry.mediaType = (item == null) - ? MediaItem.MEDIA_TYPE_UNKNOWN - : entry.item.getMediaType(); - entry.path = (item == null) ? null : item.getPath(); - entry.rotation = (item == null) ? 0 : item.getRotation(); - entry.contentLoader = new ThumbnailLoader(slotIndex, entry.item); - mData[slotIndex % mData.length] = entry; - } - - private void updateAllImageRequests() { - mActiveRequestCount = 0; - for (int i = mActiveStart, n = mActiveEnd; i < n; ++i) { - if (requestSlotImage(i)) ++mActiveRequestCount; - } - if (mActiveRequestCount == 0) { - requestNonactiveImages(); - } else { - cancelNonactiveImages(); - } - } - - private class ThumbnailLoader extends BitmapLoader { - private final int mSlotIndex; - private final MediaItem mItem; - - public ThumbnailLoader(int slotIndex, MediaItem item) { - mSlotIndex = slotIndex; - mItem = item; - } - - @Override - protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) { - return mThreadPool.submit( - mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this); - } - - @Override - protected void onLoadComplete(Bitmap bitmap) { - mHandler.obtainMessage(MSG_UPDATE_ENTRY, this).sendToTarget(); - } - - public void updateEntry() { - Bitmap bitmap = getBitmap(); - if (bitmap == null) return; // error or recycled - AlbumEntry entry = mData[mSlotIndex % mData.length]; - entry.bitmapTexture = new TiledTexture(bitmap); - entry.content = entry.bitmapTexture; - - if (isActiveSlot(mSlotIndex)) { - mTileUploader.addTexture(entry.bitmapTexture); - --mActiveRequestCount; - if (mActiveRequestCount == 0) requestNonactiveImages(); - if (mListener != null) mListener.onContentChanged(); - } else { - mTileUploader.addTexture(entry.bitmapTexture); - } - } - } - - @Override - public void onSizeChanged(int size) { - if (mSize != size) { - mSize = size; - if (mListener != null) mListener.onSizeChanged(mSize); - if (mContentEnd > mSize) mContentEnd = mSize; - if (mActiveEnd > mSize) mActiveEnd = mSize; - } - } - - @Override - public void onContentChanged(int index) { - if (index >= mContentStart && index < mContentEnd && mIsActive) { - freeSlotContent(index); - prepareSlotContent(index); - updateAllImageRequests(); - if (mListener != null && isActiveSlot(index)) { - mListener.onContentChanged(); - } - } - } - - public void resume() { - mIsActive = true; - TiledTexture.prepareResources(); - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - prepareSlotContent(i); - } - updateAllImageRequests(); - } - - public void pause() { - mIsActive = false; - mTileUploader.clear(); - TiledTexture.freeResources(); - for (int i = mContentStart, n = mContentEnd; i < n; ++i) { - freeSlotContent(i); - } - } -} diff --git a/src/com/android/gallery3d/ui/AlbumSlotRenderer.java b/src/com/android/gallery3d/ui/AlbumSlotRenderer.java deleted file mode 100644 index dc6c89b0e..000000000 --- a/src/com/android/gallery3d/ui/AlbumSlotRenderer.java +++ /dev/null @@ -1,201 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.app.AlbumDataLoader; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.ColorTexture; -import com.android.gallery3d.glrenderer.FadeInTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.Texture; -import com.android.gallery3d.glrenderer.TiledTexture; - -public class AlbumSlotRenderer extends AbstractSlotRenderer { - @SuppressWarnings("unused") - private static final String TAG = "AlbumView"; - - public interface SlotFilter { - public boolean acceptSlot(int index); - } - - private final int mPlaceholderColor; - private static final int CACHE_SIZE = 96; - - private AlbumSlidingWindow mDataWindow; - private final AbstractGalleryActivity mActivity; - private final ColorTexture mWaitLoadingTexture; - private final SlotView mSlotView; - private final SelectionManager mSelectionManager; - - private int mPressedIndex = -1; - private boolean mAnimatePressedUp; - private Path mHighlightItemPath = null; - private boolean mInSelectionMode; - - private SlotFilter mSlotFilter; - - public AlbumSlotRenderer(AbstractGalleryActivity activity, SlotView slotView, - SelectionManager selectionManager, int placeholderColor) { - super(activity); - mActivity = activity; - mSlotView = slotView; - mSelectionManager = selectionManager; - mPlaceholderColor = placeholderColor; - - mWaitLoadingTexture = new ColorTexture(mPlaceholderColor); - mWaitLoadingTexture.setSize(1, 1); - } - - public void setPressedIndex(int index) { - if (mPressedIndex == index) return; - mPressedIndex = index; - mSlotView.invalidate(); - } - - public void setPressedUp() { - if (mPressedIndex == -1) return; - mAnimatePressedUp = true; - mSlotView.invalidate(); - } - - public void setHighlightItemPath(Path path) { - if (mHighlightItemPath == path) return; - mHighlightItemPath = path; - mSlotView.invalidate(); - } - - public void setModel(AlbumDataLoader model) { - if (mDataWindow != null) { - mDataWindow.setListener(null); - mSlotView.setSlotCount(0); - mDataWindow = null; - } - if (model != null) { - mDataWindow = new AlbumSlidingWindow(mActivity, model, CACHE_SIZE); - mDataWindow.setListener(new MyDataModelListener()); - mSlotView.setSlotCount(model.size()); - } - } - - private static Texture checkTexture(Texture texture) { - return (texture instanceof TiledTexture) - && !((TiledTexture) texture).isReady() - ? null - : texture; - } - - @Override - public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) { - if (mSlotFilter != null && !mSlotFilter.acceptSlot(index)) return 0; - - AlbumSlidingWindow.AlbumEntry entry = mDataWindow.get(index); - - int renderRequestFlags = 0; - - Texture content = checkTexture(entry.content); - if (content == null) { - content = mWaitLoadingTexture; - entry.isWaitDisplayed = true; - } else if (entry.isWaitDisplayed) { - entry.isWaitDisplayed = false; - content = new FadeInTexture(mPlaceholderColor, entry.bitmapTexture); - entry.content = content; - } - drawContent(canvas, content, width, height, entry.rotation); - if ((content instanceof FadeInTexture) && - ((FadeInTexture) content).isAnimating()) { - renderRequestFlags |= SlotView.RENDER_MORE_FRAME; - } - - if (entry.mediaType == MediaObject.MEDIA_TYPE_VIDEO) { - drawVideoOverlay(canvas, width, height); - } - - if (entry.isPanorama) { - drawPanoramaIcon(canvas, width, height); - } - - renderRequestFlags |= renderOverlay(canvas, index, entry, width, height); - - return renderRequestFlags; - } - - private int renderOverlay(GLCanvas canvas, int index, - AlbumSlidingWindow.AlbumEntry entry, int width, int height) { - int renderRequestFlags = 0; - if (mPressedIndex == index) { - if (mAnimatePressedUp) { - drawPressedUpFrame(canvas, width, height); - renderRequestFlags |= SlotView.RENDER_MORE_FRAME; - if (isPressedUpFrameFinished()) { - mAnimatePressedUp = false; - mPressedIndex = -1; - } - } else { - drawPressedFrame(canvas, width, height); - } - } else if ((entry.path != null) && (mHighlightItemPath == entry.path)) { - drawSelectedFrame(canvas, width, height); - } else if (mInSelectionMode && mSelectionManager.isItemSelected(entry.path)) { - drawSelectedFrame(canvas, width, height); - } - return renderRequestFlags; - } - - private class MyDataModelListener implements AlbumSlidingWindow.Listener { - @Override - public void onContentChanged() { - mSlotView.invalidate(); - } - - @Override - public void onSizeChanged(int size) { - mSlotView.setSlotCount(size); - } - } - - public void resume() { - mDataWindow.resume(); - } - - public void pause() { - mDataWindow.pause(); - } - - @Override - public void prepareDrawing() { - mInSelectionMode = mSelectionManager.inSelectionMode(); - } - - @Override - public void onVisibleRangeChanged(int visibleStart, int visibleEnd) { - if (mDataWindow != null) { - mDataWindow.setActiveWindow(visibleStart, visibleEnd); - } - } - - @Override - public void onSlotSizeChanged(int width, int height) { - // Do nothing - } - - public void setSlotFilter(SlotFilter slotFilter) { - mSlotFilter = slotFilter; - } -} diff --git a/src/com/android/gallery3d/ui/AnimationTime.java b/src/com/android/gallery3d/ui/AnimationTime.java deleted file mode 100644 index 063677423..000000000 --- a/src/com/android/gallery3d/ui/AnimationTime.java +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.os.SystemClock; - -// -// The animation time should ideally be the vsync time the frame will be -// displayed, but that is an unknown time in the future. So we use the system -// time just after eglSwapBuffers (when GLSurfaceView.onDrawFrame is called) -// as a approximation. -// -public class AnimationTime { - private static volatile long sTime; - - // Sets current time as the animation time. - public static void update() { - sTime = SystemClock.uptimeMillis(); - } - - // Returns the animation time. - public static long get() { - return sTime; - } - - public static long startTime() { - sTime = SystemClock.uptimeMillis(); - return sTime; - } -} diff --git a/src/com/android/gallery3d/ui/BitmapLoader.java b/src/com/android/gallery3d/ui/BitmapLoader.java deleted file mode 100644 index a708a90f3..000000000 --- a/src/com/android/gallery3d/ui/BitmapLoader.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Bitmap; - -import com.android.photos.data.GalleryBitmapPool; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; - -// We use this class to -// 1.) load bitmaps in background. -// 2.) as a place holder for the loaded bitmap -public abstract class BitmapLoader implements FutureListener<Bitmap> { - @SuppressWarnings("unused") - private static final String TAG = "BitmapLoader"; - - /* Transition Map: - * INIT -> REQUESTED, RECYCLED - * REQUESTED -> INIT (cancel), LOADED, ERROR, RECYCLED - * LOADED, ERROR -> RECYCLED - */ - private static final int STATE_INIT = 0; - private static final int STATE_REQUESTED = 1; - private static final int STATE_LOADED = 2; - private static final int STATE_ERROR = 3; - private static final int STATE_RECYCLED = 4; - - private int mState = STATE_INIT; - // mTask is not null only when a task is on the way - private Future<Bitmap> mTask; - private Bitmap mBitmap; - - @Override - public void onFutureDone(Future<Bitmap> future) { - synchronized (this) { - mTask = null; - mBitmap = future.get(); - if (mState == STATE_RECYCLED) { - if (mBitmap != null) { - GalleryBitmapPool.getInstance().put(mBitmap); - mBitmap = null; - } - return; // don't call callback - } - if (future.isCancelled() && mBitmap == null) { - if (mState == STATE_REQUESTED) mTask = submitBitmapTask(this); - return; // don't call callback - } else { - mState = mBitmap == null ? STATE_ERROR : STATE_LOADED; - } - } - onLoadComplete(mBitmap); - } - - public synchronized void startLoad() { - if (mState == STATE_INIT) { - mState = STATE_REQUESTED; - if (mTask == null) mTask = submitBitmapTask(this); - } - } - - public synchronized void cancelLoad() { - if (mState == STATE_REQUESTED) { - mState = STATE_INIT; - if (mTask != null) mTask.cancel(); - } - } - - // Recycle the loader and the bitmap - public synchronized void recycle() { - mState = STATE_RECYCLED; - if (mBitmap != null) { - GalleryBitmapPool.getInstance().put(mBitmap); - mBitmap = null; - } - if (mTask != null) mTask.cancel(); - } - - public synchronized boolean isRequestInProgress() { - return mState == STATE_REQUESTED; - } - - public synchronized boolean isRecycled() { - return mState == STATE_RECYCLED; - } - - public synchronized Bitmap getBitmap() { - return mBitmap; - } - - abstract protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l); - abstract protected void onLoadComplete(Bitmap bitmap); -} diff --git a/src/com/android/gallery3d/ui/BitmapTileProvider.java b/src/com/android/gallery3d/ui/BitmapTileProvider.java deleted file mode 100644 index e1a8b7644..000000000 --- a/src/com/android/gallery3d/ui/BitmapTileProvider.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.Canvas; - -import com.android.gallery3d.common.BitmapUtils; -import com.android.photos.data.GalleryBitmapPool; - -import java.util.ArrayList; - -public class BitmapTileProvider implements TileImageView.TileSource { - private final ScreenNail mScreenNail; - private final Bitmap[] mMipmaps; - private final Config mConfig; - private final int mImageWidth; - private final int mImageHeight; - - private boolean mRecycled = false; - - public BitmapTileProvider(Bitmap bitmap, int maxBackupSize) { - mImageWidth = bitmap.getWidth(); - mImageHeight = bitmap.getHeight(); - ArrayList<Bitmap> list = new ArrayList<Bitmap>(); - list.add(bitmap); - while (bitmap.getWidth() > maxBackupSize - || bitmap.getHeight() > maxBackupSize) { - bitmap = BitmapUtils.resizeBitmapByScale(bitmap, 0.5f, false); - list.add(bitmap); - } - - mScreenNail = new BitmapScreenNail(list.remove(list.size() - 1)); - mMipmaps = list.toArray(new Bitmap[list.size()]); - mConfig = Config.ARGB_8888; - } - - @Override - public ScreenNail getScreenNail() { - return mScreenNail; - } - - @Override - public int getImageHeight() { - return mImageHeight; - } - - @Override - public int getImageWidth() { - return mImageWidth; - } - - @Override - public int getLevelCount() { - return mMipmaps.length; - } - - @Override - public Bitmap getTile(int level, int x, int y, int tileSize) { - x >>= level; - y >>= level; - - Bitmap result = GalleryBitmapPool.getInstance().get(tileSize, tileSize); - if (result == null) { - result = Bitmap.createBitmap(tileSize, tileSize, mConfig); - } else { - result.eraseColor(0); - } - - Bitmap mipmap = mMipmaps[level]; - Canvas canvas = new Canvas(result); - int offsetX = -x; - int offsetY = -y; - canvas.drawBitmap(mipmap, offsetX, offsetY, null); - return result; - } - - public void recycle() { - if (mRecycled) return; - mRecycled = true; - for (Bitmap bitmap : mMipmaps) { - BitmapUtils.recycleSilently(bitmap); - } - if (mScreenNail != null) { - mScreenNail.recycle(); - } - } -} diff --git a/src/com/android/gallery3d/ui/CacheStorageUsageInfo.java b/src/com/android/gallery3d/ui/CacheStorageUsageInfo.java deleted file mode 100644 index 46f7a2433..000000000 --- a/src/com/android/gallery3d/ui/CacheStorageUsageInfo.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.os.StatFs; - -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.File; - -public class CacheStorageUsageInfo { - @SuppressWarnings("unused") - private static final String TAG = "CacheStorageUsageInfo"; - - // number of bytes the storage has. - private long mTotalBytes; - - // number of bytes already used. - private long mUsedBytes; - - // number of bytes used for the cache (should be less then usedBytes). - private long mUsedCacheBytes; - - // number of bytes used for the cache if all pending downloads (and removals) are completed. - private long mTargetCacheBytes; - - private AbstractGalleryActivity mActivity; - private Context mContext; - private long mUserChangeDelta; - - public CacheStorageUsageInfo(AbstractGalleryActivity activity) { - mActivity = activity; - mContext = activity.getAndroidContext(); - } - - public void increaseTargetCacheSize(long delta) { - mUserChangeDelta += delta; - } - - public void loadStorageInfo(JobContext jc) { - File cacheDir = mContext.getExternalCacheDir(); - if (cacheDir == null) { - cacheDir = mContext.getCacheDir(); - } - - String path = cacheDir.getAbsolutePath(); - StatFs stat = new StatFs(path); - long blockSize = stat.getBlockSize(); - long availableBlocks = stat.getAvailableBlocks(); - long totalBlocks = stat.getBlockCount(); - - mTotalBytes = blockSize * totalBlocks; - mUsedBytes = blockSize * (totalBlocks - availableBlocks); - mUsedCacheBytes = mActivity.getDataManager().getTotalUsedCacheSize(); - mTargetCacheBytes = mActivity.getDataManager().getTotalTargetCacheSize(); - } - - public long getTotalBytes() { - return mTotalBytes; - } - - public long getExpectedUsedBytes() { - return mUsedBytes - mUsedCacheBytes + mTargetCacheBytes + mUserChangeDelta; - } - - public long getUsedBytes() { - // Should it be usedBytes - usedCacheBytes + targetCacheBytes ? - return mUsedBytes; - } - - public long getFreeBytes() { - return mTotalBytes - mUsedBytes; - } -} diff --git a/src/com/android/gallery3d/ui/CaptureAnimation.java b/src/com/android/gallery3d/ui/CaptureAnimation.java deleted file mode 100644 index 87c054ab3..000000000 --- a/src/com/android/gallery3d/ui/CaptureAnimation.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.view.animation.AccelerateDecelerateInterpolator; -import android.view.animation.AccelerateInterpolator; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -public class CaptureAnimation { - // The amount of change for zooming out. - private static final float ZOOM_DELTA = 0.2f; - // Pre-calculated value for convenience. - private static final float ZOOM_IN_BEGIN = 1f - ZOOM_DELTA; - - private static final Interpolator sZoomOutInterpolator = - new DecelerateInterpolator(); - private static final Interpolator sZoomInInterpolator = - new AccelerateInterpolator(); - private static final Interpolator sSlideInterpolator = - new AccelerateDecelerateInterpolator(); - - // Calculate the slide factor based on the give time fraction. - public static float calculateSlide(float fraction) { - return sSlideInterpolator.getInterpolation(fraction); - } - - // Calculate the scale factor based on the given time fraction. - public static float calculateScale(float fraction) { - float value; - if (fraction <= 0.5f) { - // Zoom in for the beginning. - value = 1f - ZOOM_DELTA * - sZoomOutInterpolator.getInterpolation(fraction * 2); - } else { - // Zoom out for the ending. - value = ZOOM_IN_BEGIN + ZOOM_DELTA * - sZoomInInterpolator.getInterpolation((fraction - 0.5f) * 2f); - } - return value; - } -} diff --git a/src/com/android/gallery3d/ui/DetailsAddressResolver.java b/src/com/android/gallery3d/ui/DetailsAddressResolver.java deleted file mode 100644 index 8de667745..000000000 --- a/src/com/android/gallery3d/ui/DetailsAddressResolver.java +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.location.Address; -import android.os.Handler; -import android.os.Looper; - -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ReverseGeocoder; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -public class DetailsAddressResolver { - private AddressResolvingListener mListener; - private final AbstractGalleryActivity mContext; - private Future<Address> mAddressLookupJob; - private final Handler mHandler; - - private class AddressLookupJob implements Job<Address> { - private double[] mLatlng; - - protected AddressLookupJob(double[] latlng) { - mLatlng = latlng; - } - - @Override - public Address run(JobContext jc) { - ReverseGeocoder geocoder = new ReverseGeocoder(mContext.getAndroidContext()); - return geocoder.lookupAddress(mLatlng[0], mLatlng[1], true); - } - } - - public interface AddressResolvingListener { - public void onAddressAvailable(String address); - } - - public DetailsAddressResolver(AbstractGalleryActivity context) { - mContext = context; - mHandler = new Handler(Looper.getMainLooper()); - } - - public String resolveAddress(double[] latlng, AddressResolvingListener listener) { - mListener = listener; - mAddressLookupJob = mContext.getThreadPool().submit( - new AddressLookupJob(latlng), - new FutureListener<Address>() { - @Override - public void onFutureDone(final Future<Address> future) { - mAddressLookupJob = null; - if (!future.isCancelled()) { - mHandler.post(new Runnable() { - @Override - public void run() { - updateLocation(future.get()); - } - }); - } - } - }); - return GalleryUtils.formatLatitudeLongitude("(%f,%f)", latlng[0], latlng[1]); - } - - private void updateLocation(Address address) { - if (address != null) { - Context context = mContext.getAndroidContext(); - String parts[] = { - address.getAdminArea(), - address.getSubAdminArea(), - address.getLocality(), - address.getSubLocality(), - address.getThoroughfare(), - address.getSubThoroughfare(), - address.getPremises(), - address.getPostalCode(), - address.getCountryName() - }; - - String addressText = ""; - for (int i = 0; i < parts.length; i++) { - if (parts[i] == null || parts[i].isEmpty()) continue; - if (!addressText.isEmpty()) { - addressText += ", "; - } - addressText += parts[i]; - } - String text = String.format("%s : %s", DetailsHelper.getDetailsName( - context, MediaDetails.INDEX_LOCATION), addressText); - mListener.onAddressAvailable(text); - } - } - - public void cancel() { - if (mAddressLookupJob != null) { - mAddressLookupJob.cancel(); - mAddressLookupJob = null; - } - } -} diff --git a/src/com/android/gallery3d/ui/DetailsHelper.java b/src/com/android/gallery3d/ui/DetailsHelper.java deleted file mode 100644 index 47296f655..000000000 --- a/src/com/android/gallery3d/ui/DetailsHelper.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.view.View.MeasureSpec; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener; - -public class DetailsHelper { - private static DetailsAddressResolver sAddressResolver; - private DetailsViewContainer mContainer; - - public interface DetailsSource { - public int size(); - public int setIndex(); - public MediaDetails getDetails(); - } - - public interface CloseListener { - public void onClose(); - } - - public interface DetailsViewContainer { - public void reloadDetails(); - public void setCloseListener(CloseListener listener); - public void show(); - public void hide(); - } - - public interface ResolutionResolvingListener { - public void onResolutionAvailable(int width, int height); - } - - public DetailsHelper(AbstractGalleryActivity activity, GLView rootPane, DetailsSource source) { - mContainer = new DialogDetailsView(activity, source); - } - - public void layout(int left, int top, int right, int bottom) { - if (mContainer instanceof GLView) { - GLView view = (GLView) mContainer; - view.measure(MeasureSpec.UNSPECIFIED, - MeasureSpec.makeMeasureSpec(bottom - top, MeasureSpec.AT_MOST)); - view.layout(0, top, view.getMeasuredWidth(), top + view.getMeasuredHeight()); - } - } - - public void reloadDetails() { - mContainer.reloadDetails(); - } - - public void setCloseListener(CloseListener listener) { - mContainer.setCloseListener(listener); - } - - public static String resolveAddress(AbstractGalleryActivity activity, double[] latlng, - AddressResolvingListener listener) { - if (sAddressResolver == null) { - sAddressResolver = new DetailsAddressResolver(activity); - } else { - sAddressResolver.cancel(); - } - return sAddressResolver.resolveAddress(latlng, listener); - } - - public static void resolveResolution(String path, ResolutionResolvingListener listener) { - Bitmap bitmap = BitmapFactory.decodeFile(path); - if (bitmap == null) return; - listener.onResolutionAvailable(bitmap.getWidth(), bitmap.getHeight()); - } - - public static void pause() { - if (sAddressResolver != null) sAddressResolver.cancel(); - } - - public void show() { - mContainer.show(); - } - - public void hide() { - mContainer.hide(); - } - - public static String getDetailsName(Context context, int key) { - switch (key) { - case MediaDetails.INDEX_TITLE: - return context.getString(R.string.title); - case MediaDetails.INDEX_DESCRIPTION: - return context.getString(R.string.description); - case MediaDetails.INDEX_DATETIME: - return context.getString(R.string.time); - case MediaDetails.INDEX_LOCATION: - return context.getString(R.string.location); - case MediaDetails.INDEX_PATH: - return context.getString(R.string.path); - case MediaDetails.INDEX_WIDTH: - return context.getString(R.string.width); - case MediaDetails.INDEX_HEIGHT: - return context.getString(R.string.height); - case MediaDetails.INDEX_ORIENTATION: - return context.getString(R.string.orientation); - case MediaDetails.INDEX_DURATION: - return context.getString(R.string.duration); - case MediaDetails.INDEX_MIMETYPE: - return context.getString(R.string.mimetype); - case MediaDetails.INDEX_SIZE: - return context.getString(R.string.file_size); - case MediaDetails.INDEX_MAKE: - return context.getString(R.string.maker); - case MediaDetails.INDEX_MODEL: - return context.getString(R.string.model); - case MediaDetails.INDEX_FLASH: - return context.getString(R.string.flash); - case MediaDetails.INDEX_APERTURE: - return context.getString(R.string.aperture); - case MediaDetails.INDEX_FOCAL_LENGTH: - return context.getString(R.string.focal_length); - case MediaDetails.INDEX_WHITE_BALANCE: - return context.getString(R.string.white_balance); - case MediaDetails.INDEX_EXPOSURE_TIME: - return context.getString(R.string.exposure_time); - case MediaDetails.INDEX_ISO: - return context.getString(R.string.iso); - default: - return "Unknown key" + key; - } - } -} - - diff --git a/src/com/android/gallery3d/ui/DialogDetailsView.java b/src/com/android/gallery3d/ui/DialogDetailsView.java deleted file mode 100644 index 058c03654..000000000 --- a/src/com/android/gallery3d/ui/DialogDetailsView.java +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.app.AlertDialog; -import android.app.Dialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.text.format.Formatter; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ListView; -import android.widget.TextView; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaDetails; -import com.android.gallery3d.ui.DetailsAddressResolver.AddressResolvingListener; -import com.android.gallery3d.ui.DetailsHelper.CloseListener; -import com.android.gallery3d.ui.DetailsHelper.DetailsSource; -import com.android.gallery3d.ui.DetailsHelper.DetailsViewContainer; -import com.android.gallery3d.ui.DetailsHelper.ResolutionResolvingListener; - -import java.util.ArrayList; -import java.util.Map.Entry; - -public class DialogDetailsView implements DetailsViewContainer { - @SuppressWarnings("unused") - private static final String TAG = "DialogDetailsView"; - - private final AbstractGalleryActivity mActivity; - private DetailsAdapter mAdapter; - private MediaDetails mDetails; - private final DetailsSource mSource; - private int mIndex; - private Dialog mDialog; - private CloseListener mListener; - - public DialogDetailsView(AbstractGalleryActivity activity, DetailsSource source) { - mActivity = activity; - mSource = source; - } - - @Override - public void show() { - reloadDetails(); - mDialog.show(); - } - - @Override - public void hide() { - mDialog.hide(); - } - - @Override - public void reloadDetails() { - int index = mSource.setIndex(); - if (index == -1) return; - MediaDetails details = mSource.getDetails(); - if (details != null) { - if (mIndex == index && mDetails == details) return; - mIndex = index; - mDetails = details; - setDetails(details); - } - } - - private void setDetails(MediaDetails details) { - mAdapter = new DetailsAdapter(details); - String title = String.format( - mActivity.getAndroidContext().getString(R.string.details_title), - mIndex + 1, mSource.size()); - ListView detailsList = (ListView) LayoutInflater.from(mActivity.getAndroidContext()).inflate( - R.layout.details_list, null, false); - detailsList.setAdapter(mAdapter); - mDialog = new AlertDialog.Builder(mActivity) - .setView(detailsList) - .setTitle(title) - .setPositiveButton(R.string.close, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int whichButton) { - mDialog.dismiss(); - } - }) - .create(); - - mDialog.setOnDismissListener(new OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - if (mListener != null) { - mListener.onClose(); - } - } - }); - } - - - private class DetailsAdapter extends BaseAdapter - implements AddressResolvingListener, ResolutionResolvingListener { - private final ArrayList<String> mItems; - private int mLocationIndex; - private int mWidthIndex = -1; - private int mHeightIndex = -1; - - public DetailsAdapter(MediaDetails details) { - Context context = mActivity.getAndroidContext(); - mItems = new ArrayList<String>(details.size()); - mLocationIndex = -1; - setDetails(context, details); - } - - private void setDetails(Context context, MediaDetails details) { - boolean resolutionIsValid = true; - String path = null; - for (Entry<Integer, Object> detail : details) { - String value; - switch (detail.getKey()) { - case MediaDetails.INDEX_LOCATION: { - double[] latlng = (double[]) detail.getValue(); - mLocationIndex = mItems.size(); - value = DetailsHelper.resolveAddress(mActivity, latlng, this); - break; - } - case MediaDetails.INDEX_SIZE: { - value = Formatter.formatFileSize( - context, (Long) detail.getValue()); - break; - } - case MediaDetails.INDEX_WHITE_BALANCE: { - value = "1".equals(detail.getValue()) - ? context.getString(R.string.manual) - : context.getString(R.string.auto); - break; - } - case MediaDetails.INDEX_FLASH: { - MediaDetails.FlashState flash = - (MediaDetails.FlashState) detail.getValue(); - // TODO: camera doesn't fill in the complete values, show more information - // when it is fixed. - if (flash.isFlashFired()) { - value = context.getString(R.string.flash_on); - } else { - value = context.getString(R.string.flash_off); - } - break; - } - case MediaDetails.INDEX_EXPOSURE_TIME: { - value = (String) detail.getValue(); - double time = Double.valueOf(value); - if (time < 1.0f) { - value = String.format("1/%d", (int) (0.5f + 1 / time)); - } else { - int integer = (int) time; - time -= integer; - value = String.valueOf(integer) + "''"; - if (time > 0.0001) { - value += String.format(" 1/%d", (int) (0.5f + 1 / time)); - } - } - break; - } - case MediaDetails.INDEX_WIDTH: - mWidthIndex = mItems.size(); - value = detail.getValue().toString(); - if (value.equalsIgnoreCase("0")) { - value = context.getString(R.string.unknown); - resolutionIsValid = false; - } - break; - case MediaDetails.INDEX_HEIGHT: { - mHeightIndex = mItems.size(); - value = detail.getValue().toString(); - if (value.equalsIgnoreCase("0")) { - value = context.getString(R.string.unknown); - resolutionIsValid = false; - } - break; - } - case MediaDetails.INDEX_PATH: - // Get the path and then fall through to the default case - path = detail.getValue().toString(); - default: { - Object valueObj = detail.getValue(); - // This shouldn't happen, log its key to help us diagnose the problem. - if (valueObj == null) { - Utils.fail("%s's value is Null", - DetailsHelper.getDetailsName(context, detail.getKey())); - } - value = valueObj.toString(); - } - } - int key = detail.getKey(); - if (details.hasUnit(key)) { - value = String.format("%s: %s %s", DetailsHelper.getDetailsName( - context, key), value, context.getString(details.getUnit(key))); - } else { - value = String.format("%s: %s", DetailsHelper.getDetailsName( - context, key), value); - } - mItems.add(value); - if (!resolutionIsValid) { - DetailsHelper.resolveResolution(path, this); - } - } - } - - @Override - public boolean areAllItemsEnabled() { - return false; - } - - @Override - public boolean isEnabled(int position) { - return false; - } - - @Override - public int getCount() { - return mItems.size(); - } - - @Override - public Object getItem(int position) { - return mDetails.getDetail(position); - } - - @Override - public long getItemId(int position) { - return position; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - TextView tv; - if (convertView == null) { - tv = (TextView) LayoutInflater.from(mActivity.getAndroidContext()).inflate( - R.layout.details, parent, false); - } else { - tv = (TextView) convertView; - } - tv.setText(mItems.get(position)); - return tv; - } - - @Override - public void onAddressAvailable(String address) { - mItems.set(mLocationIndex, address); - notifyDataSetChanged(); - } - - @Override - public void onResolutionAvailable(int width, int height) { - if (width == 0 || height == 0) return; - // Update the resolution with the new width and height - Context context = mActivity.getAndroidContext(); - String widthString = String.format("%s: %d", DetailsHelper.getDetailsName( - context, MediaDetails.INDEX_WIDTH), width); - String heightString = String.format("%s: %d", DetailsHelper.getDetailsName( - context, MediaDetails.INDEX_HEIGHT), height); - mItems.set(mWidthIndex, String.valueOf(widthString)); - mItems.set(mHeightIndex, String.valueOf(heightString)); - notifyDataSetChanged(); - } - } - - @Override - public void setCloseListener(CloseListener listener) { - mListener = listener; - } -} diff --git a/src/com/android/gallery3d/ui/DownUpDetector.java b/src/com/android/gallery3d/ui/DownUpDetector.java deleted file mode 100644 index 19db77262..000000000 --- a/src/com/android/gallery3d/ui/DownUpDetector.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.view.MotionEvent; - -public class DownUpDetector { - public interface DownUpListener { - void onDown(MotionEvent e); - void onUp(MotionEvent e); - } - - private boolean mStillDown; - private DownUpListener mListener; - - public DownUpDetector(DownUpListener listener) { - mListener = listener; - } - - private void setState(boolean down, MotionEvent e) { - if (down == mStillDown) return; - mStillDown = down; - if (down) { - mListener.onDown(e); - } else { - mListener.onUp(e); - } - } - - public void onTouchEvent(MotionEvent ev) { - switch (ev.getAction() & MotionEvent.ACTION_MASK) { - case MotionEvent.ACTION_DOWN: - setState(true, ev); - break; - - case MotionEvent.ACTION_UP: - case MotionEvent.ACTION_CANCEL: - case MotionEvent.ACTION_POINTER_DOWN: // Multitouch event - abort. - setState(false, ev); - break; - } - } - - public boolean isDown() { - return mStillDown; - } -} diff --git a/src/com/android/gallery3d/ui/EdgeEffect.java b/src/com/android/gallery3d/ui/EdgeEffect.java deleted file mode 100644 index 87ff0c5d3..000000000 --- a/src/com/android/gallery3d/ui/EdgeEffect.java +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.android.gallery3d.R; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.ResourceTexture; - -// This is copied from android.widget.EdgeEffect with some small modifications: -// (1) Copy the images (overscroll_{edge|glow}.png) to local resources. -// (2) Use "GLCanvas" instead of "Canvas" for draw()'s parameter. -// (3) Use a private Drawable class (which inherits from ResourceTexture) -// instead of android.graphics.drawable.Drawable to hold the images. -// The private Drawable class is used to translate original Canvas calls to -// corresponding GLCanvas calls. - -/** - * This class performs the graphical effect used at the edges of scrollable widgets - * when the user scrolls beyond the content bounds in 2D space. - * - * <p>EdgeEffect is stateful. Custom widgets using EdgeEffect should create an - * instance for each edge that should show the effect, feed it input data using - * the methods {@link #onAbsorb(int)}, {@link #onPull(float)}, and {@link #onRelease()}, - * and draw the effect using {@link #draw(Canvas)} in the widget's overridden - * {@link android.view.View#draw(Canvas)} method. If {@link #isFinished()} returns - * false after drawing, the edge effect's animation is not yet complete and the widget - * should schedule another drawing pass to continue the animation.</p> - * - * <p>When drawing, widgets should draw their main content and child views first, - * usually by invoking <code>super.draw(canvas)</code> from an overridden <code>draw</code> - * method. (This will invoke onDraw and dispatch drawing to child views as needed.) - * The edge effect may then be drawn on top of the view's content using the - * {@link #draw(Canvas)} method.</p> - */ -public class EdgeEffect { - @SuppressWarnings("unused") - private static final String TAG = "EdgeEffect"; - - // Time it will take the effect to fully recede in ms - private static final int RECEDE_TIME = 1000; - - // Time it will take before a pulled glow begins receding in ms - private static final int PULL_TIME = 167; - - // Time it will take in ms for a pulled glow to decay to partial strength before release - private static final int PULL_DECAY_TIME = 1000; - - private static final float MAX_ALPHA = 0.8f; - private static final float HELD_EDGE_ALPHA = 0.7f; - private static final float HELD_EDGE_SCALE_Y = 0.5f; - private static final float HELD_GLOW_ALPHA = 0.5f; - private static final float HELD_GLOW_SCALE_Y = 0.5f; - - private static final float MAX_GLOW_HEIGHT = 4.f; - - private static final float PULL_GLOW_BEGIN = 1.f; - private static final float PULL_EDGE_BEGIN = 0.6f; - - // Minimum velocity that will be absorbed - private static final int MIN_VELOCITY = 100; - - private static final float EPSILON = 0.001f; - - private final Drawable mEdge; - private final Drawable mGlow; - private int mWidth; - private int mHeight; - private final int MIN_WIDTH = 300; - private final int mMinWidth; - - private float mEdgeAlpha; - private float mEdgeScaleY; - private float mGlowAlpha; - private float mGlowScaleY; - - private float mEdgeAlphaStart; - private float mEdgeAlphaFinish; - private float mEdgeScaleYStart; - private float mEdgeScaleYFinish; - private float mGlowAlphaStart; - private float mGlowAlphaFinish; - private float mGlowScaleYStart; - private float mGlowScaleYFinish; - - private long mStartTime; - private float mDuration; - - private final Interpolator mInterpolator; - - private static final int STATE_IDLE = 0; - private static final int STATE_PULL = 1; - private static final int STATE_ABSORB = 2; - private static final int STATE_RECEDE = 3; - private static final int STATE_PULL_DECAY = 4; - - // How much dragging should effect the height of the edge image. - // Number determined by user testing. - private static final int PULL_DISTANCE_EDGE_FACTOR = 7; - - // How much dragging should effect the height of the glow image. - // Number determined by user testing. - private static final int PULL_DISTANCE_GLOW_FACTOR = 7; - private static final float PULL_DISTANCE_ALPHA_GLOW_FACTOR = 1.1f; - - private static final int VELOCITY_EDGE_FACTOR = 8; - private static final int VELOCITY_GLOW_FACTOR = 16; - - private int mState = STATE_IDLE; - - private float mPullDistance; - - /** - * Construct a new EdgeEffect with a theme appropriate for the provided context. - * @param context Context used to provide theming and resource information for the EdgeEffect - */ - public EdgeEffect(Context context) { - mEdge = new Drawable(context, R.drawable.overscroll_edge); - mGlow = new Drawable(context, R.drawable.overscroll_glow); - - mMinWidth = (int) (context.getResources().getDisplayMetrics().density * MIN_WIDTH + 0.5f); - mInterpolator = new DecelerateInterpolator(); - } - - /** - * Set the size of this edge effect in pixels. - * - * @param width Effect width in pixels - * @param height Effect height in pixels - */ - public void setSize(int width, int height) { - mWidth = width; - mHeight = height; - } - - /** - * Reports if this EdgeEffect's animation is finished. If this method returns false - * after a call to {@link #draw(Canvas)} the host widget should schedule another - * drawing pass to continue the animation. - * - * @return true if animation is finished, false if drawing should continue on the next frame. - */ - public boolean isFinished() { - return mState == STATE_IDLE; - } - - /** - * Immediately finish the current animation. - * After this call {@link #isFinished()} will return true. - */ - public void finish() { - mState = STATE_IDLE; - } - - /** - * A view should call this when content is pulled away from an edge by the user. - * This will update the state of the current visual effect and its associated animation. - * The host view should always {@link android.view.View#invalidate()} after this - * and draw the results accordingly. - * - * @param deltaDistance Change in distance since the last call. Values may be 0 (no change) to - * 1.f (full length of the view) or negative values to express change - * back toward the edge reached to initiate the effect. - */ - public void onPull(float deltaDistance) { - final long now = AnimationTime.get(); - if (mState == STATE_PULL_DECAY && now - mStartTime < mDuration) { - return; - } - if (mState != STATE_PULL) { - mGlowScaleY = PULL_GLOW_BEGIN; - } - mState = STATE_PULL; - - mStartTime = now; - mDuration = PULL_TIME; - - mPullDistance += deltaDistance; - float distance = Math.abs(mPullDistance); - - mEdgeAlpha = mEdgeAlphaStart = Math.max(PULL_EDGE_BEGIN, Math.min(distance, MAX_ALPHA)); - mEdgeScaleY = mEdgeScaleYStart = Math.max( - HELD_EDGE_SCALE_Y, Math.min(distance * PULL_DISTANCE_EDGE_FACTOR, 1.f)); - - mGlowAlpha = mGlowAlphaStart = Math.min(MAX_ALPHA, - mGlowAlpha + - (Math.abs(deltaDistance) * PULL_DISTANCE_ALPHA_GLOW_FACTOR)); - - float glowChange = Math.abs(deltaDistance); - if (deltaDistance > 0 && mPullDistance < 0) { - glowChange = -glowChange; - } - if (mPullDistance == 0) { - mGlowScaleY = 0; - } - - // Do not allow glow to get larger than MAX_GLOW_HEIGHT. - mGlowScaleY = mGlowScaleYStart = Math.min(MAX_GLOW_HEIGHT, Math.max( - 0, mGlowScaleY + glowChange * PULL_DISTANCE_GLOW_FACTOR)); - - mEdgeAlphaFinish = mEdgeAlpha; - mEdgeScaleYFinish = mEdgeScaleY; - mGlowAlphaFinish = mGlowAlpha; - mGlowScaleYFinish = mGlowScaleY; - } - - /** - * Call when the object is released after being pulled. - * This will begin the "decay" phase of the effect. After calling this method - * the host view should {@link android.view.View#invalidate()} and thereby - * draw the results accordingly. - */ - public void onRelease() { - mPullDistance = 0; - - if (mState != STATE_PULL && mState != STATE_PULL_DECAY) { - return; - } - - mState = STATE_RECEDE; - mEdgeAlphaStart = mEdgeAlpha; - mEdgeScaleYStart = mEdgeScaleY; - mGlowAlphaStart = mGlowAlpha; - mGlowScaleYStart = mGlowScaleY; - - mEdgeAlphaFinish = 0.f; - mEdgeScaleYFinish = 0.f; - mGlowAlphaFinish = 0.f; - mGlowScaleYFinish = 0.f; - - mStartTime = AnimationTime.get(); - mDuration = RECEDE_TIME; - } - - /** - * Call when the effect absorbs an impact at the given velocity. - * Used when a fling reaches the scroll boundary. - * - * <p>When using a {@link android.widget.Scroller} or {@link android.widget.OverScroller}, - * the method <code>getCurrVelocity</code> will provide a reasonable approximation - * to use here.</p> - * - * @param velocity Velocity at impact in pixels per second. - */ - public void onAbsorb(int velocity) { - mState = STATE_ABSORB; - velocity = Math.max(MIN_VELOCITY, Math.abs(velocity)); - - mStartTime = AnimationTime.get(); - mDuration = 0.1f + (velocity * 0.03f); - - // The edge should always be at least partially visible, regardless - // of velocity. - mEdgeAlphaStart = 0.f; - mEdgeScaleY = mEdgeScaleYStart = 0.f; - // The glow depends more on the velocity, and therefore starts out - // nearly invisible. - mGlowAlphaStart = 0.5f; - mGlowScaleYStart = 0.f; - - // Factor the velocity by 8. Testing on device shows this works best to - // reflect the strength of the user's scrolling. - mEdgeAlphaFinish = Math.max(0, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1)); - // Edge should never get larger than the size of its asset. - mEdgeScaleYFinish = Math.max( - HELD_EDGE_SCALE_Y, Math.min(velocity * VELOCITY_EDGE_FACTOR, 1.f)); - - // Growth for the size of the glow should be quadratic to properly - // respond - // to a user's scrolling speed. The faster the scrolling speed, the more - // intense the effect should be for both the size and the saturation. - mGlowScaleYFinish = Math.min(0.025f + (velocity * (velocity / 100) * 0.00015f), 1.75f); - // Alpha should change for the glow as well as size. - mGlowAlphaFinish = Math.max( - mGlowAlphaStart, Math.min(velocity * VELOCITY_GLOW_FACTOR * .00001f, MAX_ALPHA)); - } - - - /** - * Draw into the provided canvas. Assumes that the canvas has been rotated - * accordingly and the size has been set. The effect will be drawn the full - * width of X=0 to X=width, beginning from Y=0 and extending to some factor < - * 1.f of height. - * - * @param canvas Canvas to draw into - * @return true if drawing should continue beyond this frame to continue the - * animation - */ - public boolean draw(GLCanvas canvas) { - update(); - - final int edgeHeight = mEdge.getIntrinsicHeight(); - final int edgeWidth = mEdge.getIntrinsicWidth(); - final int glowHeight = mGlow.getIntrinsicHeight(); - final int glowWidth = mGlow.getIntrinsicWidth(); - - mGlow.setAlpha((int) (Math.max(0, Math.min(mGlowAlpha, 1)) * 255)); - - int glowBottom = (int) Math.min( - glowHeight * mGlowScaleY * glowHeight/ glowWidth * 0.6f, - glowHeight * MAX_GLOW_HEIGHT); - if (mWidth < mMinWidth) { - // Center the glow and clip it. - int glowLeft = (mWidth - mMinWidth)/2; - mGlow.setBounds(glowLeft, 0, mWidth - glowLeft, glowBottom); - } else { - // Stretch the glow to fit. - mGlow.setBounds(0, 0, mWidth, glowBottom); - } - - mGlow.draw(canvas); - - mEdge.setAlpha((int) (Math.max(0, Math.min(mEdgeAlpha, 1)) * 255)); - - int edgeBottom = (int) (edgeHeight * mEdgeScaleY); - if (mWidth < mMinWidth) { - // Center the edge and clip it. - int edgeLeft = (mWidth - mMinWidth)/2; - mEdge.setBounds(edgeLeft, 0, mWidth - edgeLeft, edgeBottom); - } else { - // Stretch the edge to fit. - mEdge.setBounds(0, 0, mWidth, edgeBottom); - } - mEdge.draw(canvas); - - return mState != STATE_IDLE; - } - - private void update() { - final long time = AnimationTime.get(); - final float t = Math.min((time - mStartTime) / mDuration, 1.f); - - final float interp = mInterpolator.getInterpolation(t); - - mEdgeAlpha = mEdgeAlphaStart + (mEdgeAlphaFinish - mEdgeAlphaStart) * interp; - mEdgeScaleY = mEdgeScaleYStart + (mEdgeScaleYFinish - mEdgeScaleYStart) * interp; - mGlowAlpha = mGlowAlphaStart + (mGlowAlphaFinish - mGlowAlphaStart) * interp; - mGlowScaleY = mGlowScaleYStart + (mGlowScaleYFinish - mGlowScaleYStart) * interp; - - if (t >= 1.f - EPSILON) { - switch (mState) { - case STATE_ABSORB: - mState = STATE_RECEDE; - mStartTime = AnimationTime.get(); - mDuration = RECEDE_TIME; - - mEdgeAlphaStart = mEdgeAlpha; - mEdgeScaleYStart = mEdgeScaleY; - mGlowAlphaStart = mGlowAlpha; - mGlowScaleYStart = mGlowScaleY; - - // After absorb, the glow and edge should fade to nothing. - mEdgeAlphaFinish = 0.f; - mEdgeScaleYFinish = 0.f; - mGlowAlphaFinish = 0.f; - mGlowScaleYFinish = 0.f; - break; - case STATE_PULL: - mState = STATE_PULL_DECAY; - mStartTime = AnimationTime.get(); - mDuration = PULL_DECAY_TIME; - - mEdgeAlphaStart = mEdgeAlpha; - mEdgeScaleYStart = mEdgeScaleY; - mGlowAlphaStart = mGlowAlpha; - mGlowScaleYStart = mGlowScaleY; - - // After pull, the glow and edge should fade to nothing. - mEdgeAlphaFinish = 0.f; - mEdgeScaleYFinish = 0.f; - mGlowAlphaFinish = 0.f; - mGlowScaleYFinish = 0.f; - break; - case STATE_PULL_DECAY: - // When receding, we want edge to decrease more slowly - // than the glow. - float factor = mGlowScaleYFinish != 0 ? 1 - / (mGlowScaleYFinish * mGlowScaleYFinish) - : Float.MAX_VALUE; - mEdgeScaleY = mEdgeScaleYStart + - (mEdgeScaleYFinish - mEdgeScaleYStart) * - interp * factor; - mState = STATE_RECEDE; - break; - case STATE_RECEDE: - mState = STATE_IDLE; - break; - } - } - } - - private static class Drawable extends ResourceTexture { - private Rect mBounds = new Rect(); - private int mAlpha = 255; - - public Drawable(Context context, int resId) { - super(context, resId); - } - - public int getIntrinsicWidth() { - return getWidth(); - } - - public int getIntrinsicHeight() { - return getHeight(); - } - - public void setBounds(int left, int top, int right, int bottom) { - mBounds.set(left, top, right, bottom); - } - - public void setAlpha(int alpha) { - mAlpha = alpha; - } - - public void draw(GLCanvas canvas) { - canvas.save(GLCanvas.SAVE_FLAG_ALPHA); - canvas.multiplyAlpha(mAlpha / 255.0f); - Rect b = mBounds; - draw(canvas, b.left, b.top, b.width(), b.height()); - canvas.restore(); - } - } -} diff --git a/src/com/android/gallery3d/ui/EdgeView.java b/src/com/android/gallery3d/ui/EdgeView.java deleted file mode 100644 index 051de18fa..000000000 --- a/src/com/android/gallery3d/ui/EdgeView.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.opengl.Matrix; - -import com.android.gallery3d.glrenderer.GLCanvas; - -// EdgeView draws EdgeEffect (blue glow) at four sides of the view. -public class EdgeView extends GLView { - @SuppressWarnings("unused") - private static final String TAG = "EdgeView"; - - public static final int INVALID_DIRECTION = -1; - public static final int TOP = 0; - public static final int LEFT = 1; - public static final int BOTTOM = 2; - public static final int RIGHT = 3; - - // Each edge effect has a transform matrix, and each matrix has 16 elements. - // We put all the elements in one array. These constants specify the - // starting index of each matrix. - private static final int TOP_M = TOP * 16; - private static final int LEFT_M = LEFT * 16; - private static final int BOTTOM_M = BOTTOM * 16; - private static final int RIGHT_M = RIGHT * 16; - - private EdgeEffect[] mEffect = new EdgeEffect[4]; - private float[] mMatrix = new float[4 * 16]; - - public EdgeView(Context context) { - for (int i = 0; i < 4; i++) { - mEffect[i] = new EdgeEffect(context); - } - } - - @Override - protected void onLayout( - boolean changeSize, int left, int top, int right, int bottom) { - if (!changeSize) return; - - int w = right - left; - int h = bottom - top; - for (int i = 0; i < 4; i++) { - if ((i & 1) == 0) { // top or bottom - mEffect[i].setSize(w, h); - } else { // left or right - mEffect[i].setSize(h, w); - } - } - - // Set up transforms for the four edges. Without transforms an - // EdgeEffect draws the TOP edge from (0, 0) to (w, Y * h) where Y - // is some factor < 1. For other edges we need to move, rotate, and - // flip the effects into proper places. - Matrix.setIdentityM(mMatrix, TOP_M); - Matrix.setIdentityM(mMatrix, LEFT_M); - Matrix.setIdentityM(mMatrix, BOTTOM_M); - Matrix.setIdentityM(mMatrix, RIGHT_M); - - Matrix.rotateM(mMatrix, LEFT_M, 90, 0, 0, 1); - Matrix.scaleM(mMatrix, LEFT_M, 1, -1, 1); - - Matrix.translateM(mMatrix, BOTTOM_M, 0, h, 0); - Matrix.scaleM(mMatrix, BOTTOM_M, 1, -1, 1); - - Matrix.translateM(mMatrix, RIGHT_M, w, 0, 0); - Matrix.rotateM(mMatrix, RIGHT_M, 90, 0, 0, 1); - } - - @Override - protected void render(GLCanvas canvas) { - super.render(canvas); - boolean more = false; - for (int i = 0; i < 4; i++) { - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - canvas.multiplyMatrix(mMatrix, i * 16); - more |= mEffect[i].draw(canvas); - canvas.restore(); - } - if (more) { - invalidate(); - } - } - - // Called when the content is pulled away from the edge. - // offset is in pixels. direction is one of {TOP, LEFT, BOTTOM, RIGHT}. - public void onPull(int offset, int direction) { - int fullLength = ((direction & 1) == 0) ? getWidth() : getHeight(); - mEffect[direction].onPull((float)offset / fullLength); - if (!mEffect[direction].isFinished()) { - invalidate(); - } - } - - // Call when the object is released after being pulled. - public void onRelease() { - boolean more = false; - for (int i = 0; i < 4; i++) { - mEffect[i].onRelease(); - more |= !mEffect[i].isFinished(); - } - if (more) { - invalidate(); - } - } - - // Call when the effect absorbs an impact at the given velocity. - // Used when a fling reaches the scroll boundary. velocity is in pixels - // per second. direction is one of {TOP, LEFT, BOTTOM, RIGHT}. - public void onAbsorb(int velocity, int direction) { - mEffect[direction].onAbsorb(velocity); - if (!mEffect[direction].isFinished()) { - invalidate(); - } - } -} diff --git a/src/com/android/gallery3d/ui/FlingScroller.java b/src/com/android/gallery3d/ui/FlingScroller.java deleted file mode 100644 index 6f98c64f9..000000000 --- a/src/com/android/gallery3d/ui/FlingScroller.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - - -// This is a customized version of Scroller, with a interface similar to -// android.widget.Scroller. It does fling only, not scroll. -// -// The differences between the this Scroller and the system one are: -// -// (1) The velocity does not change because of min/max limit. -// (2) The duration is different. -// (3) The deceleration curve is different. -class FlingScroller { - @SuppressWarnings("unused") - private static final String TAG = "FlingController"; - - // The fling duration (in milliseconds) when velocity is 1 pixel/second - private static final float FLING_DURATION_PARAM = 50f; - private static final int DECELERATED_FACTOR = 4; - - private int mStartX, mStartY; - private int mMinX, mMinY, mMaxX, mMaxY; - private double mSinAngle; - private double mCosAngle; - private int mDuration; - private int mDistance; - private int mFinalX, mFinalY; - - private int mCurrX, mCurrY; - private double mCurrV; - - public int getFinalX() { - return mFinalX; - } - - public int getFinalY() { - return mFinalY; - } - - public int getDuration() { - return mDuration; - } - - public int getCurrX() { - return mCurrX; - - } - - public int getCurrY() { - return mCurrY; - } - - public int getCurrVelocityX() { - return (int)Math.round(mCurrV * mCosAngle); - } - - public int getCurrVelocityY() { - return (int)Math.round(mCurrV * mSinAngle); - } - - public void fling(int startX, int startY, int velocityX, int velocityY, - int minX, int maxX, int minY, int maxY) { - mStartX = startX; - mStartY = startY; - mMinX = minX; - mMinY = minY; - mMaxX = maxX; - mMaxY = maxY; - - double velocity = Math.hypot(velocityX, velocityY); - mSinAngle = velocityY / velocity; - mCosAngle = velocityX / velocity; - // - // The position formula: x(t) = s + (e - s) * (1 - (1 - t / T) ^ d) - // velocity formula: v(t) = d * (e - s) * (1 - t / T) ^ (d - 1) / T - // Thus, - // v0 = d * (e - s) / T => (e - s) = v0 * T / d - // - - // Ta = T_ref * (Va / V_ref) ^ (1 / (d - 1)); V_ref = 1 pixel/second; - mDuration = (int)Math.round(FLING_DURATION_PARAM - * Math.pow(Math.abs(velocity), 1.0 / (DECELERATED_FACTOR - 1))); - - // (e - s) = v0 * T / d - mDistance = (int)Math.round( - velocity * mDuration / DECELERATED_FACTOR / 1000); - - mFinalX = getX(1.0f); - mFinalY = getY(1.0f); - } - - public void computeScrollOffset(float progress) { - progress = Math.min(progress, 1); - float f = 1 - progress; - f = 1 - (float) Math.pow(f, DECELERATED_FACTOR); - mCurrX = getX(f); - mCurrY = getY(f); - mCurrV = getV(progress); - } - - private int getX(float f) { - int r = (int) Math.round(mStartX + f * mDistance * mCosAngle); - if (mCosAngle > 0 && mStartX <= mMaxX) { - r = Math.min(r, mMaxX); - } else if (mCosAngle < 0 && mStartX >= mMinX) { - r = Math.max(r, mMinX); - } - return r; - } - - private int getY(float f) { - int r = (int) Math.round(mStartY + f * mDistance * mSinAngle); - if (mSinAngle > 0 && mStartY <= mMaxY) { - r = Math.min(r, mMaxY); - } else if (mSinAngle < 0 && mStartY >= mMinY) { - r = Math.max(r, mMinY); - } - return r; - } - - private double getV(float progress) { - // velocity formula: v(t) = d * (e - s) * (1 - t / T) ^ (d - 1) / T - return DECELERATED_FACTOR * mDistance * 1000 * - Math.pow(1 - progress, DECELERATED_FACTOR - 1) / mDuration; - } -} diff --git a/src/com/android/gallery3d/ui/GLRoot.java b/src/com/android/gallery3d/ui/GLRoot.java deleted file mode 100644 index 33a82eaf7..000000000 --- a/src/com/android/gallery3d/ui/GLRoot.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Matrix; - -import com.android.gallery3d.anim.CanvasAnimation; -import com.android.gallery3d.glrenderer.GLCanvas; - -public interface GLRoot { - - // Listener will be called when GL is idle AND before each frame. - // Mainly used for uploading textures. - public static interface OnGLIdleListener { - public boolean onGLIdle( - GLCanvas canvas, boolean renderRequested); - } - - public void addOnGLIdleListener(OnGLIdleListener listener); - public void registerLaunchedAnimation(CanvasAnimation animation); - public void requestRenderForced(); - public void requestRender(); - public void requestLayoutContentPane(); - - public void lockRenderThread(); - public void unlockRenderThread(); - - public void setContentPane(GLView content); - public void setOrientationSource(OrientationSource source); - public int getDisplayRotation(); - public int getCompensation(); - public Matrix getCompensationMatrix(); - public void freeze(); - public void unfreeze(); - public void setLightsOutMode(boolean enabled); - - public Context getContext(); -} diff --git a/src/com/android/gallery3d/ui/GLRootView.java b/src/com/android/gallery3d/ui/GLRootView.java deleted file mode 100644 index dc898d83d..000000000 --- a/src/com/android/gallery3d/ui/GLRootView.java +++ /dev/null @@ -1,630 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Matrix; -import android.graphics.PixelFormat; -import android.opengl.GLSurfaceView; -import android.os.Build; -import android.os.Process; -import android.os.SystemClock; -import android.util.AttributeSet; -import android.view.MotionEvent; -import android.view.SurfaceHolder; -import android.view.View; - -import com.android.gallery3d.R; -import com.android.gallery3d.anim.CanvasAnimation; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.BasicTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.GLES11Canvas; -import com.android.gallery3d.glrenderer.GLES20Canvas; -import com.android.gallery3d.glrenderer.UploadedTexture; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.MotionEventHelper; -import com.android.gallery3d.util.Profile; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.ReentrantLock; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; -import javax.microedition.khronos.opengles.GL11; - -// The root component of all <code>GLView</code>s. The rendering is done in GL -// thread while the event handling is done in the main thread. To synchronize -// the two threads, the entry points of this package need to synchronize on the -// <code>GLRootView</code> instance unless it can be proved that the rendering -// thread won't access the same thing as the method. The entry points include: -// (1) The public methods of HeadUpDisplay -// (2) The public methods of CameraHeadUpDisplay -// (3) The overridden methods in GLRootView. -public class GLRootView extends GLSurfaceView - implements GLSurfaceView.Renderer, GLRoot { - private static final String TAG = "GLRootView"; - - private static final boolean DEBUG_FPS = false; - private int mFrameCount = 0; - private long mFrameCountingStart = 0; - - private static final boolean DEBUG_INVALIDATE = false; - private int mInvalidateColor = 0; - - private static final boolean DEBUG_DRAWING_STAT = false; - - private static final boolean DEBUG_PROFILE = false; - private static final boolean DEBUG_PROFILE_SLOW_ONLY = false; - - private static final int FLAG_INITIALIZED = 1; - private static final int FLAG_NEED_LAYOUT = 2; - - private GL11 mGL; - private GLCanvas mCanvas; - private GLView mContentView; - - private OrientationSource mOrientationSource; - // mCompensation is the difference between the UI orientation on GLCanvas - // and the framework orientation. See OrientationManager for details. - private int mCompensation; - // mCompensationMatrix maps the coordinates of touch events. It is kept sync - // with mCompensation. - private Matrix mCompensationMatrix = new Matrix(); - private int mDisplayRotation; - - private int mFlags = FLAG_NEED_LAYOUT; - private volatile boolean mRenderRequested = false; - - private final ArrayList<CanvasAnimation> mAnimations = - new ArrayList<CanvasAnimation>(); - - private final ArrayDeque<OnGLIdleListener> mIdleListeners = - new ArrayDeque<OnGLIdleListener>(); - - private final IdleRunner mIdleRunner = new IdleRunner(); - - private final ReentrantLock mRenderLock = new ReentrantLock(); - private final Condition mFreezeCondition = - mRenderLock.newCondition(); - private boolean mFreeze; - - private long mLastDrawFinishTime; - private boolean mInDownState = false; - private boolean mFirstDraw = true; - - public GLRootView(Context context) { - this(context, null); - } - - public GLRootView(Context context, AttributeSet attrs) { - super(context, attrs); - mFlags |= FLAG_INITIALIZED; - setBackgroundDrawable(null); - setEGLContextClientVersion(ApiHelper.HAS_GLES20_REQUIRED ? 2 : 1); - if (ApiHelper.USE_888_PIXEL_FORMAT) { - setEGLConfigChooser(8, 8, 8, 0, 0, 0); - } else { - setEGLConfigChooser(5, 6, 5, 0, 0, 0); - } - setRenderer(this); - if (ApiHelper.USE_888_PIXEL_FORMAT) { - getHolder().setFormat(PixelFormat.RGB_888); - } else { - getHolder().setFormat(PixelFormat.RGB_565); - } - - // Uncomment this to enable gl error check. - // setDebugFlags(DEBUG_CHECK_GL_ERROR); - } - - @Override - public void registerLaunchedAnimation(CanvasAnimation animation) { - // Register the newly launched animation so that we can set the start - // time more precisely. (Usually, it takes much longer for first - // rendering, so we set the animation start time as the time we - // complete rendering) - mAnimations.add(animation); - } - - @Override - public void addOnGLIdleListener(OnGLIdleListener listener) { - synchronized (mIdleListeners) { - mIdleListeners.addLast(listener); - mIdleRunner.enable(); - } - } - - @Override - public void setContentPane(GLView content) { - if (mContentView == content) return; - if (mContentView != null) { - if (mInDownState) { - long now = SystemClock.uptimeMillis(); - MotionEvent cancelEvent = MotionEvent.obtain( - now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); - mContentView.dispatchTouchEvent(cancelEvent); - cancelEvent.recycle(); - mInDownState = false; - } - mContentView.detachFromRoot(); - BasicTexture.yieldAllTextures(); - } - mContentView = content; - if (content != null) { - content.attachToRoot(this); - requestLayoutContentPane(); - } - } - - @Override - public void requestRenderForced() { - superRequestRender(); - } - - @Override - public void requestRender() { - if (DEBUG_INVALIDATE) { - StackTraceElement e = Thread.currentThread().getStackTrace()[4]; - String caller = e.getFileName() + ":" + e.getLineNumber() + " "; - Log.d(TAG, "invalidate: " + caller); - } - if (mRenderRequested) return; - mRenderRequested = true; - if (ApiHelper.HAS_POST_ON_ANIMATION) { - postOnAnimation(mRequestRenderOnAnimationFrame); - } else { - super.requestRender(); - } - } - - private Runnable mRequestRenderOnAnimationFrame = new Runnable() { - @Override - public void run() { - superRequestRender(); - } - }; - - private void superRequestRender() { - super.requestRender(); - } - - @Override - public void requestLayoutContentPane() { - mRenderLock.lock(); - try { - if (mContentView == null || (mFlags & FLAG_NEED_LAYOUT) != 0) return; - - // "View" system will invoke onLayout() for initialization(bug ?), we - // have to ignore it since the GLThread is not ready yet. - if ((mFlags & FLAG_INITIALIZED) == 0) return; - - mFlags |= FLAG_NEED_LAYOUT; - requestRender(); - } finally { - mRenderLock.unlock(); - } - } - - private void layoutContentPane() { - mFlags &= ~FLAG_NEED_LAYOUT; - - int w = getWidth(); - int h = getHeight(); - int displayRotation = 0; - int compensation = 0; - - // Get the new orientation values - if (mOrientationSource != null) { - displayRotation = mOrientationSource.getDisplayRotation(); - compensation = mOrientationSource.getCompensation(); - } else { - displayRotation = 0; - compensation = 0; - } - - if (mCompensation != compensation) { - mCompensation = compensation; - if (mCompensation % 180 != 0) { - mCompensationMatrix.setRotate(mCompensation); - // move center to origin before rotation - mCompensationMatrix.preTranslate(-w / 2, -h / 2); - // align with the new origin after rotation - mCompensationMatrix.postTranslate(h / 2, w / 2); - } else { - mCompensationMatrix.setRotate(mCompensation, w / 2, h / 2); - } - } - mDisplayRotation = displayRotation; - - // Do the actual layout. - if (mCompensation % 180 != 0) { - int tmp = w; - w = h; - h = tmp; - } - Log.i(TAG, "layout content pane " + w + "x" + h - + " (compensation " + mCompensation + ")"); - if (mContentView != null && w != 0 && h != 0) { - mContentView.layout(0, 0, w, h); - } - // Uncomment this to dump the view hierarchy. - //mContentView.dumpTree(""); - } - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - if (changed) requestLayoutContentPane(); - } - - /** - * Called when the context is created, possibly after automatic destruction. - */ - // This is a GLSurfaceView.Renderer callback - @Override - public void onSurfaceCreated(GL10 gl1, EGLConfig config) { - GL11 gl = (GL11) gl1; - if (mGL != null) { - // The GL Object has changed - Log.i(TAG, "GLObject has changed from " + mGL + " to " + gl); - } - mRenderLock.lock(); - try { - mGL = gl; - mCanvas = ApiHelper.HAS_GLES20_REQUIRED ? new GLES20Canvas() : new GLES11Canvas(gl); - BasicTexture.invalidateAllTextures(); - } finally { - mRenderLock.unlock(); - } - - if (DEBUG_FPS || DEBUG_PROFILE) { - setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY); - } else { - setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - } - } - - /** - * Called when the OpenGL surface is recreated without destroying the - * context. - */ - // This is a GLSurfaceView.Renderer callback - @Override - public void onSurfaceChanged(GL10 gl1, int width, int height) { - Log.i(TAG, "onSurfaceChanged: " + width + "x" + height - + ", gl10: " + gl1.toString()); - Process.setThreadPriority(Process.THREAD_PRIORITY_DISPLAY); - GalleryUtils.setRenderThread(); - if (DEBUG_PROFILE) { - Log.d(TAG, "Start profiling"); - Profile.enable(20); // take a sample every 20ms - } - GL11 gl = (GL11) gl1; - Utils.assertTrue(mGL == gl); - - mCanvas.setSize(width, height); - } - - private void outputFps() { - long now = System.nanoTime(); - if (mFrameCountingStart == 0) { - mFrameCountingStart = now; - } else if ((now - mFrameCountingStart) > 1000000000) { - Log.d(TAG, "fps: " + (double) mFrameCount - * 1000000000 / (now - mFrameCountingStart)); - mFrameCountingStart = now; - mFrameCount = 0; - } - ++mFrameCount; - } - - @Override - public void onDrawFrame(GL10 gl) { - AnimationTime.update(); - long t0; - if (DEBUG_PROFILE_SLOW_ONLY) { - Profile.hold(); - t0 = System.nanoTime(); - } - mRenderLock.lock(); - - while (mFreeze) { - mFreezeCondition.awaitUninterruptibly(); - } - - try { - onDrawFrameLocked(gl); - } finally { - mRenderLock.unlock(); - } - - // We put a black cover View in front of the SurfaceView and hide it - // after the first draw. This prevents the SurfaceView being transparent - // before the first draw. - if (mFirstDraw) { - mFirstDraw = false; - post(new Runnable() { - @Override - public void run() { - View root = getRootView(); - View cover = root.findViewById(R.id.gl_root_cover); - cover.setVisibility(GONE); - } - }); - } - - if (DEBUG_PROFILE_SLOW_ONLY) { - long t = System.nanoTime(); - long durationInMs = (t - mLastDrawFinishTime) / 1000000; - long durationDrawInMs = (t - t0) / 1000000; - mLastDrawFinishTime = t; - - if (durationInMs > 34) { // 34ms -> we skipped at least 2 frames - Log.v(TAG, "----- SLOW (" + durationDrawInMs + "/" + - durationInMs + ") -----"); - Profile.commit(); - } else { - Profile.drop(); - } - } - } - - private void onDrawFrameLocked(GL10 gl) { - if (DEBUG_FPS) outputFps(); - - // release the unbound textures and deleted buffers. - mCanvas.deleteRecycledResources(); - - // reset texture upload limit - UploadedTexture.resetUploadLimit(); - - mRenderRequested = false; - - if ((mOrientationSource != null - && mDisplayRotation != mOrientationSource.getDisplayRotation()) - || (mFlags & FLAG_NEED_LAYOUT) != 0) { - layoutContentPane(); - } - - mCanvas.save(GLCanvas.SAVE_FLAG_ALL); - rotateCanvas(-mCompensation); - if (mContentView != null) { - mContentView.render(mCanvas); - } else { - // Make sure we always draw something to prevent displaying garbage - mCanvas.clearBuffer(); - } - mCanvas.restore(); - - if (!mAnimations.isEmpty()) { - long now = AnimationTime.get(); - for (int i = 0, n = mAnimations.size(); i < n; i++) { - mAnimations.get(i).setStartTime(now); - } - mAnimations.clear(); - } - - if (UploadedTexture.uploadLimitReached()) { - requestRender(); - } - - synchronized (mIdleListeners) { - if (!mIdleListeners.isEmpty()) mIdleRunner.enable(); - } - - if (DEBUG_INVALIDATE) { - mCanvas.fillRect(10, 10, 5, 5, mInvalidateColor); - mInvalidateColor = ~mInvalidateColor; - } - - if (DEBUG_DRAWING_STAT) { - mCanvas.dumpStatisticsAndClear(); - } - } - - private void rotateCanvas(int degrees) { - if (degrees == 0) return; - int w = getWidth(); - int h = getHeight(); - int cx = w / 2; - int cy = h / 2; - mCanvas.translate(cx, cy); - mCanvas.rotate(degrees, 0, 0, 1); - if (degrees % 180 != 0) { - mCanvas.translate(-cy, -cx); - } else { - mCanvas.translate(-cx, -cy); - } - } - - @Override - public boolean dispatchTouchEvent(MotionEvent event) { - if (!isEnabled()) return false; - - int action = event.getAction(); - if (action == MotionEvent.ACTION_CANCEL - || action == MotionEvent.ACTION_UP) { - mInDownState = false; - } else if (!mInDownState && action != MotionEvent.ACTION_DOWN) { - return false; - } - - if (mCompensation != 0) { - event = MotionEventHelper.transformEvent(event, mCompensationMatrix); - } - - mRenderLock.lock(); - try { - // If this has been detached from root, we don't need to handle event - boolean handled = mContentView != null - && mContentView.dispatchTouchEvent(event); - if (action == MotionEvent.ACTION_DOWN && handled) { - mInDownState = true; - } - return handled; - } finally { - mRenderLock.unlock(); - } - } - - private class IdleRunner implements Runnable { - // true if the idle runner is in the queue - private boolean mActive = false; - - @Override - public void run() { - OnGLIdleListener listener; - synchronized (mIdleListeners) { - mActive = false; - if (mIdleListeners.isEmpty()) return; - listener = mIdleListeners.removeFirst(); - } - mRenderLock.lock(); - boolean keepInQueue; - try { - keepInQueue = listener.onGLIdle(mCanvas, mRenderRequested); - } finally { - mRenderLock.unlock(); - } - synchronized (mIdleListeners) { - if (keepInQueue) mIdleListeners.addLast(listener); - if (!mRenderRequested && !mIdleListeners.isEmpty()) enable(); - } - } - - public void enable() { - // Who gets the flag can add it to the queue - if (mActive) return; - mActive = true; - queueEvent(this); - } - } - - @Override - public void lockRenderThread() { - mRenderLock.lock(); - } - - @Override - public void unlockRenderThread() { - mRenderLock.unlock(); - } - - @Override - public void onPause() { - unfreeze(); - super.onPause(); - if (DEBUG_PROFILE) { - Log.d(TAG, "Stop profiling"); - Profile.disableAll(); - Profile.dumpToFile("/sdcard/gallery.prof"); - Profile.reset(); - } - } - - @Override - public void setOrientationSource(OrientationSource source) { - mOrientationSource = source; - } - - @Override - public int getDisplayRotation() { - return mDisplayRotation; - } - - @Override - public int getCompensation() { - return mCompensation; - } - - @Override - public Matrix getCompensationMatrix() { - return mCompensationMatrix; - } - - @Override - public void freeze() { - mRenderLock.lock(); - mFreeze = true; - mRenderLock.unlock(); - } - - @Override - public void unfreeze() { - mRenderLock.lock(); - mFreeze = false; - mFreezeCondition.signalAll(); - mRenderLock.unlock(); - } - - @Override - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - public void setLightsOutMode(boolean enabled) { - if (!ApiHelper.HAS_SET_SYSTEM_UI_VISIBILITY) return; - - int flags = 0; - if (enabled) { - flags = STATUS_BAR_HIDDEN; - if (ApiHelper.HAS_VIEW_SYSTEM_UI_FLAG_LAYOUT_STABLE) { - flags |= (SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_LAYOUT_STABLE); - } - } - setSystemUiVisibility(flags); - } - - // We need to unfreeze in the following methods and in onPause(). - // These methods will wait on GLThread. If we have freezed the GLRootView, - // the GLThread will wait on main thread to call unfreeze and cause dead - // lock. - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { - unfreeze(); - super.surfaceChanged(holder, format, w, h); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - unfreeze(); - super.surfaceCreated(holder); - } - - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - unfreeze(); - super.surfaceDestroyed(holder); - } - - @Override - protected void onDetachedFromWindow() { - unfreeze(); - super.onDetachedFromWindow(); - } - - @Override - protected void finalize() throws Throwable { - try { - unfreeze(); - } finally { - super.finalize(); - } - } -} diff --git a/src/com/android/gallery3d/ui/GLView.java b/src/com/android/gallery3d/ui/GLView.java deleted file mode 100644 index 83de19fe4..000000000 --- a/src/com/android/gallery3d/ui/GLView.java +++ /dev/null @@ -1,465 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Rect; -import android.os.SystemClock; -import android.view.MotionEvent; - -import com.android.gallery3d.anim.CanvasAnimation; -import com.android.gallery3d.anim.StateTransitionAnimation; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.GLCanvas; - -import java.util.ArrayList; - -// GLView is a UI component. It can render to a GLCanvas and accept touch -// events. A GLView may have zero or more child GLView and they form a tree -// structure. The rendering and event handling will pass through the tree -// structure. -// -// A GLView tree should be attached to a GLRoot before event dispatching and -// rendering happens. GLView asks GLRoot to re-render or re-layout the -// GLView hierarchy using requestRender() and requestLayoutContentPane(). -// -// The render() method is called in a separate thread. Before calling -// dispatchTouchEvent() and layout(), GLRoot acquires a lock to avoid the -// rendering thread running at the same time. If there are other entry points -// from main thread (like a Handler) in your GLView, you need to call -// lockRendering() if the rendering thread should not run at the same time. -// -public class GLView { - private static final String TAG = "GLView"; - - public static final int VISIBLE = 0; - public static final int INVISIBLE = 1; - - private static final int FLAG_INVISIBLE = 1; - private static final int FLAG_SET_MEASURED_SIZE = 2; - private static final int FLAG_LAYOUT_REQUESTED = 4; - - public interface OnClickListener { - void onClick(GLView v); - } - - protected final Rect mBounds = new Rect(); - protected final Rect mPaddings = new Rect(); - - private GLRoot mRoot; - protected GLView mParent; - private ArrayList<GLView> mComponents; - private GLView mMotionTarget; - - private CanvasAnimation mAnimation; - - private int mViewFlags = 0; - - protected int mMeasuredWidth = 0; - protected int mMeasuredHeight = 0; - - private int mLastWidthSpec = -1; - private int mLastHeightSpec = -1; - - protected int mScrollY = 0; - protected int mScrollX = 0; - protected int mScrollHeight = 0; - protected int mScrollWidth = 0; - - private float [] mBackgroundColor; - private StateTransitionAnimation mTransition; - - public void startAnimation(CanvasAnimation animation) { - GLRoot root = getGLRoot(); - if (root == null) throw new IllegalStateException(); - mAnimation = animation; - if (mAnimation != null) { - mAnimation.start(); - root.registerLaunchedAnimation(mAnimation); - } - invalidate(); - } - - // Sets the visiblity of this GLView (either GLView.VISIBLE or - // GLView.INVISIBLE). - public void setVisibility(int visibility) { - if (visibility == getVisibility()) return; - if (visibility == VISIBLE) { - mViewFlags &= ~FLAG_INVISIBLE; - } else { - mViewFlags |= FLAG_INVISIBLE; - } - onVisibilityChanged(visibility); - invalidate(); - } - - // Returns GLView.VISIBLE or GLView.INVISIBLE - public int getVisibility() { - return (mViewFlags & FLAG_INVISIBLE) == 0 ? VISIBLE : INVISIBLE; - } - - // This should only be called on the content pane (the topmost GLView). - public void attachToRoot(GLRoot root) { - Utils.assertTrue(mParent == null && mRoot == null); - onAttachToRoot(root); - } - - // This should only be called on the content pane (the topmost GLView). - public void detachFromRoot() { - Utils.assertTrue(mParent == null && mRoot != null); - onDetachFromRoot(); - } - - // Returns the number of children of the GLView. - public int getComponentCount() { - return mComponents == null ? 0 : mComponents.size(); - } - - // Returns the children for the given index. - public GLView getComponent(int index) { - if (mComponents == null) { - throw new ArrayIndexOutOfBoundsException(index); - } - return mComponents.get(index); - } - - // Adds a child to this GLView. - public void addComponent(GLView component) { - // Make sure the component doesn't have a parent currently. - if (component.mParent != null) throw new IllegalStateException(); - - // Build parent-child links - if (mComponents == null) { - mComponents = new ArrayList<GLView>(); - } - mComponents.add(component); - component.mParent = this; - - // If this is added after we have a root, tell the component. - if (mRoot != null) { - component.onAttachToRoot(mRoot); - } - } - - // Removes a child from this GLView. - public boolean removeComponent(GLView component) { - if (mComponents == null) return false; - if (mComponents.remove(component)) { - removeOneComponent(component); - return true; - } - return false; - } - - // Removes all children of this GLView. - public void removeAllComponents() { - for (int i = 0, n = mComponents.size(); i < n; ++i) { - removeOneComponent(mComponents.get(i)); - } - mComponents.clear(); - } - - private void removeOneComponent(GLView component) { - if (mMotionTarget == component) { - long now = SystemClock.uptimeMillis(); - MotionEvent cancelEvent = MotionEvent.obtain( - now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); - dispatchTouchEvent(cancelEvent); - cancelEvent.recycle(); - } - component.onDetachFromRoot(); - component.mParent = null; - } - - public Rect bounds() { - return mBounds; - } - - public int getWidth() { - return mBounds.right - mBounds.left; - } - - public int getHeight() { - return mBounds.bottom - mBounds.top; - } - - public GLRoot getGLRoot() { - return mRoot; - } - - // Request re-rendering of the view hierarchy. - // This is used for animation or when the contents changed. - public void invalidate() { - GLRoot root = getGLRoot(); - if (root != null) root.requestRender(); - } - - // Request re-layout of the view hierarchy. - public void requestLayout() { - mViewFlags |= FLAG_LAYOUT_REQUESTED; - mLastHeightSpec = -1; - mLastWidthSpec = -1; - if (mParent != null) { - mParent.requestLayout(); - } else { - // Is this a content pane ? - GLRoot root = getGLRoot(); - if (root != null) root.requestLayoutContentPane(); - } - } - - protected void render(GLCanvas canvas) { - boolean transitionActive = false; - if (mTransition != null && mTransition.calculate(AnimationTime.get())) { - invalidate(); - transitionActive = mTransition.isActive(); - } - renderBackground(canvas); - canvas.save(); - if (transitionActive) { - mTransition.applyContentTransform(this, canvas); - } - for (int i = 0, n = getComponentCount(); i < n; ++i) { - renderChild(canvas, getComponent(i)); - } - canvas.restore(); - if (transitionActive) { - mTransition.applyOverlay(this, canvas); - } - } - - public void setIntroAnimation(StateTransitionAnimation intro) { - mTransition = intro; - if (mTransition != null) mTransition.start(); - } - - public float [] getBackgroundColor() { - return mBackgroundColor; - } - - public void setBackgroundColor(float [] color) { - mBackgroundColor = color; - } - - protected void renderBackground(GLCanvas view) { - if (mBackgroundColor != null) { - view.clearBuffer(mBackgroundColor); - } - if (mTransition != null && mTransition.isActive()) { - mTransition.applyBackground(this, view); - return; - } - } - - protected void renderChild(GLCanvas canvas, GLView component) { - if (component.getVisibility() != GLView.VISIBLE - && component.mAnimation == null) return; - - int xoffset = component.mBounds.left - mScrollX; - int yoffset = component.mBounds.top - mScrollY; - - canvas.translate(xoffset, yoffset); - - CanvasAnimation anim = component.mAnimation; - if (anim != null) { - canvas.save(anim.getCanvasSaveFlags()); - if (anim.calculate(AnimationTime.get())) { - invalidate(); - } else { - component.mAnimation = null; - } - anim.apply(canvas); - } - component.render(canvas); - if (anim != null) canvas.restore(); - canvas.translate(-xoffset, -yoffset); - } - - protected boolean onTouch(MotionEvent event) { - return false; - } - - protected boolean dispatchTouchEvent(MotionEvent event, - int x, int y, GLView component, boolean checkBounds) { - Rect rect = component.mBounds; - int left = rect.left; - int top = rect.top; - if (!checkBounds || rect.contains(x, y)) { - event.offsetLocation(-left, -top); - if (component.dispatchTouchEvent(event)) { - event.offsetLocation(left, top); - return true; - } - event.offsetLocation(left, top); - } - return false; - } - - protected boolean dispatchTouchEvent(MotionEvent event) { - int x = (int) event.getX(); - int y = (int) event.getY(); - int action = event.getAction(); - if (mMotionTarget != null) { - if (action == MotionEvent.ACTION_DOWN) { - MotionEvent cancel = MotionEvent.obtain(event); - cancel.setAction(MotionEvent.ACTION_CANCEL); - dispatchTouchEvent(cancel, x, y, mMotionTarget, false); - mMotionTarget = null; - } else { - dispatchTouchEvent(event, x, y, mMotionTarget, false); - if (action == MotionEvent.ACTION_CANCEL - || action == MotionEvent.ACTION_UP) { - mMotionTarget = null; - } - return true; - } - } - if (action == MotionEvent.ACTION_DOWN) { - // in the reverse rendering order - for (int i = getComponentCount() - 1; i >= 0; --i) { - GLView component = getComponent(i); - if (component.getVisibility() != GLView.VISIBLE) continue; - if (dispatchTouchEvent(event, x, y, component, true)) { - mMotionTarget = component; - return true; - } - } - } - return onTouch(event); - } - - public Rect getPaddings() { - return mPaddings; - } - - public void layout(int left, int top, int right, int bottom) { - boolean sizeChanged = setBounds(left, top, right, bottom); - mViewFlags &= ~FLAG_LAYOUT_REQUESTED; - // We call onLayout no matter sizeChanged is true or not because the - // orientation may change without changing the size of the View (for - // example, rotate the device by 180 degrees), and we want to handle - // orientation change in onLayout. - onLayout(sizeChanged, left, top, right, bottom); - } - - private boolean setBounds(int left, int top, int right, int bottom) { - boolean sizeChanged = (right - left) != (mBounds.right - mBounds.left) - || (bottom - top) != (mBounds.bottom - mBounds.top); - mBounds.set(left, top, right, bottom); - return sizeChanged; - } - - public void measure(int widthSpec, int heightSpec) { - if (widthSpec == mLastWidthSpec && heightSpec == mLastHeightSpec - && (mViewFlags & FLAG_LAYOUT_REQUESTED) == 0) { - return; - } - - mLastWidthSpec = widthSpec; - mLastHeightSpec = heightSpec; - - mViewFlags &= ~FLAG_SET_MEASURED_SIZE; - onMeasure(widthSpec, heightSpec); - if ((mViewFlags & FLAG_SET_MEASURED_SIZE) == 0) { - throw new IllegalStateException(getClass().getName() - + " should call setMeasuredSize() in onMeasure()"); - } - } - - protected void onMeasure(int widthSpec, int heightSpec) { - } - - protected void setMeasuredSize(int width, int height) { - mViewFlags |= FLAG_SET_MEASURED_SIZE; - mMeasuredWidth = width; - mMeasuredHeight = height; - } - - public int getMeasuredWidth() { - return mMeasuredWidth; - } - - public int getMeasuredHeight() { - return mMeasuredHeight; - } - - protected void onLayout( - boolean changeSize, int left, int top, int right, int bottom) { - } - - /** - * Gets the bounds of the given descendant that relative to this view. - */ - public boolean getBoundsOf(GLView descendant, Rect out) { - int xoffset = 0; - int yoffset = 0; - GLView view = descendant; - while (view != this) { - if (view == null) return false; - Rect bounds = view.mBounds; - xoffset += bounds.left; - yoffset += bounds.top; - view = view.mParent; - } - out.set(xoffset, yoffset, xoffset + descendant.getWidth(), - yoffset + descendant.getHeight()); - return true; - } - - protected void onVisibilityChanged(int visibility) { - for (int i = 0, n = getComponentCount(); i < n; ++i) { - GLView child = getComponent(i); - if (child.getVisibility() == GLView.VISIBLE) { - child.onVisibilityChanged(visibility); - } - } - } - - protected void onAttachToRoot(GLRoot root) { - mRoot = root; - for (int i = 0, n = getComponentCount(); i < n; ++i) { - getComponent(i).onAttachToRoot(root); - } - } - - protected void onDetachFromRoot() { - for (int i = 0, n = getComponentCount(); i < n; ++i) { - getComponent(i).onDetachFromRoot(); - } - mRoot = null; - } - - public void lockRendering() { - if (mRoot != null) { - mRoot.lockRenderThread(); - } - } - - public void unlockRendering() { - if (mRoot != null) { - mRoot.unlockRenderThread(); - } - } - - // This is for debugging only. - // Dump the view hierarchy into log. - void dumpTree(String prefix) { - Log.d(TAG, prefix + getClass().getSimpleName()); - for (int i = 0, n = getComponentCount(); i < n; ++i) { - getComponent(i).dumpTree(prefix + "...."); - } - } -} diff --git a/src/com/android/gallery3d/ui/GestureRecognizer.java b/src/com/android/gallery3d/ui/GestureRecognizer.java deleted file mode 100644 index 1e5250b9b..000000000 --- a/src/com/android/gallery3d/ui/GestureRecognizer.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.os.SystemClock; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.ScaleGestureDetector; - -// This class aggregates three gesture detectors: GestureDetector, -// ScaleGestureDetector, and DownUpDetector. -public class GestureRecognizer { - @SuppressWarnings("unused") - private static final String TAG = "GestureRecognizer"; - - public interface Listener { - boolean onSingleTapUp(float x, float y); - boolean onDoubleTap(float x, float y); - boolean onScroll(float dx, float dy, float totalX, float totalY); - boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY); - boolean onScaleBegin(float focusX, float focusY); - boolean onScale(float focusX, float focusY, float scale); - void onScaleEnd(); - void onDown(float x, float y); - void onUp(); - } - - private final GestureDetector mGestureDetector; - private final ScaleGestureDetector mScaleDetector; - private final DownUpDetector mDownUpDetector; - private final Listener mListener; - - public GestureRecognizer(Context context, Listener listener) { - mListener = listener; - mGestureDetector = new GestureDetector(context, new MyGestureListener(), - null, true /* ignoreMultitouch */); - mScaleDetector = new ScaleGestureDetector( - context, new MyScaleListener()); - mDownUpDetector = new DownUpDetector(new MyDownUpListener()); - } - - public void onTouchEvent(MotionEvent event) { - mGestureDetector.onTouchEvent(event); - mScaleDetector.onTouchEvent(event); - mDownUpDetector.onTouchEvent(event); - } - - public boolean isDown() { - return mDownUpDetector.isDown(); - } - - public void cancelScale() { - long now = SystemClock.uptimeMillis(); - MotionEvent cancelEvent = MotionEvent.obtain( - now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); - mScaleDetector.onTouchEvent(cancelEvent); - cancelEvent.recycle(); - } - - private class MyGestureListener - extends GestureDetector.SimpleOnGestureListener { - @Override - public boolean onSingleTapUp(MotionEvent e) { - return mListener.onSingleTapUp(e.getX(), e.getY()); - } - - @Override - public boolean onDoubleTap(MotionEvent e) { - return mListener.onDoubleTap(e.getX(), e.getY()); - } - - @Override - public boolean onScroll( - MotionEvent e1, MotionEvent e2, float dx, float dy) { - return mListener.onScroll( - dx, dy, e2.getX() - e1.getX(), e2.getY() - e1.getY()); - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - return mListener.onFling(e1, e2, velocityX, velocityY); - } - } - - private class MyScaleListener - extends ScaleGestureDetector.SimpleOnScaleGestureListener { - @Override - public boolean onScaleBegin(ScaleGestureDetector detector) { - return mListener.onScaleBegin( - detector.getFocusX(), detector.getFocusY()); - } - - @Override - public boolean onScale(ScaleGestureDetector detector) { - return mListener.onScale(detector.getFocusX(), - detector.getFocusY(), detector.getScaleFactor()); - } - - @Override - public void onScaleEnd(ScaleGestureDetector detector) { - mListener.onScaleEnd(); - } - } - - private class MyDownUpListener implements DownUpDetector.DownUpListener { - @Override - public void onDown(MotionEvent e) { - mListener.onDown(e.getX(), e.getY()); - } - - @Override - public void onUp(MotionEvent e) { - mListener.onUp(); - } - } -} diff --git a/src/com/android/gallery3d/ui/Log.java b/src/com/android/gallery3d/ui/Log.java deleted file mode 100644 index 5570763bb..000000000 --- a/src/com/android/gallery3d/ui/Log.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -// TODO: Delete this -public class Log { - public static int v(String tag, String msg) { - return android.util.Log.v(tag, msg); - } - public static int v(String tag, String msg, Throwable tr) { - return android.util.Log.v(tag, msg, tr); - } - public static int d(String tag, String msg) { - return android.util.Log.d(tag, msg); - } - public static int d(String tag, String msg, Throwable tr) { - return android.util.Log.d(tag, msg, tr); - } - public static int i(String tag, String msg) { - return android.util.Log.i(tag, msg); - } - public static int i(String tag, String msg, Throwable tr) { - return android.util.Log.i(tag, msg, tr); - } - public static int w(String tag, String msg) { - return android.util.Log.w(tag, msg); - } - public static int w(String tag, String msg, Throwable tr) { - return android.util.Log.w(tag, msg, tr); - } - public static int w(String tag, Throwable tr) { - return android.util.Log.w(tag, tr); - } - public static int e(String tag, String msg) { - return android.util.Log.e(tag, msg); - } - public static int e(String tag, String msg, Throwable tr) { - return android.util.Log.e(tag, msg, tr); - } -} diff --git a/src/com/android/gallery3d/ui/ManageCacheDrawer.java b/src/com/android/gallery3d/ui/ManageCacheDrawer.java deleted file mode 100644 index d210bd1f1..000000000 --- a/src/com/android/gallery3d/ui/ManageCacheDrawer.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.data.DataSourceType; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.ResourceTexture; -import com.android.gallery3d.glrenderer.StringTexture; -import com.android.gallery3d.ui.AlbumSetSlidingWindow.AlbumSetEntry; - -public class ManageCacheDrawer extends AlbumSetSlotRenderer { - private final ResourceTexture mCheckedItem; - private final ResourceTexture mUnCheckedItem; - private final SelectionManager mSelectionManager; - - private final ResourceTexture mLocalAlbumIcon; - private final StringTexture mCachingText; - - private final int mCachePinSize; - private final int mCachePinMargin; - - public ManageCacheDrawer(AbstractGalleryActivity activity, SelectionManager selectionManager, - SlotView slotView, LabelSpec labelSpec, int cachePinSize, int cachePinMargin) { - super(activity, selectionManager, slotView, labelSpec, - activity.getResources().getColor(R.color.cache_placeholder)); - Context context = activity; - mCheckedItem = new ResourceTexture( - context, R.drawable.btn_make_offline_normal_on_holo_dark); - mUnCheckedItem = new ResourceTexture( - context, R.drawable.btn_make_offline_normal_off_holo_dark); - mLocalAlbumIcon = new ResourceTexture( - context, R.drawable.btn_make_offline_disabled_on_holo_dark); - String cachingLabel = context.getString(R.string.caching_label); - mCachingText = StringTexture.newInstance(cachingLabel, 12, 0xffffffff); - mSelectionManager = selectionManager; - mCachePinSize = cachePinSize; - mCachePinMargin = cachePinMargin; - } - - private static boolean isLocal(int dataSourceType) { - return dataSourceType != DataSourceType.TYPE_PICASA; - } - - @Override - public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height) { - AlbumSetEntry entry = mDataWindow.get(index); - - boolean wantCache = entry.cacheFlag == MediaSet.CACHE_FLAG_FULL; - boolean isCaching = wantCache && ( - entry.cacheStatus != MediaSet.CACHE_STATUS_CACHED_FULL); - boolean selected = mSelectionManager.isItemSelected(entry.setPath); - boolean chooseToCache = wantCache ^ selected; - boolean available = isLocal(entry.sourceType) || chooseToCache; - - int renderRequestFlags = 0; - - if (!available) { - canvas.save(GLCanvas.SAVE_FLAG_ALPHA); - canvas.multiplyAlpha(0.6f); - } - renderRequestFlags |= renderContent(canvas, entry, width, height); - if (!available) canvas.restore(); - - renderRequestFlags |= renderLabel(canvas, entry, width, height); - - drawCachingPin(canvas, entry.setPath, - entry.sourceType, isCaching, chooseToCache, width, height); - - renderRequestFlags |= renderOverlay(canvas, index, entry, width, height); - return renderRequestFlags; - } - - private void drawCachingPin(GLCanvas canvas, Path path, int dataSourceType, - boolean isCaching, boolean chooseToCache, int width, int height) { - ResourceTexture icon; - if (isLocal(dataSourceType)) { - icon = mLocalAlbumIcon; - } else if (chooseToCache) { - icon = mCheckedItem; - } else { - icon = mUnCheckedItem; - } - - // show the icon in right bottom - int s = mCachePinSize; - int m = mCachePinMargin; - icon.draw(canvas, width - m - s, height - s, s, s); - - if (isCaching) { - int w = mCachingText.getWidth(); - int h = mCachingText.getHeight(); - // Show the caching text in bottom center - mCachingText.draw(canvas, (width - w) / 2, height - h); - } - } -} diff --git a/src/com/android/gallery3d/ui/MeasureHelper.java b/src/com/android/gallery3d/ui/MeasureHelper.java deleted file mode 100644 index f65dc10b3..000000000 --- a/src/com/android/gallery3d/ui/MeasureHelper.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Rect; -import android.view.View.MeasureSpec; - -class MeasureHelper { - - private static MeasureHelper sInstance = new MeasureHelper(null); - - private GLView mComponent; - private int mPreferredWidth; - private int mPreferredHeight; - - private MeasureHelper(GLView component) { - mComponent = component; - } - - public static MeasureHelper getInstance(GLView component) { - sInstance.mComponent = component; - return sInstance; - } - - public MeasureHelper setPreferredContentSize(int width, int height) { - mPreferredWidth = width; - mPreferredHeight = height; - return this; - } - - public void measure(int widthSpec, int heightSpec) { - Rect p = mComponent.getPaddings(); - setMeasuredSize( - getLength(widthSpec, mPreferredWidth + p.left + p.right), - getLength(heightSpec, mPreferredHeight + p.top + p.bottom)); - } - - private static int getLength(int measureSpec, int prefered) { - int specLength = MeasureSpec.getSize(measureSpec); - switch(MeasureSpec.getMode(measureSpec)) { - case MeasureSpec.EXACTLY: return specLength; - case MeasureSpec.AT_MOST: return Math.min(prefered, specLength); - default: return prefered; - } - } - - protected void setMeasuredSize(int width, int height) { - mComponent.setMeasuredSize(width, height); - } - -} diff --git a/src/com/android/gallery3d/ui/MenuExecutor.java b/src/com/android/gallery3d/ui/MenuExecutor.java deleted file mode 100644 index 29def0527..000000000 --- a/src/com/android/gallery3d/ui/MenuExecutor.java +++ /dev/null @@ -1,448 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.app.Activity; -import android.app.AlertDialog; -import android.app.ProgressDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnCancelListener; -import android.content.DialogInterface.OnClickListener; -import android.content.Intent; -import android.os.Handler; -import android.os.Message; -import android.view.Menu; -import android.view.MenuItem; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.ArrayList; - -public class MenuExecutor { - @SuppressWarnings("unused") - private static final String TAG = "MenuExecutor"; - - private static final int MSG_TASK_COMPLETE = 1; - private static final int MSG_TASK_UPDATE = 2; - private static final int MSG_TASK_START = 3; - private static final int MSG_DO_SHARE = 4; - - public static final int EXECUTION_RESULT_SUCCESS = 1; - public static final int EXECUTION_RESULT_FAIL = 2; - public static final int EXECUTION_RESULT_CANCEL = 3; - - private ProgressDialog mDialog; - private Future<?> mTask; - // wait the operation to finish when we want to stop it. - private boolean mWaitOnStop; - private boolean mPaused; - - private final AbstractGalleryActivity mActivity; - private final SelectionManager mSelectionManager; - private final Handler mHandler; - - private static ProgressDialog createProgressDialog( - Context context, int titleId, int progressMax) { - ProgressDialog dialog = new ProgressDialog(context); - dialog.setTitle(titleId); - dialog.setMax(progressMax); - dialog.setCancelable(false); - dialog.setIndeterminate(false); - if (progressMax > 1) { - dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); - } - return dialog; - } - - public interface ProgressListener { - public void onConfirmDialogShown(); - public void onConfirmDialogDismissed(boolean confirmed); - public void onProgressStart(); - public void onProgressUpdate(int index); - public void onProgressComplete(int result); - } - - public MenuExecutor( - AbstractGalleryActivity activity, SelectionManager selectionManager) { - mActivity = Utils.checkNotNull(activity); - mSelectionManager = Utils.checkNotNull(selectionManager); - mHandler = new SynchronizedHandler(mActivity.getGLRoot()) { - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_TASK_START: { - if (message.obj != null) { - ProgressListener listener = (ProgressListener) message.obj; - listener.onProgressStart(); - } - break; - } - case MSG_TASK_COMPLETE: { - stopTaskAndDismissDialog(); - if (message.obj != null) { - ProgressListener listener = (ProgressListener) message.obj; - listener.onProgressComplete(message.arg1); - } - mSelectionManager.leaveSelectionMode(); - break; - } - case MSG_TASK_UPDATE: { - if (mDialog != null && !mPaused) mDialog.setProgress(message.arg1); - if (message.obj != null) { - ProgressListener listener = (ProgressListener) message.obj; - listener.onProgressUpdate(message.arg1); - } - break; - } - case MSG_DO_SHARE: { - ((Activity) mActivity).startActivity((Intent) message.obj); - break; - } - } - } - }; - } - - private void stopTaskAndDismissDialog() { - if (mTask != null) { - if (!mWaitOnStop) mTask.cancel(); - if (mDialog != null && mDialog.isShowing()) mDialog.dismiss(); - mDialog = null; - mTask = null; - } - } - - public void resume() { - mPaused = false; - if (mDialog != null) mDialog.show(); - } - - public void pause() { - mPaused = true; - if (mDialog != null && mDialog.isShowing()) mDialog.hide(); - } - - public void destroy() { - stopTaskAndDismissDialog(); - } - - private void onProgressUpdate(int index, ProgressListener listener) { - mHandler.sendMessage( - mHandler.obtainMessage(MSG_TASK_UPDATE, index, 0, listener)); - } - - private void onProgressStart(ProgressListener listener) { - mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_START, listener)); - } - - private void onProgressComplete(int result, ProgressListener listener) { - mHandler.sendMessage(mHandler.obtainMessage(MSG_TASK_COMPLETE, result, 0, listener)); - } - - public static void updateMenuOperation(Menu menu, int supported) { - boolean supportDelete = (supported & MediaObject.SUPPORT_DELETE) != 0; - boolean supportRotate = (supported & MediaObject.SUPPORT_ROTATE) != 0; - boolean supportCrop = (supported & MediaObject.SUPPORT_CROP) != 0; - boolean supportTrim = (supported & MediaObject.SUPPORT_TRIM) != 0; - boolean supportMute = (supported & MediaObject.SUPPORT_MUTE) != 0; - boolean supportShare = (supported & MediaObject.SUPPORT_SHARE) != 0; - boolean supportSetAs = (supported & MediaObject.SUPPORT_SETAS) != 0; - boolean supportShowOnMap = (supported & MediaObject.SUPPORT_SHOW_ON_MAP) != 0; - boolean supportCache = (supported & MediaObject.SUPPORT_CACHE) != 0; - boolean supportEdit = (supported & MediaObject.SUPPORT_EDIT) != 0; - boolean supportInfo = (supported & MediaObject.SUPPORT_INFO) != 0; - - setMenuItemVisible(menu, R.id.action_delete, supportDelete); - setMenuItemVisible(menu, R.id.action_rotate_ccw, supportRotate); - setMenuItemVisible(menu, R.id.action_rotate_cw, supportRotate); - setMenuItemVisible(menu, R.id.action_crop, supportCrop); - setMenuItemVisible(menu, R.id.action_trim, supportTrim); - setMenuItemVisible(menu, R.id.action_mute, supportMute); - // Hide panorama until call to updateMenuForPanorama corrects it - setMenuItemVisible(menu, R.id.action_share_panorama, false); - setMenuItemVisible(menu, R.id.action_share, supportShare); - setMenuItemVisible(menu, R.id.action_setas, supportSetAs); - setMenuItemVisible(menu, R.id.action_show_on_map, supportShowOnMap); - setMenuItemVisible(menu, R.id.action_edit, supportEdit); - setMenuItemVisible(menu, R.id.action_simple_edit, supportEdit); - setMenuItemVisible(menu, R.id.action_details, supportInfo); - } - - public static void updateMenuForPanorama(Menu menu, boolean shareAsPanorama360, - boolean disablePanorama360Options) { - setMenuItemVisible(menu, R.id.action_share_panorama, shareAsPanorama360); - if (disablePanorama360Options) { - setMenuItemVisible(menu, R.id.action_rotate_ccw, false); - setMenuItemVisible(menu, R.id.action_rotate_cw, false); - } - } - - private static void setMenuItemVisible(Menu menu, int itemId, boolean visible) { - MenuItem item = menu.findItem(itemId); - if (item != null) item.setVisible(visible); - } - - private Path getSingleSelectedPath() { - ArrayList<Path> ids = mSelectionManager.getSelected(true); - Utils.assertTrue(ids.size() == 1); - return ids.get(0); - } - - private Intent getIntentBySingleSelectedPath(String action) { - DataManager manager = mActivity.getDataManager(); - Path path = getSingleSelectedPath(); - String mimeType = getMimeType(manager.getMediaType(path)); - return new Intent(action).setDataAndType(manager.getContentUri(path), mimeType); - } - - private void onMenuClicked(int action, ProgressListener listener) { - onMenuClicked(action, listener, false, true); - } - - public void onMenuClicked(int action, ProgressListener listener, - boolean waitOnStop, boolean showDialog) { - int title; - switch (action) { - case R.id.action_select_all: - if (mSelectionManager.inSelectAllMode()) { - mSelectionManager.deSelectAll(); - } else { - mSelectionManager.selectAll(); - } - return; - case R.id.action_crop: { - Intent intent = getIntentBySingleSelectedPath(CropActivity.CROP_ACTION); - ((Activity) mActivity).startActivity(intent); - return; - } - case R.id.action_edit: { - Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_EDIT) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - ((Activity) mActivity).startActivity(Intent.createChooser(intent, null)); - return; - } - case R.id.action_setas: { - Intent intent = getIntentBySingleSelectedPath(Intent.ACTION_ATTACH_DATA) - .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); - intent.putExtra("mimeType", intent.getType()); - Activity activity = mActivity; - activity.startActivity(Intent.createChooser( - intent, activity.getString(R.string.set_as))); - return; - } - case R.id.action_delete: - title = R.string.delete; - break; - case R.id.action_rotate_cw: - title = R.string.rotate_right; - break; - case R.id.action_rotate_ccw: - title = R.string.rotate_left; - break; - case R.id.action_show_on_map: - title = R.string.show_on_map; - break; - default: - return; - } - startAction(action, title, listener, waitOnStop, showDialog); - } - - private class ConfirmDialogListener implements OnClickListener, OnCancelListener { - private final int mActionId; - private final ProgressListener mListener; - - public ConfirmDialogListener(int actionId, ProgressListener listener) { - mActionId = actionId; - mListener = listener; - } - - @Override - public void onClick(DialogInterface dialog, int which) { - if (which == DialogInterface.BUTTON_POSITIVE) { - if (mListener != null) { - mListener.onConfirmDialogDismissed(true); - } - onMenuClicked(mActionId, mListener); - } else { - if (mListener != null) { - mListener.onConfirmDialogDismissed(false); - } - } - } - - @Override - public void onCancel(DialogInterface dialog) { - if (mListener != null) { - mListener.onConfirmDialogDismissed(false); - } - } - } - - public void onMenuClicked(MenuItem menuItem, String confirmMsg, - final ProgressListener listener) { - final int action = menuItem.getItemId(); - - if (confirmMsg != null) { - if (listener != null) listener.onConfirmDialogShown(); - ConfirmDialogListener cdl = new ConfirmDialogListener(action, listener); - new AlertDialog.Builder(mActivity.getAndroidContext()) - .setMessage(confirmMsg) - .setOnCancelListener(cdl) - .setPositiveButton(R.string.ok, cdl) - .setNegativeButton(R.string.cancel, cdl) - .create().show(); - } else { - onMenuClicked(action, listener); - } - } - - public void startAction(int action, int title, ProgressListener listener) { - startAction(action, title, listener, false, true); - } - - public void startAction(int action, int title, ProgressListener listener, - boolean waitOnStop, boolean showDialog) { - ArrayList<Path> ids = mSelectionManager.getSelected(false); - stopTaskAndDismissDialog(); - - Activity activity = mActivity; - if (showDialog) { - mDialog = createProgressDialog(activity, title, ids.size()); - mDialog.show(); - } else { - mDialog = null; - } - MediaOperation operation = new MediaOperation(action, ids, listener); - mTask = mActivity.getBatchServiceThreadPoolIfAvailable().submit(operation, null); - mWaitOnStop = waitOnStop; - } - - public void startSingleItemAction(int action, Path targetPath) { - ArrayList<Path> ids = new ArrayList<Path>(1); - ids.add(targetPath); - mDialog = null; - MediaOperation operation = new MediaOperation(action, ids, null); - mTask = mActivity.getBatchServiceThreadPoolIfAvailable().submit(operation, null); - mWaitOnStop = false; - } - - public static String getMimeType(int type) { - switch (type) { - case MediaObject.MEDIA_TYPE_IMAGE : - return GalleryUtils.MIME_TYPE_IMAGE; - case MediaObject.MEDIA_TYPE_VIDEO : - return GalleryUtils.MIME_TYPE_VIDEO; - default: return GalleryUtils.MIME_TYPE_ALL; - } - } - - private boolean execute( - DataManager manager, JobContext jc, int cmd, Path path) { - boolean result = true; - Log.v(TAG, "Execute cmd: " + cmd + " for " + path); - long startTime = System.currentTimeMillis(); - - switch (cmd) { - case R.id.action_delete: - manager.delete(path); - break; - case R.id.action_rotate_cw: - manager.rotate(path, 90); - break; - case R.id.action_rotate_ccw: - manager.rotate(path, -90); - break; - case R.id.action_toggle_full_caching: { - MediaObject obj = manager.getMediaObject(path); - int cacheFlag = obj.getCacheFlag(); - if (cacheFlag == MediaObject.CACHE_FLAG_FULL) { - cacheFlag = MediaObject.CACHE_FLAG_SCREENNAIL; - } else { - cacheFlag = MediaObject.CACHE_FLAG_FULL; - } - obj.cache(cacheFlag); - break; - } - case R.id.action_show_on_map: { - MediaItem item = (MediaItem) manager.getMediaObject(path); - double latlng[] = new double[2]; - item.getLatLong(latlng); - if (GalleryUtils.isValidLocation(latlng[0], latlng[1])) { - GalleryUtils.showOnMap(mActivity, latlng[0], latlng[1]); - } - break; - } - default: - throw new AssertionError(); - } - Log.v(TAG, "It takes " + (System.currentTimeMillis() - startTime) + - " ms to execute cmd for " + path); - return result; - } - - private class MediaOperation implements Job<Void> { - private final ArrayList<Path> mItems; - private final int mOperation; - private final ProgressListener mListener; - - public MediaOperation(int operation, ArrayList<Path> items, - ProgressListener listener) { - mOperation = operation; - mItems = items; - mListener = listener; - } - - @Override - public Void run(JobContext jc) { - int index = 0; - DataManager manager = mActivity.getDataManager(); - int result = EXECUTION_RESULT_SUCCESS; - try { - onProgressStart(mListener); - for (Path id : mItems) { - if (jc.isCancelled()) { - result = EXECUTION_RESULT_CANCEL; - break; - } - if (!execute(manager, jc, mOperation, id)) { - result = EXECUTION_RESULT_FAIL; - } - onProgressUpdate(index++, mListener); - } - } catch (Throwable th) { - Log.e(TAG, "failed to execute operation " + mOperation - + " : " + th); - } finally { - onProgressComplete(result, mListener); - } - return null; - } - } -} diff --git a/src/com/android/gallery3d/ui/OrientationSource.java b/src/com/android/gallery3d/ui/OrientationSource.java deleted file mode 100644 index e13ce1cec..000000000 --- a/src/com/android/gallery3d/ui/OrientationSource.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -public interface OrientationSource { - public int getDisplayRotation(); - public int getCompensation(); -} diff --git a/src/com/android/gallery3d/ui/Paper.java b/src/com/android/gallery3d/ui/Paper.java deleted file mode 100644 index b36f5c3a2..000000000 --- a/src/com/android/gallery3d/ui/Paper.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Rect; -import android.opengl.Matrix; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.android.gallery3d.common.Utils; - -// This class does the overscroll effect. -class Paper { - @SuppressWarnings("unused") - private static final String TAG = "Paper"; - private static final int ROTATE_FACTOR = 4; - private EdgeAnimation mAnimationLeft = new EdgeAnimation(); - private EdgeAnimation mAnimationRight = new EdgeAnimation(); - private int mWidth; - private float[] mMatrix = new float[16]; - - public void overScroll(float distance) { - distance /= mWidth; // make it relative to width - if (distance < 0) { - mAnimationLeft.onPull(-distance); - } else { - mAnimationRight.onPull(distance); - } - } - - public void edgeReached(float velocity) { - velocity /= mWidth; // make it relative to width - if (velocity < 0) { - mAnimationRight.onAbsorb(-velocity); - } else { - mAnimationLeft.onAbsorb(velocity); - } - } - - public void onRelease() { - mAnimationLeft.onRelease(); - mAnimationRight.onRelease(); - } - - public boolean advanceAnimation() { - // Note that we use "|" because we want both animations get updated. - return mAnimationLeft.update() | mAnimationRight.update(); - } - - public void setSize(int width, int height) { - mWidth = width; - } - - public float[] getTransform(Rect rect, float scrollX) { - float left = mAnimationLeft.getValue(); - float right = mAnimationRight.getValue(); - float screenX = rect.centerX() - scrollX; - // We linearly interpolate the value [left, right] for the screenX - // range int [-1/4, 5/4]*mWidth. So if part of the thumbnail is outside - // the screen, we still get some transform. - float x = screenX + mWidth / 4; - int range = 3 * mWidth / 2; - float t = ((range - x) * left - x * right) / range; - // compress t to the range (-1, 1) by the function - // f(t) = (1 / (1 + e^-t) - 0.5) * 2 - // then multiply by 90 to make the range (-45, 45) - float degrees = - (1 / (1 + (float) Math.exp(-t * ROTATE_FACTOR)) - 0.5f) * 2 * -45; - Matrix.setIdentityM(mMatrix, 0); - Matrix.translateM(mMatrix, 0, mMatrix, 0, rect.centerX(), rect.centerY(), 0); - Matrix.rotateM(mMatrix, 0, degrees, 0, 1, 0); - Matrix.translateM(mMatrix, 0, mMatrix, 0, -rect.width() / 2, -rect.height() / 2, 0); - return mMatrix; - } -} - -// This class follows the structure of frameworks's EdgeEffect class. -class EdgeAnimation { - @SuppressWarnings("unused") - private static final String TAG = "EdgeAnimation"; - - private static final int STATE_IDLE = 0; - private static final int STATE_PULL = 1; - private static final int STATE_ABSORB = 2; - private static final int STATE_RELEASE = 3; - - // Time it will take the effect to fully done in ms - private static final int ABSORB_TIME = 200; - private static final int RELEASE_TIME = 500; - - private static final float VELOCITY_FACTOR = 0.1f; - - private final Interpolator mInterpolator; - - private int mState; - private float mValue; - - private float mValueStart; - private float mValueFinish; - private long mStartTime; - private long mDuration; - - public EdgeAnimation() { - mInterpolator = new DecelerateInterpolator(); - mState = STATE_IDLE; - } - - private void startAnimation(float start, float finish, long duration, - int newState) { - mValueStart = start; - mValueFinish = finish; - mDuration = duration; - mStartTime = now(); - mState = newState; - } - - // The deltaDistance's magnitude is in the range of -1 (no change) to 1. - // The value 1 is the full length of the view. Negative values means the - // movement is in the opposite direction. - public void onPull(float deltaDistance) { - if (mState == STATE_ABSORB) return; - mValue = Utils.clamp(mValue + deltaDistance, -1.0f, 1.0f); - mState = STATE_PULL; - } - - public void onRelease() { - if (mState == STATE_IDLE || mState == STATE_ABSORB) return; - startAnimation(mValue, 0, RELEASE_TIME, STATE_RELEASE); - } - - public void onAbsorb(float velocity) { - float finish = Utils.clamp(mValue + velocity * VELOCITY_FACTOR, - -1.0f, 1.0f); - startAnimation(mValue, finish, ABSORB_TIME, STATE_ABSORB); - } - - public boolean update() { - if (mState == STATE_IDLE) return false; - if (mState == STATE_PULL) return true; - - float t = Utils.clamp((float)(now() - mStartTime) / mDuration, 0.0f, 1.0f); - /* Use linear interpolation for absorb, quadratic for others */ - float interp = (mState == STATE_ABSORB) - ? t : mInterpolator.getInterpolation(t); - - mValue = mValueStart + (mValueFinish - mValueStart) * interp; - - if (t >= 1.0f) { - switch (mState) { - case STATE_ABSORB: - startAnimation(mValue, 0, RELEASE_TIME, STATE_RELEASE); - break; - case STATE_RELEASE: - mState = STATE_IDLE; - break; - } - } - - return true; - } - - public float getValue() { - return mValue; - } - - private long now() { - return AnimationTime.get(); - } -} diff --git a/src/com/android/gallery3d/ui/PhotoFallbackEffect.java b/src/com/android/gallery3d/ui/PhotoFallbackEffect.java deleted file mode 100644 index 4603285a4..000000000 --- a/src/com/android/gallery3d/ui/PhotoFallbackEffect.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Rect; -import android.graphics.RectF; -import android.view.animation.DecelerateInterpolator; -import android.view.animation.Interpolator; - -import com.android.gallery3d.anim.Animation; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.AlbumSlotRenderer.SlotFilter; - -import java.util.ArrayList; - -public class PhotoFallbackEffect extends Animation implements SlotFilter { - - private static final int ANIM_DURATION = 300; - private static final Interpolator ANIM_INTERPOLATE = new DecelerateInterpolator(1.5f); - - public static class Entry { - public int index; - public Path path; - public Rect source; - public Rect dest; - public RawTexture texture; - - public Entry(Path path, Rect source, RawTexture texture) { - this.path = path; - this.source = source; - this.texture = texture; - } - } - - public interface PositionProvider { - public Rect getPosition(int index); - public int getItemIndex(Path path); - } - - private RectF mSource = new RectF(); - private RectF mTarget = new RectF(); - private float mProgress; - private PositionProvider mPositionProvider; - - private ArrayList<Entry> mList = new ArrayList<Entry>(); - - public PhotoFallbackEffect() { - setDuration(ANIM_DURATION); - setInterpolator(ANIM_INTERPOLATE); - } - - public void addEntry(Path path, Rect rect, RawTexture texture) { - mList.add(new Entry(path, rect, texture)); - } - - public Entry getEntry(Path path) { - for (int i = 0, n = mList.size(); i < n; ++i) { - Entry entry = mList.get(i); - if (entry.path == path) return entry; - } - return null; - } - - public boolean draw(GLCanvas canvas) { - boolean more = calculate(AnimationTime.get()); - for (int i = 0, n = mList.size(); i < n; ++i) { - Entry entry = mList.get(i); - if (entry.index < 0) continue; - entry.dest = mPositionProvider.getPosition(entry.index); - drawEntry(canvas, entry); - } - return more; - } - - private void drawEntry(GLCanvas canvas, Entry entry) { - if (!entry.texture.isLoaded()) return; - - int w = entry.texture.getWidth(); - int h = entry.texture.getHeight(); - - Rect s = entry.source; - Rect d = entry.dest; - - // the following calculation is based on d.width() == d.height() - - float p = mProgress; - - float fullScale = (float) d.height() / Math.min(s.width(), s.height()); - float scale = fullScale * p + 1 * (1 - p); - - float cx = d.centerX() * p + s.centerX() * (1 - p); - float cy = d.centerY() * p + s.centerY() * (1 - p); - - float ch = s.height() * scale; - float cw = s.width() * scale; - - if (w > h) { - // draw the center part - mTarget.set(cx - ch / 2, cy - ch / 2, cx + ch / 2, cy + ch / 2); - mSource.set((w - h) / 2, 0, (w + h) / 2, h); - canvas.drawTexture(entry.texture, mSource, mTarget); - - canvas.save(GLCanvas.SAVE_FLAG_ALPHA); - canvas.multiplyAlpha(1 - p); - - // draw the left part - mTarget.set(cx - cw / 2, cy - ch / 2, cx - ch / 2, cy + ch / 2); - mSource.set(0, 0, (w - h) / 2, h); - canvas.drawTexture(entry.texture, mSource, mTarget); - - // draw the right part - mTarget.set(cx + ch / 2, cy - ch / 2, cx + cw / 2, cy + ch / 2); - mSource.set((w + h) / 2, 0, w, h); - canvas.drawTexture(entry.texture, mSource, mTarget); - - canvas.restore(); - } else { - // draw the center part - mTarget.set(cx - cw / 2, cy - cw / 2, cx + cw / 2, cy + cw / 2); - mSource.set(0, (h - w) / 2, w, (h + w) / 2); - canvas.drawTexture(entry.texture, mSource, mTarget); - - canvas.save(GLCanvas.SAVE_FLAG_ALPHA); - canvas.multiplyAlpha(1 - p); - - // draw the upper part - mTarget.set(cx - cw / 2, cy - ch / 2, cx + cw / 2, cy - cw / 2); - mSource.set(0, 0, w, (h - w) / 2); - canvas.drawTexture(entry.texture, mSource, mTarget); - - // draw the bottom part - mTarget.set(cx - cw / 2, cy + cw / 2, cx + cw / 2, cy + ch / 2); - mSource.set(0, (w + h) / 2, w, h); - canvas.drawTexture(entry.texture, mSource, mTarget); - - canvas.restore(); - } - } - - @Override - protected void onCalculate(float progress) { - mProgress = progress; - } - - public void setPositionProvider(PositionProvider provider) { - mPositionProvider = provider; - if (mPositionProvider != null) { - for (int i = 0, n = mList.size(); i < n; ++i) { - Entry entry = mList.get(i); - entry.index = mPositionProvider.getItemIndex(entry.path); - } - } - } - - @Override - public boolean acceptSlot(int index) { - for (int i = 0, n = mList.size(); i < n; ++i) { - Entry entry = mList.get(i); - if (entry.index == index) return false; - } - return true; - } -} diff --git a/src/com/android/gallery3d/ui/PhotoView.java b/src/com/android/gallery3d/ui/PhotoView.java deleted file mode 100644 index 7afa20348..000000000 --- a/src/com/android/gallery3d/ui/PhotoView.java +++ /dev/null @@ -1,1858 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.content.res.Configuration; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Rect; -import android.os.Build; -import android.os.Message; -import android.util.FloatMath; -import android.view.MotionEvent; -import android.view.View.MeasureSpec; -import android.view.animation.AccelerateInterpolator; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.glrenderer.ResourceTexture; -import com.android.gallery3d.glrenderer.StringTexture; -import com.android.gallery3d.glrenderer.Texture; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.RangeArray; -import com.android.gallery3d.util.UsageStatistics; - -public class PhotoView extends GLView { - @SuppressWarnings("unused") - private static final String TAG = "PhotoView"; - private final int mPlaceholderColor; - - public static final int INVALID_SIZE = -1; - public static final long INVALID_DATA_VERSION = - MediaObject.INVALID_DATA_VERSION; - - public static class Size { - public int width; - public int height; - } - - public interface Model extends TileImageView.TileSource { - public int getCurrentIndex(); - public void moveTo(int index); - - // Returns the size for the specified picture. If the size information is - // not avaiable, width = height = 0. - public void getImageSize(int offset, Size size); - - // Returns the media item for the specified picture. - public MediaItem getMediaItem(int offset); - - // Returns the rotation for the specified picture. - public int getImageRotation(int offset); - - // This amends the getScreenNail() method of TileImageView.Model to get - // ScreenNail at previous (negative offset) or next (positive offset) - // positions. Returns null if the specified ScreenNail is unavailable. - public ScreenNail getScreenNail(int offset); - - // Set this to true if we need the model to provide full images. - public void setNeedFullImage(boolean enabled); - - // Returns true if the item is the Camera preview. - public boolean isCamera(int offset); - - // Returns true if the item is the Panorama. - public boolean isPanorama(int offset); - - // Returns true if the item is a static image that represents camera - // preview. - public boolean isStaticCamera(int offset); - - // Returns true if the item is a Video. - public boolean isVideo(int offset); - - // Returns true if the item can be deleted. - public boolean isDeletable(int offset); - - public static final int LOADING_INIT = 0; - public static final int LOADING_COMPLETE = 1; - public static final int LOADING_FAIL = 2; - - public int getLoadingState(int offset); - - // When data change happens, we need to decide which MediaItem to focus - // on. - // - // 1. If focus hint path != null, we try to focus on it if we can find - // it. This is used for undo a deletion, so we can focus on the - // undeleted item. - // - // 2. Otherwise try to focus on the MediaItem that is currently focused, - // if we can find it. - // - // 3. Otherwise try to focus on the previous MediaItem or the next - // MediaItem, depending on the value of focus hint direction. - public static final int FOCUS_HINT_NEXT = 0; - public static final int FOCUS_HINT_PREVIOUS = 1; - public void setFocusHintDirection(int direction); - public void setFocusHintPath(Path path); - } - - public interface Listener { - public void onSingleTapUp(int x, int y); - public void onFullScreenChanged(boolean full); - public void onActionBarAllowed(boolean allowed); - public void onActionBarWanted(); - public void onCurrentImageUpdated(); - public void onDeleteImage(Path path, int offset); - public void onUndoDeleteImage(); - public void onCommitDeleteImage(); - public void onFilmModeChanged(boolean enabled); - public void onPictureCenter(boolean isCamera); - public void onUndoBarVisibilityChanged(boolean visible); - } - - // The rules about orientation locking: - // - // (1) We need to lock the orientation if we are in page mode camera - // preview, so there is no (unwanted) rotation animation when the user - // rotates the device. - // - // (2) We need to unlock the orientation if we want to show the action bar - // because the action bar follows the system orientation. - // - // The rules about action bar: - // - // (1) If we are in film mode, we don't show action bar. - // - // (2) If we go from camera to gallery with capture animation, we show - // action bar. - private static final int MSG_CANCEL_EXTRA_SCALING = 2; - private static final int MSG_SWITCH_FOCUS = 3; - private static final int MSG_CAPTURE_ANIMATION_DONE = 4; - private static final int MSG_DELETE_ANIMATION_DONE = 5; - private static final int MSG_DELETE_DONE = 6; - private static final int MSG_UNDO_BAR_TIMEOUT = 7; - private static final int MSG_UNDO_BAR_FULL_CAMERA = 8; - - private static final float SWIPE_THRESHOLD = 300f; - - private static final float DEFAULT_TEXT_SIZE = 20; - private static float TRANSITION_SCALE_FACTOR = 0.74f; - private static final int ICON_RATIO = 6; - - // whether we want to apply card deck effect in page mode. - private static final boolean CARD_EFFECT = true; - - // whether we want to apply offset effect in film mode. - private static final boolean OFFSET_EFFECT = true; - - // Used to calculate the scaling factor for the card deck effect. - private ZInterpolator mScaleInterpolator = new ZInterpolator(0.5f); - - // Used to calculate the alpha factor for the fading animation. - private AccelerateInterpolator mAlphaInterpolator = - new AccelerateInterpolator(0.9f); - - // We keep this many previous ScreenNails. (also this many next ScreenNails) - public static final int SCREEN_NAIL_MAX = 3; - - // These are constants for the delete gesture. - private static final int SWIPE_ESCAPE_VELOCITY = 500; // dp/sec - private static final int MAX_DISMISS_VELOCITY = 2500; // dp/sec - private static final int SWIPE_ESCAPE_DISTANCE = 150; // dp - - // The picture entries, the valid index is from -SCREEN_NAIL_MAX to - // SCREEN_NAIL_MAX. - private final RangeArray<Picture> mPictures = - new RangeArray<Picture>(-SCREEN_NAIL_MAX, SCREEN_NAIL_MAX); - private Size[] mSizes = new Size[2 * SCREEN_NAIL_MAX + 1]; - - private final MyGestureListener mGestureListener; - private final GestureRecognizer mGestureRecognizer; - private final PositionController mPositionController; - - private Listener mListener; - private Model mModel; - private StringTexture mNoThumbnailText; - private TileImageView mTileView; - private EdgeView mEdgeView; - private UndoBarView mUndoBar; - private Texture mVideoPlayIcon; - - private SynchronizedHandler mHandler; - - private boolean mCancelExtraScalingPending; - private boolean mFilmMode = false; - private boolean mWantPictureCenterCallbacks = false; - private int mDisplayRotation = 0; - private int mCompensation = 0; - 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 - // there are some previous pictures, mPrevBound < 0, and if there are some - // next pictures, mNextBound > 0. - private int mPrevBound; - private int mNextBound; - - // This variable prevents us doing snapback until its values goes to 0. This - // happens if the user gesture is still in progress or we are in a capture - // animation. - private int mHolding; - private static final int HOLD_TOUCH_DOWN = 1; - private static final int HOLD_CAPTURE_ANIMATION = 2; - private static final int HOLD_DELETE = 4; - - // mTouchBoxIndex is the index of the box that is touched by the down - // gesture in film mode. The value Integer.MAX_VALUE means no box was - // touched. - private int mTouchBoxIndex = Integer.MAX_VALUE; - // Whether the box indicated by mTouchBoxIndex is deletable. Only meaningful - // if mTouchBoxIndex is not Integer.MAX_VALUE. - private boolean mTouchBoxDeletable; - // This is the index of the last deleted item. This is only used as a hint - // to hide the undo button when we are too far away from the deleted - // item. The value Integer.MAX_VALUE means there is no such hint. - private int mUndoIndexHint = Integer.MAX_VALUE; - - private Context mContext; - - public PhotoView(AbstractGalleryActivity activity) { - mTileView = new TileImageView(activity); - addComponent(mTileView); - mContext = activity.getAndroidContext(); - mPlaceholderColor = mContext.getResources().getColor( - R.color.photo_placeholder); - mEdgeView = new EdgeView(mContext); - addComponent(mEdgeView); - mUndoBar = new UndoBarView(mContext); - addComponent(mUndoBar); - mUndoBar.setVisibility(GLView.INVISIBLE); - mUndoBar.setOnClickListener(new OnClickListener() { - @Override - public void onClick(GLView v) { - mListener.onUndoDeleteImage(); - hideUndoBar(); - } - }); - mNoThumbnailText = StringTexture.newInstance( - mContext.getString(R.string.no_thumbnail), - DEFAULT_TEXT_SIZE, Color.WHITE); - - mHandler = new MyHandler(activity.getGLRoot()); - - mGestureListener = new MyGestureListener(); - mGestureRecognizer = new GestureRecognizer(mContext, mGestureListener); - - mPositionController = new PositionController(mContext, - new PositionController.Listener() { - - @Override - public void invalidate() { - PhotoView.this.invalidate(); - } - - @Override - public boolean isHoldingDown() { - return (mHolding & HOLD_TOUCH_DOWN) != 0; - } - - @Override - public boolean isHoldingDelete() { - return (mHolding & HOLD_DELETE) != 0; - } - - @Override - public void onPull(int offset, int direction) { - mEdgeView.onPull(offset, direction); - } - - @Override - public void onRelease() { - mEdgeView.onRelease(); - } - - @Override - public void onAbsorb(int velocity, int direction) { - mEdgeView.onAbsorb(velocity, direction); - } - }); - mVideoPlayIcon = new ResourceTexture(mContext, R.drawable.ic_control_play); - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - if (i == 0) { - mPictures.put(i, new FullPicture()); - } else { - mPictures.put(i, new ScreenNailPicture(i)); - } - } - } - - public void stopScrolling() { - mPositionController.stopScrolling(); - } - - public void setModel(Model model) { - mModel = model; - mTileView.setModel(mModel); - } - - class MyHandler extends SynchronizedHandler { - public MyHandler(GLRoot root) { - super(root); - } - - @Override - public void handleMessage(Message message) { - switch (message.what) { - case MSG_CANCEL_EXTRA_SCALING: { - mGestureRecognizer.cancelScale(); - mPositionController.setExtraScalingRange(false); - mCancelExtraScalingPending = false; - break; - } - case MSG_SWITCH_FOCUS: { - switchFocus(); - break; - } - case MSG_CAPTURE_ANIMATION_DONE: { - // message.arg1 is the offset parameter passed to - // switchWithCaptureAnimation(). - captureAnimationDone(message.arg1); - break; - } - case MSG_DELETE_ANIMATION_DONE: { - // message.obj is the Path of the MediaItem which should be - // deleted. message.arg1 is the offset of the image. - mListener.onDeleteImage((Path) message.obj, message.arg1); - // Normally a box which finishes delete animation will hold - // position until the underlying MediaItem is actually - // deleted, and HOLD_DELETE will be cancelled that time. In - // case the MediaItem didn't actually get deleted in 2 - // seconds, we will cancel HOLD_DELETE and make it bounce - // back. - - // We make sure there is at most one MSG_DELETE_DONE - // in the handler. - mHandler.removeMessages(MSG_DELETE_DONE); - Message m = mHandler.obtainMessage(MSG_DELETE_DONE); - mHandler.sendMessageDelayed(m, 2000); - - int numberOfPictures = mNextBound - mPrevBound + 1; - if (numberOfPictures == 2) { - if (mModel.isCamera(mNextBound) - || mModel.isCamera(mPrevBound)) { - numberOfPictures--; - } - } - showUndoBar(numberOfPictures <= 1); - break; - } - case MSG_DELETE_DONE: { - if (!mHandler.hasMessages(MSG_DELETE_ANIMATION_DONE)) { - mHolding &= ~HOLD_DELETE; - snapback(); - } - break; - } - case MSG_UNDO_BAR_TIMEOUT: { - checkHideUndoBar(UNDO_BAR_TIMEOUT); - break; - } - case MSG_UNDO_BAR_FULL_CAMERA: { - checkHideUndoBar(UNDO_BAR_FULL_CAMERA); - break; - } - default: throw new AssertionError(message.what); - } - } - } - - public void setWantPictureCenterCallbacks(boolean wanted) { - mWantPictureCenterCallbacks = wanted; - } - - //////////////////////////////////////////////////////////////////////////// - // Data/Image change notifications - //////////////////////////////////////////////////////////////////////////// - - public void notifyDataChange(int[] fromIndex, int prevBound, int nextBound) { - mPrevBound = prevBound; - mNextBound = nextBound; - - // Update mTouchBoxIndex - if (mTouchBoxIndex != Integer.MAX_VALUE) { - int k = mTouchBoxIndex; - mTouchBoxIndex = Integer.MAX_VALUE; - for (int i = 0; i < 2 * SCREEN_NAIL_MAX + 1; i++) { - if (fromIndex[i] == k) { - mTouchBoxIndex = i - SCREEN_NAIL_MAX; - break; - } - } - } - - // Hide undo button if we are too far away - if (mUndoIndexHint != Integer.MAX_VALUE) { - if (Math.abs(mUndoIndexHint - mModel.getCurrentIndex()) >= 3) { - hideUndoBar(); - } - } - - // Update the ScreenNails. - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - Picture p = mPictures.get(i); - p.reload(); - mSizes[i + SCREEN_NAIL_MAX] = p.getSize(); - } - - boolean wasDeleting = mPositionController.hasDeletingBox(); - - // Move the boxes - mPositionController.moveBox(fromIndex, mPrevBound < 0, mNextBound > 0, - mModel.isCamera(0), mSizes); - - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - setPictureSize(i); - } - - boolean isDeleting = mPositionController.hasDeletingBox(); - - // If the deletion is done, make HOLD_DELETE persist for only the time - // needed for a snapback animation. - if (wasDeleting && !isDeleting) { - mHandler.removeMessages(MSG_DELETE_DONE); - Message m = mHandler.obtainMessage(MSG_DELETE_DONE); - mHandler.sendMessageDelayed( - m, PositionController.SNAPBACK_ANIMATION_TIME); - } - - invalidate(); - } - - public boolean isDeleting() { - return (mHolding & HOLD_DELETE) != 0 - && mPositionController.hasDeletingBox(); - } - - public void notifyImageChange(int index) { - if (index == 0) { - mListener.onCurrentImageUpdated(); - } - mPictures.get(index).reload(); - setPictureSize(index); - invalidate(); - } - - private void setPictureSize(int index) { - Picture p = mPictures.get(index); - mPositionController.setImageSize(index, p.getSize(), - index == 0 && p.isCamera() ? mCameraRect : null); - } - - @Override - protected void onLayout( - boolean changeSize, int left, int top, int right, int bottom) { - int w = right - left; - int h = bottom - top; - mTileView.layout(0, 0, w, h); - mEdgeView.layout(0, 0, w, h); - mUndoBar.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED); - mUndoBar.layout(0, h - mUndoBar.getMeasuredHeight(), w, h); - - GLRoot root = getGLRoot(); - int displayRotation = root.getDisplayRotation(); - int compensation = root.getCompensation(); - if (mDisplayRotation != displayRotation - || mCompensation != compensation) { - mDisplayRotation = displayRotation; - mCompensation = compensation; - - // We need to change the size and rotation of the Camera ScreenNail, - // but we don't want it to animate because the size doen't actually - // change in the eye of the user. - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - Picture p = mPictures.get(i); - if (p.isCamera()) { - p.forceSize(); - } - } - } - - updateCameraRect(); - mPositionController.setConstrainedFrame(mCameraRect); - if (changeSize) { - mPositionController.setViewSize(getWidth(), getHeight()); - } - } - - // Update the camera rectangle due to layout change or camera relative frame - // change. - private void updateCameraRect() { - // Get the width and height in framework orientation because the given - // mCameraRelativeFrame is in that coordinates. - int w = getWidth(); - int h = getHeight(); - if (mCompensation % 180 != 0) { - int tmp = w; - w = h; - h = tmp; - } - int l = mCameraRelativeFrame.left; - int t = mCameraRelativeFrame.top; - int r = mCameraRelativeFrame.right; - int b = mCameraRelativeFrame.bottom; - - // Now convert it to the coordinates we are using. - switch (mCompensation) { - case 0: mCameraRect.set(l, t, r, b); break; - case 90: mCameraRect.set(h - b, l, h - t, r); break; - case 180: mCameraRect.set(w - r, h - b, w - l, h - t); break; - case 270: mCameraRect.set(t, w - r, b, w - l); break; - } - - Log.d(TAG, "compensation = " + mCompensation - + ", CameraRelativeFrame = " + mCameraRelativeFrame - + ", mCameraRect = " + mCameraRect); - } - - public void setCameraRelativeFrame(Rect frame) { - mCameraRelativeFrame.set(frame); - updateCameraRect(); - // Originally we do - // mPositionController.setConstrainedFrame(mCameraRect); - // here, but it is moved to a parameter of the setImageSize() call, so - // it can be updated atomically with the CameraScreenNail's size change. - } - - // Returns the rotation we need to do to the camera texture before drawing - // it to the canvas, assuming the camera texture is correct when the device - // is in its natural orientation. - private int getCameraRotation() { - return (mCompensation - mDisplayRotation + 360) % 360; - } - - private int getPanoramaRotation() { - // This function is magic - // The issue here is that Pano makes bad assumptions about rotation and - // orientation. The first is it assumes only two rotations are possible, - // 0 and 90. Thus, if display rotation is >= 180, we invert the output. - // The second is that it assumes landscape is a 90 rotation from portrait, - // however on landscape devices this is not true. Thus, if we are in portrait - // on a landscape device, we need to invert the output - int orientation = mContext.getResources().getConfiguration().orientation; - boolean invertPortrait = (orientation == Configuration.ORIENTATION_PORTRAIT - && (mDisplayRotation == 90 || mDisplayRotation == 270)); - boolean invert = (mDisplayRotation >= 180); - if (invert != invertPortrait) { - return (mCompensation + 180) % 360; - } - return mCompensation; - } - - //////////////////////////////////////////////////////////////////////////// - // Pictures - //////////////////////////////////////////////////////////////////////////// - - private interface Picture { - void reload(); - void draw(GLCanvas canvas, Rect r); - void setScreenNail(ScreenNail s); - boolean isCamera(); // whether the picture is a camera preview - boolean isDeletable(); // whether the picture can be deleted - void forceSize(); // called when mCompensation changes - Size getSize(); - } - - class FullPicture implements Picture { - private int mRotation; - private boolean mIsCamera; - private boolean mIsPanorama; - private boolean mIsStaticCamera; - private boolean mIsVideo; - private boolean mIsDeletable; - private int mLoadingState = Model.LOADING_INIT; - private Size mSize = new Size(); - - @Override - public void reload() { - // mImageWidth and mImageHeight will get updated - mTileView.notifyModelInvalidated(); - - mIsCamera = mModel.isCamera(0); - mIsPanorama = mModel.isPanorama(0); - mIsStaticCamera = mModel.isStaticCamera(0); - mIsVideo = mModel.isVideo(0); - mIsDeletable = mModel.isDeletable(0); - mLoadingState = mModel.getLoadingState(0); - setScreenNail(mModel.getScreenNail(0)); - updateSize(); - } - - @Override - public Size getSize() { - return mSize; - } - - @Override - public void forceSize() { - updateSize(); - mPositionController.forceImageSize(0, mSize); - } - - private void updateSize() { - if (mIsPanorama) { - mRotation = getPanoramaRotation(); - } else if (mIsCamera && !mIsStaticCamera) { - mRotation = getCameraRotation(); - } else { - mRotation = mModel.getImageRotation(0); - } - - int w = mTileView.mImageWidth; - int h = mTileView.mImageHeight; - mSize.width = getRotated(mRotation, w, h); - mSize.height = getRotated(mRotation, h, w); - } - - @Override - public void draw(GLCanvas canvas, Rect r) { - drawTileView(canvas, r); - - // We want to have the following transitions: - // (1) Move camera preview out of its place: switch to film mode - // (2) Move camera preview into its place: switch to page mode - // The extra mWasCenter check makes sure (1) does not apply if in - // page mode, we move _to_ the camera preview from another picture. - - // Holdings except touch-down prevent the transitions. - if ((mHolding & ~HOLD_TOUCH_DOWN) != 0) return; - - if (mWantPictureCenterCallbacks && mPositionController.isCenter()) { - mListener.onPictureCenter(mIsCamera); - } - } - - @Override - public void setScreenNail(ScreenNail s) { - mTileView.setScreenNail(s); - } - - @Override - public boolean isCamera() { - return mIsCamera; - } - - @Override - public boolean isDeletable() { - return mIsDeletable; - } - - private void drawTileView(GLCanvas canvas, Rect r) { - float imageScale = mPositionController.getImageScale(); - int viewW = getWidth(); - int viewH = getHeight(); - float cx = r.exactCenterX(); - float cy = r.exactCenterY(); - float scale = 1f; // the scaling factor due to card effect - - canvas.save(GLCanvas.SAVE_FLAG_MATRIX | GLCanvas.SAVE_FLAG_ALPHA); - float filmRatio = mPositionController.getFilmRatio(); - boolean wantsCardEffect = CARD_EFFECT && !mIsCamera - && filmRatio != 1f && !mPictures.get(-1).isCamera() - && !mPositionController.inOpeningAnimation(); - boolean wantsOffsetEffect = OFFSET_EFFECT && mIsDeletable - && filmRatio == 1f && r.centerY() != viewH / 2; - if (wantsCardEffect) { - // Calculate the move-out progress value. - int left = r.left; - int right = r.right; - float progress = calculateMoveOutProgress(left, right, viewW); - progress = Utils.clamp(progress, -1f, 1f); - - // We only want to apply the fading animation if the scrolling - // movement is to the right. - if (progress < 0) { - scale = getScrollScale(progress); - float alpha = getScrollAlpha(progress); - scale = interpolate(filmRatio, scale, 1f); - alpha = interpolate(filmRatio, alpha, 1f); - - imageScale *= scale; - canvas.multiplyAlpha(alpha); - - float cxPage; // the cx value in page mode - if (right - left <= viewW) { - // If the picture is narrower than the view, keep it at - // the center of the view. - cxPage = viewW / 2f; - } else { - // If the picture is wider than the view (it's - // zoomed-in), keep the left edge of the object align - // the the left edge of the view. - cxPage = (right - left) * scale / 2f; - } - cx = interpolate(filmRatio, cxPage, cx); - } - } else if (wantsOffsetEffect) { - float offset = (float) (r.centerY() - viewH / 2) / viewH; - float alpha = getOffsetAlpha(offset); - canvas.multiplyAlpha(alpha); - } - - // Draw the tile view. - setTileViewPosition(cx, cy, viewW, viewH, imageScale); - renderChild(canvas, mTileView); - - // Draw the play video icon and the message. - canvas.translate((int) (cx + 0.5f), (int) (cy + 0.5f)); - int s = (int) (scale * Math.min(r.width(), r.height()) + 0.5f); - if (mIsVideo) drawVideoPlayIcon(canvas, s); - if (mLoadingState == Model.LOADING_FAIL) { - drawLoadingFailMessage(canvas); - } - - // Draw a debug indicator showing which picture has focus (index == - // 0). - //canvas.fillRect(-10, -10, 20, 20, 0x80FF00FF); - - canvas.restore(); - } - - // Set the position of the tile view - private void setTileViewPosition(float cx, float cy, - int viewW, int viewH, float scale) { - // Find out the bitmap coordinates of the center of the view - int imageW = mPositionController.getImageWidth(); - int imageH = mPositionController.getImageHeight(); - int centerX = (int) (imageW / 2f + (viewW / 2f - cx) / scale + 0.5f); - int centerY = (int) (imageH / 2f + (viewH / 2f - cy) / scale + 0.5f); - - int inverseX = imageW - centerX; - int inverseY = imageH - centerY; - int x, y; - switch (mRotation) { - case 0: x = centerX; y = centerY; break; - case 90: x = centerY; y = inverseX; break; - case 180: x = inverseX; y = inverseY; break; - case 270: x = inverseY; y = centerX; break; - default: - throw new RuntimeException(String.valueOf(mRotation)); - } - mTileView.setPosition(x, y, scale, mRotation); - } - } - - private class ScreenNailPicture implements Picture { - private int mIndex; - private int mRotation; - private ScreenNail mScreenNail; - private boolean mIsCamera; - private boolean mIsPanorama; - private boolean mIsStaticCamera; - private boolean mIsVideo; - private boolean mIsDeletable; - private int mLoadingState = Model.LOADING_INIT; - private Size mSize = new Size(); - - public ScreenNailPicture(int index) { - mIndex = index; - } - - @Override - public void reload() { - mIsCamera = mModel.isCamera(mIndex); - mIsPanorama = mModel.isPanorama(mIndex); - mIsStaticCamera = mModel.isStaticCamera(mIndex); - mIsVideo = mModel.isVideo(mIndex); - mIsDeletable = mModel.isDeletable(mIndex); - mLoadingState = mModel.getLoadingState(mIndex); - setScreenNail(mModel.getScreenNail(mIndex)); - updateSize(); - } - - @Override - public Size getSize() { - return mSize; - } - - @Override - public void draw(GLCanvas canvas, Rect r) { - if (mScreenNail == null) { - // Draw a placeholder rectange if there should be a picture in - // this position (but somehow there isn't). - if (mIndex >= mPrevBound && mIndex <= mNextBound) { - drawPlaceHolder(canvas, r); - } - return; - } - int w = getWidth(); - int h = getHeight(); - if (r.left >= w || r.right <= 0 || r.top >= h || r.bottom <= 0) { - mScreenNail.noDraw(); - return; - } - - float filmRatio = mPositionController.getFilmRatio(); - boolean wantsCardEffect = CARD_EFFECT && mIndex > 0 - && filmRatio != 1f && !mPictures.get(0).isCamera(); - boolean wantsOffsetEffect = OFFSET_EFFECT && mIsDeletable - && filmRatio == 1f && r.centerY() != h / 2; - int cx = wantsCardEffect - ? (int) (interpolate(filmRatio, w / 2, r.centerX()) + 0.5f) - : r.centerX(); - int cy = r.centerY(); - canvas.save(GLCanvas.SAVE_FLAG_MATRIX | GLCanvas.SAVE_FLAG_ALPHA); - canvas.translate(cx, cy); - if (wantsCardEffect) { - float progress = (float) (w / 2 - r.centerX()) / w; - progress = Utils.clamp(progress, -1, 1); - float alpha = getScrollAlpha(progress); - float scale = getScrollScale(progress); - alpha = interpolate(filmRatio, alpha, 1f); - scale = interpolate(filmRatio, scale, 1f); - canvas.multiplyAlpha(alpha); - canvas.scale(scale, scale, 1); - } else if (wantsOffsetEffect) { - float offset = (float) (r.centerY() - h / 2) / h; - float alpha = getOffsetAlpha(offset); - canvas.multiplyAlpha(alpha); - } - if (mRotation != 0) { - canvas.rotate(mRotation, 0, 0, 1); - } - int drawW = getRotated(mRotation, r.width(), r.height()); - int drawH = getRotated(mRotation, r.height(), r.width()); - mScreenNail.draw(canvas, -drawW / 2, -drawH / 2, drawW, drawH); - if (isScreenNailAnimating()) { - invalidate(); - } - int s = Math.min(drawW, drawH); - if (mIsVideo) drawVideoPlayIcon(canvas, s); - if (mLoadingState == Model.LOADING_FAIL) { - drawLoadingFailMessage(canvas); - } - canvas.restore(); - } - - private boolean isScreenNailAnimating() { - return (mScreenNail instanceof TiledScreenNail) - && ((TiledScreenNail) mScreenNail).isAnimating(); - } - - @Override - public void setScreenNail(ScreenNail s) { - mScreenNail = s; - } - - @Override - public void forceSize() { - updateSize(); - mPositionController.forceImageSize(mIndex, mSize); - } - - private void updateSize() { - if (mIsPanorama) { - mRotation = getPanoramaRotation(); - } else if (mIsCamera && !mIsStaticCamera) { - mRotation = getCameraRotation(); - } else { - mRotation = mModel.getImageRotation(mIndex); - } - - if (mScreenNail != null) { - mSize.width = mScreenNail.getWidth(); - mSize.height = mScreenNail.getHeight(); - } else { - // If we don't have ScreenNail available, we can still try to - // get the size information of it. - mModel.getImageSize(mIndex, mSize); - } - - int w = mSize.width; - int h = mSize.height; - mSize.width = getRotated(mRotation, w, h); - mSize.height = getRotated(mRotation, h, w); - } - - @Override - public boolean isCamera() { - return mIsCamera; - } - - @Override - public boolean isDeletable() { - return mIsDeletable; - } - } - - // Draw a gray placeholder in the specified rectangle. - private void drawPlaceHolder(GLCanvas canvas, Rect r) { - canvas.fillRect(r.left, r.top, r.width(), r.height(), mPlaceholderColor); - } - - // Draw the video play icon (in the place where the spinner was) - private void drawVideoPlayIcon(GLCanvas canvas, int side) { - int s = side / ICON_RATIO; - // Draw the video play icon at the center - mVideoPlayIcon.draw(canvas, -s / 2, -s / 2, s, s); - } - - // Draw the "no thumbnail" message - private void drawLoadingFailMessage(GLCanvas canvas) { - StringTexture m = mNoThumbnailText; - m.draw(canvas, -m.getWidth() / 2, -m.getHeight() / 2); - } - - private static int getRotated(int degree, int original, int theother) { - return (degree % 180 == 0) ? original : theother; - } - - //////////////////////////////////////////////////////////////////////////// - // Gestures Handling - //////////////////////////////////////////////////////////////////////////// - - @Override - protected boolean onTouch(MotionEvent event) { - mGestureRecognizer.onTouchEvent(event); - return true; - } - - private class MyGestureListener implements GestureRecognizer.Listener { - private boolean mIgnoreUpEvent = false; - // If we can change mode for this scale gesture. - private boolean mCanChangeMode; - // If we have changed the film mode in this scaling gesture. - private boolean mModeChanged; - // If this scaling gesture should be ignored. - private boolean mIgnoreScalingGesture; - // whether the down action happened while the view is scrolling. - private boolean mDownInScrolling; - // If we should ignore all gestures other than onSingleTapUp. - private boolean mIgnoreSwipingGesture; - // If a scrolling has happened after a down gesture. - private boolean mScrolledAfterDown; - // If the first scrolling move is in X direction. In the film mode, X - // direction scrolling is normal scrolling. but Y direction scrolling is - // a delete gesture. - private boolean mFirstScrollX; - // The accumulated Y delta that has been sent to mPositionController. - private int mDeltaY; - // The accumulated scaling change from a scaling gesture. - private float mAccScale; - // If an onFling happened after the last onDown - private boolean mHadFling; - - @Override - public boolean onSingleTapUp(float x, float y) { - // On crespo running Android 2.3.6 (gingerbread), a pinch out gesture results in the - // following call sequence: onDown(), onUp() and then onSingleTapUp(). The correct - // sequence for a single-tap-up gesture should be: onDown(), onSingleTapUp() and onUp(). - // The call sequence for a pinch out gesture in JB is: onDown(), then onUp() and there's - // no onSingleTapUp(). Base on these observations, the following condition is added to - // filter out the false alarm where onSingleTapUp() is called within a pinch out - // gesture. The framework fix went into ICS. Refer to b/4588114. - if (Build.VERSION.SDK_INT < ApiHelper.VERSION_CODES.ICE_CREAM_SANDWICH) { - if ((mHolding & HOLD_TOUCH_DOWN) == 0) { - return true; - } - } - - // We do this in addition to onUp() because we want the snapback of - // setFilmMode to happen. - mHolding &= ~HOLD_TOUCH_DOWN; - - if (mFilmMode && !mDownInScrolling) { - switchToHitPicture((int) (x + 0.5f), (int) (y + 0.5f)); - - // If this is a lock screen photo, let the listener handle the - // event. Tapping on lock screen photo should take the user - // directly to the lock screen. - MediaItem item = mModel.getMediaItem(0); - int supported = 0; - if (item != null) supported = item.getSupportedOperations(); - if ((supported & MediaItem.SUPPORT_ACTION) == 0) { - setFilmMode(false); - mIgnoreUpEvent = true; - return true; - } - } - - if (mListener != null) { - // Do the inverse transform of the touch coordinates. - Matrix m = getGLRoot().getCompensationMatrix(); - Matrix inv = new Matrix(); - m.invert(inv); - float[] pts = new float[] {x, y}; - inv.mapPoints(pts); - mListener.onSingleTapUp((int) (pts[0] + 0.5f), (int) (pts[1] + 0.5f)); - } - return true; - } - - @Override - public boolean onDoubleTap(float x, float y) { - if (mIgnoreSwipingGesture) return true; - if (mPictures.get(0).isCamera()) return false; - PositionController controller = mPositionController; - float scale = controller.getImageScale(); - // onDoubleTap happened on the second ACTION_DOWN. - // We need to ignore the next UP event. - mIgnoreUpEvent = true; - if (scale <= .75f || controller.isAtMinimalScale()) { - controller.zoomIn(x, y, Math.max(1.0f, scale * 1.5f)); - } else { - controller.resetToFullView(); - } - return true; - } - - @Override - public boolean onScroll(float dx, float dy, float totalX, float totalY) { - if (mIgnoreSwipingGesture) return true; - if (!mScrolledAfterDown) { - mScrolledAfterDown = true; - mFirstScrollX = (Math.abs(dx) > Math.abs(dy)); - } - - int dxi = (int) (-dx + 0.5f); - int dyi = (int) (-dy + 0.5f); - if (mFilmMode) { - if (mFirstScrollX) { - mPositionController.scrollFilmX(dxi); - } else { - if (mTouchBoxIndex == Integer.MAX_VALUE) return true; - int newDeltaY = calculateDeltaY(totalY); - int d = newDeltaY - mDeltaY; - if (d != 0) { - mPositionController.scrollFilmY(mTouchBoxIndex, d); - mDeltaY = newDeltaY; - } - } - } else { - mPositionController.scrollPage(dxi, dyi); - } - return true; - } - - private int calculateDeltaY(float delta) { - if (mTouchBoxDeletable) return (int) (delta + 0.5f); - - // don't let items that can't be deleted be dragged more than - // maxScrollDistance, and make it harder and harder to drag. - int size = getHeight(); - float maxScrollDistance = 0.15f * size; - if (Math.abs(delta) >= size) { - delta = delta > 0 ? maxScrollDistance : -maxScrollDistance; - } else { - delta = maxScrollDistance * - FloatMath.sin((delta / size) * (float) (Math.PI / 2)); - } - return (int) (delta + 0.5f); - } - - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { - if (mIgnoreSwipingGesture) return true; - if (mModeChanged) return true; - if (swipeImages(velocityX, velocityY)) { - mIgnoreUpEvent = true; - } else { - flingImages(velocityX, velocityY, Math.abs(e2.getY() - e1.getY())); - } - mHadFling = true; - return true; - } - - private boolean flingImages(float velocityX, float velocityY, float dY) { - int vx = (int) (velocityX + 0.5f); - int vy = (int) (velocityY + 0.5f); - if (!mFilmMode) { - return mPositionController.flingPage(vx, vy); - } - if (Math.abs(velocityX) > Math.abs(velocityY)) { - return mPositionController.flingFilmX(vx); - } - // If we scrolled in Y direction fast enough, treat it as a delete - // gesture. - if (!mFilmMode || mTouchBoxIndex == Integer.MAX_VALUE - || !mTouchBoxDeletable) { - return false; - } - int maxVelocity = GalleryUtils.dpToPixel(MAX_DISMISS_VELOCITY); - int escapeVelocity = GalleryUtils.dpToPixel(SWIPE_ESCAPE_VELOCITY); - int escapeDistance = GalleryUtils.dpToPixel(SWIPE_ESCAPE_DISTANCE); - int centerY = mPositionController.getPosition(mTouchBoxIndex) - .centerY(); - boolean fastEnough = (Math.abs(vy) > escapeVelocity) - && (Math.abs(vy) > Math.abs(vx)) - && ((vy > 0) == (centerY > getHeight() / 2)) - && dY >= escapeDistance; - if (fastEnough) { - vy = Math.min(vy, maxVelocity); - int duration = mPositionController.flingFilmY(mTouchBoxIndex, vy); - if (duration >= 0) { - mPositionController.setPopFromTop(vy < 0); - deleteAfterAnimation(duration); - // We reset mTouchBoxIndex, so up() won't check if Y - // scrolled far enough to be a delete gesture. - mTouchBoxIndex = Integer.MAX_VALUE; - return true; - } - } - return false; - } - - private void deleteAfterAnimation(int duration) { - MediaItem item = mModel.getMediaItem(mTouchBoxIndex); - if (item == null) return; - mListener.onCommitDeleteImage(); - mUndoIndexHint = mModel.getCurrentIndex() + mTouchBoxIndex; - mHolding |= HOLD_DELETE; - Message m = mHandler.obtainMessage(MSG_DELETE_ANIMATION_DONE); - m.obj = item.getPath(); - m.arg1 = mTouchBoxIndex; - mHandler.sendMessageDelayed(m, duration); - } - - @Override - public boolean onScaleBegin(float focusX, float focusY) { - if (mIgnoreSwipingGesture) return true; - // We ignore the scaling gesture if it is a camera preview. - mIgnoreScalingGesture = mPictures.get(0).isCamera(); - if (mIgnoreScalingGesture) { - return true; - } - mPositionController.beginScale(focusX, focusY); - // We can change mode if we are in film mode, or we are in page - // mode and at minimal scale. - mCanChangeMode = mFilmMode - || mPositionController.isAtMinimalScale(); - mAccScale = 1f; - return true; - } - - @Override - public boolean onScale(float focusX, float focusY, float scale) { - if (mIgnoreSwipingGesture) return true; - if (mIgnoreScalingGesture) return true; - if (mModeChanged) return true; - if (Float.isNaN(scale) || Float.isInfinite(scale)) return false; - - int outOfRange = mPositionController.scaleBy(scale, focusX, focusY); - - // We wait for a large enough scale change before changing mode. - // Otherwise we may mistakenly treat a zoom-in gesture as zoom-out - // or vice versa. - mAccScale *= scale; - boolean largeEnough = (mAccScale < 0.97f || mAccScale > 1.03f); - - // If mode changes, we treat this scaling gesture has ended. - if (mCanChangeMode && largeEnough) { - if ((outOfRange < 0 && !mFilmMode) || - (outOfRange > 0 && mFilmMode)) { - stopExtraScalingIfNeeded(); - - // Removing the touch down flag allows snapback to happen - // for film mode change. - mHolding &= ~HOLD_TOUCH_DOWN; - if (mFilmMode) { - UsageStatistics.setPendingTransitionCause( - UsageStatistics.TRANSITION_PINCH_OUT); - } else { - UsageStatistics.setPendingTransitionCause( - UsageStatistics.TRANSITION_PINCH_IN); - } - setFilmMode(!mFilmMode); - - - // We need to call onScaleEnd() before setting mModeChanged - // to true. - onScaleEnd(); - mModeChanged = true; - return true; - } - } - - if (outOfRange != 0) { - startExtraScalingIfNeeded(); - } else { - stopExtraScalingIfNeeded(); - } - return true; - } - - @Override - public void onScaleEnd() { - if (mIgnoreSwipingGesture) return; - if (mIgnoreScalingGesture) return; - if (mModeChanged) return; - mPositionController.endScale(); - } - - private void startExtraScalingIfNeeded() { - if (!mCancelExtraScalingPending) { - mHandler.sendEmptyMessageDelayed( - MSG_CANCEL_EXTRA_SCALING, 700); - mPositionController.setExtraScalingRange(true); - mCancelExtraScalingPending = true; - } - } - - private void stopExtraScalingIfNeeded() { - if (mCancelExtraScalingPending) { - mHandler.removeMessages(MSG_CANCEL_EXTRA_SCALING); - mPositionController.setExtraScalingRange(false); - mCancelExtraScalingPending = false; - } - } - - @Override - public void onDown(float x, float y) { - checkHideUndoBar(UNDO_BAR_TOUCHED); - - mDeltaY = 0; - mModeChanged = false; - - if (mIgnoreSwipingGesture) return; - - mHolding |= HOLD_TOUCH_DOWN; - - if (mFilmMode && mPositionController.isScrolling()) { - mDownInScrolling = true; - mPositionController.stopScrolling(); - } else { - mDownInScrolling = false; - } - mHadFling = false; - mScrolledAfterDown = false; - if (mFilmMode) { - int xi = (int) (x + 0.5f); - int yi = (int) (y + 0.5f); - // We only care about being within the x bounds, necessary for - // handling very wide images which are otherwise very hard to fling - mTouchBoxIndex = mPositionController.hitTest(xi, getHeight() / 2); - - if (mTouchBoxIndex < mPrevBound || mTouchBoxIndex > mNextBound) { - mTouchBoxIndex = Integer.MAX_VALUE; - } else { - mTouchBoxDeletable = - mPictures.get(mTouchBoxIndex).isDeletable(); - } - } else { - mTouchBoxIndex = Integer.MAX_VALUE; - } - } - - @Override - public void onUp() { - if (mIgnoreSwipingGesture) return; - - mHolding &= ~HOLD_TOUCH_DOWN; - mEdgeView.onRelease(); - - // If we scrolled in Y direction far enough, treat it as a delete - // gesture. - if (mFilmMode && mScrolledAfterDown && !mFirstScrollX - && mTouchBoxIndex != Integer.MAX_VALUE) { - Rect r = mPositionController.getPosition(mTouchBoxIndex); - int h = getHeight(); - if (Math.abs(r.centerY() - h * 0.5f) > 0.4f * h) { - int duration = mPositionController - .flingFilmY(mTouchBoxIndex, 0); - if (duration >= 0) { - mPositionController.setPopFromTop(r.centerY() < h * 0.5f); - deleteAfterAnimation(duration); - } - } - } - - if (mIgnoreUpEvent) { - mIgnoreUpEvent = false; - return; - } - - if (!(mFilmMode && !mHadFling && mFirstScrollX - && snapToNeighborImage())) { - snapback(); - } - } - - public void setSwipingEnabled(boolean enabled) { - mIgnoreSwipingGesture = !enabled; - } - } - - public void setSwipingEnabled(boolean enabled) { - mGestureListener.setSwipingEnabled(enabled); - } - - private void updateActionBar() { - boolean isCamera = mPictures.get(0).isCamera(); - if (isCamera && !mFilmMode) { - // Move into camera in page mode, lock - mListener.onActionBarAllowed(false); - } else { - mListener.onActionBarAllowed(true); - if (mFilmMode) mListener.onActionBarWanted(); - } - } - - public void setFilmMode(boolean enabled) { - if (mFilmMode == enabled) return; - mFilmMode = enabled; - mPositionController.setFilmMode(mFilmMode); - mModel.setNeedFullImage(!enabled); - mModel.setFocusHintDirection( - mFilmMode ? Model.FOCUS_HINT_PREVIOUS : Model.FOCUS_HINT_NEXT); - updateActionBar(); - mListener.onFilmModeChanged(enabled); - } - - public boolean getFilmMode() { - return mFilmMode; - } - - //////////////////////////////////////////////////////////////////////////// - // Framework events - //////////////////////////////////////////////////////////////////////////// - - public void pause() { - mPositionController.skipAnimation(); - mTileView.freeTextures(); - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; i++) { - mPictures.get(i).setScreenNail(null); - } - hideUndoBar(); - } - - public void resume() { - mTileView.prepareTextures(); - mPositionController.skipToFinalPosition(); - } - - // move to the camera preview and show controls after resume - public void resetToFirstPicture() { - mModel.moveTo(0); - setFilmMode(false); - } - - //////////////////////////////////////////////////////////////////////////// - // Undo Bar - //////////////////////////////////////////////////////////////////////////// - - private int mUndoBarState; - private static final int UNDO_BAR_SHOW = 1; - private static final int UNDO_BAR_TIMEOUT = 2; - private static final int UNDO_BAR_TOUCHED = 4; - private static final int UNDO_BAR_FULL_CAMERA = 8; - private static final int UNDO_BAR_DELETE_LAST = 16; - - // "deleteLast" means if the deletion is on the last remaining picture in - // the album. - private void showUndoBar(boolean deleteLast) { - mHandler.removeMessages(MSG_UNDO_BAR_TIMEOUT); - mUndoBarState = UNDO_BAR_SHOW; - if(deleteLast) mUndoBarState |= UNDO_BAR_DELETE_LAST; - mUndoBar.animateVisibility(GLView.VISIBLE); - mHandler.sendEmptyMessageDelayed(MSG_UNDO_BAR_TIMEOUT, 3000); - if (mListener != null) mListener.onUndoBarVisibilityChanged(true); - } - - private void hideUndoBar() { - mHandler.removeMessages(MSG_UNDO_BAR_TIMEOUT); - mListener.onCommitDeleteImage(); - mUndoBar.animateVisibility(GLView.INVISIBLE); - mUndoBarState = 0; - mUndoIndexHint = Integer.MAX_VALUE; - mListener.onUndoBarVisibilityChanged(false); - } - - // Check if the one of the conditions for hiding the undo bar has been - // met. The conditions are: - // - // 1. It has been three seconds since last showing, and (a) the user has - // touched, or (b) the deleted picture is the last remaining picture in the - // album. - // - // 2. The camera is shown in full screen. - private void checkHideUndoBar(int addition) { - mUndoBarState |= addition; - if ((mUndoBarState & UNDO_BAR_SHOW) == 0) return; - boolean timeout = (mUndoBarState & UNDO_BAR_TIMEOUT) != 0; - boolean touched = (mUndoBarState & UNDO_BAR_TOUCHED) != 0; - boolean fullCamera = (mUndoBarState & UNDO_BAR_FULL_CAMERA) != 0; - boolean deleteLast = (mUndoBarState & UNDO_BAR_DELETE_LAST) != 0; - if ((timeout && deleteLast) || fullCamera || touched) { - hideUndoBar(); - } - } - - public boolean canUndo() { - return (mUndoBarState & UNDO_BAR_SHOW) != 0; - } - - //////////////////////////////////////////////////////////////////////////// - // Rendering - //////////////////////////////////////////////////////////////////////////// - - @Override - protected void render(GLCanvas canvas) { - if (mFirst) { - // Make sure the fields are properly initialized before checking - // whether isCamera() - mPictures.get(0).reload(); - } - // Check if the camera preview occupies the full screen. - boolean full = !mFilmMode && mPictures.get(0).isCamera() - && mPositionController.isCenter() - && mPositionController.isAtMinimalScale(); - if (mFirst || full != mFullScreenCamera) { - mFullScreenCamera = full; - mFirst = false; - mListener.onFullScreenChanged(full); - if (full) mHandler.sendEmptyMessage(MSG_UNDO_BAR_FULL_CAMERA); - } - - // Determine how many photos we need to draw in addition to the center - // one. - int neighbors; - if (mFullScreenCamera) { - neighbors = 0; - } else { - // In page mode, we draw only one previous/next photo. But if we are - // doing capture animation, we want to draw all photos. - boolean inPageMode = (mPositionController.getFilmRatio() == 0f); - boolean inCaptureAnimation = - ((mHolding & HOLD_CAPTURE_ANIMATION) != 0); - if (inPageMode && !inCaptureAnimation) { - neighbors = 1; - } else { - neighbors = SCREEN_NAIL_MAX; - } - } - - // Draw photos from back to front - for (int i = neighbors; i >= -neighbors; i--) { - Rect r = mPositionController.getPosition(i); - mPictures.get(i).draw(canvas, r); - } - - renderChild(canvas, mEdgeView); - renderChild(canvas, mUndoBar); - - mPositionController.advanceAnimation(); - checkFocusSwitching(); - } - - //////////////////////////////////////////////////////////////////////////// - // Film mode focus switching - //////////////////////////////////////////////////////////////////////////// - - // Runs in GL thread. - private void checkFocusSwitching() { - if (!mFilmMode) return; - if (mHandler.hasMessages(MSG_SWITCH_FOCUS)) return; - if (switchPosition() != 0) { - mHandler.sendEmptyMessage(MSG_SWITCH_FOCUS); - } - } - - // Runs in main thread. - private void switchFocus() { - if (mHolding != 0) return; - switch (switchPosition()) { - case -1: - switchToPrevImage(); - break; - case 1: - switchToNextImage(); - break; - } - } - - // Returns -1 if we should switch focus to the previous picture, +1 if we - // should switch to the next, 0 otherwise. - private int switchPosition() { - Rect curr = mPositionController.getPosition(0); - int center = getWidth() / 2; - - if (curr.left > center && mPrevBound < 0) { - Rect prev = mPositionController.getPosition(-1); - int currDist = curr.left - center; - int prevDist = center - prev.right; - if (prevDist < currDist) { - return -1; - } - } else if (curr.right < center && mNextBound > 0) { - Rect next = mPositionController.getPosition(1); - int currDist = center - curr.right; - int nextDist = next.left - center; - if (nextDist < currDist) { - return 1; - } - } - - return 0; - } - - // Switch to the previous or next picture if the hit position is inside - // one of their boxes. This runs in main thread. - private void switchToHitPicture(int x, int y) { - if (mPrevBound < 0) { - Rect r = mPositionController.getPosition(-1); - if (r.right >= x) { - slideToPrevPicture(); - return; - } - } - - if (mNextBound > 0) { - Rect r = mPositionController.getPosition(1); - if (r.left <= x) { - slideToNextPicture(); - return; - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // Page mode focus switching - // - // We slide image to the next one or the previous one in two cases: 1: If - // the user did a fling gesture with enough velocity. 2 If the user has - // moved the picture a lot. - //////////////////////////////////////////////////////////////////////////// - - private boolean swipeImages(float velocityX, float velocityY) { - if (mFilmMode) return false; - - // Avoid swiping images if we're possibly flinging to view the - // zoomed in picture vertically. - PositionController controller = mPositionController; - boolean isMinimal = controller.isAtMinimalScale(); - int edges = controller.getImageAtEdges(); - if (!isMinimal && Math.abs(velocityY) > Math.abs(velocityX)) - if ((edges & PositionController.IMAGE_AT_TOP_EDGE) == 0 - || (edges & PositionController.IMAGE_AT_BOTTOM_EDGE) == 0) - return false; - - // If we are at the edge of the current photo and the sweeping velocity - // exceeds the threshold, slide to the next / previous image. - if (velocityX < -SWIPE_THRESHOLD && (isMinimal - || (edges & PositionController.IMAGE_AT_RIGHT_EDGE) != 0)) { - return slideToNextPicture(); - } else if (velocityX > SWIPE_THRESHOLD && (isMinimal - || (edges & PositionController.IMAGE_AT_LEFT_EDGE) != 0)) { - return slideToPrevPicture(); - } - - return false; - } - - private void snapback() { - if ((mHolding & ~HOLD_DELETE) != 0) return; - if (mFilmMode || !snapToNeighborImage()) { - mPositionController.snapback(); - } - } - - private boolean snapToNeighborImage() { - Rect r = mPositionController.getPosition(0); - int viewW = getWidth(); - // Setting the move threshold proportional to the width of the view - int moveThreshold = viewW / 5 ; - int threshold = moveThreshold + gapToSide(r.width(), viewW); - - // If we have moved the picture a lot, switching. - if (viewW - r.right > threshold) { - return slideToNextPicture(); - } else if (r.left > threshold) { - return slideToPrevPicture(); - } - - return false; - } - - private boolean slideToNextPicture() { - if (mNextBound <= 0) return false; - switchToNextImage(); - mPositionController.startHorizontalSlide(); - return true; - } - - private boolean slideToPrevPicture() { - if (mPrevBound >= 0) return false; - switchToPrevImage(); - mPositionController.startHorizontalSlide(); - return true; - } - - private static int gapToSide(int imageWidth, int viewWidth) { - return Math.max(0, (viewWidth - imageWidth) / 2); - } - - //////////////////////////////////////////////////////////////////////////// - // Focus switching - //////////////////////////////////////////////////////////////////////////// - - public void switchToImage(int index) { - mModel.moveTo(index); - } - - private void switchToNextImage() { - mModel.moveTo(mModel.getCurrentIndex() + 1); - } - - private void switchToPrevImage() { - mModel.moveTo(mModel.getCurrentIndex() - 1); - } - - private void switchToFirstImage() { - mModel.moveTo(0); - } - - //////////////////////////////////////////////////////////////////////////// - // Opening Animation - //////////////////////////////////////////////////////////////////////////// - - public void setOpenAnimationRect(Rect rect) { - mPositionController.setOpenAnimationRect(rect); - } - - //////////////////////////////////////////////////////////////////////////// - // Capture Animation - //////////////////////////////////////////////////////////////////////////// - - public boolean switchWithCaptureAnimation(int offset) { - GLRoot root = getGLRoot(); - if(root == null) return false; - root.lockRenderThread(); - try { - return switchWithCaptureAnimationLocked(offset); - } finally { - root.unlockRenderThread(); - } - } - - private boolean switchWithCaptureAnimationLocked(int offset) { - if (mHolding != 0) return true; - if (offset == 1) { - if (mNextBound <= 0) return false; - // Temporary disable action bar until the capture animation is done. - if (!mFilmMode) mListener.onActionBarAllowed(false); - switchToNextImage(); - mPositionController.startCaptureAnimationSlide(-1); - } else if (offset == -1) { - if (mPrevBound >= 0) return false; - if (mFilmMode) setFilmMode(false); - - // If we are too far away from the first image (so that we don't - // have all the ScreenNails in-between), we go directly without - // animation. - if (mModel.getCurrentIndex() > SCREEN_NAIL_MAX) { - switchToFirstImage(); - mPositionController.skipToFinalPosition(); - return true; - } - - switchToFirstImage(); - mPositionController.startCaptureAnimationSlide(1); - } else { - return false; - } - mHolding |= HOLD_CAPTURE_ANIMATION; - Message m = mHandler.obtainMessage(MSG_CAPTURE_ANIMATION_DONE, offset, 0); - mHandler.sendMessageDelayed(m, PositionController.CAPTURE_ANIMATION_TIME); - return true; - } - - private void captureAnimationDone(int offset) { - mHolding &= ~HOLD_CAPTURE_ANIMATION; - if (offset == 1 && !mFilmMode) { - // Now the capture animation is done, enable the action bar. - mListener.onActionBarAllowed(true); - mListener.onActionBarWanted(); - } - snapback(); - } - - //////////////////////////////////////////////////////////////////////////// - // Card deck effect calculation - //////////////////////////////////////////////////////////////////////////// - - // Returns the scrolling progress value for an object moving out of a - // view. The progress value measures how much the object has moving out of - // the view. The object currently displays in [left, right), and the view is - // at [0, viewWidth]. - // - // The returned value is negative when the object is moving right, and - // positive when the object is moving left. The value goes to -1 or 1 when - // the object just moves out of the view completely. The value is 0 if the - // object currently fills the view. - private static float calculateMoveOutProgress(int left, int right, - int viewWidth) { - // w = object width - // viewWidth = view width - int w = right - left; - - // If the object width is smaller than the view width, - // |....view....| - // |<-->| progress = -1 when left = viewWidth - // |<-->| progress = 0 when left = viewWidth / 2 - w / 2 - // |<-->| progress = 1 when left = -w - if (w < viewWidth) { - int zx = viewWidth / 2 - w / 2; - if (left > zx) { - return -(left - zx) / (float) (viewWidth - zx); // progress = (0, -1] - } else { - return (left - zx) / (float) (-w - zx); // progress = [0, 1] - } - } - - // If the object width is larger than the view width, - // |..view..| - // |<--------->| progress = -1 when left = viewWidth - // |<--------->| progress = 0 between left = 0 - // |<--------->| and right = viewWidth - // |<--------->| progress = 1 when right = 0 - if (left > 0) { - return -left / (float) viewWidth; - } - - if (right < viewWidth) { - return (viewWidth - right) / (float) viewWidth; - } - - return 0; - } - - // Maps a scrolling progress value to the alpha factor in the fading - // animation. - private float getScrollAlpha(float scrollProgress) { - return scrollProgress < 0 ? mAlphaInterpolator.getInterpolation( - 1 - Math.abs(scrollProgress)) : 1.0f; - } - - // Maps a scrolling progress value to the scaling factor in the fading - // animation. - private float getScrollScale(float scrollProgress) { - float interpolatedProgress = mScaleInterpolator.getInterpolation( - Math.abs(scrollProgress)); - float scale = (1 - interpolatedProgress) + - interpolatedProgress * TRANSITION_SCALE_FACTOR; - return scale; - } - - - // This interpolator emulates the rate at which the perceived scale of an - // object changes as its distance from a camera increases. When this - // interpolator is applied to a scale animation on a view, it evokes the - // sense that the object is shrinking due to moving away from the camera. - private static class ZInterpolator { - private float focalLength; - - public ZInterpolator(float foc) { - focalLength = foc; - } - - public float getInterpolation(float input) { - return (1.0f - focalLength / (focalLength + input)) / - (1.0f - focalLength / (focalLength + 1.0f)); - } - } - - // Returns an interpolated value for the page/film transition. - // When ratio = 0, the result is from. - // When ratio = 1, the result is to. - private static float interpolate(float ratio, float from, float to) { - return from + (to - from) * ratio * ratio; - } - - // Returns the alpha factor in film mode if a picture is not in the center. - // The 0.03 lower bound is to make the item always visible a bit. - private float getOffsetAlpha(float offset) { - offset /= 0.5f; - float alpha = (offset > 0) ? (1 - offset) : (1 + offset); - return Utils.clamp(alpha, 0.03f, 1f); - } - - //////////////////////////////////////////////////////////////////////////// - // Simple public utilities - //////////////////////////////////////////////////////////////////////////// - - public void setListener(Listener listener) { - mListener = listener; - } - - public Rect getPhotoRect(int index) { - return mPositionController.getPosition(index); - } - - public PhotoFallbackEffect buildFallbackEffect(GLView root, GLCanvas canvas) { - Rect location = new Rect(); - Utils.assertTrue(root.getBoundsOf(this, location)); - - Rect fullRect = bounds(); - PhotoFallbackEffect effect = new PhotoFallbackEffect(); - for (int i = -SCREEN_NAIL_MAX; i <= SCREEN_NAIL_MAX; ++i) { - MediaItem item = mModel.getMediaItem(i); - if (item == null) continue; - ScreenNail sc = mModel.getScreenNail(i); - if (!(sc instanceof TiledScreenNail) - || ((TiledScreenNail) sc).isShowingPlaceholder()) continue; - - // Now, sc is BitmapScreenNail and is not showing placeholder - Rect rect = new Rect(getPhotoRect(i)); - if (!Rect.intersects(fullRect, rect)) continue; - rect.offset(location.left, location.top); - - int width = sc.getWidth(); - int height = sc.getHeight(); - - int rotation = mModel.getImageRotation(i); - RawTexture texture; - if ((rotation % 180) == 0) { - texture = new RawTexture(width, height, true); - canvas.beginRenderTarget(texture); - canvas.translate(width / 2f, height / 2f); - } else { - texture = new RawTexture(height, width, true); - canvas.beginRenderTarget(texture); - canvas.translate(height / 2f, width / 2f); - } - - canvas.rotate(rotation, 0, 0, 1); - canvas.translate(-width / 2f, -height / 2f); - sc.draw(canvas, 0, 0, width, height); - canvas.endRenderTarget(); - effect.addEntry(item.getPath(), rect, texture); - } - return effect; - } -} diff --git a/src/com/android/gallery3d/ui/PopupList.java b/src/com/android/gallery3d/ui/PopupList.java deleted file mode 100644 index 248f50b25..000000000 --- a/src/com/android/gallery3d/ui/PopupList.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Rect; -import android.view.LayoutInflater; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; -import android.view.ViewTreeObserver; -import android.view.ViewTreeObserver.OnGlobalLayoutListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.BaseAdapter; -import android.widget.ListView; -import android.widget.PopupWindow; -import android.widget.TextView; - -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class PopupList { - - public static interface OnPopupItemClickListener { - public boolean onPopupItemClick(int itemId); - } - - public static class Item { - public final int id; - public String title; - - public Item(int id, String title) { - this.id = id; - this.title = title; - } - - public void setTitle(String title) { - this.title = title; - } - } - - private final Context mContext; - private final View mAnchorView; - private final ArrayList<Item> mItems = new ArrayList<Item>(); - private PopupWindow mPopupWindow; - private ListView mContentList; - private OnPopupItemClickListener mOnPopupItemClickListener; - private int mPopupOffsetX; - private int mPopupOffsetY; - private int mPopupWidth; - private int mPopupHeight; - - public PopupList(Context context, View anchorView) { - mContext = context; - mAnchorView = anchorView; - } - - public void setOnPopupItemClickListener(OnPopupItemClickListener listener) { - mOnPopupItemClickListener = listener; - } - - public void addItem(int id, String title) { - mItems.add(new Item(id, title)); - } - - public void clearItems() { - mItems.clear(); - } - - private final PopupWindow.OnDismissListener mOnDismissListener = - new PopupWindow.OnDismissListener() { - @SuppressWarnings("deprecation") - @Override - public void onDismiss() { - if (mPopupWindow == null) return; - mPopupWindow = null; - ViewTreeObserver observer = mAnchorView.getViewTreeObserver(); - if (observer.isAlive()) { - // We used the deprecated function for backward compatibility - // The new "removeOnGlobalLayoutListener" is introduced in API level 16 - observer.removeGlobalOnLayoutListener(mOnGLobalLayoutListener); - } - } - }; - - private final OnItemClickListener mOnItemClickListener = - new OnItemClickListener() { - @Override - public void onItemClick(AdapterView<?> parent, View view, int position, long id) { - if (mPopupWindow == null) return; - mPopupWindow.dismiss(); - if (mOnPopupItemClickListener != null) { - mOnPopupItemClickListener.onPopupItemClick((int) id); - } - } - }; - - private final OnGlobalLayoutListener mOnGLobalLayoutListener = - new OnGlobalLayoutListener() { - @Override - public void onGlobalLayout() { - if (mPopupWindow == null) return; - updatePopupLayoutParams(); - // Need to update the position of the popup window - mPopupWindow.update(mAnchorView, - mPopupOffsetX, mPopupOffsetY, mPopupWidth, mPopupHeight); - } - }; - - public void show() { - if (mPopupWindow != null) return; - mAnchorView.getViewTreeObserver() - .addOnGlobalLayoutListener(mOnGLobalLayoutListener); - mPopupWindow = createPopupWindow(); - updatePopupLayoutParams(); - mPopupWindow.setWidth(mPopupWidth); - mPopupWindow.setHeight(mPopupHeight); - mPopupWindow.showAsDropDown(mAnchorView, mPopupOffsetX, mPopupOffsetY); - } - - private void updatePopupLayoutParams() { - ListView content = mContentList; - PopupWindow popup = mPopupWindow; - - Rect p = new Rect(); - popup.getBackground().getPadding(p); - - int maxHeight = mPopupWindow.getMaxAvailableHeight(mAnchorView) - p.top - p.bottom; - mContentList.measure( - MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), - MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST)); - mPopupWidth = content.getMeasuredWidth() + p.top + p.bottom; - mPopupHeight = Math.min(maxHeight, content.getMeasuredHeight() + p.left + p.right); - mPopupOffsetX = -p.left; - mPopupOffsetY = -p.top; - } - - private PopupWindow createPopupWindow() { - PopupWindow popup = new PopupWindow(mContext); - popup.setOnDismissListener(mOnDismissListener); - - popup.setBackgroundDrawable(mContext.getResources().getDrawable( - R.drawable.menu_dropdown_panel_holo_dark)); - - mContentList = new ListView(mContext, null, - android.R.attr.dropDownListViewStyle); - mContentList.setAdapter(new ItemDataAdapter()); - mContentList.setOnItemClickListener(mOnItemClickListener); - popup.setContentView(mContentList); - popup.setFocusable(true); - popup.setOutsideTouchable(true); - - return popup; - } - - public Item findItem(int id) { - for (Item item : mItems) { - if (item.id == id) return item; - } - return null; - } - - private class ItemDataAdapter extends BaseAdapter { - @Override - public int getCount() { - return mItems.size(); - } - - @Override - public Object getItem(int position) { - return mItems.get(position); - } - - @Override - public long getItemId(int position) { - return mItems.get(position).id; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - if (convertView == null) { - convertView = LayoutInflater.from(mContext) - .inflate(R.layout.popup_list_item, null); - } - TextView text = (TextView) convertView.findViewById(android.R.id.text1); - text.setText(mItems.get(position).title); - return convertView; - } - } -} diff --git a/src/com/android/gallery3d/ui/PositionController.java b/src/com/android/gallery3d/ui/PositionController.java deleted file mode 100644 index 6a4bcea87..000000000 --- a/src/com/android/gallery3d/ui/PositionController.java +++ /dev/null @@ -1,1821 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Rect; -import android.util.Log; -import android.widget.Scroller; - -import com.android.gallery3d.app.PhotoPage; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.ui.PhotoView.Size; -import com.android.gallery3d.util.GalleryUtils; -import com.android.gallery3d.util.RangeArray; -import com.android.gallery3d.util.RangeIntArray; - -class PositionController { - private static final String TAG = "PositionController"; - - public static final int IMAGE_AT_LEFT_EDGE = 1; - public static final int IMAGE_AT_RIGHT_EDGE = 2; - public static final int IMAGE_AT_TOP_EDGE = 4; - public static final int IMAGE_AT_BOTTOM_EDGE = 8; - - public static final int CAPTURE_ANIMATION_TIME = 700; - public static final int SNAPBACK_ANIMATION_TIME = 600; - - // Special values for animation time. - private static final long NO_ANIMATION = -1; - private static final long LAST_ANIMATION = -2; - - private static final int ANIM_KIND_NONE = -1; - private static final int ANIM_KIND_SCROLL = 0; - private static final int ANIM_KIND_SCALE = 1; - private static final int ANIM_KIND_SNAPBACK = 2; - private static final int ANIM_KIND_SLIDE = 3; - private static final int ANIM_KIND_ZOOM = 4; - private static final int ANIM_KIND_OPENING = 5; - private static final int ANIM_KIND_FLING = 6; - private static final int ANIM_KIND_FLING_X = 7; - private static final int ANIM_KIND_DELETE = 8; - private static final int ANIM_KIND_CAPTURE = 9; - - // Animation time in milliseconds. The order must match ANIM_KIND_* above. - // - // The values for ANIM_KIND_FLING_X does't matter because we use - // mFilmScroller.isFinished() to decide when to stop. We set it to 0 so it's - // faster for Animatable.advanceAnimation() to calculate the progress - // (always 1). - private static final int ANIM_TIME[] = { - 0, // ANIM_KIND_SCROLL - 0, // ANIM_KIND_SCALE - SNAPBACK_ANIMATION_TIME, // ANIM_KIND_SNAPBACK - 400, // ANIM_KIND_SLIDE - 300, // ANIM_KIND_ZOOM - 300, // ANIM_KIND_OPENING - 0, // ANIM_KIND_FLING (the duration is calculated dynamically) - 0, // ANIM_KIND_FLING_X (see the comment above) - 0, // ANIM_KIND_DELETE (the duration is calculated dynamically) - CAPTURE_ANIMATION_TIME, // ANIM_KIND_CAPTURE - }; - - // We try to scale up the image to fill the screen. But in order not to - // scale too much for small icons, we limit the max up-scaling factor here. - private static final float SCALE_LIMIT = 4; - - // For user's gestures, we give a temporary extra scaling range which goes - // above or below the usual scaling limits. - private static final float SCALE_MIN_EXTRA = 0.7f; - private static final float SCALE_MAX_EXTRA = 1.4f; - - // Setting this true makes the extra scaling range permanent (until this is - // set to false again). - private boolean mExtraScalingRange = false; - - // Film Mode v.s. Page Mode: in film mode we show smaller pictures. - private boolean mFilmMode = false; - - // These are the limits for width / height of the picture in film mode. - private static final float FILM_MODE_PORTRAIT_HEIGHT = 0.48f; - private static final float FILM_MODE_PORTRAIT_WIDTH = 0.7f; - private static final float FILM_MODE_LANDSCAPE_HEIGHT = 0.7f; - private static final float FILM_MODE_LANDSCAPE_WIDTH = 0.7f; - - // In addition to the focused box (index == 0). We also keep information - // about this many boxes on each side. - private static final int BOX_MAX = PhotoView.SCREEN_NAIL_MAX; - private static final int[] CENTER_OUT_INDEX = new int[2 * BOX_MAX + 1]; - - private static final int IMAGE_GAP = GalleryUtils.dpToPixel(16); - private static final int HORIZONTAL_SLACK = GalleryUtils.dpToPixel(12); - - // These are constants for the delete gesture. - private static final int DEFAULT_DELETE_ANIMATION_DURATION = 200; // ms - private static final int MAX_DELETE_ANIMATION_DURATION = 400; // ms - - private Listener mListener; - private volatile Rect mOpenAnimationRect; - - // Use a large enough value, so we won't see the gray shadow in the beginning. - private int mViewW = 1200; - private int mViewH = 1200; - - // A scaling gesture is in progress. - private boolean mInScale; - // The focus point of the scaling gesture, relative to the center of the - // picture in bitmap pixels. - private float mFocusX, mFocusY; - - // whether there is a previous/next picture. - private boolean mHasPrev, mHasNext; - - // This is used by the fling animation (page mode). - private FlingScroller mPageScroller; - - // This is used by the fling animation (film mode). - private Scroller mFilmScroller; - - // The bound of the stable region that the focused box can stay, see the - // comments above calculateStableBound() for details. - private int mBoundLeft, mBoundRight, mBoundTop, mBoundBottom; - - // Constrained frame is a rectangle that the focused box should fit into if - // it is constrained. It has two effects: - // - // (1) In page mode, if the focused box is constrained, scaling for the - // focused box is adjusted to fit into the constrained frame, instead of the - // whole view. - // - // (2) In page mode, if the focused box is constrained, the mPlatform's - // default center (mDefaultX/Y) is moved to the center of the constrained - // frame, instead of the view center. - // - private Rect mConstrainedFrame = new Rect(); - - // Whether the focused box is constrained. - // - // Our current program's first call to moveBox() sets constrained = true, so - // we set the initial value of this variable to true, and we will not see - // see unwanted transition animation. - private boolean mConstrained = true; - - // - // ___________________________________________________________ - // | _____ _____ _____ _____ _____ | - // | | | | | | | | | | | | - // | | Box | | Box | | Box*| | Box | | Box | | - // | |_____|.....|_____|.....|_____|.....|_____|.....|_____| | - // | Gap Gap Gap Gap | - // |___________________________________________________________| - // - // <-- Platform --> - // - // The focused box (Box*) centers at mPlatform's (mCurrentX, mCurrentY) - - private Platform mPlatform = new Platform(); - private RangeArray<Box> mBoxes = new RangeArray<Box>(-BOX_MAX, BOX_MAX); - // The gap at the right of a Box i is at index i. The gap at the left of a - // Box i is at index i - 1. - private RangeArray<Gap> mGaps = new RangeArray<Gap>(-BOX_MAX, BOX_MAX - 1); - private FilmRatio mFilmRatio = new FilmRatio(); - - // These are only used during moveBox(). - private RangeArray<Box> mTempBoxes = new RangeArray<Box>(-BOX_MAX, BOX_MAX); - private RangeArray<Gap> mTempGaps = - new RangeArray<Gap>(-BOX_MAX, BOX_MAX - 1); - - // The output of the PositionController. Available through getPosition(). - private RangeArray<Rect> mRects = new RangeArray<Rect>(-BOX_MAX, BOX_MAX); - - // The direction of a new picture should appear. New pictures pop from top - // if this value is true, or from bottom if this value is false. - boolean mPopFromTop; - - public interface Listener { - void invalidate(); - boolean isHoldingDown(); - boolean isHoldingDelete(); - - // EdgeView - void onPull(int offset, int direction); - void onRelease(); - void onAbsorb(int velocity, int direction); - } - - static { - // Initialize the CENTER_OUT_INDEX array. - // The array maps 0, 1, 2, 3, 4, ..., 2 * BOX_MAX - // to 0, 1, -1, 2, -2, ..., BOX_MAX, -BOX_MAX - for (int i = 0; i < CENTER_OUT_INDEX.length; i++) { - int j = (i + 1) / 2; - if ((i & 1) == 0) j = -j; - CENTER_OUT_INDEX[i] = j; - } - } - - public PositionController(Context context, Listener listener) { - mListener = listener; - mPageScroller = new FlingScroller(); - mFilmScroller = new Scroller(context, null, false); - - // Initialize the areas. - initPlatform(); - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - mBoxes.put(i, new Box()); - initBox(i); - mRects.put(i, new Rect()); - } - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - mGaps.put(i, new Gap()); - initGap(i); - } - } - - public void setOpenAnimationRect(Rect r) { - mOpenAnimationRect = r; - } - - public void setViewSize(int viewW, int viewH) { - if (viewW == mViewW && viewH == mViewH) return; - - boolean wasMinimal = isAtMinimalScale(); - - mViewW = viewW; - mViewH = viewH; - initPlatform(); - - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - setBoxSize(i, viewW, viewH, true); - } - - updateScaleAndGapLimit(); - - // If the focused box was at minimal scale, we try to make it the - // minimal scale under the new view size. - if (wasMinimal) { - Box b = mBoxes.get(0); - b.mCurrentScale = b.mScaleMin; - } - - // If we have the opening animation, do it. Otherwise go directly to the - // right position. - if (!startOpeningAnimationIfNeeded()) { - skipToFinalPosition(); - } - } - - public void setConstrainedFrame(Rect cFrame) { - if (mConstrainedFrame.equals(cFrame)) return; - mConstrainedFrame.set(cFrame); - mPlatform.updateDefaultXY(); - updateScaleAndGapLimit(); - snapAndRedraw(); - } - - public void forceImageSize(int index, Size s) { - if (s.width == 0 || s.height == 0) return; - Box b = mBoxes.get(index); - b.mImageW = s.width; - b.mImageH = s.height; - return; - } - - public void setImageSize(int index, Size s, Rect cFrame) { - if (s.width == 0 || s.height == 0) return; - - boolean needUpdate = false; - if (cFrame != null && !mConstrainedFrame.equals(cFrame)) { - mConstrainedFrame.set(cFrame); - mPlatform.updateDefaultXY(); - needUpdate = true; - } - needUpdate |= setBoxSize(index, s.width, s.height, false); - - if (!needUpdate) return; - updateScaleAndGapLimit(); - snapAndRedraw(); - } - - // Returns false if the box size doesn't change. - private boolean setBoxSize(int i, int width, int height, boolean isViewSize) { - Box b = mBoxes.get(i); - boolean wasViewSize = b.mUseViewSize; - - // If we already have an image size, we don't want to use the view size. - if (!wasViewSize && isViewSize) return false; - - b.mUseViewSize = isViewSize; - - if (width == b.mImageW && height == b.mImageH) { - return false; - } - - // The ratio of the old size and the new size. - // - // If the aspect ratio changes, we don't know if it is because one side - // grows or the other side shrinks. Currently we just assume the view - // angle of the longer side doesn't change (so the aspect ratio change - // is because the view angle of the shorter side changes). This matches - // what camera preview does. - float ratio = (width > height) - ? (float) b.mImageW / width - : (float) b.mImageH / height; - - b.mImageW = width; - b.mImageH = height; - - // If this is the first time we receive an image size or we are in fullscreen, - // we change the scale directly. Otherwise adjust the scales by a ratio, - // and snapback will animate the scale into the min/max bounds if necessary. - if ((wasViewSize && !isViewSize) || !mFilmMode) { - b.mCurrentScale = getMinimalScale(b); - b.mAnimationStartTime = NO_ANIMATION; - } else { - b.mCurrentScale *= ratio; - b.mFromScale *= ratio; - b.mToScale *= ratio; - } - - if (i == 0) { - mFocusX /= ratio; - mFocusY /= ratio; - } - - return true; - } - - private boolean startOpeningAnimationIfNeeded() { - if (mOpenAnimationRect == null) return false; - Box b = mBoxes.get(0); - if (b.mUseViewSize) return false; - - // Start animation from the saved rectangle if we have one. - Rect r = mOpenAnimationRect; - mOpenAnimationRect = null; - - mPlatform.mCurrentX = r.centerX() - mViewW / 2; - b.mCurrentY = r.centerY() - mViewH / 2; - b.mCurrentScale = Math.max(r.width() / (float) b.mImageW, - r.height() / (float) b.mImageH); - startAnimation(mPlatform.mDefaultX, 0, b.mScaleMin, - ANIM_KIND_OPENING); - - // Animate from large gaps for neighbor boxes to avoid them - // shown on the screen during opening animation. - for (int i = -1; i < 1; i++) { - Gap g = mGaps.get(i); - g.mCurrentGap = mViewW; - g.doAnimation(g.mDefaultSize, ANIM_KIND_OPENING); - } - - return true; - } - - public void setFilmMode(boolean enabled) { - if (enabled == mFilmMode) return; - mFilmMode = enabled; - - mPlatform.updateDefaultXY(); - updateScaleAndGapLimit(); - stopAnimation(); - snapAndRedraw(); - } - - public void setExtraScalingRange(boolean enabled) { - if (mExtraScalingRange == enabled) return; - mExtraScalingRange = enabled; - if (!enabled) { - snapAndRedraw(); - } - } - - // This should be called whenever the scale range of boxes or the default - // gap size may change. Currently this can happen due to change of view - // size, image size, mFilmMode, mConstrained, and mConstrainedFrame. - private void updateScaleAndGapLimit() { - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - Box b = mBoxes.get(i); - b.mScaleMin = getMinimalScale(b); - b.mScaleMax = getMaximalScale(b); - } - - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - Gap g = mGaps.get(i); - g.mDefaultSize = getDefaultGapSize(i); - } - } - - // Returns the default gap size according the the size of the boxes around - // the gap and the current mode. - private int getDefaultGapSize(int i) { - if (mFilmMode) return IMAGE_GAP; - Box a = mBoxes.get(i); - Box b = mBoxes.get(i + 1); - return IMAGE_GAP + Math.max(gapToSide(a), gapToSide(b)); - } - - // Here is how we layout the boxes in the page mode. - // - // previous current next - // ___________ ________________ __________ - // | _______ | | __________ | | ______ | - // | | | | | | right->| | | | | | - // | | |<-------->|<--left | | | | | | - // | |_______| | | | |__________| | | |______| | - // |___________| | |________________| |__________| - // | <--> gapToSide() - // | - // IMAGE_GAP + MAX(gapToSide(previous), gapToSide(current)) - private int gapToSide(Box b) { - return (int) ((mViewW - getMinimalScale(b) * b.mImageW) / 2 + 0.5f); - } - - // Stop all animations at where they are now. - public void stopAnimation() { - mPlatform.mAnimationStartTime = NO_ANIMATION; - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - mBoxes.get(i).mAnimationStartTime = NO_ANIMATION; - } - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - mGaps.get(i).mAnimationStartTime = NO_ANIMATION; - } - } - - public void skipAnimation() { - if (mPlatform.mAnimationStartTime != NO_ANIMATION) { - mPlatform.mCurrentX = mPlatform.mToX; - mPlatform.mCurrentY = mPlatform.mToY; - mPlatform.mAnimationStartTime = NO_ANIMATION; - } - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - Box b = mBoxes.get(i); - if (b.mAnimationStartTime == NO_ANIMATION) continue; - b.mCurrentY = b.mToY; - b.mCurrentScale = b.mToScale; - b.mAnimationStartTime = NO_ANIMATION; - } - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - Gap g = mGaps.get(i); - if (g.mAnimationStartTime == NO_ANIMATION) continue; - g.mCurrentGap = g.mToGap; - g.mAnimationStartTime = NO_ANIMATION; - } - redraw(); - } - - public void snapback() { - snapAndRedraw(); - } - - public void skipToFinalPosition() { - stopAnimation(); - snapAndRedraw(); - skipAnimation(); - } - - //////////////////////////////////////////////////////////////////////////// - // Start an animations for the focused box - //////////////////////////////////////////////////////////////////////////// - - public void zoomIn(float tapX, float tapY, float targetScale) { - tapX -= mViewW / 2; - tapY -= mViewH / 2; - Box b = mBoxes.get(0); - - // Convert the tap position to distance to center in bitmap coordinates - float tempX = (tapX - mPlatform.mCurrentX) / b.mCurrentScale; - float tempY = (tapY - b.mCurrentY) / b.mCurrentScale; - - int x = (int) (-tempX * targetScale + 0.5f); - int y = (int) (-tempY * targetScale + 0.5f); - - calculateStableBound(targetScale); - int targetX = Utils.clamp(x, mBoundLeft, mBoundRight); - int targetY = Utils.clamp(y, mBoundTop, mBoundBottom); - targetScale = Utils.clamp(targetScale, b.mScaleMin, b.mScaleMax); - - startAnimation(targetX, targetY, targetScale, ANIM_KIND_ZOOM); - } - - public void resetToFullView() { - Box b = mBoxes.get(0); - startAnimation(mPlatform.mDefaultX, 0, b.mScaleMin, ANIM_KIND_ZOOM); - } - - public void beginScale(float focusX, float focusY) { - focusX -= mViewW / 2; - focusY -= mViewH / 2; - Box b = mBoxes.get(0); - Platform p = mPlatform; - mInScale = true; - mFocusX = (int) ((focusX - p.mCurrentX) / b.mCurrentScale + 0.5f); - mFocusY = (int) ((focusY - b.mCurrentY) / b.mCurrentScale + 0.5f); - } - - // Scales the image by the given factor. - // Returns an out-of-range indicator: - // 1 if the intended scale is too large for the stable range. - // 0 if the intended scale is in the stable range. - // -1 if the intended scale is too small for the stable range. - public int scaleBy(float s, float focusX, float focusY) { - focusX -= mViewW / 2; - focusY -= mViewH / 2; - Box b = mBoxes.get(0); - Platform p = mPlatform; - - // We want to keep the focus point (on the bitmap) the same as when we - // begin the scale gesture, that is, - // - // (focusX' - currentX') / scale' = (focusX - currentX) / scale - // - s = b.clampScale(s * getTargetScale(b)); - int x = mFilmMode ? p.mCurrentX : (int) (focusX - s * mFocusX + 0.5f); - int y = mFilmMode ? b.mCurrentY : (int) (focusY - s * mFocusY + 0.5f); - startAnimation(x, y, s, ANIM_KIND_SCALE); - if (s < b.mScaleMin) return -1; - if (s > b.mScaleMax) return 1; - return 0; - } - - public void endScale() { - mInScale = false; - snapAndRedraw(); - } - - // Slide the focused box to the center of the view. - public void startHorizontalSlide() { - Box b = mBoxes.get(0); - startAnimation(mPlatform.mDefaultX, 0, b.mScaleMin, ANIM_KIND_SLIDE); - } - - // Slide the focused box to the center of the view with the capture - // animation. In addition to the sliding, the animation will also scale the - // the focused box, the specified neighbor box, and the gap between the - // two. The specified offset should be 1 or -1. - public void startCaptureAnimationSlide(int offset) { - Box b = mBoxes.get(0); - Box n = mBoxes.get(offset); // the neighbor box - Gap g = mGaps.get(offset); // the gap between the two boxes - - mPlatform.doAnimation(mPlatform.mDefaultX, mPlatform.mDefaultY, - ANIM_KIND_CAPTURE); - b.doAnimation(0, b.mScaleMin, ANIM_KIND_CAPTURE); - n.doAnimation(0, n.mScaleMin, ANIM_KIND_CAPTURE); - g.doAnimation(g.mDefaultSize, ANIM_KIND_CAPTURE); - redraw(); - } - - // Only allow scrolling when we are not currently in an animation or we - // are in some animation with can be interrupted. - private boolean canScroll() { - Box b = mBoxes.get(0); - if (b.mAnimationStartTime == NO_ANIMATION) return true; - switch (b.mAnimationKind) { - case ANIM_KIND_SCROLL: - case ANIM_KIND_FLING: - case ANIM_KIND_FLING_X: - return true; - } - return false; - } - - public void scrollPage(int dx, int dy) { - if (!canScroll()) return; - - Box b = mBoxes.get(0); - Platform p = mPlatform; - - calculateStableBound(b.mCurrentScale); - - int x = p.mCurrentX + dx; - int y = b.mCurrentY + dy; - - // Vertical direction: If we have space to move in the vertical - // direction, we show the edge effect when scrolling reaches the edge. - if (mBoundTop != mBoundBottom) { - if (y < mBoundTop) { - mListener.onPull(mBoundTop - y, EdgeView.BOTTOM); - } else if (y > mBoundBottom) { - mListener.onPull(y - mBoundBottom, EdgeView.TOP); - } - } - - y = Utils.clamp(y, mBoundTop, mBoundBottom); - - // Horizontal direction: we show the edge effect when the scrolling - // tries to go left of the first image or go right of the last image. - if (!mHasPrev && x > mBoundRight) { - int pixels = x - mBoundRight; - mListener.onPull(pixels, EdgeView.LEFT); - x = mBoundRight; - } else if (!mHasNext && x < mBoundLeft) { - int pixels = mBoundLeft - x; - mListener.onPull(pixels, EdgeView.RIGHT); - x = mBoundLeft; - } - - startAnimation(x, y, b.mCurrentScale, ANIM_KIND_SCROLL); - } - - public void scrollFilmX(int dx) { - if (!canScroll()) return; - - Box b = mBoxes.get(0); - Platform p = mPlatform; - - // Only allow scrolling when we are not currently in an animation or we - // are in some animation with can be interrupted. - if (b.mAnimationStartTime != NO_ANIMATION) { - switch (b.mAnimationKind) { - case ANIM_KIND_SCROLL: - case ANIM_KIND_FLING: - case ANIM_KIND_FLING_X: - break; - default: - return; - } - } - - int x = p.mCurrentX + dx; - - // Horizontal direction: we show the edge effect when the scrolling - // tries to go left of the first image or go right of the last image. - x -= mPlatform.mDefaultX; - if (!mHasPrev && x > 0) { - mListener.onPull(x, EdgeView.LEFT); - x = 0; - } else if (!mHasNext && x < 0) { - mListener.onPull(-x, EdgeView.RIGHT); - x = 0; - } - x += mPlatform.mDefaultX; - startAnimation(x, b.mCurrentY, b.mCurrentScale, ANIM_KIND_SCROLL); - } - - public void scrollFilmY(int boxIndex, int dy) { - if (!canScroll()) return; - - Box b = mBoxes.get(boxIndex); - int y = b.mCurrentY + dy; - b.doAnimation(y, b.mCurrentScale, ANIM_KIND_SCROLL); - redraw(); - } - - public boolean flingPage(int velocityX, int velocityY) { - Box b = mBoxes.get(0); - Platform p = mPlatform; - - // We only want to do fling when the picture is zoomed-in. - if (viewWiderThanScaledImage(b.mCurrentScale) && - viewTallerThanScaledImage(b.mCurrentScale)) { - return false; - } - - // We only allow flinging in the directions where it won't go over the - // picture. - int edges = getImageAtEdges(); - if ((velocityX > 0 && (edges & IMAGE_AT_LEFT_EDGE) != 0) || - (velocityX < 0 && (edges & IMAGE_AT_RIGHT_EDGE) != 0)) { - velocityX = 0; - } - if ((velocityY > 0 && (edges & IMAGE_AT_TOP_EDGE) != 0) || - (velocityY < 0 && (edges & IMAGE_AT_BOTTOM_EDGE) != 0)) { - velocityY = 0; - } - - if (velocityX == 0 && velocityY == 0) return false; - - mPageScroller.fling(p.mCurrentX, b.mCurrentY, velocityX, velocityY, - mBoundLeft, mBoundRight, mBoundTop, mBoundBottom); - int targetX = mPageScroller.getFinalX(); - int targetY = mPageScroller.getFinalY(); - ANIM_TIME[ANIM_KIND_FLING] = mPageScroller.getDuration(); - return startAnimation(targetX, targetY, b.mCurrentScale, ANIM_KIND_FLING); - } - - public boolean flingFilmX(int velocityX) { - if (velocityX == 0) return false; - - Box b = mBoxes.get(0); - Platform p = mPlatform; - - // If we are already at the edge, don't start the fling. - int defaultX = p.mDefaultX; - if ((!mHasPrev && p.mCurrentX >= defaultX) - || (!mHasNext && p.mCurrentX <= defaultX)) { - return false; - } - - mFilmScroller.fling(p.mCurrentX, 0, velocityX, 0, - Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); - int targetX = mFilmScroller.getFinalX(); - return startAnimation( - targetX, b.mCurrentY, b.mCurrentScale, ANIM_KIND_FLING_X); - } - - // Moves the specified box out of screen. If velocityY is 0, a default - // velocity is used. Returns the time for the duration, or -1 if we cannot - // not do the animation. - public int flingFilmY(int boxIndex, int velocityY) { - Box b = mBoxes.get(boxIndex); - - // Calculate targetY - int h = heightOf(b); - int targetY; - int FUZZY = 3; // TODO: figure out why this is needed. - if (velocityY < 0 || (velocityY == 0 && b.mCurrentY <= 0)) { - targetY = -mViewH / 2 - (h + 1) / 2 - FUZZY; - } else { - targetY = (mViewH + 1) / 2 + h / 2 + FUZZY; - } - - // Calculate duration - int duration; - if (velocityY != 0) { - duration = (int) (Math.abs(targetY - b.mCurrentY) * 1000f - / Math.abs(velocityY)); - duration = Math.min(MAX_DELETE_ANIMATION_DURATION, duration); - } else { - duration = DEFAULT_DELETE_ANIMATION_DURATION; - } - - // Start animation - ANIM_TIME[ANIM_KIND_DELETE] = duration; - if (b.doAnimation(targetY, b.mCurrentScale, ANIM_KIND_DELETE)) { - redraw(); - return duration; - } - return -1; - } - - // Returns the index of the box which contains the given point (x, y) - // Returns Integer.MAX_VALUE if there is no hit. There may be more than - // one box contains the given point, and we want to give priority to the - // one closer to the focused index (0). - public int hitTest(int x, int y) { - for (int i = 0; i < 2 * BOX_MAX + 1; i++) { - int j = CENTER_OUT_INDEX[i]; - Rect r = mRects.get(j); - if (r.contains(x, y)) { - return j; - } - } - - return Integer.MAX_VALUE; - } - - //////////////////////////////////////////////////////////////////////////// - // Redraw - // - // If a method changes box positions directly, redraw() - // should be called. - // - // If a method may also cause a snapback to happen, snapAndRedraw() should - // be called. - // - // If a method starts an animation to change the position of focused box, - // startAnimation() should be called. - // - // If time advances to change the box position, advanceAnimation() should - // be called. - //////////////////////////////////////////////////////////////////////////// - private void redraw() { - layoutAndSetPosition(); - mListener.invalidate(); - } - - private void snapAndRedraw() { - mPlatform.startSnapback(); - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - mBoxes.get(i).startSnapback(); - } - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - mGaps.get(i).startSnapback(); - } - mFilmRatio.startSnapback(); - redraw(); - } - - private boolean startAnimation(int targetX, int targetY, float targetScale, - int kind) { - boolean changed = false; - changed |= mPlatform.doAnimation(targetX, mPlatform.mDefaultY, kind); - changed |= mBoxes.get(0).doAnimation(targetY, targetScale, kind); - if (changed) redraw(); - return changed; - } - - public void advanceAnimation() { - boolean changed = false; - changed |= mPlatform.advanceAnimation(); - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - changed |= mBoxes.get(i).advanceAnimation(); - } - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - changed |= mGaps.get(i).advanceAnimation(); - } - changed |= mFilmRatio.advanceAnimation(); - if (changed) redraw(); - } - - public boolean inOpeningAnimation() { - return (mPlatform.mAnimationKind == ANIM_KIND_OPENING && - mPlatform.mAnimationStartTime != NO_ANIMATION) || - (mBoxes.get(0).mAnimationKind == ANIM_KIND_OPENING && - mBoxes.get(0).mAnimationStartTime != NO_ANIMATION); - } - - //////////////////////////////////////////////////////////////////////////// - // Layout - //////////////////////////////////////////////////////////////////////////// - - // Returns the display width of this box. - private int widthOf(Box b) { - return (int) (b.mImageW * b.mCurrentScale + 0.5f); - } - - // Returns the display height of this box. - private int heightOf(Box b) { - return (int) (b.mImageH * b.mCurrentScale + 0.5f); - } - - // Returns the display width of this box, using the given scale. - private int widthOf(Box b, float scale) { - return (int) (b.mImageW * scale + 0.5f); - } - - // Returns the display height of this box, using the given scale. - private int heightOf(Box b, float scale) { - return (int) (b.mImageH * scale + 0.5f); - } - - // Convert the information in mPlatform and mBoxes to mRects, so the user - // can get the position of each box by getPosition(). - // - // Note we go from center-out because each box's X coordinate - // is relative to its anchor box (except the focused box). - private void layoutAndSetPosition() { - for (int i = 0; i < 2 * BOX_MAX + 1; i++) { - convertBoxToRect(CENTER_OUT_INDEX[i]); - } - //dumpState(); - } - - @SuppressWarnings("unused") - private void dumpState() { - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - Log.d(TAG, "Gap " + i + ": " + mGaps.get(i).mCurrentGap); - } - - for (int i = 0; i < 2 * BOX_MAX + 1; i++) { - dumpRect(CENTER_OUT_INDEX[i]); - } - - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - for (int j = i + 1; j <= BOX_MAX; j++) { - if (Rect.intersects(mRects.get(i), mRects.get(j))) { - Log.d(TAG, "rect " + i + " and rect " + j + "intersects!"); - } - } - } - } - - private void dumpRect(int i) { - StringBuilder sb = new StringBuilder(); - Rect r = mRects.get(i); - sb.append("Rect " + i + ":"); - sb.append("("); - sb.append(r.centerX()); - sb.append(","); - sb.append(r.centerY()); - sb.append(") ["); - sb.append(r.width()); - sb.append("x"); - sb.append(r.height()); - sb.append("]"); - Log.d(TAG, sb.toString()); - } - - private void convertBoxToRect(int i) { - Box b = mBoxes.get(i); - Rect r = mRects.get(i); - int y = b.mCurrentY + mPlatform.mCurrentY + mViewH / 2; - int w = widthOf(b); - int h = heightOf(b); - if (i == 0) { - int x = mPlatform.mCurrentX + mViewW / 2; - r.left = x - w / 2; - r.right = r.left + w; - } else if (i > 0) { - Rect a = mRects.get(i - 1); - Gap g = mGaps.get(i - 1); - r.left = a.right + g.mCurrentGap; - r.right = r.left + w; - } else { // i < 0 - Rect a = mRects.get(i + 1); - Gap g = mGaps.get(i); - r.right = a.left - g.mCurrentGap; - r.left = r.right - w; - } - r.top = y - h / 2; - r.bottom = r.top + h; - } - - // Returns the position of a box. - public Rect getPosition(int index) { - return mRects.get(index); - } - - //////////////////////////////////////////////////////////////////////////// - // Box management - //////////////////////////////////////////////////////////////////////////// - - // Initialize the platform to be at the view center. - private void initPlatform() { - mPlatform.updateDefaultXY(); - mPlatform.mCurrentX = mPlatform.mDefaultX; - mPlatform.mCurrentY = mPlatform.mDefaultY; - mPlatform.mAnimationStartTime = NO_ANIMATION; - } - - // Initialize a box to have the size of the view. - private void initBox(int index) { - Box b = mBoxes.get(index); - b.mImageW = mViewW; - b.mImageH = mViewH; - b.mUseViewSize = true; - b.mScaleMin = getMinimalScale(b); - b.mScaleMax = getMaximalScale(b); - b.mCurrentY = 0; - b.mCurrentScale = b.mScaleMin; - b.mAnimationStartTime = NO_ANIMATION; - b.mAnimationKind = ANIM_KIND_NONE; - } - - // Initialize a box to a given size. - private void initBox(int index, Size size) { - if (size.width == 0 || size.height == 0) { - initBox(index); - return; - } - Box b = mBoxes.get(index); - b.mImageW = size.width; - b.mImageH = size.height; - b.mUseViewSize = false; - b.mScaleMin = getMinimalScale(b); - b.mScaleMax = getMaximalScale(b); - b.mCurrentY = 0; - b.mCurrentScale = b.mScaleMin; - b.mAnimationStartTime = NO_ANIMATION; - b.mAnimationKind = ANIM_KIND_NONE; - } - - // Initialize a gap. This can only be called after the boxes around the gap - // has been initialized. - private void initGap(int index) { - Gap g = mGaps.get(index); - g.mDefaultSize = getDefaultGapSize(index); - g.mCurrentGap = g.mDefaultSize; - g.mAnimationStartTime = NO_ANIMATION; - } - - private void initGap(int index, int size) { - Gap g = mGaps.get(index); - g.mDefaultSize = getDefaultGapSize(index); - g.mCurrentGap = size; - g.mAnimationStartTime = NO_ANIMATION; - } - - @SuppressWarnings("unused") - private void debugMoveBox(int fromIndex[]) { - StringBuilder s = new StringBuilder("moveBox:"); - for (int i = 0; i < fromIndex.length; i++) { - int j = fromIndex[i]; - if (j == Integer.MAX_VALUE) { - s.append(" N"); - } else { - s.append(" "); - s.append(fromIndex[i]); - } - } - Log.d(TAG, s.toString()); - } - - // Move the boxes: it may indicate focus change, box deleted, box appearing, - // box reordered, etc. - // - // Each element in the fromIndex array indicates where each box was in the - // old array. If the value is Integer.MAX_VALUE (pictured as N below), it - // means the box is new. - // - // For example: - // N N N N N N N -- all new boxes - // -3 -2 -1 0 1 2 3 -- nothing changed - // -2 -1 0 1 2 3 N -- focus goes to the next box - // N -3 -2 -1 0 1 2 -- focus goes to the previous box - // -3 -2 -1 1 2 3 N -- the focused box was deleted. - // - // hasPrev/hasNext indicates if there are previous/next boxes for the - // focused box. constrained indicates whether the focused box should be put - // into the constrained frame. - public void moveBox(int fromIndex[], boolean hasPrev, boolean hasNext, - boolean constrained, Size[] sizes) { - //debugMoveBox(fromIndex); - mHasPrev = hasPrev; - mHasNext = hasNext; - - RangeIntArray from = new RangeIntArray(fromIndex, -BOX_MAX, BOX_MAX); - - // 1. Get the absolute X coordinates for the boxes. - layoutAndSetPosition(); - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - Box b = mBoxes.get(i); - Rect r = mRects.get(i); - b.mAbsoluteX = r.centerX() - mViewW / 2; - } - - // 2. copy boxes and gaps to temporary storage. - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - mTempBoxes.put(i, mBoxes.get(i)); - mBoxes.put(i, null); - } - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - mTempGaps.put(i, mGaps.get(i)); - mGaps.put(i, null); - } - - // 3. move back boxes that are used in the new array. - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - int j = from.get(i); - if (j == Integer.MAX_VALUE) continue; - mBoxes.put(i, mTempBoxes.get(j)); - mTempBoxes.put(j, null); - } - - // 4. move back gaps if both boxes around it are kept together. - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - int j = from.get(i); - if (j == Integer.MAX_VALUE) continue; - int k = from.get(i + 1); - if (k == Integer.MAX_VALUE) continue; - if (j + 1 == k) { - mGaps.put(i, mTempGaps.get(j)); - mTempGaps.put(j, null); - } - } - - // 5. recycle the boxes that are not used in the new array. - int k = -BOX_MAX; - for (int i = -BOX_MAX; i <= BOX_MAX; i++) { - if (mBoxes.get(i) != null) continue; - while (mTempBoxes.get(k) == null) { - k++; - } - mBoxes.put(i, mTempBoxes.get(k++)); - initBox(i, sizes[i + BOX_MAX]); - } - - // 6. Now give the recycled box a reasonable absolute X position. - // - // First try to find the first and the last box which the absolute X - // position is known. - int first, last; - for (first = -BOX_MAX; first <= BOX_MAX; first++) { - if (from.get(first) != Integer.MAX_VALUE) break; - } - for (last = BOX_MAX; last >= -BOX_MAX; last--) { - if (from.get(last) != Integer.MAX_VALUE) break; - } - // If there is no box has known X position at all, make the focused one - // as known. - if (first > BOX_MAX) { - mBoxes.get(0).mAbsoluteX = mPlatform.mCurrentX; - first = last = 0; - } - // Now for those boxes between first and last, assign their position to - // align to the previous box or the next box with known position. For - // the boxes before first or after last, we will use a new default gap - // size below. - - // Align to the previous box - for (int i = Math.max(0, first + 1); i < last; i++) { - if (from.get(i) != Integer.MAX_VALUE) continue; - Box a = mBoxes.get(i - 1); - Box b = mBoxes.get(i); - int wa = widthOf(a); - int wb = widthOf(b); - b.mAbsoluteX = a.mAbsoluteX + (wa - wa / 2) + wb / 2 - + getDefaultGapSize(i); - if (mPopFromTop) { - b.mCurrentY = -(mViewH / 2 + heightOf(b) / 2); - } else { - b.mCurrentY = (mViewH / 2 + heightOf(b) / 2); - } - } - - // Align to the next box - for (int i = Math.min(-1, last - 1); i > first; i--) { - if (from.get(i) != Integer.MAX_VALUE) continue; - Box a = mBoxes.get(i + 1); - Box b = mBoxes.get(i); - int wa = widthOf(a); - int wb = widthOf(b); - b.mAbsoluteX = a.mAbsoluteX - wa / 2 - (wb - wb / 2) - - getDefaultGapSize(i); - if (mPopFromTop) { - b.mCurrentY = -(mViewH / 2 + heightOf(b) / 2); - } else { - b.mCurrentY = (mViewH / 2 + heightOf(b) / 2); - } - } - - // 7. recycle the gaps that are not used in the new array. - k = -BOX_MAX; - for (int i = -BOX_MAX; i < BOX_MAX; i++) { - if (mGaps.get(i) != null) continue; - while (mTempGaps.get(k) == null) { - k++; - } - mGaps.put(i, mTempGaps.get(k++)); - Box a = mBoxes.get(i); - Box b = mBoxes.get(i + 1); - int wa = widthOf(a); - int wb = widthOf(b); - if (i >= first && i < last) { - int g = b.mAbsoluteX - a.mAbsoluteX - wb / 2 - (wa - wa / 2); - initGap(i, g); - } else { - initGap(i); - } - } - - // 8. calculate the new absolute X coordinates for those box before - // first or after last. - for (int i = first - 1; i >= -BOX_MAX; i--) { - Box a = mBoxes.get(i + 1); - Box b = mBoxes.get(i); - int wa = widthOf(a); - int wb = widthOf(b); - Gap g = mGaps.get(i); - b.mAbsoluteX = a.mAbsoluteX - wa / 2 - (wb - wb / 2) - g.mCurrentGap; - } - - for (int i = last + 1; i <= BOX_MAX; i++) { - Box a = mBoxes.get(i - 1); - Box b = mBoxes.get(i); - int wa = widthOf(a); - int wb = widthOf(b); - Gap g = mGaps.get(i - 1); - b.mAbsoluteX = a.mAbsoluteX + (wa - wa / 2) + wb / 2 + g.mCurrentGap; - } - - // 9. offset the Platform position - int dx = mBoxes.get(0).mAbsoluteX - mPlatform.mCurrentX; - mPlatform.mCurrentX += dx; - mPlatform.mFromX += dx; - mPlatform.mToX += dx; - mPlatform.mFlingOffset += dx; - - if (mConstrained != constrained) { - mConstrained = constrained; - mPlatform.updateDefaultXY(); - updateScaleAndGapLimit(); - } - - snapAndRedraw(); - } - - //////////////////////////////////////////////////////////////////////////// - // Public utilities - //////////////////////////////////////////////////////////////////////////// - - public boolean isAtMinimalScale() { - Box b = mBoxes.get(0); - return isAlmostEqual(b.mCurrentScale, b.mScaleMin); - } - - public boolean isCenter() { - Box b = mBoxes.get(0); - return mPlatform.mCurrentX == mPlatform.mDefaultX - && b.mCurrentY == 0; - } - - public int getImageWidth() { - Box b = mBoxes.get(0); - return b.mImageW; - } - - public int getImageHeight() { - Box b = mBoxes.get(0); - return b.mImageH; - } - - public float getImageScale() { - Box b = mBoxes.get(0); - return b.mCurrentScale; - } - - public int getImageAtEdges() { - Box b = mBoxes.get(0); - Platform p = mPlatform; - calculateStableBound(b.mCurrentScale); - int edges = 0; - if (p.mCurrentX <= mBoundLeft) { - edges |= IMAGE_AT_RIGHT_EDGE; - } - if (p.mCurrentX >= mBoundRight) { - edges |= IMAGE_AT_LEFT_EDGE; - } - if (b.mCurrentY <= mBoundTop) { - edges |= IMAGE_AT_BOTTOM_EDGE; - } - if (b.mCurrentY >= mBoundBottom) { - edges |= IMAGE_AT_TOP_EDGE; - } - return edges; - } - - public boolean isScrolling() { - return mPlatform.mAnimationStartTime != NO_ANIMATION - && mPlatform.mCurrentX != mPlatform.mToX; - } - - public void stopScrolling() { - if (mPlatform.mAnimationStartTime == NO_ANIMATION) return; - if (mFilmMode) mFilmScroller.forceFinished(true); - mPlatform.mFromX = mPlatform.mToX = mPlatform.mCurrentX; - } - - public float getFilmRatio() { - return mFilmRatio.mCurrentRatio; - } - - public void setPopFromTop(boolean top) { - mPopFromTop = top; - } - - public boolean hasDeletingBox() { - for(int i = -BOX_MAX; i <= BOX_MAX; i++) { - if (mBoxes.get(i).mAnimationKind == ANIM_KIND_DELETE) { - return true; - } - } - return false; - } - - //////////////////////////////////////////////////////////////////////////// - // Private utilities - //////////////////////////////////////////////////////////////////////////// - - private float getMinimalScale(Box b) { - float wFactor = 1.0f; - float hFactor = 1.0f; - int viewW, viewH; - - if (!mFilmMode && mConstrained && !mConstrainedFrame.isEmpty() - && b == mBoxes.get(0)) { - viewW = mConstrainedFrame.width(); - viewH = mConstrainedFrame.height(); - } else { - viewW = mViewW; - viewH = mViewH; - } - - if (mFilmMode) { - if (mViewH > mViewW) { // portrait - wFactor = FILM_MODE_PORTRAIT_WIDTH; - hFactor = FILM_MODE_PORTRAIT_HEIGHT; - } else { // landscape - wFactor = FILM_MODE_LANDSCAPE_WIDTH; - hFactor = FILM_MODE_LANDSCAPE_HEIGHT; - } - } - - float s = Math.min(wFactor * viewW / b.mImageW, - hFactor * viewH / b.mImageH); - return Math.min(SCALE_LIMIT, s); - } - - private float getMaximalScale(Box b) { - if (mFilmMode) return getMinimalScale(b); - if (mConstrained && !mConstrainedFrame.isEmpty()) return getMinimalScale(b); - return SCALE_LIMIT; - } - - private static boolean isAlmostEqual(float a, float b) { - float diff = a - b; - return (diff < 0 ? -diff : diff) < 0.02f; - } - - // Calculates the stable region of mPlatform.mCurrentX and - // mBoxes.get(0).mCurrentY, where "stable" means - // - // (1) If the dimension of scaled image >= view dimension, we will not - // see black region outside the image (at that dimension). - // (2) If the dimension of scaled image < view dimension, we will center - // the scaled image. - // - // We might temporarily go out of this stable during user interaction, - // but will "snap back" after user stops interaction. - // - // The results are stored in mBound{Left/Right/Top/Bottom}. - // - // An extra parameter "horizontalSlack" (which has the value of 0 usually) - // is used to extend the stable region by some pixels on each side - // horizontally. - private void calculateStableBound(float scale, int horizontalSlack) { - Box b = mBoxes.get(0); - - // The width and height of the box in number of view pixels - int w = widthOf(b, scale); - int h = heightOf(b, scale); - - // When the edge of the view is aligned with the edge of the box - mBoundLeft = (mViewW + 1) / 2 - (w + 1) / 2 - horizontalSlack; - mBoundRight = w / 2 - mViewW / 2 + horizontalSlack; - mBoundTop = (mViewH + 1) / 2 - (h + 1) / 2; - mBoundBottom = h / 2 - mViewH / 2; - - // If the scaled height is smaller than the view height, - // force it to be in the center. - if (viewTallerThanScaledImage(scale)) { - mBoundTop = mBoundBottom = 0; - } - - // Same for width - if (viewWiderThanScaledImage(scale)) { - mBoundLeft = mBoundRight = mPlatform.mDefaultX; - } - } - - private void calculateStableBound(float scale) { - calculateStableBound(scale, 0); - } - - private boolean viewTallerThanScaledImage(float scale) { - return mViewH >= heightOf(mBoxes.get(0), scale); - } - - private boolean viewWiderThanScaledImage(float scale) { - return mViewW >= widthOf(mBoxes.get(0), scale); - } - - private float getTargetScale(Box b) { - return b.mAnimationStartTime == NO_ANIMATION - ? b.mCurrentScale : b.mToScale; - } - - //////////////////////////////////////////////////////////////////////////// - // Animatable: an thing which can do animation. - //////////////////////////////////////////////////////////////////////////// - private abstract static class Animatable { - public long mAnimationStartTime; - public int mAnimationKind; - public int mAnimationDuration; - - // This should be overridden in subclass to change the animation values - // give the progress value in [0, 1]. - protected abstract boolean interpolate(float progress); - public abstract boolean startSnapback(); - - // Returns true if the animation values changes, so things need to be - // redrawn. - public boolean advanceAnimation() { - if (mAnimationStartTime == NO_ANIMATION) { - return false; - } - if (mAnimationStartTime == LAST_ANIMATION) { - mAnimationStartTime = NO_ANIMATION; - return startSnapback(); - } - - float progress; - if (mAnimationDuration == 0) { - progress = 1; - } else { - long now = AnimationTime.get(); - progress = - (float) (now - mAnimationStartTime) / mAnimationDuration; - } - - if (progress >= 1) { - progress = 1; - } else { - progress = applyInterpolationCurve(mAnimationKind, progress); - } - - boolean done = interpolate(progress); - - if (done) { - mAnimationStartTime = LAST_ANIMATION; - } - - return true; - } - - private static float applyInterpolationCurve(int kind, float progress) { - float f = 1 - progress; - switch (kind) { - case ANIM_KIND_SCROLL: - case ANIM_KIND_FLING: - case ANIM_KIND_FLING_X: - case ANIM_KIND_DELETE: - case ANIM_KIND_CAPTURE: - progress = 1 - f; // linear - break; - case ANIM_KIND_OPENING: - case ANIM_KIND_SCALE: - progress = 1 - f * f; // quadratic - break; - case ANIM_KIND_SNAPBACK: - case ANIM_KIND_ZOOM: - case ANIM_KIND_SLIDE: - progress = 1 - f * f * f * f * f; // x^5 - break; - } - return progress; - } - } - - //////////////////////////////////////////////////////////////////////////// - // Platform: captures the global X/Y movement. - //////////////////////////////////////////////////////////////////////////// - private class Platform extends Animatable { - public int mCurrentX, mFromX, mToX, mDefaultX; - public int mCurrentY, mFromY, mToY, mDefaultY; - public int mFlingOffset; - - @Override - public boolean startSnapback() { - if (mAnimationStartTime != NO_ANIMATION) return false; - if (mAnimationKind == ANIM_KIND_SCROLL - && mListener.isHoldingDown()) return false; - if (mInScale) return false; - - Box b = mBoxes.get(0); - float scaleMin = mExtraScalingRange ? - b.mScaleMin * SCALE_MIN_EXTRA : b.mScaleMin; - float scaleMax = mExtraScalingRange ? - b.mScaleMax * SCALE_MAX_EXTRA : b.mScaleMax; - float scale = Utils.clamp(b.mCurrentScale, scaleMin, scaleMax); - int x = mCurrentX; - int y = mDefaultY; - if (mFilmMode) { - x = mDefaultX; - } else { - calculateStableBound(scale, HORIZONTAL_SLACK); - // If the picture is zoomed-in, we want to keep the focus point - // stay in the same position on screen, so we need to adjust - // target mCurrentX (which is the center of the focused - // box). The position of the focus point on screen (relative the - // the center of the view) is: - // - // mCurrentX + scale * mFocusX = mCurrentX' + scale' * mFocusX - // => mCurrentX' = mCurrentX + (scale - scale') * mFocusX - // - if (!viewWiderThanScaledImage(scale)) { - float scaleDiff = b.mCurrentScale - scale; - x += (int) (mFocusX * scaleDiff + 0.5f); - } - x = Utils.clamp(x, mBoundLeft, mBoundRight); - } - if (mCurrentX != x || mCurrentY != y) { - return doAnimation(x, y, ANIM_KIND_SNAPBACK); - } - return false; - } - - // The updateDefaultXY() should be called whenever these variables - // changes: (1) mConstrained (2) mConstrainedFrame (3) mViewW/H (4) - // mFilmMode - public void updateDefaultXY() { - // We don't check mFilmMode and return 0 for mDefaultX. Because - // otherwise if we decide to leave film mode because we are - // centered, we will immediately back into film mode because we find - // we are not centered. - if (mConstrained && !mConstrainedFrame.isEmpty()) { - mDefaultX = mConstrainedFrame.centerX() - mViewW / 2; - mDefaultY = mFilmMode ? 0 : - mConstrainedFrame.centerY() - mViewH / 2; - } else { - mDefaultX = 0; - mDefaultY = 0; - } - } - - // Starts an animation for the platform. - private boolean doAnimation(int targetX, int targetY, int kind) { - if (mCurrentX == targetX && mCurrentY == targetY) return false; - mAnimationKind = kind; - mFromX = mCurrentX; - mFromY = mCurrentY; - mToX = targetX; - mToY = targetY; - mAnimationStartTime = AnimationTime.startTime(); - mAnimationDuration = ANIM_TIME[kind]; - mFlingOffset = 0; - advanceAnimation(); - return true; - } - - @Override - protected boolean interpolate(float progress) { - if (mAnimationKind == ANIM_KIND_FLING) { - return interpolateFlingPage(progress); - } else if (mAnimationKind == ANIM_KIND_FLING_X) { - return interpolateFlingFilm(progress); - } else { - return interpolateLinear(progress); - } - } - - private boolean interpolateFlingFilm(float progress) { - mFilmScroller.computeScrollOffset(); - mCurrentX = mFilmScroller.getCurrX() + mFlingOffset; - - int dir = EdgeView.INVALID_DIRECTION; - if (mCurrentX < mDefaultX) { - if (!mHasNext) { - dir = EdgeView.RIGHT; - } - } else if (mCurrentX > mDefaultX) { - if (!mHasPrev) { - dir = EdgeView.LEFT; - } - } - if (dir != EdgeView.INVALID_DIRECTION) { - // TODO: restore this onAbsorb call - //int v = (int) (mFilmScroller.getCurrVelocity() + 0.5f); - //mListener.onAbsorb(v, dir); - mFilmScroller.forceFinished(true); - mCurrentX = mDefaultX; - } - return mFilmScroller.isFinished(); - } - - private boolean interpolateFlingPage(float progress) { - mPageScroller.computeScrollOffset(progress); - Box b = mBoxes.get(0); - calculateStableBound(b.mCurrentScale); - - int oldX = mCurrentX; - mCurrentX = mPageScroller.getCurrX(); - - // Check if we hit the edges; show edge effects if we do. - if (oldX > mBoundLeft && mCurrentX == mBoundLeft) { - int v = (int) (-mPageScroller.getCurrVelocityX() + 0.5f); - mListener.onAbsorb(v, EdgeView.RIGHT); - } else if (oldX < mBoundRight && mCurrentX == mBoundRight) { - int v = (int) (mPageScroller.getCurrVelocityX() + 0.5f); - mListener.onAbsorb(v, EdgeView.LEFT); - } - - return progress >= 1; - } - - private boolean interpolateLinear(float progress) { - // Other animations - if (progress >= 1) { - mCurrentX = mToX; - mCurrentY = mToY; - return true; - } else { - if (mAnimationKind == ANIM_KIND_CAPTURE) { - progress = CaptureAnimation.calculateSlide(progress); - } - mCurrentX = (int) (mFromX + progress * (mToX - mFromX)); - mCurrentY = (int) (mFromY + progress * (mToY - mFromY)); - if (mAnimationKind == ANIM_KIND_CAPTURE) { - return false; - } else { - return (mCurrentX == mToX && mCurrentY == mToY); - } - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // Box: represents a rectangular area which shows a picture. - //////////////////////////////////////////////////////////////////////////// - private class Box extends Animatable { - // Size of the bitmap - public int mImageW, mImageH; - - // This is true if we assume the image size is the same as view size - // until we know the actual size of image. This is also used to - // determine if there is an image ready to show. - public boolean mUseViewSize; - - // The minimum and maximum scale we allow for this box. - public float mScaleMin, mScaleMax; - - // The X/Y value indicates where the center of the box is on the view - // coordinate. We always keep the mCurrent{X,Y,Scale} sync with the - // actual values used currently. Note that the X values are implicitly - // defined by Platform and Gaps. - public int mCurrentY, mFromY, mToY; - public float mCurrentScale, mFromScale, mToScale; - - // The absolute X coordinate of the center of the box. This is only used - // during moveBox(). - public int mAbsoluteX; - - @Override - public boolean startSnapback() { - if (mAnimationStartTime != NO_ANIMATION) return false; - if (mAnimationKind == ANIM_KIND_SCROLL - && mListener.isHoldingDown()) return false; - if (mAnimationKind == ANIM_KIND_DELETE - && mListener.isHoldingDelete()) return false; - if (mInScale && this == mBoxes.get(0)) return false; - - int y = mCurrentY; - float scale; - - if (this == mBoxes.get(0)) { - float scaleMin = mExtraScalingRange ? - mScaleMin * SCALE_MIN_EXTRA : mScaleMin; - float scaleMax = mExtraScalingRange ? - mScaleMax * SCALE_MAX_EXTRA : mScaleMax; - scale = Utils.clamp(mCurrentScale, scaleMin, scaleMax); - if (mFilmMode) { - y = 0; - } else { - calculateStableBound(scale, HORIZONTAL_SLACK); - // If the picture is zoomed-in, we want to keep the focus - // point stay in the same position on screen. See the - // comment in Platform.startSnapback for details. - if (!viewTallerThanScaledImage(scale)) { - float scaleDiff = mCurrentScale - scale; - y += (int) (mFocusY * scaleDiff + 0.5f); - } - y = Utils.clamp(y, mBoundTop, mBoundBottom); - } - } else { - y = 0; - scale = mScaleMin; - } - - if (mCurrentY != y || mCurrentScale != scale) { - return doAnimation(y, scale, ANIM_KIND_SNAPBACK); - } - return false; - } - - private boolean doAnimation(int targetY, float targetScale, int kind) { - targetScale = clampScale(targetScale); - - if (mCurrentY == targetY && mCurrentScale == targetScale - && kind != ANIM_KIND_CAPTURE) { - return false; - } - - // Now starts an animation for the box. - mAnimationKind = kind; - mFromY = mCurrentY; - mFromScale = mCurrentScale; - mToY = targetY; - mToScale = targetScale; - mAnimationStartTime = AnimationTime.startTime(); - mAnimationDuration = ANIM_TIME[kind]; - advanceAnimation(); - return true; - } - - // Clamps the input scale to the range that doAnimation() can reach. - public float clampScale(float s) { - return Utils.clamp(s, - SCALE_MIN_EXTRA * mScaleMin, - SCALE_MAX_EXTRA * mScaleMax); - } - - @Override - protected boolean interpolate(float progress) { - if (mAnimationKind == ANIM_KIND_FLING) { - return interpolateFlingPage(progress); - } else { - return interpolateLinear(progress); - } - } - - private boolean interpolateFlingPage(float progress) { - mPageScroller.computeScrollOffset(progress); - calculateStableBound(mCurrentScale); - - int oldY = mCurrentY; - mCurrentY = mPageScroller.getCurrY(); - - // Check if we hit the edges; show edge effects if we do. - if (oldY > mBoundTop && mCurrentY == mBoundTop) { - int v = (int) (-mPageScroller.getCurrVelocityY() + 0.5f); - mListener.onAbsorb(v, EdgeView.BOTTOM); - } else if (oldY < mBoundBottom && mCurrentY == mBoundBottom) { - int v = (int) (mPageScroller.getCurrVelocityY() + 0.5f); - mListener.onAbsorb(v, EdgeView.TOP); - } - - return progress >= 1; - } - - private boolean interpolateLinear(float progress) { - if (progress >= 1) { - mCurrentY = mToY; - mCurrentScale = mToScale; - return true; - } else { - mCurrentY = (int) (mFromY + progress * (mToY - mFromY)); - mCurrentScale = mFromScale + progress * (mToScale - mFromScale); - if (mAnimationKind == ANIM_KIND_CAPTURE) { - float f = CaptureAnimation.calculateScale(progress); - mCurrentScale *= f; - return false; - } else { - return (mCurrentY == mToY && mCurrentScale == mToScale); - } - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // Gap: represents a rectangular area which is between two boxes. - //////////////////////////////////////////////////////////////////////////// - private class Gap extends Animatable { - // The default gap size between two boxes. The value may vary for - // different image size of the boxes and for different modes (page or - // film). - public int mDefaultSize; - - // The gap size between the two boxes. - public int mCurrentGap, mFromGap, mToGap; - - @Override - public boolean startSnapback() { - if (mAnimationStartTime != NO_ANIMATION) return false; - return doAnimation(mDefaultSize, ANIM_KIND_SNAPBACK); - } - - // Starts an animation for a gap. - public boolean doAnimation(int targetSize, int kind) { - if (mCurrentGap == targetSize && kind != ANIM_KIND_CAPTURE) { - return false; - } - mAnimationKind = kind; - mFromGap = mCurrentGap; - mToGap = targetSize; - mAnimationStartTime = AnimationTime.startTime(); - mAnimationDuration = ANIM_TIME[mAnimationKind]; - advanceAnimation(); - return true; - } - - @Override - protected boolean interpolate(float progress) { - if (progress >= 1) { - mCurrentGap = mToGap; - return true; - } else { - mCurrentGap = (int) (mFromGap + progress * (mToGap - mFromGap)); - if (mAnimationKind == ANIM_KIND_CAPTURE) { - float f = CaptureAnimation.calculateScale(progress); - mCurrentGap = (int) (mCurrentGap * f); - return false; - } else { - return (mCurrentGap == mToGap); - } - } - } - } - - //////////////////////////////////////////////////////////////////////////// - // FilmRatio: represents the progress of film mode change. - //////////////////////////////////////////////////////////////////////////// - private class FilmRatio extends Animatable { - // The film ratio: 1 means switching to film mode is complete, 0 means - // switching to page mode is complete. - public float mCurrentRatio, mFromRatio, mToRatio; - - @Override - public boolean startSnapback() { - float target = mFilmMode ? 1f : 0f; - if (target == mToRatio) return false; - return doAnimation(target, ANIM_KIND_SNAPBACK); - } - - // Starts an animation for the film ratio. - private boolean doAnimation(float targetRatio, int kind) { - mAnimationKind = kind; - mFromRatio = mCurrentRatio; - mToRatio = targetRatio; - mAnimationStartTime = AnimationTime.startTime(); - mAnimationDuration = ANIM_TIME[mAnimationKind]; - advanceAnimation(); - return true; - } - - @Override - protected boolean interpolate(float progress) { - if (progress >= 1) { - mCurrentRatio = mToRatio; - return true; - } else { - mCurrentRatio = mFromRatio + progress * (mToRatio - mFromRatio); - return (mCurrentRatio == mToRatio); - } - } - } -} diff --git a/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java b/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java deleted file mode 100644 index ce672f211..000000000 --- a/src/com/android/gallery3d/ui/PreparePageFadeoutTexture.java +++ /dev/null @@ -1,85 +0,0 @@ -package com.android.gallery3d.ui; - -import android.os.ConditionVariable; - -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.RawTexture; -import com.android.gallery3d.ui.GLRoot.OnGLIdleListener; - -public class PreparePageFadeoutTexture implements OnGLIdleListener { - private static final long TIMEOUT = 200; - public static final String KEY_FADE_TEXTURE = "fade_texture"; - - private RawTexture mTexture; - private ConditionVariable mResultReady = new ConditionVariable(false); - private boolean mCancelled = false; - private GLView mRootPane; - - public PreparePageFadeoutTexture(GLView rootPane) { - if (rootPane == null) { - mCancelled = true; - return; - } - int w = rootPane.getWidth(); - int h = rootPane.getHeight(); - if (w == 0 || h == 0) { - mCancelled = true; - return; - } - mTexture = new RawTexture(w, h, true); - mRootPane = rootPane; - } - - public boolean isCancelled() { - return mCancelled; - } - - public synchronized RawTexture get() { - if (mCancelled) { - return null; - } else if (mResultReady.block(TIMEOUT)) { - return mTexture; - } else { - mCancelled = true; - return null; - } - } - - @Override - public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) { - if (!mCancelled) { - try { - canvas.beginRenderTarget(mTexture); - mRootPane.render(canvas); - canvas.endRenderTarget(); - } catch (RuntimeException e) { - mTexture = null; - } - } else { - mTexture = null; - } - mResultReady.open(); - return false; - } - - public static void prepareFadeOutTexture(AbstractGalleryActivity activity, - GLView rootPane) { - PreparePageFadeoutTexture task = new PreparePageFadeoutTexture(rootPane); - if (task.isCancelled()) return; - GLRoot root = activity.getGLRoot(); - RawTexture texture = null; - root.unlockRenderThread(); - try { - root.addOnGLIdleListener(task); - texture = task.get(); - } finally { - root.lockRenderThread(); - } - - if (texture == null) { - return; - } - activity.getTransitionStore().put(KEY_FADE_TEXTURE, texture); - } -} diff --git a/src/com/android/gallery3d/ui/ProgressSpinner.java b/src/com/android/gallery3d/ui/ProgressSpinner.java deleted file mode 100644 index 1b31af278..000000000 --- a/src/com/android/gallery3d/ui/ProgressSpinner.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; - -import com.android.gallery3d.R; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.ResourceTexture; - -public class ProgressSpinner { - private static float ROTATE_SPEED_OUTER = 1080f / 3500f; - private static float ROTATE_SPEED_INNER = -720f / 3500f; - private final ResourceTexture mOuter; - private final ResourceTexture mInner; - private final int mWidth; - private final int mHeight; - - private float mInnerDegree = 0f; - private float mOuterDegree = 0f; - private long mAnimationTimestamp = -1; - - public ProgressSpinner(Context context) { - mOuter = new ResourceTexture(context, R.drawable.spinner_76_outer_holo); - mInner = new ResourceTexture(context, R.drawable.spinner_76_inner_holo); - - mWidth = Math.max(mOuter.getWidth(), mInner.getWidth()); - mHeight = Math.max(mOuter.getHeight(), mInner.getHeight()); - } - - public int getWidth() { - return mWidth; - } - - public int getHeight() { - return mHeight; - } - - public void startAnimation() { - mAnimationTimestamp = -1; - mOuterDegree = 0; - mInnerDegree = 0; - } - - public void draw(GLCanvas canvas, int x, int y) { - long now = AnimationTime.get(); - if (mAnimationTimestamp == -1) mAnimationTimestamp = now; - mOuterDegree += (now - mAnimationTimestamp) * ROTATE_SPEED_OUTER; - mInnerDegree += (now - mAnimationTimestamp) * ROTATE_SPEED_INNER; - - mAnimationTimestamp = now; - - // just preventing overflow - if (mOuterDegree > 360) mOuterDegree -= 360f; - if (mInnerDegree < 0) mInnerDegree += 360f; - - canvas.save(GLCanvas.SAVE_FLAG_MATRIX); - - canvas.translate(x + mWidth / 2, y + mHeight / 2); - canvas.rotate(mInnerDegree, 0, 0, 1); - mOuter.draw(canvas, -mOuter.getWidth() / 2, -mOuter.getHeight() / 2); - canvas.rotate(mOuterDegree - mInnerDegree, 0, 0, 1); - mInner.draw(canvas, -mInner.getWidth() / 2, -mInner.getHeight() / 2); - canvas.restore(); - } -} diff --git a/src/com/android/gallery3d/ui/RelativePosition.java b/src/com/android/gallery3d/ui/RelativePosition.java deleted file mode 100644 index 0f2bfd812..000000000 --- a/src/com/android/gallery3d/ui/RelativePosition.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -public class RelativePosition { - private float mAbsoluteX; - private float mAbsoluteY; - private float mReferenceX; - private float mReferenceY; - - public void setAbsolutePosition(int absoluteX, int absoluteY) { - mAbsoluteX = absoluteX; - mAbsoluteY = absoluteY; - } - - public void setReferencePosition(int x, int y) { - mReferenceX = x; - mReferenceY = y; - } - - public float getX() { - return mAbsoluteX - mReferenceX; - } - - public float getY() { - return mAbsoluteY - mReferenceY; - } -} diff --git a/src/com/android/gallery3d/ui/ScreenNail.java b/src/com/android/gallery3d/ui/ScreenNail.java deleted file mode 100644 index 965bf0b54..000000000 --- a/src/com/android/gallery3d/ui/ScreenNail.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.ui; - -import android.graphics.RectF; - -import com.android.gallery3d.glrenderer.GLCanvas; - -public interface ScreenNail { - public int getWidth(); - public int getHeight(); - public void draw(GLCanvas canvas, int x, int y, int width, int height); - - // We do not need to draw this ScreenNail in this frame. - public void noDraw(); - - // This ScreenNail will not be used anymore. Release related resources. - public void recycle(); - - // This is only used by TileImageView to back up the tiles not yet loaded. - public void draw(GLCanvas canvas, RectF source, RectF dest); -} diff --git a/src/com/android/gallery3d/ui/ScrollBarView.java b/src/com/android/gallery3d/ui/ScrollBarView.java deleted file mode 100644 index 34fbcef7a..000000000 --- a/src/com/android/gallery3d/ui/ScrollBarView.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Rect; -import android.util.TypedValue; - -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.NinePatchTexture; - -public class ScrollBarView extends GLView { - @SuppressWarnings("unused") - private static final String TAG = "ScrollBarView"; - - private int mBarHeight; - - private int mGripHeight; - private int mGripPosition; // left side of the grip - private int mGripWidth; // zero if the grip is disabled - private int mGivenGripWidth; - - private int mContentPosition; - private int mContentTotal; - - private NinePatchTexture mScrollBarTexture; - - public ScrollBarView(Context context, int gripHeight, int gripWidth) { - TypedValue outValue = new TypedValue(); - context.getTheme().resolveAttribute( - android.R.attr.scrollbarThumbHorizontal, outValue, true); - mScrollBarTexture = new NinePatchTexture( - context, outValue.resourceId); - mGripPosition = 0; - mGripWidth = 0; - mGivenGripWidth = gripWidth; - mGripHeight = gripHeight; - } - - @Override - protected void onLayout( - boolean changed, int left, int top, int right, int bottom) { - if (!changed) return; - mBarHeight = bottom - top; - } - - // The content position is between 0 to "total". The current position is - // in "position". - public void setContentPosition(int position, int total) { - if (position == mContentPosition && total == mContentTotal) { - return; - } - - invalidate(); - - mContentPosition = position; - mContentTotal = total; - - // If the grip cannot move, don't draw it. - if (mContentTotal <= 0) { - mGripPosition = 0; - mGripWidth = 0; - return; - } - - // Map from the content range to scroll bar range. - // - // mContentTotal --> getWidth() - mGripWidth - // mContentPosition --> mGripPosition - mGripWidth = mGivenGripWidth; - float r = (getWidth() - mGripWidth) / (float) mContentTotal; - mGripPosition = Math.round(r * mContentPosition); - } - - @Override - protected void render(GLCanvas canvas) { - super.render(canvas); - if (mGripWidth == 0) return; - Rect b = bounds(); - int y = (mBarHeight - mGripHeight) / 2; - mScrollBarTexture.draw(canvas, mGripPosition, y, mGripWidth, mGripHeight); - } -} diff --git a/src/com/android/gallery3d/ui/ScrollerHelper.java b/src/com/android/gallery3d/ui/ScrollerHelper.java deleted file mode 100644 index aa68d19d9..000000000 --- a/src/com/android/gallery3d/ui/ScrollerHelper.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.view.ViewConfiguration; - -import com.android.gallery3d.common.OverScroller; -import com.android.gallery3d.common.Utils; - -public class ScrollerHelper { - private OverScroller mScroller; - private int mOverflingDistance; - private boolean mOverflingEnabled; - - public ScrollerHelper(Context context) { - mScroller = new OverScroller(context); - ViewConfiguration configuration = ViewConfiguration.get(context); - mOverflingDistance = configuration.getScaledOverflingDistance(); - } - - public void setOverfling(boolean enabled) { - mOverflingEnabled = enabled; - } - - /** - * Call this when you want to know the new location. The position will be - * updated and can be obtained by getPosition(). Returns true if the - * animation is not yet finished. - */ - public boolean advanceAnimation(long currentTimeMillis) { - return mScroller.computeScrollOffset(); - } - - public boolean isFinished() { - return mScroller.isFinished(); - } - - public void forceFinished() { - mScroller.forceFinished(true); - } - - public int getPosition() { - return mScroller.getCurrX(); - } - - public float getCurrVelocity() { - return mScroller.getCurrVelocity(); - } - - public void setPosition(int position) { - mScroller.startScroll( - position, 0, // startX, startY - 0, 0, 0); // dx, dy, duration - - // This forces the scroller to reach the final position. - mScroller.abortAnimation(); - } - - public void fling(int velocity, int min, int max) { - int currX = getPosition(); - mScroller.fling( - currX, 0, // startX, startY - velocity, 0, // velocityX, velocityY - min, max, // minX, maxX - 0, 0, // minY, maxY - mOverflingEnabled ? mOverflingDistance : 0, 0); - } - - // Returns the distance that over the scroll limit. - public int startScroll(int distance, int min, int max) { - int currPosition = mScroller.getCurrX(); - int finalPosition = mScroller.isFinished() ? currPosition : - mScroller.getFinalX(); - int newPosition = Utils.clamp(finalPosition + distance, min, max); - if (newPosition != currPosition) { - mScroller.startScroll( - currPosition, 0, // startX, startY - newPosition - currPosition, 0, 0); // dx, dy, duration - } - return finalPosition + distance - newPosition; - } -} diff --git a/src/com/android/gallery3d/ui/SelectionManager.java b/src/com/android/gallery3d/ui/SelectionManager.java deleted file mode 100644 index be6811bc1..000000000 --- a/src/com/android/gallery3d/ui/SelectionManager.java +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -public class SelectionManager { - @SuppressWarnings("unused") - private static final String TAG = "SelectionManager"; - - public static final int ENTER_SELECTION_MODE = 1; - public static final int LEAVE_SELECTION_MODE = 2; - public static final int SELECT_ALL_MODE = 3; - - private Set<Path> mClickedSet; - private MediaSet mSourceMediaSet; - private SelectionListener mListener; - private DataManager mDataManager; - private boolean mInverseSelection; - private boolean mIsAlbumSet; - private boolean mInSelectionMode; - private boolean mAutoLeave = true; - private int mTotal; - - public interface SelectionListener { - public void onSelectionModeChange(int mode); - public void onSelectionChange(Path path, boolean selected); - } - - public SelectionManager(AbstractGalleryActivity activity, boolean isAlbumSet) { - mDataManager = activity.getDataManager(); - mClickedSet = new HashSet<Path>(); - mIsAlbumSet = isAlbumSet; - mTotal = -1; - } - - // Whether we will leave selection mode automatically once the number of - // selected items is down to zero. - public void setAutoLeaveSelectionMode(boolean enable) { - mAutoLeave = enable; - } - - public void setSelectionListener(SelectionListener listener) { - mListener = listener; - } - - public void selectAll() { - mInverseSelection = true; - mClickedSet.clear(); - enterSelectionMode(); - if (mListener != null) mListener.onSelectionModeChange(SELECT_ALL_MODE); - } - - public void deSelectAll() { - leaveSelectionMode(); - mInverseSelection = false; - mClickedSet.clear(); - } - - public boolean inSelectAllMode() { - return mInverseSelection; - } - - public boolean inSelectionMode() { - return mInSelectionMode; - } - - public void enterSelectionMode() { - if (mInSelectionMode) return; - - mInSelectionMode = true; - if (mListener != null) mListener.onSelectionModeChange(ENTER_SELECTION_MODE); - } - - public void leaveSelectionMode() { - if (!mInSelectionMode) return; - - mInSelectionMode = false; - mInverseSelection = false; - mClickedSet.clear(); - if (mListener != null) mListener.onSelectionModeChange(LEAVE_SELECTION_MODE); - } - - public boolean isItemSelected(Path itemId) { - return mInverseSelection ^ mClickedSet.contains(itemId); - } - - private int getTotalCount() { - if (mSourceMediaSet == null) return -1; - - if (mTotal < 0) { - mTotal = mIsAlbumSet - ? mSourceMediaSet.getSubMediaSetCount() - : mSourceMediaSet.getMediaItemCount(); - } - return mTotal; - } - - public int getSelectedCount() { - int count = mClickedSet.size(); - if (mInverseSelection) { - count = getTotalCount() - count; - } - return count; - } - - public void toggle(Path path) { - if (mClickedSet.contains(path)) { - mClickedSet.remove(path); - } else { - enterSelectionMode(); - mClickedSet.add(path); - } - - // Convert to inverse selection mode if everything is selected. - int count = getSelectedCount(); - if (count == getTotalCount()) { - selectAll(); - } - - if (mListener != null) mListener.onSelectionChange(path, isItemSelected(path)); - if (count == 0 && mAutoLeave) { - leaveSelectionMode(); - } - } - - private static boolean expandMediaSet(ArrayList<Path> items, MediaSet set, int maxSelection) { - int subCount = set.getSubMediaSetCount(); - for (int i = 0; i < subCount; i++) { - if (!expandMediaSet(items, set.getSubMediaSet(i), maxSelection)) { - return false; - } - } - int total = set.getMediaItemCount(); - int batch = 50; - int index = 0; - - while (index < total) { - int count = index + batch < total - ? batch - : total - index; - ArrayList<MediaItem> list = set.getMediaItem(index, count); - if (list != null - && list.size() > (maxSelection - items.size())) { - return false; - } - for (MediaItem item : list) { - items.add(item.getPath()); - } - index += batch; - } - return true; - } - - public ArrayList<Path> getSelected(boolean expandSet) { - return getSelected(expandSet, Integer.MAX_VALUE); - } - - public ArrayList<Path> getSelected(boolean expandSet, int maxSelection) { - ArrayList<Path> selected = new ArrayList<Path>(); - if (mIsAlbumSet) { - if (mInverseSelection) { - int total = getTotalCount(); - for (int i = 0; i < total; i++) { - MediaSet set = mSourceMediaSet.getSubMediaSet(i); - Path id = set.getPath(); - if (!mClickedSet.contains(id)) { - if (expandSet) { - if (!expandMediaSet(selected, set, maxSelection)) { - return null; - } - } else { - selected.add(id); - if (selected.size() > maxSelection) { - return null; - } - } - } - } - } else { - for (Path id : mClickedSet) { - if (expandSet) { - if (!expandMediaSet(selected, mDataManager.getMediaSet(id), - maxSelection)) { - return null; - } - } else { - selected.add(id); - if (selected.size() > maxSelection) { - return null; - } - } - } - } - } else { - if (mInverseSelection) { - int total = getTotalCount(); - int index = 0; - while (index < total) { - int count = Math.min(total - index, MediaSet.MEDIAITEM_BATCH_FETCH_COUNT); - ArrayList<MediaItem> list = mSourceMediaSet.getMediaItem(index, count); - for (MediaItem item : list) { - Path id = item.getPath(); - if (!mClickedSet.contains(id)) { - selected.add(id); - if (selected.size() > maxSelection) { - return null; - } - } - } - index += count; - } - } else { - for (Path id : mClickedSet) { - selected.add(id); - if (selected.size() > maxSelection) { - return null; - } - } - } - } - return selected; - } - - public void setSourceMediaSet(MediaSet set) { - mSourceMediaSet = set; - mTotal = -1; - } -} diff --git a/src/com/android/gallery3d/ui/SelectionMenu.java b/src/com/android/gallery3d/ui/SelectionMenu.java deleted file mode 100644 index 5b0828328..000000000 --- a/src/com/android/gallery3d/ui/SelectionMenu.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; - -import com.android.gallery3d.R; -import com.android.gallery3d.ui.PopupList.OnPopupItemClickListener; - -public class SelectionMenu implements OnClickListener { - @SuppressWarnings("unused") - private static final String TAG = "SelectionMenu"; - - private final Context mContext; - private final Button mButton; - private final PopupList mPopupList; - - public SelectionMenu(Context context, Button button, OnPopupItemClickListener listener) { - mContext = context; - mButton = button; - mPopupList = new PopupList(context, mButton); - mPopupList.addItem(R.id.action_select_all, - context.getString(R.string.select_all)); - mPopupList.setOnPopupItemClickListener(listener); - mButton.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - mPopupList.show(); - } - - public void updateSelectAllMode(boolean inSelectAllMode) { - PopupList.Item item = mPopupList.findItem(R.id.action_select_all); - if (item != null) { - item.setTitle(mContext.getString( - inSelectAllMode ? R.string.deselect_all : R.string.select_all)); - } - } - - public void setTitle(CharSequence title) { - mButton.setText(title); - } -} diff --git a/src/com/android/gallery3d/ui/SlideshowView.java b/src/com/android/gallery3d/ui/SlideshowView.java deleted file mode 100644 index 43784232d..000000000 --- a/src/com/android/gallery3d/ui/SlideshowView.java +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Bitmap; -import android.graphics.PointF; - -import com.android.gallery3d.anim.CanvasAnimation; -import com.android.gallery3d.anim.FloatAnimation; -import com.android.gallery3d.glrenderer.BitmapTexture; -import com.android.gallery3d.glrenderer.GLCanvas; - -import java.util.Random; - -public class SlideshowView extends GLView { - @SuppressWarnings("unused") - private static final String TAG = "SlideshowView"; - - private static final int SLIDESHOW_DURATION = 3500; - private static final int TRANSITION_DURATION = 1000; - - private static final float SCALE_SPEED = 0.20f ; - private static final float MOVE_SPEED = SCALE_SPEED; - - private int mCurrentRotation; - private BitmapTexture mCurrentTexture; - private SlideshowAnimation mCurrentAnimation; - - private int mPrevRotation; - private BitmapTexture mPrevTexture; - private SlideshowAnimation mPrevAnimation; - - private final FloatAnimation mTransitionAnimation = - new FloatAnimation(0, 1, TRANSITION_DURATION); - - private Random mRandom = new Random(); - - public void next(Bitmap bitmap, int rotation) { - - mTransitionAnimation.start(); - - if (mPrevTexture != null) { - mPrevTexture.getBitmap().recycle(); - mPrevTexture.recycle(); - } - - mPrevTexture = mCurrentTexture; - mPrevAnimation = mCurrentAnimation; - mPrevRotation = mCurrentRotation; - - mCurrentRotation = rotation; - mCurrentTexture = new BitmapTexture(bitmap); - if (((rotation / 90) & 0x01) == 0) { - mCurrentAnimation = new SlideshowAnimation( - mCurrentTexture.getWidth(), mCurrentTexture.getHeight(), - mRandom); - } else { - mCurrentAnimation = new SlideshowAnimation( - mCurrentTexture.getHeight(), mCurrentTexture.getWidth(), - mRandom); - } - mCurrentAnimation.start(); - - invalidate(); - } - - public void release() { - if (mPrevTexture != null) { - mPrevTexture.recycle(); - mPrevTexture = null; - } - if (mCurrentTexture != null) { - mCurrentTexture.recycle(); - mCurrentTexture = null; - } - } - - @Override - protected void render(GLCanvas canvas) { - long animTime = AnimationTime.get(); - boolean requestRender = mTransitionAnimation.calculate(animTime); - float alpha = mPrevTexture == null ? 1f : mTransitionAnimation.get(); - - if (mPrevTexture != null && alpha != 1f) { - requestRender |= mPrevAnimation.calculate(animTime); - canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX); - canvas.setAlpha(1f - alpha); - mPrevAnimation.apply(canvas); - canvas.rotate(mPrevRotation, 0, 0, 1); - mPrevTexture.draw(canvas, -mPrevTexture.getWidth() / 2, - -mPrevTexture.getHeight() / 2); - canvas.restore(); - } - if (mCurrentTexture != null) { - requestRender |= mCurrentAnimation.calculate(animTime); - canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX); - canvas.setAlpha(alpha); - mCurrentAnimation.apply(canvas); - canvas.rotate(mCurrentRotation, 0, 0, 1); - mCurrentTexture.draw(canvas, -mCurrentTexture.getWidth() / 2, - -mCurrentTexture.getHeight() / 2); - canvas.restore(); - } - if (requestRender) invalidate(); - } - - private class SlideshowAnimation extends CanvasAnimation { - private final int mWidth; - private final int mHeight; - - private final PointF mMovingVector; - private float mProgress; - - public SlideshowAnimation(int width, int height, Random random) { - mWidth = width; - mHeight = height; - mMovingVector = new PointF( - MOVE_SPEED * mWidth * (random.nextFloat() - 0.5f), - MOVE_SPEED * mHeight * (random.nextFloat() - 0.5f)); - setDuration(SLIDESHOW_DURATION); - } - - @Override - public void apply(GLCanvas canvas) { - int viewWidth = getWidth(); - int viewHeight = getHeight(); - - float initScale = Math.min((float) - viewWidth / mWidth, (float) viewHeight / mHeight); - float scale = initScale * (1 + SCALE_SPEED * mProgress); - - float centerX = viewWidth / 2 + mMovingVector.x * mProgress; - float centerY = viewHeight / 2 + mMovingVector.y * mProgress; - - canvas.translate(centerX, centerY); - canvas.scale(scale, scale, 0); - } - - @Override - public int getCanvasSaveFlags() { - return GLCanvas.SAVE_FLAG_MATRIX; - } - - @Override - protected void onCalculate(float progress) { - mProgress = progress; - } - } -} diff --git a/src/com/android/gallery3d/ui/SlotView.java b/src/com/android/gallery3d/ui/SlotView.java deleted file mode 100644 index bd0ffdc15..000000000 --- a/src/com/android/gallery3d/ui/SlotView.java +++ /dev/null @@ -1,788 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Rect; -import android.os.Handler; -import android.view.GestureDetector; -import android.view.MotionEvent; -import android.view.animation.DecelerateInterpolator; - -import com.android.gallery3d.anim.Animation; -import com.android.gallery3d.app.AbstractGalleryActivity; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.GLCanvas; - -public class SlotView extends GLView { - @SuppressWarnings("unused") - private static final String TAG = "SlotView"; - - private static final boolean WIDE = true; - private static final int INDEX_NONE = -1; - - public static final int RENDER_MORE_PASS = 1; - public static final int RENDER_MORE_FRAME = 2; - - public interface Listener { - public void onDown(int index); - public void onUp(boolean followedByLongPress); - public void onSingleTapUp(int index); - public void onLongTap(int index); - public void onScrollPositionChanged(int position, int total); - } - - public static class SimpleListener implements Listener { - @Override public void onDown(int index) {} - @Override public void onUp(boolean followedByLongPress) {} - @Override public void onSingleTapUp(int index) {} - @Override public void onLongTap(int index) {} - @Override public void onScrollPositionChanged(int position, int total) {} - } - - public static interface SlotRenderer { - public void prepareDrawing(); - public void onVisibleRangeChanged(int visibleStart, int visibleEnd); - public void onSlotSizeChanged(int width, int height); - public int renderSlot(GLCanvas canvas, int index, int pass, int width, int height); - } - - private final GestureDetector mGestureDetector; - private final ScrollerHelper mScroller; - private final Paper mPaper = new Paper(); - - private Listener mListener; - private UserInteractionListener mUIListener; - - private boolean mMoreAnimation = false; - private SlotAnimation mAnimation = null; - private final Layout mLayout = new Layout(); - private int mStartIndex = INDEX_NONE; - - // whether the down action happened while the view is scrolling. - private boolean mDownInScrolling; - private int mOverscrollEffect = OVERSCROLL_3D; - private final Handler mHandler; - - private SlotRenderer mRenderer; - - private int[] mRequestRenderSlots = new int[16]; - - public static final int OVERSCROLL_3D = 0; - public static final int OVERSCROLL_SYSTEM = 1; - public static final int OVERSCROLL_NONE = 2; - - // to prevent allocating memory - private final Rect mTempRect = new Rect(); - - public SlotView(AbstractGalleryActivity activity, Spec spec) { - mGestureDetector = new GestureDetector(activity, new MyGestureListener()); - mScroller = new ScrollerHelper(activity); - mHandler = new SynchronizedHandler(activity.getGLRoot()); - setSlotSpec(spec); - } - - public void setSlotRenderer(SlotRenderer slotDrawer) { - mRenderer = slotDrawer; - if (mRenderer != null) { - mRenderer.onSlotSizeChanged(mLayout.mSlotWidth, mLayout.mSlotHeight); - mRenderer.onVisibleRangeChanged(getVisibleStart(), getVisibleEnd()); - } - } - - public void setCenterIndex(int index) { - int slotCount = mLayout.mSlotCount; - if (index < 0 || index >= slotCount) { - return; - } - Rect rect = mLayout.getSlotRect(index, mTempRect); - int position = WIDE - ? (rect.left + rect.right - getWidth()) / 2 - : (rect.top + rect.bottom - getHeight()) / 2; - setScrollPosition(position); - } - - public void makeSlotVisible(int index) { - Rect rect = mLayout.getSlotRect(index, mTempRect); - int visibleBegin = WIDE ? mScrollX : mScrollY; - int visibleLength = WIDE ? getWidth() : getHeight(); - int visibleEnd = visibleBegin + visibleLength; - int slotBegin = WIDE ? rect.left : rect.top; - int slotEnd = WIDE ? rect.right : rect.bottom; - - int position = visibleBegin; - if (visibleLength < slotEnd - slotBegin) { - position = visibleBegin; - } else if (slotBegin < visibleBegin) { - position = slotBegin; - } else if (slotEnd > visibleEnd) { - position = slotEnd - visibleLength; - } - - setScrollPosition(position); - } - - public void setScrollPosition(int position) { - position = Utils.clamp(position, 0, mLayout.getScrollLimit()); - mScroller.setPosition(position); - updateScrollPosition(position, false); - } - - public void setSlotSpec(Spec spec) { - mLayout.setSlotSpec(spec); - } - - @Override - public void addComponent(GLView view) { - throw new UnsupportedOperationException(); - } - - @Override - protected void onLayout(boolean changeSize, int l, int t, int r, int b) { - if (!changeSize) return; - - // Make sure we are still at a resonable scroll position after the size - // is changed (like orientation change). We choose to keep the center - // visible slot still visible. This is arbitrary but reasonable. - int visibleIndex = - (mLayout.getVisibleStart() + mLayout.getVisibleEnd()) / 2; - mLayout.setSize(r - l, b - t); - makeSlotVisible(visibleIndex); - if (mOverscrollEffect == OVERSCROLL_3D) { - mPaper.setSize(r - l, b - t); - } - } - - public void startScatteringAnimation(RelativePosition position) { - mAnimation = new ScatteringAnimation(position); - mAnimation.start(); - if (mLayout.mSlotCount != 0) invalidate(); - } - - public void startRisingAnimation() { - mAnimation = new RisingAnimation(); - mAnimation.start(); - if (mLayout.mSlotCount != 0) invalidate(); - } - - private void updateScrollPosition(int position, boolean force) { - if (!force && (WIDE ? position == mScrollX : position == mScrollY)) return; - if (WIDE) { - mScrollX = position; - } else { - mScrollY = position; - } - mLayout.setScrollPosition(position); - onScrollPositionChanged(position); - } - - protected void onScrollPositionChanged(int newPosition) { - int limit = mLayout.getScrollLimit(); - mListener.onScrollPositionChanged(newPosition, limit); - } - - public Rect getSlotRect(int slotIndex) { - return mLayout.getSlotRect(slotIndex, new Rect()); - } - - @Override - protected boolean onTouch(MotionEvent event) { - if (mUIListener != null) mUIListener.onUserInteraction(); - mGestureDetector.onTouchEvent(event); - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mDownInScrolling = !mScroller.isFinished(); - mScroller.forceFinished(); - break; - case MotionEvent.ACTION_UP: - mPaper.onRelease(); - invalidate(); - break; - } - return true; - } - - public void setListener(Listener listener) { - mListener = listener; - } - - public void setUserInteractionListener(UserInteractionListener listener) { - mUIListener = listener; - } - - public void setOverscrollEffect(int kind) { - mOverscrollEffect = kind; - mScroller.setOverfling(kind == OVERSCROLL_SYSTEM); - } - - private static int[] expandIntArray(int array[], int capacity) { - while (array.length < capacity) { - array = new int[array.length * 2]; - } - return array; - } - - @Override - protected void render(GLCanvas canvas) { - super.render(canvas); - - if (mRenderer == null) return; - mRenderer.prepareDrawing(); - - long animTime = AnimationTime.get(); - boolean more = mScroller.advanceAnimation(animTime); - more |= mLayout.advanceAnimation(animTime); - int oldX = mScrollX; - updateScrollPosition(mScroller.getPosition(), false); - - boolean paperActive = false; - if (mOverscrollEffect == OVERSCROLL_3D) { - // Check if an edge is reached and notify mPaper if so. - int newX = mScrollX; - int limit = mLayout.getScrollLimit(); - if (oldX > 0 && newX == 0 || oldX < limit && newX == limit) { - float v = mScroller.getCurrVelocity(); - if (newX == limit) v = -v; - - // I don't know why, but getCurrVelocity() can return NaN. - if (!Float.isNaN(v)) { - mPaper.edgeReached(v); - } - } - paperActive = mPaper.advanceAnimation(); - } - - more |= paperActive; - - if (mAnimation != null) { - more |= mAnimation.calculate(animTime); - } - - canvas.translate(-mScrollX, -mScrollY); - - int requestCount = 0; - int requestedSlot[] = expandIntArray(mRequestRenderSlots, - mLayout.mVisibleEnd - mLayout.mVisibleStart); - - for (int i = mLayout.mVisibleEnd - 1; i >= mLayout.mVisibleStart; --i) { - int r = renderItem(canvas, i, 0, paperActive); - if ((r & RENDER_MORE_FRAME) != 0) more = true; - if ((r & RENDER_MORE_PASS) != 0) requestedSlot[requestCount++] = i; - } - - for (int pass = 1; requestCount != 0; ++pass) { - int newCount = 0; - for (int i = 0; i < requestCount; ++i) { - int r = renderItem(canvas, - requestedSlot[i], pass, paperActive); - if ((r & RENDER_MORE_FRAME) != 0) more = true; - if ((r & RENDER_MORE_PASS) != 0) requestedSlot[newCount++] = i; - } - requestCount = newCount; - } - - canvas.translate(mScrollX, mScrollY); - - if (more) invalidate(); - - final UserInteractionListener listener = mUIListener; - if (mMoreAnimation && !more && listener != null) { - mHandler.post(new Runnable() { - @Override - public void run() { - listener.onUserInteractionEnd(); - } - }); - } - mMoreAnimation = more; - } - - private int renderItem( - GLCanvas canvas, int index, int pass, boolean paperActive) { - canvas.save(GLCanvas.SAVE_FLAG_ALPHA | GLCanvas.SAVE_FLAG_MATRIX); - Rect rect = mLayout.getSlotRect(index, mTempRect); - if (paperActive) { - canvas.multiplyMatrix(mPaper.getTransform(rect, mScrollX), 0); - } else { - canvas.translate(rect.left, rect.top, 0); - } - if (mAnimation != null && mAnimation.isActive()) { - mAnimation.apply(canvas, index, rect); - } - int result = mRenderer.renderSlot( - canvas, index, pass, rect.right - rect.left, rect.bottom - rect.top); - canvas.restore(); - return result; - } - - public static abstract class SlotAnimation extends Animation { - protected float mProgress = 0; - - public SlotAnimation() { - setInterpolator(new DecelerateInterpolator(4)); - setDuration(1500); - } - - @Override - protected void onCalculate(float progress) { - mProgress = progress; - } - - abstract public void apply(GLCanvas canvas, int slotIndex, Rect target); - } - - public static class RisingAnimation extends SlotAnimation { - private static final int RISING_DISTANCE = 128; - - @Override - public void apply(GLCanvas canvas, int slotIndex, Rect target) { - canvas.translate(0, 0, RISING_DISTANCE * (1 - mProgress)); - } - } - - public static class ScatteringAnimation extends SlotAnimation { - private int PHOTO_DISTANCE = 1000; - private RelativePosition mCenter; - - public ScatteringAnimation(RelativePosition center) { - mCenter = center; - } - - @Override - public void apply(GLCanvas canvas, int slotIndex, Rect target) { - canvas.translate( - (mCenter.getX() - target.centerX()) * (1 - mProgress), - (mCenter.getY() - target.centerY()) * (1 - mProgress), - slotIndex * PHOTO_DISTANCE * (1 - mProgress)); - canvas.setAlpha(mProgress); - } - } - - // This Spec class is used to specify the size of each slot in the SlotView. - // There are two ways to do it: - // - // (1) Specify slotWidth and slotHeight: they specify the width and height - // of each slot. The number of rows and the gap between slots will be - // determined automatically. - // (2) Specify rowsLand, rowsPort, and slotGap: they specify the number - // of rows in landscape/portrait mode and the gap between slots. The - // width and height of each slot is determined automatically. - // - // The initial value of -1 means they are not specified. - public static class Spec { - public int slotWidth = -1; - public int slotHeight = -1; - public int slotHeightAdditional = 0; - - public int rowsLand = -1; - public int rowsPort = -1; - public int slotGap = -1; - } - - public class Layout { - - private int mVisibleStart; - private int mVisibleEnd; - - private int mSlotCount; - private int mSlotWidth; - private int mSlotHeight; - private int mSlotGap; - - private Spec mSpec; - - private int mWidth; - private int mHeight; - - private int mUnitCount; - private int mContentLength; - private int mScrollPosition; - - private IntegerAnimation mVerticalPadding = new IntegerAnimation(); - private IntegerAnimation mHorizontalPadding = new IntegerAnimation(); - - public void setSlotSpec(Spec spec) { - mSpec = spec; - } - - public boolean setSlotCount(int slotCount) { - if (slotCount == mSlotCount) return false; - if (mSlotCount != 0) { - mHorizontalPadding.setEnabled(true); - mVerticalPadding.setEnabled(true); - } - mSlotCount = slotCount; - int hPadding = mHorizontalPadding.getTarget(); - int vPadding = mVerticalPadding.getTarget(); - initLayoutParameters(); - return vPadding != mVerticalPadding.getTarget() - || hPadding != mHorizontalPadding.getTarget(); - } - - public Rect getSlotRect(int index, Rect rect) { - int col, row; - if (WIDE) { - col = index / mUnitCount; - row = index - col * mUnitCount; - } else { - row = index / mUnitCount; - col = index - row * mUnitCount; - } - - int x = mHorizontalPadding.get() + col * (mSlotWidth + mSlotGap); - int y = mVerticalPadding.get() + row * (mSlotHeight + mSlotGap); - rect.set(x, y, x + mSlotWidth, y + mSlotHeight); - return rect; - } - - public int getSlotWidth() { - return mSlotWidth; - } - - public int getSlotHeight() { - return mSlotHeight; - } - - // Calculate - // (1) mUnitCount: the number of slots we can fit into one column (or row). - // (2) mContentLength: the width (or height) we need to display all the - // columns (rows). - // (3) padding[]: the vertical and horizontal padding we need in order - // to put the slots towards to the center of the display. - // - // The "major" direction is the direction the user can scroll. The other - // direction is the "minor" direction. - // - // The comments inside this method are the description when the major - // directon is horizontal (X), and the minor directon is vertical (Y). - private void initLayoutParameters( - int majorLength, int minorLength, /* The view width and height */ - int majorUnitSize, int minorUnitSize, /* The slot width and height */ - int[] padding) { - int unitCount = (minorLength + mSlotGap) / (minorUnitSize + mSlotGap); - if (unitCount == 0) unitCount = 1; - mUnitCount = unitCount; - - // We put extra padding above and below the column. - int availableUnits = Math.min(mUnitCount, mSlotCount); - int usedMinorLength = availableUnits * minorUnitSize + - (availableUnits - 1) * mSlotGap; - padding[0] = (minorLength - usedMinorLength) / 2; - - // Then calculate how many columns we need for all slots. - int count = ((mSlotCount + mUnitCount - 1) / mUnitCount); - mContentLength = count * majorUnitSize + (count - 1) * mSlotGap; - - // If the content length is less then the screen width, put - // extra padding in left and right. - padding[1] = Math.max(0, (majorLength - mContentLength) / 2); - } - - private void initLayoutParameters() { - // Initialize mSlotWidth and mSlotHeight from mSpec - if (mSpec.slotWidth != -1) { - mSlotGap = 0; - mSlotWidth = mSpec.slotWidth; - mSlotHeight = mSpec.slotHeight; - } else { - int rows = (mWidth > mHeight) ? mSpec.rowsLand : mSpec.rowsPort; - mSlotGap = mSpec.slotGap; - mSlotHeight = Math.max(1, (mHeight - (rows - 1) * mSlotGap) / rows); - mSlotWidth = mSlotHeight - mSpec.slotHeightAdditional; - } - - if (mRenderer != null) { - mRenderer.onSlotSizeChanged(mSlotWidth, mSlotHeight); - } - - int[] padding = new int[2]; - if (WIDE) { - initLayoutParameters(mWidth, mHeight, mSlotWidth, mSlotHeight, padding); - mVerticalPadding.startAnimateTo(padding[0]); - mHorizontalPadding.startAnimateTo(padding[1]); - } else { - initLayoutParameters(mHeight, mWidth, mSlotHeight, mSlotWidth, padding); - mVerticalPadding.startAnimateTo(padding[1]); - mHorizontalPadding.startAnimateTo(padding[0]); - } - updateVisibleSlotRange(); - } - - public void setSize(int width, int height) { - mWidth = width; - mHeight = height; - initLayoutParameters(); - } - - private void updateVisibleSlotRange() { - int position = mScrollPosition; - - if (WIDE) { - int startCol = position / (mSlotWidth + mSlotGap); - int start = Math.max(0, mUnitCount * startCol); - int endCol = (position + mWidth + mSlotWidth + mSlotGap - 1) / - (mSlotWidth + mSlotGap); - int end = Math.min(mSlotCount, mUnitCount * endCol); - setVisibleRange(start, end); - } else { - int startRow = position / (mSlotHeight + mSlotGap); - int start = Math.max(0, mUnitCount * startRow); - int endRow = (position + mHeight + mSlotHeight + mSlotGap - 1) / - (mSlotHeight + mSlotGap); - int end = Math.min(mSlotCount, mUnitCount * endRow); - setVisibleRange(start, end); - } - } - - public void setScrollPosition(int position) { - if (mScrollPosition == position) return; - mScrollPosition = position; - updateVisibleSlotRange(); - } - - private void setVisibleRange(int start, int end) { - if (start == mVisibleStart && end == mVisibleEnd) return; - if (start < end) { - mVisibleStart = start; - mVisibleEnd = end; - } else { - mVisibleStart = mVisibleEnd = 0; - } - if (mRenderer != null) { - mRenderer.onVisibleRangeChanged(mVisibleStart, mVisibleEnd); - } - } - - public int getVisibleStart() { - return mVisibleStart; - } - - public int getVisibleEnd() { - return mVisibleEnd; - } - - public int getSlotIndexByPosition(float x, float y) { - int absoluteX = Math.round(x) + (WIDE ? mScrollPosition : 0); - int absoluteY = Math.round(y) + (WIDE ? 0 : mScrollPosition); - - absoluteX -= mHorizontalPadding.get(); - absoluteY -= mVerticalPadding.get(); - - if (absoluteX < 0 || absoluteY < 0) { - return INDEX_NONE; - } - - int columnIdx = absoluteX / (mSlotWidth + mSlotGap); - int rowIdx = absoluteY / (mSlotHeight + mSlotGap); - - if (!WIDE && columnIdx >= mUnitCount) { - return INDEX_NONE; - } - - if (WIDE && rowIdx >= mUnitCount) { - return INDEX_NONE; - } - - if (absoluteX % (mSlotWidth + mSlotGap) >= mSlotWidth) { - return INDEX_NONE; - } - - if (absoluteY % (mSlotHeight + mSlotGap) >= mSlotHeight) { - return INDEX_NONE; - } - - int index = WIDE - ? (columnIdx * mUnitCount + rowIdx) - : (rowIdx * mUnitCount + columnIdx); - - return index >= mSlotCount ? INDEX_NONE : index; - } - - public int getScrollLimit() { - int limit = WIDE ? mContentLength - mWidth : mContentLength - mHeight; - return limit <= 0 ? 0 : limit; - } - - public boolean advanceAnimation(long animTime) { - // use '|' to make sure both sides will be executed - return mVerticalPadding.calculate(animTime) | mHorizontalPadding.calculate(animTime); - } - } - - private class MyGestureListener implements GestureDetector.OnGestureListener { - private boolean isDown; - - // We call the listener's onDown() when our onShowPress() is called and - // call the listener's onUp() when we receive any further event. - @Override - public void onShowPress(MotionEvent e) { - GLRoot root = getGLRoot(); - root.lockRenderThread(); - try { - if (isDown) return; - int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY()); - if (index != INDEX_NONE) { - isDown = true; - mListener.onDown(index); - } - } finally { - root.unlockRenderThread(); - } - } - - private void cancelDown(boolean byLongPress) { - if (!isDown) return; - isDown = false; - mListener.onUp(byLongPress); - } - - @Override - public boolean onDown(MotionEvent e) { - return false; - } - - @Override - public boolean onFling(MotionEvent e1, - MotionEvent e2, float velocityX, float velocityY) { - cancelDown(false); - int scrollLimit = mLayout.getScrollLimit(); - if (scrollLimit == 0) return false; - float velocity = WIDE ? velocityX : velocityY; - mScroller.fling((int) -velocity, 0, scrollLimit); - if (mUIListener != null) mUIListener.onUserInteractionBegin(); - invalidate(); - return true; - } - - @Override - public boolean onScroll(MotionEvent e1, - MotionEvent e2, float distanceX, float distanceY) { - cancelDown(false); - float distance = WIDE ? distanceX : distanceY; - int overDistance = mScroller.startScroll( - Math.round(distance), 0, mLayout.getScrollLimit()); - if (mOverscrollEffect == OVERSCROLL_3D && overDistance != 0) { - mPaper.overScroll(overDistance); - } - invalidate(); - return true; - } - - @Override - public boolean onSingleTapUp(MotionEvent e) { - cancelDown(false); - if (mDownInScrolling) return true; - int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY()); - if (index != INDEX_NONE) mListener.onSingleTapUp(index); - return true; - } - - @Override - public void onLongPress(MotionEvent e) { - cancelDown(true); - if (mDownInScrolling) return; - lockRendering(); - try { - int index = mLayout.getSlotIndexByPosition(e.getX(), e.getY()); - if (index != INDEX_NONE) mListener.onLongTap(index); - } finally { - unlockRendering(); - } - } - } - - public void setStartIndex(int index) { - mStartIndex = index; - } - - // Return true if the layout parameters have been changed - public boolean setSlotCount(int slotCount) { - boolean changed = mLayout.setSlotCount(slotCount); - - // mStartIndex is applied the first time setSlotCount is called. - if (mStartIndex != INDEX_NONE) { - setCenterIndex(mStartIndex); - mStartIndex = INDEX_NONE; - } - // Reset the scroll position to avoid scrolling over the updated limit. - setScrollPosition(WIDE ? mScrollX : mScrollY); - return changed; - } - - public int getVisibleStart() { - return mLayout.getVisibleStart(); - } - - public int getVisibleEnd() { - return mLayout.getVisibleEnd(); - } - - public int getScrollX() { - return mScrollX; - } - - public int getScrollY() { - return mScrollY; - } - - public Rect getSlotRect(int slotIndex, GLView rootPane) { - // Get slot rectangle relative to this root pane. - Rect offset = new Rect(); - rootPane.getBoundsOf(this, offset); - Rect r = getSlotRect(slotIndex); - r.offset(offset.left - getScrollX(), - offset.top - getScrollY()); - return r; - } - - private static class IntegerAnimation extends Animation { - private int mTarget; - private int mCurrent = 0; - private int mFrom = 0; - private boolean mEnabled = false; - - public void setEnabled(boolean enabled) { - mEnabled = enabled; - } - - public void startAnimateTo(int target) { - if (!mEnabled) { - mTarget = mCurrent = target; - return; - } - if (target == mTarget) return; - - mFrom = mCurrent; - mTarget = target; - setDuration(180); - start(); - } - - public int get() { - return mCurrent; - } - - public int getTarget() { - return mTarget; - } - - @Override - protected void onCalculate(float progress) { - mCurrent = Math.round(mFrom + progress * (mTarget - mFrom)); - if (progress == 1f) mEnabled = false; - } - } -} diff --git a/src/com/android/gallery3d/ui/SynchronizedHandler.java b/src/com/android/gallery3d/ui/SynchronizedHandler.java deleted file mode 100644 index ba1035747..000000000 --- a/src/com/android/gallery3d/ui/SynchronizedHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.os.Handler; -import android.os.Message; - -import com.android.gallery3d.common.Utils; - -public class SynchronizedHandler extends Handler { - - private final GLRoot mRoot; - - public SynchronizedHandler(GLRoot root) { - mRoot = Utils.checkNotNull(root); - } - - @Override - public void dispatchMessage(Message message) { - mRoot.lockRenderThread(); - try { - super.dispatchMessage(message); - } finally { - mRoot.unlockRenderThread(); - } - } -} diff --git a/src/com/android/gallery3d/ui/TileImageView.java b/src/com/android/gallery3d/ui/TileImageView.java deleted file mode 100644 index 3185c7598..000000000 --- a/src/com/android/gallery3d/ui/TileImageView.java +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Point; -import android.graphics.Rect; -import android.graphics.RectF; -import android.support.v4.util.LongSparseArray; -import android.util.DisplayMetrics; -import android.util.FloatMath; -import android.view.WindowManager; - -import com.android.gallery3d.app.GalleryContext; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DecodeUtils; -import com.android.photos.data.GalleryBitmapPool; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.UploadedTexture; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.ThreadPool; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.concurrent.atomic.AtomicBoolean; - -public class TileImageView extends GLView { - public static final int SIZE_UNKNOWN = -1; - - @SuppressWarnings("unused") - private static final String TAG = "TileImageView"; - private static final int UPLOAD_LIMIT = 1; - - // TILE_SIZE must be 2^N - private static int sTileSize; - - /* - * This is the tile state in the CPU side. - * Life of a Tile: - * ACTIVATED (initial state) - * --> IN_QUEUE - by queueForDecode() - * --> RECYCLED - by recycleTile() - * IN_QUEUE --> DECODING - by decodeTile() - * --> RECYCLED - by recycleTile) - * DECODING --> RECYCLING - by recycleTile() - * --> DECODED - by decodeTile() - * --> DECODE_FAIL - by decodeTile() - * RECYCLING --> RECYCLED - by decodeTile() - * DECODED --> ACTIVATED - (after the decoded bitmap is uploaded) - * DECODED --> RECYCLED - by recycleTile() - * DECODE_FAIL -> RECYCLED - by recycleTile() - * RECYCLED --> ACTIVATED - by obtainTile() - */ - private static final int STATE_ACTIVATED = 0x01; - private static final int STATE_IN_QUEUE = 0x02; - private static final int STATE_DECODING = 0x04; - private static final int STATE_DECODED = 0x08; - private static final int STATE_DECODE_FAIL = 0x10; - private static final int STATE_RECYCLING = 0x20; - private static final int STATE_RECYCLED = 0x40; - - private TileSource mModel; - private ScreenNail mScreenNail; - protected int mLevelCount; // cache the value of mScaledBitmaps.length - - // The mLevel variable indicates which level of bitmap we should use. - // Level 0 means the original full-sized bitmap, and a larger value means - // a smaller scaled bitmap (The width and height of each scaled bitmap is - // half size of the previous one). If the value is in [0, mLevelCount), we - // use the bitmap in mScaledBitmaps[mLevel] for display, otherwise the value - // is mLevelCount, and that means we use mScreenNail for display. - private int mLevel = 0; - - // The offsets of the (left, top) of the upper-left tile to the (left, top) - // of the view. - private int mOffsetX; - private int mOffsetY; - - private int mUploadQuota; - private boolean mRenderComplete; - - private final RectF mSourceRect = new RectF(); - private final RectF mTargetRect = new RectF(); - - private final LongSparseArray<Tile> mActiveTiles = new LongSparseArray<Tile>(); - - // The following three queue is guarded by TileImageView.this - private final TileQueue mRecycledQueue = new TileQueue(); - private final TileQueue mUploadQueue = new TileQueue(); - private final TileQueue mDecodeQueue = new TileQueue(); - - // The width and height of the full-sized bitmap - protected int mImageWidth = SIZE_UNKNOWN; - protected int mImageHeight = SIZE_UNKNOWN; - - protected int mCenterX; - protected int mCenterY; - protected float mScale; - protected int mRotation; - - // Temp variables to avoid memory allocation - private final Rect mTileRange = new Rect(); - private final Rect mActiveRange[] = {new Rect(), new Rect()}; - - private final TileUploader mTileUploader = new TileUploader(); - private boolean mIsTextureFreed; - private Future<Void> mTileDecoder; - private final ThreadPool mThreadPool; - private boolean mBackgroundTileUploaded; - - public static interface TileSource { - public int getLevelCount(); - public ScreenNail getScreenNail(); - public int getImageWidth(); - public int getImageHeight(); - - // The tile returned by this method can be specified this way: Assuming - // the image size is (width, height), first take the intersection of (0, - // 0) - (width, height) and (x, y) - (x + tileSize, y + tileSize). If - // in extending the region, we found some part of the region are outside - // the image, those pixels are filled with black. - // - // If level > 0, it does the same operation on a down-scaled version of - // the original image (down-scaled by a factor of 2^level), but (x, y) - // still refers to the coordinate on the original image. - // - // The method would be called in another thread. - public Bitmap getTile(int level, int x, int y, int tileSize); - } - - public static boolean isHighResolution(Context context) { - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) - context.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(metrics); - return metrics.heightPixels > 2048 || metrics.widthPixels > 2048; - } - - public TileImageView(GalleryContext context) { - mThreadPool = context.getThreadPool(); - mTileDecoder = mThreadPool.submit(new TileDecoder()); - if (sTileSize == 0) { - if (isHighResolution(context.getAndroidContext())) { - sTileSize = 512 ; - } else { - sTileSize = 256; - } - } - } - - public void setModel(TileSource model) { - mModel = model; - if (model != null) notifyModelInvalidated(); - } - - public void setScreenNail(ScreenNail s) { - mScreenNail = s; - } - - public void notifyModelInvalidated() { - invalidateTiles(); - if (mModel == null) { - mScreenNail = null; - mImageWidth = 0; - mImageHeight = 0; - mLevelCount = 0; - } else { - setScreenNail(mModel.getScreenNail()); - mImageWidth = mModel.getImageWidth(); - mImageHeight = mModel.getImageHeight(); - mLevelCount = mModel.getLevelCount(); - } - layoutTiles(mCenterX, mCenterY, mScale, mRotation); - invalidate(); - } - - @Override - protected void onLayout( - boolean changeSize, int left, int top, int right, int bottom) { - super.onLayout(changeSize, left, top, right, bottom); - if (changeSize) layoutTiles(mCenterX, mCenterY, mScale, mRotation); - } - - // Prepare the tiles we want to use for display. - // - // 1. Decide the tile level we want to use for display. - // 2. Decide the tile levels we want to keep as texture (in addition to - // the one we use for display). - // 3. Recycle unused tiles. - // 4. Activate the tiles we want. - private void layoutTiles(int centerX, int centerY, float scale, int rotation) { - // The width and height of this view. - int width = getWidth(); - int height = getHeight(); - - // The tile levels we want to keep as texture is in the range - // [fromLevel, endLevel). - int fromLevel; - int endLevel; - - // We want to use a texture larger than or equal to the display size. - mLevel = Utils.clamp(Utils.floorLog2(1f / scale), 0, mLevelCount); - - // We want to keep one more tile level as texture in addition to what - // we use for display. So it can be faster when the scale moves to the - // next level. We choose a level closer to the current scale. - if (mLevel != mLevelCount) { - Rect range = mTileRange; - getRange(range, centerX, centerY, mLevel, scale, rotation); - mOffsetX = Math.round(width / 2f + (range.left - centerX) * scale); - mOffsetY = Math.round(height / 2f + (range.top - centerY) * scale); - fromLevel = scale * (1 << mLevel) > 0.75f ? mLevel - 1 : mLevel; - } else { - // Activate the tiles of the smallest two levels. - fromLevel = mLevel - 2; - mOffsetX = Math.round(width / 2f - centerX * scale); - mOffsetY = Math.round(height / 2f - centerY * scale); - } - - fromLevel = Math.max(0, Math.min(fromLevel, mLevelCount - 2)); - endLevel = Math.min(fromLevel + 2, mLevelCount); - - Rect range[] = mActiveRange; - for (int i = fromLevel; i < endLevel; ++i) { - getRange(range[i - fromLevel], centerX, centerY, i, rotation); - } - - // If rotation is transient, don't update the tile. - if (rotation % 90 != 0) return; - - synchronized (this) { - mDecodeQueue.clean(); - mUploadQueue.clean(); - mBackgroundTileUploaded = false; - - // Recycle unused tiles: if the level of the active tile is outside the - // range [fromLevel, endLevel) or not in the visible range. - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile tile = mActiveTiles.valueAt(i); - int level = tile.mTileLevel; - if (level < fromLevel || level >= endLevel - || !range[level - fromLevel].contains(tile.mX, tile.mY)) { - mActiveTiles.removeAt(i); - i--; - n--; - recycleTile(tile); - } - } - } - - for (int i = fromLevel; i < endLevel; ++i) { - int size = sTileSize << i; - Rect r = range[i - fromLevel]; - for (int y = r.top, bottom = r.bottom; y < bottom; y += size) { - for (int x = r.left, right = r.right; x < right; x += size) { - activateTile(x, y, i); - } - } - } - invalidate(); - } - - protected synchronized void invalidateTiles() { - mDecodeQueue.clean(); - mUploadQueue.clean(); - - // TODO disable decoder - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile tile = mActiveTiles.valueAt(i); - recycleTile(tile); - } - mActiveTiles.clear(); - } - - private void getRange(Rect out, int cX, int cY, int level, int rotation) { - getRange(out, cX, cY, level, 1f / (1 << (level + 1)), rotation); - } - - // If the bitmap is scaled by the given factor "scale", return the - // rectangle containing visible range. The left-top coordinate returned is - // aligned to the tile boundary. - // - // (cX, cY) is the point on the original bitmap which will be put in the - // center of the ImageViewer. - private void getRange(Rect out, - int cX, int cY, int level, float scale, int rotation) { - - double radians = Math.toRadians(-rotation); - double w = getWidth(); - double h = getHeight(); - - double cos = Math.cos(radians); - double sin = Math.sin(radians); - int width = (int) Math.ceil(Math.max( - Math.abs(cos * w - sin * h), Math.abs(cos * w + sin * h))); - int height = (int) Math.ceil(Math.max( - Math.abs(sin * w + cos * h), Math.abs(sin * w - cos * h))); - - int left = (int) FloatMath.floor(cX - width / (2f * scale)); - int top = (int) FloatMath.floor(cY - height / (2f * scale)); - int right = (int) FloatMath.ceil(left + width / scale); - int bottom = (int) FloatMath.ceil(top + height / scale); - - // align the rectangle to tile boundary - int size = sTileSize << level; - left = Math.max(0, size * (left / size)); - top = Math.max(0, size * (top / size)); - right = Math.min(mImageWidth, right); - bottom = Math.min(mImageHeight, bottom); - - out.set(left, top, right, bottom); - } - - // Calculate where the center of the image is, in the view coordinates. - public void getImageCenter(Point center) { - // The width and height of this view. - int viewW = getWidth(); - int viewH = getHeight(); - - // The distance between the center of the view to the center of the - // bitmap, in bitmap units. (mCenterX and mCenterY are the bitmap - // coordinates correspond to the center of view) - int distW, distH; - if (mRotation % 180 == 0) { - distW = mImageWidth / 2 - mCenterX; - distH = mImageHeight / 2 - mCenterY; - } else { - distW = mImageHeight / 2 - mCenterY; - distH = mImageWidth / 2 - mCenterX; - } - - // Convert to view coordinates. mScale translates from bitmap units to - // view units. - center.x = Math.round(viewW / 2f + distW * mScale); - center.y = Math.round(viewH / 2f + distH * mScale); - } - - public boolean setPosition(int centerX, int centerY, float scale, int rotation) { - if (mCenterX == centerX && mCenterY == centerY - && mScale == scale && mRotation == rotation) return false; - mCenterX = centerX; - mCenterY = centerY; - mScale = scale; - mRotation = rotation; - layoutTiles(centerX, centerY, scale, rotation); - invalidate(); - return true; - } - - public void freeTextures() { - mIsTextureFreed = true; - - if (mTileDecoder != null) { - mTileDecoder.cancel(); - mTileDecoder.get(); - mTileDecoder = null; - } - - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile texture = mActiveTiles.valueAt(i); - texture.recycle(); - } - mActiveTiles.clear(); - mTileRange.set(0, 0, 0, 0); - - synchronized (this) { - mUploadQueue.clean(); - mDecodeQueue.clean(); - Tile tile = mRecycledQueue.pop(); - while (tile != null) { - tile.recycle(); - tile = mRecycledQueue.pop(); - } - } - setScreenNail(null); - } - - public void prepareTextures() { - if (mTileDecoder == null) { - mTileDecoder = mThreadPool.submit(new TileDecoder()); - } - if (mIsTextureFreed) { - layoutTiles(mCenterX, mCenterY, mScale, mRotation); - mIsTextureFreed = false; - setScreenNail(mModel == null ? null : mModel.getScreenNail()); - } - } - - @Override - protected void render(GLCanvas canvas) { - mUploadQuota = UPLOAD_LIMIT; - mRenderComplete = true; - - int level = mLevel; - int rotation = mRotation; - int flags = 0; - if (rotation != 0) flags |= GLCanvas.SAVE_FLAG_MATRIX; - - if (flags != 0) { - canvas.save(flags); - if (rotation != 0) { - int centerX = getWidth() / 2, centerY = getHeight() / 2; - canvas.translate(centerX, centerY); - canvas.rotate(rotation, 0, 0, 1); - canvas.translate(-centerX, -centerY); - } - } - try { - if (level != mLevelCount && !isScreenNailAnimating()) { - if (mScreenNail != null) { - mScreenNail.noDraw(); - } - - int size = (sTileSize << level); - float length = size * mScale; - Rect r = mTileRange; - - for (int ty = r.top, i = 0; ty < r.bottom; ty += size, i++) { - float y = mOffsetY + i * length; - for (int tx = r.left, j = 0; tx < r.right; tx += size, j++) { - float x = mOffsetX + j * length; - drawTile(canvas, tx, ty, level, x, y, length); - } - } - } else if (mScreenNail != null) { - mScreenNail.draw(canvas, mOffsetX, mOffsetY, - Math.round(mImageWidth * mScale), - Math.round(mImageHeight * mScale)); - if (isScreenNailAnimating()) { - invalidate(); - } - } - } finally { - if (flags != 0) canvas.restore(); - } - - if (mRenderComplete) { - if (!mBackgroundTileUploaded) uploadBackgroundTiles(canvas); - } else { - invalidate(); - } - } - - private boolean isScreenNailAnimating() { - return (mScreenNail instanceof TiledScreenNail) - && ((TiledScreenNail) mScreenNail).isAnimating(); - } - - private void uploadBackgroundTiles(GLCanvas canvas) { - mBackgroundTileUploaded = true; - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile tile = mActiveTiles.valueAt(i); - if (!tile.isContentValid()) queueForDecode(tile); - } - } - - void queueForUpload(Tile tile) { - synchronized (this) { - mUploadQueue.push(tile); - } - if (mTileUploader.mActive.compareAndSet(false, true)) { - getGLRoot().addOnGLIdleListener(mTileUploader); - } - } - - synchronized void queueForDecode(Tile tile) { - if (tile.mTileState == STATE_ACTIVATED) { - tile.mTileState = STATE_IN_QUEUE; - if (mDecodeQueue.push(tile)) notifyAll(); - } - } - - boolean decodeTile(Tile tile) { - synchronized (this) { - if (tile.mTileState != STATE_IN_QUEUE) return false; - tile.mTileState = STATE_DECODING; - } - boolean decodeComplete = tile.decode(); - synchronized (this) { - if (tile.mTileState == STATE_RECYCLING) { - tile.mTileState = STATE_RECYCLED; - if (tile.mDecodedTile != null) { - GalleryBitmapPool.getInstance().put(tile.mDecodedTile); - tile.mDecodedTile = null; - } - mRecycledQueue.push(tile); - return false; - } - tile.mTileState = decodeComplete ? STATE_DECODED : STATE_DECODE_FAIL; - return decodeComplete; - } - } - - private synchronized Tile obtainTile(int x, int y, int level) { - Tile tile = mRecycledQueue.pop(); - if (tile != null) { - tile.mTileState = STATE_ACTIVATED; - tile.update(x, y, level); - return tile; - } - return new Tile(x, y, level); - } - - synchronized void recycleTile(Tile tile) { - if (tile.mTileState == STATE_DECODING) { - tile.mTileState = STATE_RECYCLING; - return; - } - tile.mTileState = STATE_RECYCLED; - if (tile.mDecodedTile != null) { - GalleryBitmapPool.getInstance().put(tile.mDecodedTile); - tile.mDecodedTile = null; - } - mRecycledQueue.push(tile); - } - - private void activateTile(int x, int y, int level) { - long key = makeTileKey(x, y, level); - Tile tile = mActiveTiles.get(key); - if (tile != null) { - if (tile.mTileState == STATE_IN_QUEUE) { - tile.mTileState = STATE_ACTIVATED; - } - return; - } - tile = obtainTile(x, y, level); - mActiveTiles.put(key, tile); - } - - private Tile getTile(int x, int y, int level) { - return mActiveTiles.get(makeTileKey(x, y, level)); - } - - private static long makeTileKey(int x, int y, int level) { - long result = x; - result = (result << 16) | y; - result = (result << 16) | level; - return result; - } - - private class TileUploader implements GLRoot.OnGLIdleListener { - AtomicBoolean mActive = new AtomicBoolean(false); - - @Override - public boolean onGLIdle(GLCanvas canvas, boolean renderRequested) { - // Skips uploading if there is a pending rendering request. - // Returns true to keep uploading in next rendering loop. - if (renderRequested) return true; - int quota = UPLOAD_LIMIT; - Tile tile = null; - while (quota > 0) { - synchronized (TileImageView.this) { - tile = mUploadQueue.pop(); - } - if (tile == null) break; - if (!tile.isContentValid()) { - boolean hasBeenLoaded = tile.isLoaded(); - Utils.assertTrue(tile.mTileState == STATE_DECODED); - tile.updateContent(canvas); - if (!hasBeenLoaded) tile.draw(canvas, 0, 0); - --quota; - } - } - if (tile == null) mActive.set(false); - return tile != null; - } - } - - // Draw the tile to a square at canvas that locates at (x, y) and - // has a side length of length. - public void drawTile(GLCanvas canvas, - int tx, int ty, int level, float x, float y, float length) { - RectF source = mSourceRect; - RectF target = mTargetRect; - target.set(x, y, x + length, y + length); - source.set(0, 0, sTileSize, sTileSize); - - Tile tile = getTile(tx, ty, level); - if (tile != null) { - if (!tile.isContentValid()) { - if (tile.mTileState == STATE_DECODED) { - if (mUploadQuota > 0) { - --mUploadQuota; - tile.updateContent(canvas); - } else { - mRenderComplete = false; - } - } else if (tile.mTileState != STATE_DECODE_FAIL){ - mRenderComplete = false; - queueForDecode(tile); - } - } - if (drawTile(tile, canvas, source, target)) return; - } - if (mScreenNail != null) { - int size = sTileSize << level; - float scaleX = (float) mScreenNail.getWidth() / mImageWidth; - float scaleY = (float) mScreenNail.getHeight() / mImageHeight; - source.set(tx * scaleX, ty * scaleY, (tx + size) * scaleX, - (ty + size) * scaleY); - mScreenNail.draw(canvas, source, target); - } - } - - static boolean drawTile( - Tile tile, GLCanvas canvas, RectF source, RectF target) { - while (true) { - if (tile.isContentValid()) { - canvas.drawTexture(tile, source, target); - return true; - } - - // Parent can be divided to four quads and tile is one of the four. - Tile parent = tile.getParentTile(); - if (parent == null) return false; - if (tile.mX == parent.mX) { - source.left /= 2f; - source.right /= 2f; - } else { - source.left = (sTileSize + source.left) / 2f; - source.right = (sTileSize + source.right) / 2f; - } - if (tile.mY == parent.mY) { - source.top /= 2f; - source.bottom /= 2f; - } else { - source.top = (sTileSize + source.top) / 2f; - source.bottom = (sTileSize + source.bottom) / 2f; - } - tile = parent; - } - } - - private class Tile extends UploadedTexture { - public int mX; - public int mY; - public int mTileLevel; - public Tile mNext; - public Bitmap mDecodedTile; - public volatile int mTileState = STATE_ACTIVATED; - - public Tile(int x, int y, int level) { - mX = x; - mY = y; - mTileLevel = level; - } - - @Override - protected void onFreeBitmap(Bitmap bitmap) { - GalleryBitmapPool.getInstance().put(bitmap); - } - - boolean decode() { - // Get a tile from the original image. The tile is down-scaled - // by (1 << mTilelevel) from a region in the original image. - try { - mDecodedTile = DecodeUtils.ensureGLCompatibleBitmap(mModel.getTile( - mTileLevel, mX, mY, sTileSize)); - } catch (Throwable t) { - Log.w(TAG, "fail to decode tile", t); - } - return mDecodedTile != null; - } - - @Override - protected Bitmap onGetBitmap() { - Utils.assertTrue(mTileState == STATE_DECODED); - - // We need to override the width and height, so that we won't - // draw beyond the boundaries. - int rightEdge = ((mImageWidth - mX) >> mTileLevel); - int bottomEdge = ((mImageHeight - mY) >> mTileLevel); - setSize(Math.min(sTileSize, rightEdge), Math.min(sTileSize, bottomEdge)); - - Bitmap bitmap = mDecodedTile; - mDecodedTile = null; - mTileState = STATE_ACTIVATED; - return bitmap; - } - - // We override getTextureWidth() and getTextureHeight() here, so the - // texture can be re-used for different tiles regardless of the actual - // size of the tile (which may be small because it is a tile at the - // boundary). - @Override - public int getTextureWidth() { - return sTileSize; - } - - @Override - public int getTextureHeight() { - return sTileSize; - } - - public void update(int x, int y, int level) { - mX = x; - mY = y; - mTileLevel = level; - invalidateContent(); - } - - public Tile getParentTile() { - if (mTileLevel + 1 == mLevelCount) return null; - int size = sTileSize << (mTileLevel + 1); - int x = size * (mX / size); - int y = size * (mY / size); - return getTile(x, y, mTileLevel + 1); - } - - @Override - public String toString() { - return String.format("tile(%s, %s, %s / %s)", - mX / sTileSize, mY / sTileSize, mLevel, mLevelCount); - } - } - - private static class TileQueue { - private Tile mHead; - - public Tile pop() { - Tile tile = mHead; - if (tile != null) mHead = tile.mNext; - return tile; - } - - public boolean push(Tile tile) { - boolean wasEmpty = mHead == null; - tile.mNext = mHead; - mHead = tile; - return wasEmpty; - } - - public void clean() { - mHead = null; - } - } - - private class TileDecoder implements ThreadPool.Job<Void> { - - private CancelListener mNotifier = new CancelListener() { - @Override - public void onCancel() { - synchronized (TileImageView.this) { - TileImageView.this.notifyAll(); - } - } - }; - - @Override - public Void run(JobContext jc) { - jc.setMode(ThreadPool.MODE_NONE); - jc.setCancelListener(mNotifier); - while (!jc.isCancelled()) { - Tile tile = null; - synchronized(TileImageView.this) { - tile = mDecodeQueue.pop(); - if (tile == null && !jc.isCancelled()) { - Utils.waitWithoutInterrupt(TileImageView.this); - } - } - if (tile == null) continue; - if (decodeTile(tile)) queueForUpload(tile); - } - return null; - } - } -} diff --git a/src/com/android/gallery3d/ui/TileImageViewAdapter.java b/src/com/android/gallery3d/ui/TileImageViewAdapter.java deleted file mode 100644 index 0c1f66d0c..000000000 --- a/src/com/android/gallery3d/ui/TileImageViewAdapter.java +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.annotation.TargetApi; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Canvas; -import android.graphics.Rect; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.common.Utils; -import com.android.photos.data.GalleryBitmapPool; - -public class TileImageViewAdapter implements TileImageView.TileSource { - private static final String TAG = "TileImageViewAdapter"; - protected ScreenNail mScreenNail; - protected boolean mOwnScreenNail; - protected BitmapRegionDecoder mRegionDecoder; - protected int mImageWidth; - protected int mImageHeight; - protected int mLevelCount; - - public TileImageViewAdapter() { - } - - public synchronized void clear() { - mScreenNail = null; - mImageWidth = 0; - mImageHeight = 0; - mLevelCount = 0; - mRegionDecoder = null; - } - - // Caller is responsible to recycle the ScreenNail - public synchronized void setScreenNail( - ScreenNail screenNail, int width, int height) { - Utils.checkNotNull(screenNail); - mScreenNail = screenNail; - mImageWidth = width; - mImageHeight = height; - mRegionDecoder = null; - mLevelCount = 0; - } - - public synchronized void setRegionDecoder(BitmapRegionDecoder decoder) { - mRegionDecoder = Utils.checkNotNull(decoder); - mImageWidth = decoder.getWidth(); - mImageHeight = decoder.getHeight(); - mLevelCount = calculateLevelCount(); - } - - private int calculateLevelCount() { - return Math.max(0, Utils.ceilLog2( - (float) mImageWidth / mScreenNail.getWidth())); - } - - // Gets a sub image on a rectangle of the current photo. For example, - // getTile(1, 50, 50, 100, 3, pool) means to get the region located - // at (50, 50) with sample level 1 (ie, down sampled by 2^1) and the - // target tile size (after sampling) 100 with border 3. - // - // From this spec, we can infer the actual tile size to be - // 100 + 3x2 = 106, and the size of the region to be extracted from the - // photo to be 200 with border 6. - // - // As a result, we should decode region (50-6, 50-6, 250+6, 250+6) or - // (44, 44, 256, 256) from the original photo and down sample it to 106. - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - @Override - public Bitmap getTile(int level, int x, int y, int tileSize) { - if (!ApiHelper.HAS_REUSING_BITMAP_IN_BITMAP_REGION_DECODER) { - return getTileWithoutReusingBitmap(level, x, y, tileSize); - } - - int t = tileSize << level; - - Rect wantRegion = new Rect(x, y, x + t, y + t); - - boolean needClear; - BitmapRegionDecoder regionDecoder = null; - - synchronized (this) { - regionDecoder = mRegionDecoder; - if (regionDecoder == null) return null; - - // We need to clear a reused bitmap, if wantRegion is not fully - // within the image. - needClear = !new Rect(0, 0, mImageWidth, mImageHeight) - .contains(wantRegion); - } - - Bitmap bitmap = GalleryBitmapPool.getInstance().get(tileSize, tileSize); - if (bitmap != null) { - if (needClear) bitmap.eraseColor(0); - } else { - bitmap = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888); - } - - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Config.ARGB_8888; - options.inPreferQualityOverSpeed = true; - options.inSampleSize = (1 << level); - options.inBitmap = bitmap; - - try { - // In CropImage, we may call the decodeRegion() concurrently. - synchronized (regionDecoder) { - bitmap = regionDecoder.decodeRegion(wantRegion, options); - } - } finally { - if (options.inBitmap != bitmap && options.inBitmap != null) { - GalleryBitmapPool.getInstance().put(options.inBitmap); - options.inBitmap = null; - } - } - - if (bitmap == null) { - Log.w(TAG, "fail in decoding region"); - } - return bitmap; - } - - private Bitmap getTileWithoutReusingBitmap( - int level, int x, int y, int tileSize) { - int t = tileSize << level; - Rect wantRegion = new Rect(x, y, x + t, y + t); - - BitmapRegionDecoder regionDecoder; - Rect overlapRegion; - - synchronized (this) { - regionDecoder = mRegionDecoder; - if (regionDecoder == null) return null; - overlapRegion = new Rect(0, 0, mImageWidth, mImageHeight); - Utils.assertTrue(overlapRegion.intersect(wantRegion)); - } - - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Config.ARGB_8888; - options.inPreferQualityOverSpeed = true; - options.inSampleSize = (1 << level); - Bitmap bitmap = null; - - // In CropImage, we may call the decodeRegion() concurrently. - synchronized (regionDecoder) { - bitmap = regionDecoder.decodeRegion(overlapRegion, options); - } - - if (bitmap == null) { - Log.w(TAG, "fail in decoding region"); - } - - if (wantRegion.equals(overlapRegion)) return bitmap; - - Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888); - Canvas canvas = new Canvas(result); - canvas.drawBitmap(bitmap, - (overlapRegion.left - wantRegion.left) >> level, - (overlapRegion.top - wantRegion.top) >> level, null); - return result; - } - - - @Override - public ScreenNail getScreenNail() { - return mScreenNail; - } - - @Override - public int getImageHeight() { - return mImageHeight; - } - - @Override - public int getImageWidth() { - return mImageWidth; - } - - @Override - public int getLevelCount() { - return mLevelCount; - } -} diff --git a/src/com/android/gallery3d/ui/TiledScreenNail.java b/src/com/android/gallery3d/ui/TiledScreenNail.java deleted file mode 100644 index 860e230bb..000000000 --- a/src/com/android/gallery3d/ui/TiledScreenNail.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.graphics.Bitmap; -import android.graphics.RectF; - -import com.android.gallery3d.common.Utils; -import com.android.photos.data.GalleryBitmapPool; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.TiledTexture; - -// This is a ScreenNail wraps a Bitmap. There are some extra functions: -// -// - If we need to draw before the bitmap is available, we draw a rectange of -// placeholder color (gray). -// -// - When the the bitmap is available, and we have drawn the placeholder color -// before, we will do a fade-in animation. -public class TiledScreenNail implements ScreenNail { - @SuppressWarnings("unused") - private static final String TAG = "TiledScreenNail"; - - // The duration of the fading animation in milliseconds - private static final int DURATION = 180; - - private static int sMaxSide = 640; - - // These are special values for mAnimationStartTime - private static final long ANIMATION_NOT_NEEDED = -1; - private static final long ANIMATION_NEEDED = -2; - private static final long ANIMATION_DONE = -3; - - private int mWidth; - private int mHeight; - private long mAnimationStartTime = ANIMATION_NOT_NEEDED; - - private Bitmap mBitmap; - private TiledTexture mTexture; - - public TiledScreenNail(Bitmap bitmap) { - mWidth = bitmap.getWidth(); - mHeight = bitmap.getHeight(); - mBitmap = bitmap; - mTexture = new TiledTexture(bitmap); - } - - public TiledScreenNail(int width, int height) { - setSize(width, height); - } - - // This gets overridden by bitmap_screennail_placeholder - // in GalleryUtils.initialize - private static int mPlaceholderColor = 0xFF222222; - private static boolean mDrawPlaceholder = true; - - public static void setPlaceholderColor(int color) { - mPlaceholderColor = color; - } - - private void setSize(int width, int height) { - if (width == 0 || height == 0) { - width = sMaxSide; - height = sMaxSide * 3 / 4; - } - float scale = Math.min(1, (float) sMaxSide / Math.max(width, height)); - mWidth = Math.round(scale * width); - mHeight = Math.round(scale * height); - } - - // Combines the two ScreenNails. - // Returns the used one and recycle the unused one. - public ScreenNail combine(ScreenNail other) { - if (other == null) { - return this; - } - - if (!(other instanceof TiledScreenNail)) { - recycle(); - return other; - } - - // Now both are TiledScreenNail. Move over the information about width, - // height, and Bitmap, then recycle the other. - TiledScreenNail newer = (TiledScreenNail) other; - mWidth = newer.mWidth; - mHeight = newer.mHeight; - if (newer.mTexture != null) { - if (mBitmap != null) GalleryBitmapPool.getInstance().put(mBitmap); - if (mTexture != null) mTexture.recycle(); - mBitmap = newer.mBitmap; - mTexture = newer.mTexture; - newer.mBitmap = null; - newer.mTexture = null; - } - newer.recycle(); - return this; - } - - public void updatePlaceholderSize(int width, int height) { - if (mBitmap != null) return; - if (width == 0 || height == 0) return; - setSize(width, height); - } - - @Override - public int getWidth() { - return mWidth; - } - - @Override - public int getHeight() { - return mHeight; - } - - @Override - public void noDraw() { - } - - @Override - public void recycle() { - if (mTexture != null) { - mTexture.recycle(); - mTexture = null; - } - if (mBitmap != null) { - GalleryBitmapPool.getInstance().put(mBitmap); - mBitmap = null; - } - } - - public static void disableDrawPlaceholder() { - mDrawPlaceholder = false; - } - - public static void enableDrawPlaceholder() { - mDrawPlaceholder = true; - } - - @Override - public void draw(GLCanvas canvas, int x, int y, int width, int height) { - if (mTexture == null || !mTexture.isReady()) { - if (mAnimationStartTime == ANIMATION_NOT_NEEDED) { - mAnimationStartTime = ANIMATION_NEEDED; - } - if(mDrawPlaceholder) { - canvas.fillRect(x, y, width, height, mPlaceholderColor); - } - return; - } - - if (mAnimationStartTime == ANIMATION_NEEDED) { - mAnimationStartTime = AnimationTime.get(); - } - - if (isAnimating()) { - mTexture.drawMixed(canvas, mPlaceholderColor, getRatio(), x, y, - width, height); - } else { - mTexture.draw(canvas, x, y, width, height); - } - } - - @Override - public void draw(GLCanvas canvas, RectF source, RectF dest) { - if (mTexture == null || !mTexture.isReady()) { - canvas.fillRect(dest.left, dest.top, dest.width(), dest.height(), - mPlaceholderColor); - return; - } - - mTexture.draw(canvas, source, dest); - } - - public boolean isAnimating() { - // The TiledTexture may not be uploaded completely yet. - // In that case, we count it as animating state and we will draw - // the placeholder in TileImageView. - if (mTexture == null || !mTexture.isReady()) return true; - if (mAnimationStartTime < 0) return false; - if (AnimationTime.get() - mAnimationStartTime >= DURATION) { - mAnimationStartTime = ANIMATION_DONE; - return false; - } - return true; - } - - private float getRatio() { - float r = (float) (AnimationTime.get() - mAnimationStartTime) / DURATION; - return Utils.clamp(1.0f - r, 0.0f, 1.0f); - } - - public boolean isShowingPlaceholder() { - return (mBitmap == null) || isAnimating(); - } - - public TiledTexture getTexture() { - return mTexture; - } - - public static void setMaxSide(int size) { - sMaxSide = size; - } -} diff --git a/src/com/android/gallery3d/ui/UndoBarView.java b/src/com/android/gallery3d/ui/UndoBarView.java deleted file mode 100644 index 42f12ae72..000000000 --- a/src/com/android/gallery3d/ui/UndoBarView.java +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.content.Context; -import android.view.MotionEvent; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.NinePatchTexture; -import com.android.gallery3d.glrenderer.ResourceTexture; -import com.android.gallery3d.glrenderer.StringTexture; -import com.android.gallery3d.util.GalleryUtils; - -public class UndoBarView extends GLView { - @SuppressWarnings("unused") - private static final String TAG = "UndoBarView"; - - private static final int WHITE = 0xFFFFFFFF; - private static final int GRAY = 0xFFAAAAAA; - - private final NinePatchTexture mPanel; - private final StringTexture mUndoText; - private final StringTexture mDeletedText; - private final ResourceTexture mUndoIcon; - private final int mBarHeight; - private final int mBarMargin; - private final int mUndoTextMargin; - private final int mIconSize; - private final int mIconMargin; - private final int mSeparatorTopMargin; - private final int mSeparatorBottomMargin; - private final int mSeparatorRightMargin; - private final int mSeparatorWidth; - private final int mDeletedTextMargin; - private final int mClickRegion; - - private OnClickListener mOnClickListener; - private boolean mDownOnButton; - - // This is the layout of UndoBarView. The unit is dp. - // - // +-+----+----------------+-+--+----+-+------+--+-+ - // 48 | | | Deleted | | | <- | | UNDO | | | - // +-+----+----------------+-+--+----+-+------+--+-+ - // 4 16 1 12 32 8 16 4 - public UndoBarView(Context context) { - mBarHeight = GalleryUtils.dpToPixel(48); - mBarMargin = GalleryUtils.dpToPixel(4); - mUndoTextMargin = GalleryUtils.dpToPixel(16); - mIconMargin = GalleryUtils.dpToPixel(8); - mIconSize = GalleryUtils.dpToPixel(32); - mSeparatorRightMargin = GalleryUtils.dpToPixel(12); - mSeparatorTopMargin = GalleryUtils.dpToPixel(10); - mSeparatorBottomMargin = GalleryUtils.dpToPixel(10); - mSeparatorWidth = GalleryUtils.dpToPixel(1); - mDeletedTextMargin = GalleryUtils.dpToPixel(16); - - mPanel = new NinePatchTexture(context, R.drawable.panel_undo_holo); - mUndoText = StringTexture.newInstance(context.getString(R.string.undo), - GalleryUtils.dpToPixel(12), GRAY, 0, true); - mDeletedText = StringTexture.newInstance( - context.getString(R.string.deleted), - GalleryUtils.dpToPixel(16), WHITE); - mUndoIcon = new ResourceTexture( - context, R.drawable.ic_menu_revert_holo_dark); - mClickRegion = mBarMargin + mUndoTextMargin + mUndoText.getWidth() - + mIconMargin + mIconSize + mSeparatorRightMargin; - } - - public void setOnClickListener(OnClickListener listener) { - mOnClickListener = listener; - } - - @Override - protected void onMeasure(int widthSpec, int heightSpec) { - setMeasuredSize(0 /* unused */, mBarHeight); - } - - @Override - protected void render(GLCanvas canvas) { - super.render(canvas); - advanceAnimation(); - - canvas.save(GLCanvas.SAVE_FLAG_ALPHA); - canvas.multiplyAlpha(mAlpha); - - int w = getWidth(); - int h = getHeight(); - mPanel.draw(canvas, mBarMargin, 0, w - mBarMargin * 2, mBarHeight); - - int x = w - mBarMargin; - int y; - - x -= mUndoTextMargin + mUndoText.getWidth(); - y = (mBarHeight - mUndoText.getHeight()) / 2; - mUndoText.draw(canvas, x, y); - - x -= mIconMargin + mIconSize; - y = (mBarHeight - mIconSize) / 2; - mUndoIcon.draw(canvas, x, y, mIconSize, mIconSize); - - x -= mSeparatorRightMargin + mSeparatorWidth; - y = mSeparatorTopMargin; - canvas.fillRect(x, y, mSeparatorWidth, - mBarHeight - mSeparatorTopMargin - mSeparatorBottomMargin, GRAY); - - x = mBarMargin + mDeletedTextMargin; - y = (mBarHeight - mDeletedText.getHeight()) / 2; - mDeletedText.draw(canvas, x, y); - - canvas.restore(); - } - - @Override - protected boolean onTouch(MotionEvent event) { - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - mDownOnButton = inUndoButton(event); - break; - case MotionEvent.ACTION_UP: - if (mDownOnButton) { - if (mOnClickListener != null && inUndoButton(event)) { - mOnClickListener.onClick(this); - } - mDownOnButton = false; - } - break; - case MotionEvent.ACTION_CANCEL: - mDownOnButton = false; - break; - } - return true; - } - - // Check if the event is on the right of the separator - private boolean inUndoButton(MotionEvent event) { - float x = event.getX(); - float y = event.getY(); - int w = getWidth(); - int h = getHeight(); - return (x >= w - mClickRegion && x < w && y >= 0 && y < h); - } - - //////////////////////////////////////////////////////////////////////////// - // Alpha Animation - //////////////////////////////////////////////////////////////////////////// - - private static final long NO_ANIMATION = -1; - private static long ANIM_TIME = 200; - private long mAnimationStartTime = NO_ANIMATION; - private float mFromAlpha, mToAlpha; - private float mAlpha; - - private static float getTargetAlpha(int visibility) { - return (visibility == VISIBLE) ? 1f : 0f; - } - - @Override - public void setVisibility(int visibility) { - mAlpha = getTargetAlpha(visibility); - mAnimationStartTime = NO_ANIMATION; - super.setVisibility(visibility); - invalidate(); - } - - public void animateVisibility(int visibility) { - float target = getTargetAlpha(visibility); - if (mAnimationStartTime == NO_ANIMATION && mAlpha == target) return; - if (mAnimationStartTime != NO_ANIMATION && mToAlpha == target) return; - - mFromAlpha = mAlpha; - mToAlpha = target; - mAnimationStartTime = AnimationTime.startTime(); - - super.setVisibility(VISIBLE); - invalidate(); - } - - private void advanceAnimation() { - if (mAnimationStartTime == NO_ANIMATION) return; - - float delta = (float) (AnimationTime.get() - mAnimationStartTime) / - ANIM_TIME; - mAlpha = mFromAlpha + ((mToAlpha > mFromAlpha) ? delta : -delta); - mAlpha = Utils.clamp(mAlpha, 0f, 1f); - - if (mAlpha == mToAlpha) { - mAnimationStartTime = NO_ANIMATION; - if (mAlpha == 0) { - super.setVisibility(INVISIBLE); - } - } - invalidate(); - } -} diff --git a/src/com/android/gallery3d/ui/UserInteractionListener.java b/src/com/android/gallery3d/ui/UserInteractionListener.java deleted file mode 100644 index bc4a71800..000000000 --- a/src/com/android/gallery3d/ui/UserInteractionListener.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -public interface UserInteractionListener { - // Called when a user interaction begins (for example, fling). - public void onUserInteractionBegin(); - // Called when the user interaction ends. - public void onUserInteractionEnd(); - // Other one-shot user interactions. - public void onUserInteraction(); -} diff --git a/src/com/android/gallery3d/ui/WakeLockHoldingProgressListener.java b/src/com/android/gallery3d/ui/WakeLockHoldingProgressListener.java deleted file mode 100644 index ee61d8edb..000000000 --- a/src/com/android/gallery3d/ui/WakeLockHoldingProgressListener.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.ui; - -import android.app.Activity; -import android.content.Context; -import android.os.PowerManager; - -import com.android.gallery3d.app.AbstractGalleryActivity; - -public class WakeLockHoldingProgressListener implements MenuExecutor.ProgressListener { - static private final String DEFAULT_WAKE_LOCK_LABEL = "Gallery Progress Listener"; - private AbstractGalleryActivity mActivity; - private PowerManager.WakeLock mWakeLock; - - public WakeLockHoldingProgressListener(AbstractGalleryActivity galleryActivity) { - this(galleryActivity, DEFAULT_WAKE_LOCK_LABEL); - } - - public WakeLockHoldingProgressListener(AbstractGalleryActivity galleryActivity, String label) { - mActivity = galleryActivity; - PowerManager pm = - (PowerManager) ((Activity) mActivity).getSystemService(Context.POWER_SERVICE); - mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK, label); - } - - @Override - public void onProgressComplete(int result) { - mWakeLock.release(); - } - - @Override - public void onProgressStart() { - mWakeLock.acquire(); - } - - protected AbstractGalleryActivity getActivity() { - return mActivity; - } - - @Override - public void onProgressUpdate(int index) { - } - - @Override - public void onConfirmDialogDismissed(boolean confirmed) { - } - - @Override - public void onConfirmDialogShown() { - } -} diff --git a/src/com/android/gallery3d/util/BucketNames.java b/src/com/android/gallery3d/util/BucketNames.java deleted file mode 100644 index 990dc8224..000000000 --- a/src/com/android/gallery3d/util/BucketNames.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -/** - * Bucket names for buckets that are created and used in the Gallery. - */ -public class BucketNames { - - public static final String CAMERA = "DCIM/Camera"; - public static final String IMPORTED = "Imported"; - public static final String DOWNLOAD = "download"; - public static final String EDITED_ONLINE_PHOTOS = "EditedOnlinePhotos"; - public static final String SCREENSHOTS = "Pictures/Screenshots"; -} diff --git a/src/com/android/gallery3d/util/CacheManager.java b/src/com/android/gallery3d/util/CacheManager.java deleted file mode 100644 index ba466f79b..000000000 --- a/src/com/android/gallery3d/util/CacheManager.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import android.content.Context; -import android.content.SharedPreferences; -import android.preference.PreferenceManager; - -import com.android.gallery3d.common.BlobCache; - -import java.io.File; -import java.io.IOException; -import java.util.HashMap; - -public class CacheManager { - private static final String TAG = "CacheManager"; - private static final String KEY_CACHE_UP_TO_DATE = "cache-up-to-date"; - private static HashMap<String, BlobCache> sCacheMap = - new HashMap<String, BlobCache>(); - private static boolean sOldCheckDone = false; - - // Return null when we cannot instantiate a BlobCache, e.g.: - // there is no SD card found. - // This can only be called from data thread. - public static BlobCache getCache(Context context, String filename, - int maxEntries, int maxBytes, int version) { - synchronized (sCacheMap) { - if (!sOldCheckDone) { - removeOldFilesIfNecessary(context); - sOldCheckDone = true; - } - BlobCache cache = sCacheMap.get(filename); - if (cache == null) { - File cacheDir = context.getExternalCacheDir(); - String path = cacheDir.getAbsolutePath() + "/" + filename; - try { - cache = new BlobCache(path, maxEntries, maxBytes, false, - version); - sCacheMap.put(filename, cache); - } catch (IOException e) { - Log.e(TAG, "Cannot instantiate cache!", e); - } - } - return cache; - } - } - - // Removes the old files if the data is wiped. - private static void removeOldFilesIfNecessary(Context context) { - SharedPreferences pref = PreferenceManager - .getDefaultSharedPreferences(context); - int n = 0; - try { - n = pref.getInt(KEY_CACHE_UP_TO_DATE, 0); - } catch (Throwable t) { - // ignore. - } - if (n != 0) return; - pref.edit().putInt(KEY_CACHE_UP_TO_DATE, 1).commit(); - - File cacheDir = context.getExternalCacheDir(); - String prefix = cacheDir.getAbsolutePath() + "/"; - - BlobCache.deleteFiles(prefix + "imgcache"); - BlobCache.deleteFiles(prefix + "rev_geocoding"); - BlobCache.deleteFiles(prefix + "bookmark"); - } -} diff --git a/src/com/android/gallery3d/util/GalleryUtils.java b/src/com/android/gallery3d/util/GalleryUtils.java deleted file mode 100644 index 9245e2c5f..000000000 --- a/src/com/android/gallery3d/util/GalleryUtils.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import android.annotation.TargetApi; -import android.content.ActivityNotFoundException; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.content.res.Resources; -import android.graphics.Color; -import android.net.Uri; -import android.os.ConditionVariable; -import android.os.Environment; -import android.os.StatFs; -import android.preference.PreferenceManager; -import android.provider.MediaStore; -import android.util.DisplayMetrics; -import android.util.Log; -import android.view.WindowManager; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.Gallery; -import com.android.gallery3d.app.PackagesMonitor; -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.ui.TiledScreenNail; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.io.File; -import java.util.Arrays; -import java.util.List; -import java.util.Locale; - -public class GalleryUtils { - private static final String TAG = "GalleryUtils"; - private static final String MAPS_PACKAGE_NAME = "com.google.android.apps.maps"; - private static final String MAPS_CLASS_NAME = "com.google.android.maps.MapsActivity"; - private static final String CAMERA_LAUNCHER_NAME = "com.android.camera.CameraLauncher"; - - public static final String MIME_TYPE_IMAGE = "image/*"; - public static final String MIME_TYPE_VIDEO = "video/*"; - public static final String MIME_TYPE_PANORAMA360 = "application/vnd.google.panorama360+jpg"; - public static final String MIME_TYPE_ALL = "*/*"; - - private static final String DIR_TYPE_IMAGE = "vnd.android.cursor.dir/image"; - private static final String DIR_TYPE_VIDEO = "vnd.android.cursor.dir/video"; - - private static final String PREFIX_PHOTO_EDITOR_UPDATE = "editor-update-"; - private static final String PREFIX_HAS_PHOTO_EDITOR = "has-editor-"; - - private static final String KEY_CAMERA_UPDATE = "camera-update"; - private static final String KEY_HAS_CAMERA = "has-camera"; - - private static float sPixelDensity = -1f; - private static boolean sCameraAvailableInitialized = false; - private static boolean sCameraAvailable; - - public static void initialize(Context context) { - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) - context.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(metrics); - sPixelDensity = metrics.density; - Resources r = context.getResources(); - TiledScreenNail.setPlaceholderColor(r.getColor( - R.color.bitmap_screennail_placeholder)); - initializeThumbnailSizes(metrics, r); - } - - private static void initializeThumbnailSizes(DisplayMetrics metrics, Resources r) { - int maxPixels = Math.max(metrics.heightPixels, metrics.widthPixels); - - // For screen-nails, we never need to completely fill the screen - MediaItem.setThumbnailSizes(maxPixels / 2, maxPixels / 5); - TiledScreenNail.setMaxSide(maxPixels / 2); - } - - public static float[] intColorToFloatARGBArray(int from) { - return new float[] { - Color.alpha(from) / 255f, - Color.red(from) / 255f, - Color.green(from) / 255f, - Color.blue(from) / 255f - }; - } - - public static float dpToPixel(float dp) { - return sPixelDensity * dp; - } - - public static int dpToPixel(int dp) { - return Math.round(dpToPixel((float) dp)); - } - - public static int meterToPixel(float meter) { - // 1 meter = 39.37 inches, 1 inch = 160 dp. - return Math.round(dpToPixel(meter * 39.37f * 160)); - } - - public static byte[] getBytes(String in) { - byte[] result = new byte[in.length() * 2]; - int output = 0; - for (char ch : in.toCharArray()) { - result[output++] = (byte) (ch & 0xFF); - result[output++] = (byte) (ch >> 8); - } - return result; - } - - // Below are used the detect using database in the render thread. It only - // works most of the time, but that's ok because it's for debugging only. - - private static volatile Thread sCurrentThread; - private static volatile boolean sWarned; - - public static void setRenderThread() { - sCurrentThread = Thread.currentThread(); - } - - public static void assertNotInRenderThread() { - if (!sWarned) { - if (Thread.currentThread() == sCurrentThread) { - sWarned = true; - Log.w(TAG, new Throwable("Should not do this in render thread")); - } - } - } - - private static final double RAD_PER_DEG = Math.PI / 180.0; - private static final double EARTH_RADIUS_METERS = 6367000.0; - - public static double fastDistanceMeters(double latRad1, double lngRad1, - double latRad2, double lngRad2) { - if ((Math.abs(latRad1 - latRad2) > RAD_PER_DEG) - || (Math.abs(lngRad1 - lngRad2) > RAD_PER_DEG)) { - return accurateDistanceMeters(latRad1, lngRad1, latRad2, lngRad2); - } - // Approximate sin(x) = x. - double sineLat = (latRad1 - latRad2); - - // Approximate sin(x) = x. - double sineLng = (lngRad1 - lngRad2); - - // Approximate cos(lat1) * cos(lat2) using - // cos((lat1 + lat2)/2) ^ 2 - double cosTerms = Math.cos((latRad1 + latRad2) / 2.0); - cosTerms = cosTerms * cosTerms; - double trigTerm = sineLat * sineLat + cosTerms * sineLng * sineLng; - trigTerm = Math.sqrt(trigTerm); - - // Approximate arcsin(x) = x - return EARTH_RADIUS_METERS * trigTerm; - } - - public static double accurateDistanceMeters(double lat1, double lng1, - double lat2, double lng2) { - double dlat = Math.sin(0.5 * (lat2 - lat1)); - double dlng = Math.sin(0.5 * (lng2 - lng1)); - double x = dlat * dlat + dlng * dlng * Math.cos(lat1) * Math.cos(lat2); - return (2 * Math.atan2(Math.sqrt(x), Math.sqrt(Math.max(0.0, - 1.0 - x)))) * EARTH_RADIUS_METERS; - } - - - public static final double toMile(double meter) { - return meter / 1609; - } - - // For debugging, it will block the caller for timeout millis. - public static void fakeBusy(JobContext jc, int timeout) { - final ConditionVariable cv = new ConditionVariable(); - jc.setCancelListener(new CancelListener() { - @Override - public void onCancel() { - cv.open(); - } - }); - cv.block(timeout); - jc.setCancelListener(null); - } - - public static boolean isEditorAvailable(Context context, String mimeType) { - int version = PackagesMonitor.getPackagesVersion(context); - - String updateKey = PREFIX_PHOTO_EDITOR_UPDATE + mimeType; - String hasKey = PREFIX_HAS_PHOTO_EDITOR + mimeType; - - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - if (prefs.getInt(updateKey, 0) != version) { - PackageManager packageManager = context.getPackageManager(); - List<ResolveInfo> infos = packageManager.queryIntentActivities( - new Intent(Intent.ACTION_EDIT).setType(mimeType), 0); - prefs.edit().putInt(updateKey, version) - .putBoolean(hasKey, !infos.isEmpty()) - .commit(); - } - - return prefs.getBoolean(hasKey, true); - } - - public static boolean isAnyCameraAvailable(Context context) { - int version = PackagesMonitor.getPackagesVersion(context); - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - if (prefs.getInt(KEY_CAMERA_UPDATE, 0) != version) { - PackageManager packageManager = context.getPackageManager(); - List<ResolveInfo> infos = packageManager.queryIntentActivities( - new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA), 0); - prefs.edit().putInt(KEY_CAMERA_UPDATE, version) - .putBoolean(KEY_HAS_CAMERA, !infos.isEmpty()) - .commit(); - } - return prefs.getBoolean(KEY_HAS_CAMERA, true); - } - - public static boolean isCameraAvailable(Context context) { - if (sCameraAvailableInitialized) return sCameraAvailable; - PackageManager pm = context.getPackageManager(); - ComponentName name = new ComponentName(context, CAMERA_LAUNCHER_NAME); - int state = pm.getComponentEnabledSetting(name); - sCameraAvailableInitialized = true; - sCameraAvailable = - (state == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT) - || (state == PackageManager.COMPONENT_ENABLED_STATE_ENABLED); - return sCameraAvailable; - } - - public static void startCameraActivity(Context context) { - Intent intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA) - .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP - | Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } - - public static void startGalleryActivity(Context context) { - Intent intent = new Intent(context, Gallery.class) - .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP - | Intent.FLAG_ACTIVITY_NEW_TASK); - context.startActivity(intent); - } - - public static boolean isValidLocation(double latitude, double longitude) { - // TODO: change || to && after we fix the default location issue - return (latitude != MediaItem.INVALID_LATLNG || longitude != MediaItem.INVALID_LATLNG); - } - - public static String formatLatitudeLongitude(String format, double latitude, - double longitude) { - // We need to specify the locale otherwise it may go wrong in some language - // (e.g. Locale.FRENCH) - return String.format(Locale.ENGLISH, format, latitude, longitude); - } - - public static void showOnMap(Context context, double latitude, double longitude) { - try { - // We don't use "geo:latitude,longitude" because it only centers - // the MapView to the specified location, but we need a marker - // for further operations (routing to/from). - // The q=(lat, lng) syntax is suggested by geo-team. - String uri = formatLatitudeLongitude("http://maps.google.com/maps?f=q&q=(%f,%f)", - latitude, longitude); - ComponentName compName = new ComponentName(MAPS_PACKAGE_NAME, - MAPS_CLASS_NAME); - Intent mapsIntent = new Intent(Intent.ACTION_VIEW, - Uri.parse(uri)).setComponent(compName); - context.startActivity(mapsIntent); - } catch (ActivityNotFoundException e) { - // Use the "geo intent" if no GMM is installed - Log.e(TAG, "GMM activity not found!", e); - String url = formatLatitudeLongitude("geo:%f,%f", latitude, longitude); - Intent mapsIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); - context.startActivity(mapsIntent); - } - } - - public static void setViewPointMatrix( - float matrix[], float x, float y, float z) { - // The matrix is - // -z, 0, x, 0 - // 0, -z, y, 0 - // 0, 0, 1, 0 - // 0, 0, 1, -z - Arrays.fill(matrix, 0, 16, 0); - matrix[0] = matrix[5] = matrix[15] = -z; - matrix[8] = x; - matrix[9] = y; - matrix[10] = matrix[11] = 1; - } - - public static int getBucketId(String path) { - return path.toLowerCase().hashCode(); - } - - // Return the local path that matches the given bucketId. If no match is - // found, return null - public static String searchDirForPath(File dir, int bucketId) { - File[] files = dir.listFiles(); - if (files != null) { - for (File file : files) { - if (file.isDirectory()) { - String path = file.getAbsolutePath(); - if (GalleryUtils.getBucketId(path) == bucketId) { - return path; - } else { - path = searchDirForPath(file, bucketId); - if (path != null) return path; - } - } - } - } - return null; - } - - // Returns a (localized) string for the given duration (in seconds). - public static String formatDuration(final Context context, int duration) { - int h = duration / 3600; - int m = (duration - h * 3600) / 60; - int s = duration - (h * 3600 + m * 60); - String durationValue; - if (h == 0) { - durationValue = String.format(context.getString(R.string.details_ms), m, s); - } else { - durationValue = String.format(context.getString(R.string.details_hms), h, m, s); - } - return durationValue; - } - - @TargetApi(ApiHelper.VERSION_CODES.HONEYCOMB) - public static int determineTypeBits(Context context, Intent intent) { - int typeBits = 0; - String type = intent.resolveType(context); - - if (MIME_TYPE_ALL.equals(type)) { - typeBits = DataManager.INCLUDE_ALL; - } else if (MIME_TYPE_IMAGE.equals(type) || - DIR_TYPE_IMAGE.equals(type)) { - typeBits = DataManager.INCLUDE_IMAGE; - } else if (MIME_TYPE_VIDEO.equals(type) || - DIR_TYPE_VIDEO.equals(type)) { - typeBits = DataManager.INCLUDE_VIDEO; - } else { - typeBits = DataManager.INCLUDE_ALL; - } - - if (ApiHelper.HAS_INTENT_EXTRA_LOCAL_ONLY) { - if (intent.getBooleanExtra(Intent.EXTRA_LOCAL_ONLY, false)) { - typeBits |= DataManager.INCLUDE_LOCAL_ONLY; - } - } - - return typeBits; - } - - public static int getSelectionModePrompt(int typeBits) { - if ((typeBits & DataManager.INCLUDE_VIDEO) != 0) { - return (typeBits & DataManager.INCLUDE_IMAGE) == 0 - ? R.string.select_video - : R.string.select_item; - } - return R.string.select_image; - } - - public static boolean hasSpaceForSize(long size) { - String state = Environment.getExternalStorageState(); - if (!Environment.MEDIA_MOUNTED.equals(state)) { - return false; - } - - String path = Environment.getExternalStorageDirectory().getPath(); - try { - StatFs stat = new StatFs(path); - return stat.getAvailableBlocks() * (long) stat.getBlockSize() > size; - } catch (Exception e) { - Log.i(TAG, "Fail to access external storage", e); - } - return false; - } - - public static boolean isPanorama(MediaItem item) { - if (item == null) return false; - int w = item.getWidth(); - int h = item.getHeight(); - return (h > 0 && w / h >= 2); - } -} diff --git a/src/com/android/gallery3d/util/Holder.java b/src/com/android/gallery3d/util/Holder.java deleted file mode 100644 index 0ce914c1d..000000000 --- a/src/com/android/gallery3d/util/Holder.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -public class Holder<T> { - private T mObject; - - public void set(T object) { - mObject = object; - } - - public T get() { - return mObject; - } -} diff --git a/src/com/android/gallery3d/util/IdentityCache.java b/src/com/android/gallery3d/util/IdentityCache.java deleted file mode 100644 index 3edc424a3..000000000 --- a/src/com/android/gallery3d/util/IdentityCache.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Set; - -public class IdentityCache<K, V> { - - private final HashMap<K, Entry<K, V>> mWeakMap = - new HashMap<K, Entry<K, V>>(); - private ReferenceQueue<V> mQueue = new ReferenceQueue<V>(); - - public IdentityCache() { - } - - private static class Entry<K, V> extends WeakReference<V> { - K mKey; - - public Entry(K key, V value, ReferenceQueue<V> queue) { - super(value, queue); - mKey = key; - } - } - - private void cleanUpWeakMap() { - Entry<K, V> entry = (Entry<K, V>) mQueue.poll(); - while (entry != null) { - mWeakMap.remove(entry.mKey); - entry = (Entry<K, V>) mQueue.poll(); - } - } - - public synchronized V put(K key, V value) { - cleanUpWeakMap(); - Entry<K, V> entry = mWeakMap.put( - key, new Entry<K, V>(key, value, mQueue)); - return entry == null ? null : entry.get(); - } - - public synchronized V get(K key) { - cleanUpWeakMap(); - Entry<K, V> entry = mWeakMap.get(key); - return entry == null ? null : entry.get(); - } - - // This is currently unused. - /* - public synchronized void clear() { - mWeakMap.clear(); - mQueue = new ReferenceQueue<V>(); - } - */ - - // This is for debugging only - public synchronized ArrayList<K> keys() { - Set<K> set = mWeakMap.keySet(); - ArrayList<K> result = new ArrayList<K>(set); - return result; - } -} diff --git a/src/com/android/gallery3d/util/IntArray.java b/src/com/android/gallery3d/util/IntArray.java deleted file mode 100644 index 2c4dc2c83..000000000 --- a/src/com/android/gallery3d/util/IntArray.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -public class IntArray { - private static final int INIT_CAPACITY = 8; - - private int mData[] = new int[INIT_CAPACITY]; - private int mSize = 0; - - public void add(int value) { - if (mData.length == mSize) { - int temp[] = new int[mSize + mSize]; - System.arraycopy(mData, 0, temp, 0, mSize); - mData = temp; - } - mData[mSize++] = value; - } - - public int removeLast() { - mSize--; - return mData[mSize]; - } - - public int size() { - return mSize; - } - - // For testing only - public int[] toArray(int[] result) { - if (result == null || result.length < mSize) { - result = new int[mSize]; - } - System.arraycopy(mData, 0, result, 0, mSize); - return result; - } - - public int[] getInternalArray() { - return mData; - } - - public void clear() { - mSize = 0; - if (mData.length != INIT_CAPACITY) mData = new int[INIT_CAPACITY]; - } -} diff --git a/src/com/android/gallery3d/util/InterruptableOutputStream.java b/src/com/android/gallery3d/util/InterruptableOutputStream.java deleted file mode 100644 index 1ab62ab98..000000000 --- a/src/com/android/gallery3d/util/InterruptableOutputStream.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import com.android.gallery3d.common.Utils; - -import java.io.IOException; -import java.io.InterruptedIOException; -import java.io.OutputStream; - -public class InterruptableOutputStream extends OutputStream { - - private static final int MAX_WRITE_BYTES = 4096; - - private OutputStream mOutputStream; - private volatile boolean mIsInterrupted = false; - - public InterruptableOutputStream(OutputStream outputStream) { - mOutputStream = Utils.checkNotNull(outputStream); - } - - @Override - public void write(int oneByte) throws IOException { - if (mIsInterrupted) throw new InterruptedIOException(); - mOutputStream.write(oneByte); - } - - @Override - public void write(byte[] buffer, int offset, int count) throws IOException { - int end = offset + count; - while (offset < end) { - if (mIsInterrupted) throw new InterruptedIOException(); - int bytesCount = Math.min(MAX_WRITE_BYTES, end - offset); - mOutputStream.write(buffer, offset, bytesCount); - offset += bytesCount; - } - } - - @Override - public void close() throws IOException { - mOutputStream.close(); - } - - @Override - public void flush() throws IOException { - if (mIsInterrupted) throw new InterruptedIOException(); - mOutputStream.flush(); - } - - public void interrupt() { - mIsInterrupted = true; - } -} diff --git a/src/com/android/gallery3d/util/JobLimiter.java b/src/com/android/gallery3d/util/JobLimiter.java deleted file mode 100644 index 42b754153..000000000 --- a/src/com/android/gallery3d/util/JobLimiter.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (C) 2011 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.util.ThreadPool.Job; -import com.android.gallery3d.util.ThreadPool.JobContext; - -import java.util.LinkedList; - -// Limit the number of concurrent jobs that has been submitted into a ThreadPool -@SuppressWarnings("rawtypes") -public class JobLimiter implements FutureListener { - private static final String TAG = "JobLimiter"; - - // State Transition: - // INIT -> DONE, CANCELLED - // DONE -> CANCELLED - private static final int STATE_INIT = 0; - private static final int STATE_DONE = 1; - private static final int STATE_CANCELLED = 2; - - private final LinkedList<JobWrapper<?>> mJobs = new LinkedList<JobWrapper<?>>(); - private final ThreadPool mPool; - private int mLimit; - - private static class JobWrapper<T> implements Future<T>, Job<T> { - private int mState = STATE_INIT; - private Job<T> mJob; - private Future<T> mDelegate; - private FutureListener<T> mListener; - private T mResult; - - public JobWrapper(Job<T> job, FutureListener<T> listener) { - mJob = job; - mListener = listener; - } - - public synchronized void setFuture(Future<T> future) { - if (mState != STATE_INIT) return; - mDelegate = future; - } - - @Override - public void cancel() { - FutureListener<T> listener = null; - synchronized (this) { - if (mState != STATE_DONE) { - listener = mListener; - mJob = null; - mListener = null; - if (mDelegate != null) { - mDelegate.cancel(); - mDelegate = null; - } - } - mState = STATE_CANCELLED; - mResult = null; - notifyAll(); - } - if (listener != null) listener.onFutureDone(this); - } - - @Override - public synchronized boolean isCancelled() { - return mState == STATE_CANCELLED; - } - - @Override - public boolean isDone() { - // Both CANCELLED AND DONE is considered as done - return mState != STATE_INIT; - } - - @Override - public synchronized T get() { - while (mState == STATE_INIT) { - // handle the interrupted exception of wait() - Utils.waitWithoutInterrupt(this); - } - return mResult; - } - - @Override - public void waitDone() { - get(); - } - - @Override - public T run(JobContext jc) { - Job<T> job = null; - synchronized (this) { - if (mState == STATE_CANCELLED) return null; - job = mJob; - } - T result = null; - try { - result = job.run(jc); - } catch (Throwable t) { - Log.w(TAG, "error executing job: " + job, t); - } - FutureListener<T> listener = null; - synchronized (this) { - if (mState == STATE_CANCELLED) return null; - mState = STATE_DONE; - listener = mListener; - mListener = null; - mJob = null; - mResult = result; - notifyAll(); - } - if (listener != null) listener.onFutureDone(this); - return result; - } - } - - public JobLimiter(ThreadPool pool, int limit) { - mPool = Utils.checkNotNull(pool); - mLimit = limit; - } - - public synchronized <T> Future<T> submit(Job<T> job, FutureListener<T> listener) { - JobWrapper<T> future = new JobWrapper<T>(Utils.checkNotNull(job), listener); - mJobs.addLast(future); - submitTasksIfAllowed(); - return future; - } - - @SuppressWarnings({"rawtypes", "unchecked"}) - private void submitTasksIfAllowed() { - while (mLimit > 0 && !mJobs.isEmpty()) { - JobWrapper wrapper = mJobs.removeFirst(); - if (!wrapper.isCancelled()) { - --mLimit; - wrapper.setFuture(mPool.submit(wrapper, this)); - } - } - } - - @Override - public synchronized void onFutureDone(Future future) { - ++mLimit; - submitTasksIfAllowed(); - } -} diff --git a/src/com/android/gallery3d/util/LinkedNode.java b/src/com/android/gallery3d/util/LinkedNode.java deleted file mode 100644 index 4cfc3cded..000000000 --- a/src/com/android/gallery3d/util/LinkedNode.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - - -public class LinkedNode { - private LinkedNode mPrev; - private LinkedNode mNext; - - public LinkedNode() { - mPrev = mNext = this; - } - - public void insert(LinkedNode node) { - node.mNext = mNext; - mNext.mPrev = node; - node.mPrev = this; - mNext = node; - } - - public void remove() { - if (mNext == this) throw new IllegalStateException(); - mPrev.mNext = mNext; - mNext.mPrev = mPrev; - mPrev = mNext = null; - } - - @SuppressWarnings("unchecked") - public static class List<T extends LinkedNode> { - private LinkedNode mHead = new LinkedNode(); - - public void insertLast(T node) { - mHead.mPrev.insert(node); - } - - public T getFirst() { - return (T) (mHead.mNext == mHead ? null : mHead.mNext); - } - - public T getLast() { - return (T) (mHead.mPrev == mHead ? null : mHead.mPrev); - } - - public T nextOf(T node) { - return (T) (node.mNext == mHead ? null : node.mNext); - } - - public T previousOf(T node) { - return (T) (node.mPrev == mHead ? null : node.mPrev); - } - - } - - public static <T extends LinkedNode> List<T> newList() { - return new List<T>(); - } -} diff --git a/src/com/android/gallery3d/util/Log.java b/src/com/android/gallery3d/util/Log.java deleted file mode 100644 index d7f8e85d0..000000000 --- a/src/com/android/gallery3d/util/Log.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -public class Log { - public static int v(String tag, String msg) { - return android.util.Log.v(tag, msg); - } - public static int v(String tag, String msg, Throwable tr) { - return android.util.Log.v(tag, msg, tr); - } - public static int d(String tag, String msg) { - return android.util.Log.d(tag, msg); - } - public static int d(String tag, String msg, Throwable tr) { - return android.util.Log.d(tag, msg, tr); - } - public static int i(String tag, String msg) { - return android.util.Log.i(tag, msg); - } - public static int i(String tag, String msg, Throwable tr) { - return android.util.Log.i(tag, msg, tr); - } - public static int w(String tag, String msg) { - return android.util.Log.w(tag, msg); - } - public static int w(String tag, String msg, Throwable tr) { - return android.util.Log.w(tag, msg, tr); - } - public static int w(String tag, Throwable tr) { - return android.util.Log.w(tag, tr); - } - public static int e(String tag, String msg) { - return android.util.Log.e(tag, msg); - } - public static int e(String tag, String msg, Throwable tr) { - return android.util.Log.e(tag, msg, tr); - } -} diff --git a/src/com/android/gallery3d/util/MediaSetUtils.java b/src/com/android/gallery3d/util/MediaSetUtils.java deleted file mode 100644 index 043800561..000000000 --- a/src/com/android/gallery3d/util/MediaSetUtils.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import android.os.Environment; - -import com.android.gallery3d.data.LocalAlbum; -import com.android.gallery3d.data.LocalMergeAlbum; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; - -import java.util.Comparator; - -public class MediaSetUtils { - public static final Comparator<MediaSet> NAME_COMPARATOR = new NameComparator(); - - public static final int CAMERA_BUCKET_ID = GalleryUtils.getBucketId( - Environment.getExternalStorageDirectory().toString() + "/" - + BucketNames.CAMERA); - public static final int DOWNLOAD_BUCKET_ID = GalleryUtils.getBucketId( - Environment.getExternalStorageDirectory().toString() + "/" - + BucketNames.DOWNLOAD); - public static final int EDITED_ONLINE_PHOTOS_BUCKET_ID = GalleryUtils.getBucketId( - Environment.getExternalStorageDirectory().toString() + "/" - + BucketNames.EDITED_ONLINE_PHOTOS); - public static final int IMPORTED_BUCKET_ID = GalleryUtils.getBucketId( - Environment.getExternalStorageDirectory().toString() + "/" - + BucketNames.IMPORTED); - public static final int SNAPSHOT_BUCKET_ID = GalleryUtils.getBucketId( - Environment.getExternalStorageDirectory().toString() + - "/" + BucketNames.SCREENSHOTS); - - private static final Path[] CAMERA_PATHS = { - Path.fromString("/local/all/" + CAMERA_BUCKET_ID), - Path.fromString("/local/image/" + CAMERA_BUCKET_ID), - Path.fromString("/local/video/" + CAMERA_BUCKET_ID)}; - - public static boolean isCameraSource(Path path) { - return CAMERA_PATHS[0] == path || CAMERA_PATHS[1] == path - || CAMERA_PATHS[2] == path; - } - - // Sort MediaSets by name - public static class NameComparator implements Comparator<MediaSet> { - @Override - public int compare(MediaSet set1, MediaSet set2) { - int result = set1.getName().compareToIgnoreCase(set2.getName()); - if (result != 0) return result; - return set1.getPath().toString().compareTo(set2.getPath().toString()); - } - } -} diff --git a/src/com/android/gallery3d/util/Profile.java b/src/com/android/gallery3d/util/Profile.java deleted file mode 100644 index 7ed72c90e..000000000 --- a/src/com/android/gallery3d/util/Profile.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import android.os.Handler; -import android.os.HandlerThread; -import android.os.Process; - -import java.util.ArrayList; -import java.util.Random; - -// The Profile class is used to collect profiling information for a thread. It -// samples stack traces for a thread periodically. enable() and disable() is -// used to enable and disable profiling for the calling thread. The profiling -// information can then be dumped to a file using the dumpToFile() method. -// -// The disableAll() method can be used to disable profiling for all threads and -// can be called in onPause() to ensure all profiling is disabled when an -// activity is paused. -public class Profile { - @SuppressWarnings("unused") - private static final String TAG = "Profile"; - private static final int NS_PER_MS = 1000000; - - // This is a watchdog entry for one thread. - // For every cycleTime period, we dump the stack of the thread. - private static class WatchEntry { - Thread thread; - - // Both are in milliseconds - int cycleTime; - int wakeTime; - - boolean isHolding; - ArrayList<String[]> holdingStacks = new ArrayList<String[]>(); - } - - // This is a watchdog thread which dumps stacks of other threads periodically. - private static Watchdog sWatchdog = new Watchdog(); - - private static class Watchdog { - private ArrayList<WatchEntry> mList = new ArrayList<WatchEntry>(); - private HandlerThread mHandlerThread; - private Handler mHandler; - private Runnable mProcessRunnable = new Runnable() { - @Override - public void run() { - synchronized (Watchdog.this) { - processList(); - } - } - }; - private Random mRandom = new Random(); - private ProfileData mProfileData = new ProfileData(); - - public Watchdog() { - mHandlerThread = new HandlerThread("Watchdog Handler", - Process.THREAD_PRIORITY_FOREGROUND); - mHandlerThread.start(); - mHandler = new Handler(mHandlerThread.getLooper()); - } - - public synchronized void addWatchEntry(Thread thread, int cycleTime) { - WatchEntry e = new WatchEntry(); - e.thread = thread; - e.cycleTime = cycleTime; - int firstDelay = 1 + mRandom.nextInt(cycleTime); - e.wakeTime = (int) (System.nanoTime() / NS_PER_MS) + firstDelay; - mList.add(e); - processList(); - } - - public synchronized void removeWatchEntry(Thread thread) { - for (int i = 0; i < mList.size(); i++) { - if (mList.get(i).thread == thread) { - mList.remove(i); - break; - } - } - processList(); - } - - public synchronized void removeAllWatchEntries() { - mList.clear(); - processList(); - } - - private void processList() { - mHandler.removeCallbacks(mProcessRunnable); - if (mList.size() == 0) return; - - int currentTime = (int) (System.nanoTime() / NS_PER_MS); - int nextWakeTime = 0; - - for (WatchEntry entry : mList) { - if (currentTime > entry.wakeTime) { - entry.wakeTime += entry.cycleTime; - Thread thread = entry.thread; - sampleStack(entry); - } - - if (entry.wakeTime > nextWakeTime) { - nextWakeTime = entry.wakeTime; - } - } - - long delay = nextWakeTime - currentTime; - mHandler.postDelayed(mProcessRunnable, delay); - } - - private void sampleStack(WatchEntry entry) { - Thread thread = entry.thread; - StackTraceElement[] stack = thread.getStackTrace(); - String[] lines = new String[stack.length]; - for (int i = 0; i < stack.length; i++) { - lines[i] = stack[i].toString(); - } - if (entry.isHolding) { - entry.holdingStacks.add(lines); - } else { - mProfileData.addSample(lines); - } - } - - private WatchEntry findEntry(Thread thread) { - for (int i = 0; i < mList.size(); i++) { - WatchEntry entry = mList.get(i); - if (entry.thread == thread) return entry; - } - return null; - } - - public synchronized void dumpToFile(String filename) { - mProfileData.dumpToFile(filename); - } - - public synchronized void reset() { - mProfileData.reset(); - } - - public synchronized void hold(Thread t) { - WatchEntry entry = findEntry(t); - - // This can happen if the profiling is disabled (probably from - // another thread). Same check is applied in commit() and drop() - // below. - if (entry == null) return; - - entry.isHolding = true; - } - - public synchronized void commit(Thread t) { - WatchEntry entry = findEntry(t); - if (entry == null) return; - ArrayList<String[]> stacks = entry.holdingStacks; - for (int i = 0; i < stacks.size(); i++) { - mProfileData.addSample(stacks.get(i)); - } - entry.isHolding = false; - entry.holdingStacks.clear(); - } - - public synchronized void drop(Thread t) { - WatchEntry entry = findEntry(t); - if (entry == null) return; - entry.isHolding = false; - entry.holdingStacks.clear(); - } - } - - // Enable profiling for the calling thread. Periodically (every cycleTimeInMs - // milliseconds) sample the stack trace of the calling thread. - public static void enable(int cycleTimeInMs) { - Thread t = Thread.currentThread(); - sWatchdog.addWatchEntry(t, cycleTimeInMs); - } - - // Disable profiling for the calling thread. - public static void disable() { - sWatchdog.removeWatchEntry(Thread.currentThread()); - } - - // Disable profiling for all threads. - public static void disableAll() { - sWatchdog.removeAllWatchEntries(); - } - - // Dump the profiling data to a file. - public static void dumpToFile(String filename) { - sWatchdog.dumpToFile(filename); - } - - // Reset the collected profiling data. - public static void reset() { - sWatchdog.reset(); - } - - // Hold the future samples coming from current thread until commit() or - // drop() is called, and those samples are recorded or ignored as a result. - // This must called after enable() to be effective. - public static void hold() { - sWatchdog.hold(Thread.currentThread()); - } - - public static void commit() { - sWatchdog.commit(Thread.currentThread()); - } - - public static void drop() { - sWatchdog.drop(Thread.currentThread()); - } -} diff --git a/src/com/android/gallery3d/util/ProfileData.java b/src/com/android/gallery3d/util/ProfileData.java deleted file mode 100644 index a1bb8e1e4..000000000 --- a/src/com/android/gallery3d/util/ProfileData.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import android.util.Log; - -import com.android.gallery3d.common.Utils; - -import java.io.DataOutputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Map.Entry; - -// ProfileData keeps profiling samples in a tree structure. -// The addSample() method adds a sample. The dumpToFile() method saves the data -// to a file. The reset() method clears all samples. -public class ProfileData { - @SuppressWarnings("unused") - private static final String TAG = "ProfileData"; - - private static class Node { - public int id; // this is the name of this node, mapped from mNameToId - public Node parent; - public int sampleCount; - public ArrayList<Node> children; - public Node(Node parent, int id) { - this.parent = parent; - this.id = id; - } - } - - private Node mRoot; - private int mNextId; - private HashMap<String, Integer> mNameToId; - private DataOutputStream mOut; - private byte mScratch[] = new byte[4]; // scratch space for writeInt() - - public ProfileData() { - mRoot = new Node(null, -1); // The id of the root node is unused. - mNameToId = new HashMap<String, Integer>(); - } - - public void reset() { - mRoot = new Node(null, -1); - mNameToId.clear(); - mNextId = 0; - } - - private int nameToId(String name) { - Integer id = mNameToId.get(name); - if (id == null) { - id = ++mNextId; // The tool doesn't want id=0, so we start from 1. - mNameToId.put(name, id); - } - return id; - } - - public void addSample(String[] stack) { - int[] ids = new int[stack.length]; - for (int i = 0; i < stack.length; i++) { - ids[i] = nameToId(stack[i]); - } - - Node node = mRoot; - for (int i = stack.length - 1; i >= 0; i--) { - if (node.children == null) { - node.children = new ArrayList<Node>(); - } - - int id = ids[i]; - ArrayList<Node> children = node.children; - int j; - for (j = 0; j < children.size(); j++) { - if (children.get(j).id == id) break; - } - if (j == children.size()) { - children.add(new Node(node, id)); - } - - node = children.get(j); - } - - node.sampleCount++; - } - - public void dumpToFile(String filename) { - try { - mOut = new DataOutputStream(new FileOutputStream(filename)); - // Start record - writeInt(0); - writeInt(3); - writeInt(1); - writeInt(20000); // Sampling period: 20ms - writeInt(0); - - // Samples - writeAllStacks(mRoot, 0); - - // End record - writeInt(0); - writeInt(1); - writeInt(0); - writeAllSymbols(); - } catch (IOException ex) { - Log.w("Failed to dump to file", ex); - } finally { - Utils.closeSilently(mOut); - } - } - - // Writes out one stack, consisting of N+2 words: - // first word: sample count - // second word: depth of the stack (N) - // N words: each word is the id of one address in the stack - private void writeOneStack(Node node, int depth) throws IOException { - writeInt(node.sampleCount); - writeInt(depth); - while (depth-- > 0) { - writeInt(node.id); - node = node.parent; - } - } - - private void writeAllStacks(Node node, int depth) throws IOException { - if (node.sampleCount > 0) { - writeOneStack(node, depth); - } - - ArrayList<Node> children = node.children; - if (children != null) { - for (int i = 0; i < children.size(); i++) { - writeAllStacks(children.get(i), depth + 1); - } - } - } - - // Writes out the symbol table. Each line is like: - // 0x17e java.util.ArrayList.isEmpty(ArrayList.java:319) - private void writeAllSymbols() throws IOException { - for (Entry<String, Integer> entry : mNameToId.entrySet()) { - mOut.writeBytes(String.format("0x%x %s\n", entry.getValue(), entry.getKey())); - } - } - - private void writeInt(int v) throws IOException { - mScratch[0] = (byte) v; - mScratch[1] = (byte) (v >> 8); - mScratch[2] = (byte) (v >> 16); - mScratch[3] = (byte) (v >> 24); - mOut.write(mScratch); - } -} diff --git a/src/com/android/gallery3d/util/RangeArray.java b/src/com/android/gallery3d/util/RangeArray.java deleted file mode 100644 index 8e61348a3..000000000 --- a/src/com/android/gallery3d/util/RangeArray.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -// This is an array whose index ranges from min to max (inclusive). -public class RangeArray<T> { - private T[] mData; - private int mOffset; - - public RangeArray(int min, int max) { - mData = (T[]) new Object[max - min + 1]; - mOffset = min; - } - - // Wraps around an existing array - public RangeArray(T[] src, int min, int max) { - if (max - min + 1 != src.length) { - throw new AssertionError(); - } - mData = src; - mOffset = min; - } - - public void put(int i, T object) { - mData[i - mOffset] = object; - } - - public T get(int i) { - return mData[i - mOffset]; - } - - public int indexOf(T object) { - for (int i = 0; i < mData.length; i++) { - if (mData[i] == object) return i + mOffset; - } - return Integer.MAX_VALUE; - } -} diff --git a/src/com/android/gallery3d/util/RangeBoolArray.java b/src/com/android/gallery3d/util/RangeBoolArray.java deleted file mode 100644 index 035fc40a4..000000000 --- a/src/com/android/gallery3d/util/RangeBoolArray.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -// This is an array whose index ranges from min to max (inclusive). -public class RangeBoolArray { - private boolean[] mData; - private int mOffset; - - public RangeBoolArray(int min, int max) { - mData = new boolean[max - min + 1]; - mOffset = min; - } - - // Wraps around an existing array - public RangeBoolArray(boolean[] src, int min, int max) { - mData = src; - mOffset = min; - } - - public void put(int i, boolean object) { - mData[i - mOffset] = object; - } - - public boolean get(int i) { - return mData[i - mOffset]; - } - - public int indexOf(boolean object) { - for (int i = 0; i < mData.length; i++) { - if (mData[i] == object) return i + mOffset; - } - return Integer.MAX_VALUE; - } -} diff --git a/src/com/android/gallery3d/util/RangeIntArray.java b/src/com/android/gallery3d/util/RangeIntArray.java deleted file mode 100644 index 9dbb99fac..000000000 --- a/src/com/android/gallery3d/util/RangeIntArray.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -// This is an array whose index ranges from min to max (inclusive). -public class RangeIntArray { - private int[] mData; - private int mOffset; - - public RangeIntArray(int min, int max) { - mData = new int[max - min + 1]; - mOffset = min; - } - - // Wraps around an existing array - public RangeIntArray(int[] src, int min, int max) { - mData = src; - mOffset = min; - } - - public void put(int i, int object) { - mData[i - mOffset] = object; - } - - public int get(int i) { - return mData[i - mOffset]; - } - - public int indexOf(int object) { - for (int i = 0; i < mData.length; i++) { - if (mData[i] == object) return i + mOffset; - } - return Integer.MAX_VALUE; - } -} diff --git a/src/com/android/gallery3d/util/ReverseGeocoder.java b/src/com/android/gallery3d/util/ReverseGeocoder.java deleted file mode 100644 index a8b26d9b5..000000000 --- a/src/com/android/gallery3d/util/ReverseGeocoder.java +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import android.content.Context; -import android.location.Address; -import android.location.Geocoder; -import android.location.Location; -import android.location.LocationManager; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; - -import com.android.gallery3d.common.BlobCache; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.util.List; -import java.util.Locale; - -public class ReverseGeocoder { - @SuppressWarnings("unused") - private static final String TAG = "ReverseGeocoder"; - public static final int EARTH_RADIUS_METERS = 6378137; - public static final int LAT_MIN = -90; - public static final int LAT_MAX = 90; - public static final int LON_MIN = -180; - public static final int LON_MAX = 180; - private static final int MAX_COUNTRY_NAME_LENGTH = 8; - // If two points are within 20 miles of each other, use - // "Around Palo Alto, CA" or "Around Mountain View, CA". - // instead of directly jumping to the next level and saying - // "California, US". - private static final int MAX_LOCALITY_MILE_RANGE = 20; - - private static final String GEO_CACHE_FILE = "rev_geocoding"; - private static final int GEO_CACHE_MAX_ENTRIES = 1000; - private static final int GEO_CACHE_MAX_BYTES = 500 * 1024; - private static final int GEO_CACHE_VERSION = 0; - - public static class SetLatLong { - // The latitude and longitude of the min latitude point. - public double mMinLatLatitude = LAT_MAX; - public double mMinLatLongitude; - // The latitude and longitude of the max latitude point. - public double mMaxLatLatitude = LAT_MIN; - public double mMaxLatLongitude; - // The latitude and longitude of the min longitude point. - public double mMinLonLatitude; - public double mMinLonLongitude = LON_MAX; - // The latitude and longitude of the max longitude point. - public double mMaxLonLatitude; - public double mMaxLonLongitude = LON_MIN; - } - - private Context mContext; - private Geocoder mGeocoder; - private BlobCache mGeoCache; - private ConnectivityManager mConnectivityManager; - private static Address sCurrentAddress; // last known address - - public ReverseGeocoder(Context context) { - mContext = context; - mGeocoder = new Geocoder(mContext); - mGeoCache = CacheManager.getCache(context, GEO_CACHE_FILE, - GEO_CACHE_MAX_ENTRIES, GEO_CACHE_MAX_BYTES, - GEO_CACHE_VERSION); - mConnectivityManager = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - } - - public String computeAddress(SetLatLong set) { - // The overall min and max latitudes and longitudes of the set. - double setMinLatitude = set.mMinLatLatitude; - double setMinLongitude = set.mMinLatLongitude; - double setMaxLatitude = set.mMaxLatLatitude; - double setMaxLongitude = set.mMaxLatLongitude; - if (Math.abs(set.mMaxLatLatitude - set.mMinLatLatitude) - < Math.abs(set.mMaxLonLongitude - set.mMinLonLongitude)) { - setMinLatitude = set.mMinLonLatitude; - setMinLongitude = set.mMinLonLongitude; - setMaxLatitude = set.mMaxLonLatitude; - setMaxLongitude = set.mMaxLonLongitude; - } - Address addr1 = lookupAddress(setMinLatitude, setMinLongitude, true); - Address addr2 = lookupAddress(setMaxLatitude, setMaxLongitude, true); - if (addr1 == null) - addr1 = addr2; - if (addr2 == null) - addr2 = addr1; - if (addr1 == null || addr2 == null) { - return null; - } - - // Get current location, we decide the granularity of the string based - // on this. - LocationManager locationManager = - (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE); - Location location = null; - List<String> providers = locationManager.getAllProviders(); - for (int i = 0; i < providers.size(); ++i) { - String provider = providers.get(i); - location = (provider != null) ? locationManager.getLastKnownLocation(provider) : null; - if (location != null) - break; - } - String currentCity = ""; - String currentAdminArea = ""; - String currentCountry = Locale.getDefault().getCountry(); - if (location != null) { - Address currentAddress = lookupAddress( - location.getLatitude(), location.getLongitude(), true); - if (currentAddress == null) { - currentAddress = sCurrentAddress; - } else { - sCurrentAddress = currentAddress; - } - if (currentAddress != null && currentAddress.getCountryCode() != null) { - currentCity = checkNull(currentAddress.getLocality()); - currentCountry = checkNull(currentAddress.getCountryCode()); - currentAdminArea = checkNull(currentAddress.getAdminArea()); - } - } - - String closestCommonLocation = null; - String addr1Locality = checkNull(addr1.getLocality()); - String addr2Locality = checkNull(addr2.getLocality()); - String addr1AdminArea = checkNull(addr1.getAdminArea()); - String addr2AdminArea = checkNull(addr2.getAdminArea()); - String addr1CountryCode = checkNull(addr1.getCountryCode()); - String addr2CountryCode = checkNull(addr2.getCountryCode()); - - if (currentCity.equals(addr1Locality) || currentCity.equals(addr2Locality)) { - String otherCity = currentCity; - if (currentCity.equals(addr1Locality)) { - otherCity = addr2Locality; - if (otherCity.length() == 0) { - otherCity = addr2AdminArea; - if (!currentCountry.equals(addr2CountryCode)) { - otherCity += " " + addr2CountryCode; - } - } - addr2Locality = addr1Locality; - addr2AdminArea = addr1AdminArea; - addr2CountryCode = addr1CountryCode; - } else { - otherCity = addr1Locality; - if (otherCity.length() == 0) { - otherCity = addr1AdminArea; - if (!currentCountry.equals(addr1CountryCode)) { - otherCity += " " + addr1CountryCode; - } - } - addr1Locality = addr2Locality; - addr1AdminArea = addr2AdminArea; - addr1CountryCode = addr2CountryCode; - } - closestCommonLocation = valueIfEqual(addr1.getAddressLine(0), addr2.getAddressLine(0)); - if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) { - if (!currentCity.equals(otherCity)) { - closestCommonLocation += " - " + otherCity; - } - return closestCommonLocation; - } - - // Compare thoroughfare (street address) next. - closestCommonLocation = valueIfEqual(addr1.getThoroughfare(), addr2.getThoroughfare()); - if (closestCommonLocation != null && !("null".equals(closestCommonLocation))) { - return closestCommonLocation; - } - } - - // Compare the locality. - closestCommonLocation = valueIfEqual(addr1Locality, addr2Locality); - if (closestCommonLocation != null && !("".equals(closestCommonLocation))) { - String adminArea = addr1AdminArea; - String countryCode = addr1CountryCode; - if (adminArea != null && adminArea.length() > 0) { - if (!countryCode.equals(currentCountry)) { - closestCommonLocation += ", " + adminArea + " " + countryCode; - } else { - closestCommonLocation += ", " + adminArea; - } - } - return closestCommonLocation; - } - - // If the admin area is the same as the current location, we hide it and - // instead show the city name. - if (currentAdminArea.equals(addr1AdminArea) && currentAdminArea.equals(addr2AdminArea)) { - if ("".equals(addr1Locality)) { - addr1Locality = addr2Locality; - } - if ("".equals(addr2Locality)) { - addr2Locality = addr1Locality; - } - if (!"".equals(addr1Locality)) { - if (addr1Locality.equals(addr2Locality)) { - closestCommonLocation = addr1Locality + ", " + currentAdminArea; - } else { - closestCommonLocation = addr1Locality + " - " + addr2Locality; - } - return closestCommonLocation; - } - } - - // Just choose one of the localities if within a MAX_LOCALITY_MILE_RANGE - // mile radius. - float[] distanceFloat = new float[1]; - Location.distanceBetween(setMinLatitude, setMinLongitude, - setMaxLatitude, setMaxLongitude, distanceFloat); - int distance = (int) GalleryUtils.toMile(distanceFloat[0]); - if (distance < MAX_LOCALITY_MILE_RANGE) { - // Try each of the points and just return the first one to have a - // valid address. - closestCommonLocation = getLocalityAdminForAddress(addr1, true); - if (closestCommonLocation != null) { - return closestCommonLocation; - } - closestCommonLocation = getLocalityAdminForAddress(addr2, true); - if (closestCommonLocation != null) { - return closestCommonLocation; - } - } - - // Check the administrative area. - closestCommonLocation = valueIfEqual(addr1AdminArea, addr2AdminArea); - if (closestCommonLocation != null && !("".equals(closestCommonLocation))) { - String countryCode = addr1CountryCode; - if (!countryCode.equals(currentCountry)) { - if (countryCode != null && countryCode.length() > 0) { - closestCommonLocation += " " + countryCode; - } - } - return closestCommonLocation; - } - - // Check the country codes. - closestCommonLocation = valueIfEqual(addr1CountryCode, addr2CountryCode); - if (closestCommonLocation != null && !("".equals(closestCommonLocation))) { - return closestCommonLocation; - } - // There is no intersection, let's choose a nicer name. - String addr1Country = addr1.getCountryName(); - String addr2Country = addr2.getCountryName(); - if (addr1Country == null) - addr1Country = addr1CountryCode; - if (addr2Country == null) - addr2Country = addr2CountryCode; - if (addr1Country == null || addr2Country == null) - return null; - if (addr1Country.length() > MAX_COUNTRY_NAME_LENGTH || addr2Country.length() > MAX_COUNTRY_NAME_LENGTH) { - closestCommonLocation = addr1CountryCode + " - " + addr2CountryCode; - } else { - closestCommonLocation = addr1Country + " - " + addr2Country; - } - return closestCommonLocation; - } - - private String checkNull(String locality) { - if (locality == null) - return ""; - if (locality.equals("null")) - return ""; - return locality; - } - - private String getLocalityAdminForAddress(final Address addr, final boolean approxLocation) { - if (addr == null) - return ""; - String localityAdminStr = addr.getLocality(); - if (localityAdminStr != null && !("null".equals(localityAdminStr))) { - if (approxLocation) { - // TODO: Uncomment these lines as soon as we may translations - // for Res.string.around. - // localityAdminStr = - // mContext.getResources().getString(Res.string.around) + " " + - // localityAdminStr; - } - String adminArea = addr.getAdminArea(); - if (adminArea != null && adminArea.length() > 0) { - localityAdminStr += ", " + adminArea; - } - return localityAdminStr; - } - return null; - } - - public Address lookupAddress(final double latitude, final double longitude, - boolean useCache) { - try { - long locationKey = (long) (((latitude + LAT_MAX) * 2 * LAT_MAX - + (longitude + LON_MAX)) * EARTH_RADIUS_METERS); - byte[] cachedLocation = null; - if (useCache && mGeoCache != null) { - cachedLocation = mGeoCache.lookup(locationKey); - } - Address address = null; - NetworkInfo networkInfo = mConnectivityManager.getActiveNetworkInfo(); - if (cachedLocation == null || cachedLocation.length == 0) { - if (networkInfo == null || !networkInfo.isConnected()) { - return null; - } - List<Address> addresses = mGeocoder.getFromLocation(latitude, longitude, 1); - if (!addresses.isEmpty()) { - address = addresses.get(0); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(bos); - Locale locale = address.getLocale(); - writeUTF(dos, locale.getLanguage()); - writeUTF(dos, locale.getCountry()); - writeUTF(dos, locale.getVariant()); - - writeUTF(dos, address.getThoroughfare()); - int numAddressLines = address.getMaxAddressLineIndex(); - dos.writeInt(numAddressLines); - for (int i = 0; i < numAddressLines; ++i) { - writeUTF(dos, address.getAddressLine(i)); - } - writeUTF(dos, address.getFeatureName()); - writeUTF(dos, address.getLocality()); - writeUTF(dos, address.getAdminArea()); - writeUTF(dos, address.getSubAdminArea()); - - writeUTF(dos, address.getCountryName()); - writeUTF(dos, address.getCountryCode()); - writeUTF(dos, address.getPostalCode()); - writeUTF(dos, address.getPhone()); - writeUTF(dos, address.getUrl()); - - dos.flush(); - if (mGeoCache != null) { - mGeoCache.insert(locationKey, bos.toByteArray()); - } - dos.close(); - } - } else { - // Parsing the address from the byte stream. - DataInputStream dis = new DataInputStream( - new ByteArrayInputStream(cachedLocation)); - String language = readUTF(dis); - String country = readUTF(dis); - String variant = readUTF(dis); - Locale locale = null; - if (language != null) { - if (country == null) { - locale = new Locale(language); - } else if (variant == null) { - locale = new Locale(language, country); - } else { - locale = new Locale(language, country, variant); - } - } - if (!locale.getLanguage().equals(Locale.getDefault().getLanguage())) { - dis.close(); - return lookupAddress(latitude, longitude, false); - } - address = new Address(locale); - - address.setThoroughfare(readUTF(dis)); - int numAddressLines = dis.readInt(); - for (int i = 0; i < numAddressLines; ++i) { - address.setAddressLine(i, readUTF(dis)); - } - address.setFeatureName(readUTF(dis)); - address.setLocality(readUTF(dis)); - address.setAdminArea(readUTF(dis)); - address.setSubAdminArea(readUTF(dis)); - - address.setCountryName(readUTF(dis)); - address.setCountryCode(readUTF(dis)); - address.setPostalCode(readUTF(dis)); - address.setPhone(readUTF(dis)); - address.setUrl(readUTF(dis)); - dis.close(); - } - return address; - } catch (Exception e) { - // Ignore. - } - return null; - } - - private String valueIfEqual(String a, String b) { - return (a != null && b != null && a.equalsIgnoreCase(b)) ? a : null; - } - - public static final void writeUTF(DataOutputStream dos, String string) throws IOException { - if (string == null) { - dos.writeUTF(""); - } else { - dos.writeUTF(string); - } - } - - public static final String readUTF(DataInputStream dis) throws IOException { - String retVal = dis.readUTF(); - if (retVal.length() == 0) - return null; - return retVal; - } -} diff --git a/src/com/android/gallery3d/util/SaveVideoFileInfo.java b/src/com/android/gallery3d/util/SaveVideoFileInfo.java deleted file mode 100644 index c7e5e8568..000000000 --- a/src/com/android/gallery3d/util/SaveVideoFileInfo.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import java.io.File; - -public class SaveVideoFileInfo { - public File mFile = null; - public String mFileName = null; - // This the full directory path. - public File mDirectory = null; - // This is just the folder's name. - public String mFolderName = null; - -} diff --git a/src/com/android/gallery3d/util/SaveVideoFileUtils.java b/src/com/android/gallery3d/util/SaveVideoFileUtils.java deleted file mode 100644 index 10c41de90..000000000 --- a/src/com/android/gallery3d/util/SaveVideoFileUtils.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.gallery3d.util; - -import android.content.ContentResolver; -import android.content.ContentValues; -import android.database.Cursor; -import android.media.MediaMetadataRetriever; -import android.net.Uri; -import android.os.Environment; -import android.provider.MediaStore.Video; -import android.provider.MediaStore.Video.VideoColumns; - -import com.android.gallery3d.filtershow.tools.SaveImage.ContentResolverQueryCallback; - -import java.io.File; -import java.sql.Date; -import java.text.SimpleDateFormat; - -public class SaveVideoFileUtils { - // This function can decide which folder to save the video file, and generate - // the needed information for the video file including filename. - public static SaveVideoFileInfo getDstMp4FileInfo(String fileNameFormat, - ContentResolver contentResolver, Uri uri, String defaultFolderName) { - SaveVideoFileInfo dstFileInfo = new SaveVideoFileInfo(); - // Use the default save directory if the source directory cannot be - // saved. - dstFileInfo.mDirectory = getSaveDirectory(contentResolver, uri); - if ((dstFileInfo.mDirectory == null) || !dstFileInfo.mDirectory.canWrite()) { - dstFileInfo.mDirectory = new File(Environment.getExternalStorageDirectory(), - BucketNames.DOWNLOAD); - dstFileInfo.mFolderName = defaultFolderName; - } else { - dstFileInfo.mFolderName = dstFileInfo.mDirectory.getName(); - } - dstFileInfo.mFileName = new SimpleDateFormat(fileNameFormat).format( - new Date(System.currentTimeMillis())); - - dstFileInfo.mFile = new File(dstFileInfo.mDirectory, dstFileInfo.mFileName + ".mp4"); - return dstFileInfo; - } - - private static void querySource(ContentResolver contentResolver, Uri uri, - String[] projection, ContentResolverQueryCallback callback) { - Cursor cursor = null; - try { - cursor = contentResolver.query(uri, projection, null, null, null); - if ((cursor != null) && cursor.moveToNext()) { - callback.onCursorResult(cursor); - } - } catch (Exception e) { - // Ignore error for lacking the data column from the source. - } finally { - if (cursor != null) { - cursor.close(); - } - } - } - - private static File getSaveDirectory(ContentResolver contentResolver, Uri uri) { - final File[] dir = new File[1]; - querySource(contentResolver, uri, - new String[] { VideoColumns.DATA }, - new ContentResolverQueryCallback() { - @Override - public void onCursorResult(Cursor cursor) { - dir[0] = new File(cursor.getString(0)).getParentFile(); - } - }); - return dir[0]; - } - - - /** - * Insert the content (saved file) with proper video properties. - */ - public static Uri insertContent(SaveVideoFileInfo mDstFileInfo, - ContentResolver contentResolver, Uri uri ) { - long nowInMs = System.currentTimeMillis(); - long nowInSec = nowInMs / 1000; - final ContentValues values = new ContentValues(13); - values.put(Video.Media.TITLE, mDstFileInfo.mFileName); - values.put(Video.Media.DISPLAY_NAME, mDstFileInfo.mFile.getName()); - values.put(Video.Media.MIME_TYPE, "video/mp4"); - values.put(Video.Media.DATE_TAKEN, nowInMs); - values.put(Video.Media.DATE_MODIFIED, nowInSec); - values.put(Video.Media.DATE_ADDED, nowInSec); - values.put(Video.Media.DATA, mDstFileInfo.mFile.getAbsolutePath()); - values.put(Video.Media.SIZE, mDstFileInfo.mFile.length()); - int durationMs = retriveVideoDurationMs(mDstFileInfo.mFile.getPath()); - values.put(Video.Media.DURATION, durationMs); - // Copy the data taken and location info from src. - String[] projection = new String[] { - VideoColumns.DATE_TAKEN, - VideoColumns.LATITUDE, - VideoColumns.LONGITUDE, - VideoColumns.RESOLUTION, - }; - - // Copy some info from the source file. - querySource(contentResolver, uri, projection, - new ContentResolverQueryCallback() { - @Override - public void onCursorResult(Cursor cursor) { - long timeTaken = cursor.getLong(0); - if (timeTaken > 0) { - values.put(Video.Media.DATE_TAKEN, timeTaken); - } - double latitude = cursor.getDouble(1); - double longitude = cursor.getDouble(2); - // TODO: Change || to && after the default location - // issue is - // fixed. - if ((latitude != 0f) || (longitude != 0f)) { - values.put(Video.Media.LATITUDE, latitude); - values.put(Video.Media.LONGITUDE, longitude); - } - values.put(Video.Media.RESOLUTION, cursor.getString(3)); - - } - }); - - return contentResolver.insert(Video.Media.EXTERNAL_CONTENT_URI, values); - } - - public static int retriveVideoDurationMs(String path) { - int durationMs = 0; - // Calculate the duration of the destination file. - MediaMetadataRetriever retriever = new MediaMetadataRetriever(); - retriever.setDataSource(path); - String duration = retriever.extractMetadata( - MediaMetadataRetriever.METADATA_KEY_DURATION); - if (duration != null) { - durationMs = Integer.parseInt(duration); - } - retriever.release(); - return durationMs; - } - -} diff --git a/src/com/android/gallery3d/util/UpdateHelper.java b/src/com/android/gallery3d/util/UpdateHelper.java deleted file mode 100644 index f76705d06..000000000 --- a/src/com/android/gallery3d/util/UpdateHelper.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.gallery3d.util; - -import com.android.gallery3d.common.Utils; - -public class UpdateHelper { - - private boolean mUpdated = false; - - public int update(int original, int update) { - if (original != update) { - mUpdated = true; - original = update; - } - return original; - } - - public long update(long original, long update) { - if (original != update) { - mUpdated = true; - original = update; - } - return original; - } - - public double update(double original, double update) { - if (original != update) { - mUpdated = true; - original = update; - } - return original; - } - - public <T> T update(T original, T update) { - if (!Utils.equals(original, update)) { - mUpdated = true; - original = update; - } - return original; - } - - public boolean isUpdated() { - return mUpdated; - } -} diff --git a/src/com/android/photos/AlbumActivity.java b/src/com/android/photos/AlbumActivity.java deleted file mode 100644 index c616b998b..000000000 --- a/src/com/android/photos/AlbumActivity.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.Activity; -import android.os.Bundle; - -public class AlbumActivity extends Activity implements MultiChoiceManager.Provider { - - public static final String KEY_ALBUM_URI = AlbumFragment.KEY_ALBUM_URI; - public static final String KEY_ALBUM_TITLE = AlbumFragment.KEY_ALBUM_TITLE; - - private MultiChoiceManager mMultiChoiceManager; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Bundle intentExtras = getIntent().getExtras(); - mMultiChoiceManager = new MultiChoiceManager(this); - if (savedInstanceState == null) { - AlbumFragment albumFragment = new AlbumFragment(); - mMultiChoiceManager.setDelegate(albumFragment); - albumFragment.setArguments(intentExtras); - getFragmentManager().beginTransaction().add(android.R.id.content, - albumFragment).commit(); - } - getActionBar().setTitle(intentExtras.getString(KEY_ALBUM_TITLE)); - } - - @Override - public MultiChoiceManager getMultiChoiceManager() { - return mMultiChoiceManager; - } -} diff --git a/src/com/android/photos/AlbumFragment.java b/src/com/android/photos/AlbumFragment.java deleted file mode 100644 index 406fd2a29..000000000 --- a/src/com/android/photos/AlbumFragment.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.LoaderManager.LoaderCallbacks; -import android.content.Context; -import android.content.Intent; -import android.content.Loader; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.GridView; -import android.widget.ImageView; -import android.widget.TextView; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.Gallery; -import com.android.photos.adapters.PhotoThumbnailAdapter; -import com.android.photos.data.PhotoSetLoader; -import com.android.photos.shims.LoaderCompatShim; -import com.android.photos.shims.MediaItemsLoader; -import com.android.photos.views.HeaderGridView; - -import java.util.ArrayList; - -public class AlbumFragment extends MultiSelectGridFragment implements LoaderCallbacks<Cursor> { - - protected static final String KEY_ALBUM_URI = "AlbumUri"; - protected static final String KEY_ALBUM_TITLE = "AlbumTitle"; - private static final int LOADER_ALBUM = 1; - - private LoaderCompatShim<Cursor> mLoaderCompatShim; - private PhotoThumbnailAdapter mAdapter; - private String mAlbumPath; - private String mAlbumTitle; - private View mHeaderView; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Context context = getActivity(); - mAdapter = new PhotoThumbnailAdapter(context); - Bundle args = getArguments(); - if (args != null) { - mAlbumPath = args.getString(KEY_ALBUM_URI, null); - mAlbumTitle = args.getString(KEY_ALBUM_TITLE, null); - } - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - getLoaderManager().initLoader(LOADER_ALBUM, null, this); - return inflater.inflate(R.layout.album_content, container, false); - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - // TODO: Remove once UI stabilizes - getGridView().setColumnWidth(MediaItemsLoader.getThumbnailSize()); - } - - private void updateHeaderView() { - if (mHeaderView == null) { - mHeaderView = LayoutInflater.from(getActivity()) - .inflate(R.layout.album_header, getGridView(), false); - ((HeaderGridView) getGridView()).addHeaderView(mHeaderView, null, false); - - // TODO remove this when the data model stabilizes - mHeaderView.setMinimumHeight(200); - } - ImageView iv = (ImageView) mHeaderView.findViewById(R.id.album_header_image); - TextView title = (TextView) mHeaderView.findViewById(R.id.album_header_title); - TextView subtitle = (TextView) mHeaderView.findViewById(R.id.album_header_subtitle); - title.setText(mAlbumTitle); - int count = mAdapter.getCount(); - subtitle.setText(getActivity().getResources().getQuantityString( - R.plurals.number_of_photos, count, count)); - if (count > 0) { - iv.setImageDrawable(mLoaderCompatShim.drawableForItem(mAdapter.getItem(0), null)); - } - } - - @Override - public void onGridItemClick(GridView g, View v, int position, long id) { - if (mLoaderCompatShim == null) { - // Not fully initialized yet, discard - return; - } - Cursor item = (Cursor) getItemAtPosition(position); - Uri uri = mLoaderCompatShim.uriForItem(item); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - intent.setClass(getActivity(), Gallery.class); - startActivity(intent); - } - - @Override - public Loader<Cursor> onCreateLoader(int id, Bundle args) { - // TODO: Switch to PhotoSetLoader - MediaItemsLoader loader = new MediaItemsLoader(getActivity(), mAlbumPath); - mLoaderCompatShim = loader; - mAdapter.setDrawableFactory(mLoaderCompatShim); - return loader; - } - - @Override - public void onLoadFinished(Loader<Cursor> loader, - Cursor data) { - mAdapter.swapCursor(data); - updateHeaderView(); - setAdapter(mAdapter); - } - - @Override - public void onLoaderReset(Loader<Cursor> loader) { - } - - @Override - public int getItemMediaType(Object item) { - return ((Cursor) item).getInt(PhotoSetLoader.INDEX_MEDIA_TYPE); - } - - @Override - public int getItemSupportedOperations(Object item) { - return ((Cursor) item).getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS); - } - - private ArrayList<Uri> mSubItemUriTemp = new ArrayList<Uri>(1); - @Override - public ArrayList<Uri> getSubItemUrisForItem(Object item) { - mSubItemUriTemp.clear(); - mSubItemUriTemp.add(mLoaderCompatShim.uriForItem((Cursor) item)); - return mSubItemUriTemp; - } - - @Override - public void deleteItemWithPath(Object itemPath) { - mLoaderCompatShim.deleteItemWithPath(itemPath); - } - - @Override - public Uri getItemUri(Object item) { - return mLoaderCompatShim.uriForItem((Cursor) item); - } - - @Override - public Object getPathForItem(Object item) { - return mLoaderCompatShim.getPathForItem((Cursor) item); - } -} diff --git a/src/com/android/photos/AlbumSetFragment.java b/src/com/android/photos/AlbumSetFragment.java deleted file mode 100644 index bc5289ee1..000000000 --- a/src/com/android/photos/AlbumSetFragment.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.LoaderManager.LoaderCallbacks; -import android.content.Context; -import android.content.Intent; -import android.content.Loader; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.provider.MediaStore.Files.FileColumns; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.GridView; - -import com.android.gallery3d.R; -import com.android.photos.adapters.AlbumSetCursorAdapter; -import com.android.photos.data.AlbumSetLoader; -import com.android.photos.shims.LoaderCompatShim; -import com.android.photos.shims.MediaSetLoader; - -import java.util.ArrayList; - - -public class AlbumSetFragment extends MultiSelectGridFragment implements LoaderCallbacks<Cursor> { - - private AlbumSetCursorAdapter mAdapter; - private LoaderCompatShim<Cursor> mLoaderCompatShim; - - private static final int LOADER_ALBUMSET = 1; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Context context = getActivity(); - mAdapter = new AlbumSetCursorAdapter(context); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View root = super.onCreateView(inflater, container, savedInstanceState); - getLoaderManager().initLoader(LOADER_ALBUMSET, null, this); - return root; - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - getGridView().setColumnWidth(getActivity().getResources() - .getDimensionPixelSize(R.dimen.album_set_item_width)); - } - - @Override - public Loader<Cursor> onCreateLoader(int id, Bundle args) { - // TODO: Switch to AlbumSetLoader - MediaSetLoader loader = new MediaSetLoader(getActivity()); - mAdapter.setDrawableFactory(loader); - mLoaderCompatShim = loader; - return loader; - } - - @Override - public void onLoadFinished(Loader<Cursor> loader, - Cursor data) { - mAdapter.swapCursor(data); - setAdapter(mAdapter); - } - - @Override - public void onLoaderReset(Loader<Cursor> loader) { - } - - @Override - public void onGridItemClick(GridView g, View v, int position, long id) { - if (mLoaderCompatShim == null) { - // Not fully initialized yet, discard - return; - } - Cursor item = (Cursor) getItemAtPosition(position); - Context context = getActivity(); - Intent intent = new Intent(context, AlbumActivity.class); - intent.putExtra(AlbumActivity.KEY_ALBUM_URI, - mLoaderCompatShim.getPathForItem(item).toString()); - intent.putExtra(AlbumActivity.KEY_ALBUM_TITLE, - item.getString(AlbumSetLoader.INDEX_TITLE)); - context.startActivity(intent); - } - - @Override - public int getItemMediaType(Object item) { - return FileColumns.MEDIA_TYPE_NONE; - } - - @Override - public int getItemSupportedOperations(Object item) { - return ((Cursor) item).getInt(AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS); - } - - @Override - public ArrayList<Uri> getSubItemUrisForItem(Object item) { - return mLoaderCompatShim.urisForSubItems((Cursor) item); - } - - @Override - public void deleteItemWithPath(Object itemPath) { - mLoaderCompatShim.deleteItemWithPath(itemPath); - } - - @Override - public Uri getItemUri(Object item) { - return mLoaderCompatShim.uriForItem((Cursor) item); - } - - @Override - public Object getPathForItem(Object item) { - return mLoaderCompatShim.getPathForItem((Cursor) item); - } -} diff --git a/src/com/android/photos/BitmapRegionTileSource.java b/src/com/android/photos/BitmapRegionTileSource.java deleted file mode 100644 index d7d52f67a..000000000 --- a/src/com/android/photos/BitmapRegionTileSource.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.graphics.BitmapRegionDecoder; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.os.Build; -import android.os.Build.VERSION_CODES; -import android.util.Log; - -import com.android.gallery3d.glrenderer.BasicTexture; -import com.android.gallery3d.glrenderer.BitmapTexture; -import com.android.photos.views.TiledImageRenderer; - -import java.io.IOException; - -/** - * A {@link com.android.photos.views.TiledImageRenderer.TileSource} using - * {@link BitmapRegionDecoder} to wrap a local file - */ -public class BitmapRegionTileSource implements TiledImageRenderer.TileSource { - - private static final String TAG = "BitmapRegionTileSource"; - - private static final boolean REUSE_BITMAP = - Build.VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN; - private static final int MAX_PREVIEW_SIZE = 1024; - - BitmapRegionDecoder mDecoder; - int mWidth; - int mHeight; - int mTileSize; - private BasicTexture mPreview; - private final int mRotation; - - // For use only by getTile - private Rect mWantRegion = new Rect(); - private Rect mOverlapRegion = new Rect(); - private BitmapFactory.Options mOptions; - private Canvas mCanvas; - - public BitmapRegionTileSource(Context context, String path, int previewSize, int rotation) { - mTileSize = TiledImageRenderer.suggestedTileSize(context); - mRotation = rotation; - try { - mDecoder = BitmapRegionDecoder.newInstance(path, true); - mWidth = mDecoder.getWidth(); - mHeight = mDecoder.getHeight(); - } catch (IOException e) { - Log.w("BitmapRegionTileSource", "ctor failed", e); - } - mOptions = new BitmapFactory.Options(); - mOptions.inPreferredConfig = Bitmap.Config.ARGB_8888; - mOptions.inPreferQualityOverSpeed = true; - mOptions.inTempStorage = new byte[16 * 1024]; - if (previewSize != 0) { - previewSize = Math.min(previewSize, MAX_PREVIEW_SIZE); - // Although this is the same size as the Bitmap that is likely already - // loaded, the lifecycle is different and interactions are on a different - // thread. Thus to simplify, this source will decode its own bitmap. - int sampleSize = (int) Math.ceil(Math.max( - mWidth / (float) previewSize, mHeight / (float) previewSize)); - mOptions.inSampleSize = Math.max(sampleSize, 1); - Bitmap preview = mDecoder.decodeRegion( - new Rect(0, 0, mWidth, mHeight), mOptions); - if (preview.getWidth() <= MAX_PREVIEW_SIZE && preview.getHeight() <= MAX_PREVIEW_SIZE) { - mPreview = new BitmapTexture(preview); - } else { - Log.w(TAG, String.format( - "Failed to create preview of apropriate size! " - + " in: %dx%d, sample: %d, out: %dx%d", - mWidth, mHeight, sampleSize, - preview.getWidth(), preview.getHeight())); - } - } - } - - @Override - public int getTileSize() { - return mTileSize; - } - - @Override - public int getImageWidth() { - return mWidth; - } - - @Override - public int getImageHeight() { - return mHeight; - } - - @Override - public BasicTexture getPreview() { - return mPreview; - } - - @Override - public int getRotation() { - return mRotation; - } - - @Override - public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { - int tileSize = getTileSize(); - if (!REUSE_BITMAP) { - return getTileWithoutReusingBitmap(level, x, y, tileSize); - } - - int t = tileSize << level; - mWantRegion.set(x, y, x + t, y + t); - - if (bitmap == null) { - bitmap = Bitmap.createBitmap(tileSize, tileSize, Bitmap.Config.ARGB_8888); - } - - mOptions.inSampleSize = (1 << level); - mOptions.inBitmap = bitmap; - - try { - bitmap = mDecoder.decodeRegion(mWantRegion, mOptions); - } finally { - if (mOptions.inBitmap != bitmap && mOptions.inBitmap != null) { - mOptions.inBitmap = null; - } - } - - if (bitmap == null) { - Log.w("BitmapRegionTileSource", "fail in decoding region"); - } - return bitmap; - } - - private Bitmap getTileWithoutReusingBitmap( - int level, int x, int y, int tileSize) { - - int t = tileSize << level; - mWantRegion.set(x, y, x + t, y + t); - - mOverlapRegion.set(0, 0, mWidth, mHeight); - - mOptions.inSampleSize = (1 << level); - Bitmap bitmap = mDecoder.decodeRegion(mOverlapRegion, mOptions); - - if (bitmap == null) { - Log.w(TAG, "fail in decoding region"); - } - - if (mWantRegion.equals(mOverlapRegion)) { - return bitmap; - } - - Bitmap result = Bitmap.createBitmap(tileSize, tileSize, Config.ARGB_8888); - if (mCanvas == null) { - mCanvas = new Canvas(); - } - mCanvas.setBitmap(result); - mCanvas.drawBitmap(bitmap, - (mOverlapRegion.left - mWantRegion.left) >> level, - (mOverlapRegion.top - mWantRegion.top) >> level, null); - mCanvas.setBitmap(null); - return result; - } -} diff --git a/src/com/android/photos/FullscreenViewer.java b/src/com/android/photos/FullscreenViewer.java deleted file mode 100644 index a3761395e..000000000 --- a/src/com/android/photos/FullscreenViewer.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.Activity; -import android.os.Bundle; -import com.android.photos.views.TiledImageView; - - -public class FullscreenViewer extends Activity { - - private TiledImageView mTextureView; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - String path = getIntent().getData().toString(); - mTextureView = new TiledImageView(this); - mTextureView.setTileSource(new BitmapRegionTileSource(this, path, 0, 0), null); - setContentView(mTextureView); - } - - @Override - protected void onDestroy() { - super.onDestroy(); - mTextureView.destroy(); - } - -} diff --git a/src/com/android/photos/GalleryActivity.java b/src/com/android/photos/GalleryActivity.java deleted file mode 100644 index 710767d77..000000000 --- a/src/com/android/photos/GalleryActivity.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.ActionBar; -import android.app.ActionBar.Tab; -import android.app.Activity; -import android.app.Fragment; -import android.app.FragmentTransaction; -import android.content.Intent; -import android.os.Bundle; -import android.support.v13.app.FragmentPagerAdapter; -import android.support.v4.view.ViewPager; -import android.view.Menu; -import android.view.MenuItem; -import android.view.ViewGroup; - -import com.android.camera.CameraActivity; -import com.android.gallery3d.R; - -import java.util.ArrayList; - -public class GalleryActivity extends Activity implements MultiChoiceManager.Provider { - - private MultiChoiceManager mMultiChoiceManager; - private ViewPager mViewPager; - private TabsAdapter mTabsAdapter; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - mMultiChoiceManager = new MultiChoiceManager(this); - mViewPager = new ViewPager(this); - mViewPager.setId(R.id.viewpager); - setContentView(mViewPager); - - ActionBar ab = getActionBar(); - ab.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); - ab.setDisplayShowHomeEnabled(false); - ab.setDisplayShowTitleEnabled(false); - - mTabsAdapter = new TabsAdapter(this, mViewPager); - mTabsAdapter.addTab(ab.newTab().setText(R.string.tab_photos), - PhotoSetFragment.class, null); - mTabsAdapter.addTab(ab.newTab().setText(R.string.tab_albums), - AlbumSetFragment.class, null); - - if (savedInstanceState != null) { - ab.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0)); - } - } - - @Override - protected void onSaveInstanceState(Bundle outState) { - super.onSaveInstanceState(outState); - outState.putInt("tab", getActionBar().getSelectedNavigationIndex()); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.gallery, menu); - return true; - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_camera: - Intent intent = new Intent(this, CameraActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - startActivity(intent); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - public static class TabsAdapter extends FragmentPagerAdapter implements - ActionBar.TabListener, ViewPager.OnPageChangeListener { - - private final GalleryActivity mActivity; - private final ActionBar mActionBar; - private final ViewPager mViewPager; - private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); - - static final class TabInfo { - - private final Class<?> clss; - private final Bundle args; - - TabInfo(Class<?> _class, Bundle _args) { - clss = _class; - args = _args; - } - } - - public TabsAdapter(GalleryActivity activity, ViewPager pager) { - super(activity.getFragmentManager()); - mActivity = activity; - mActionBar = activity.getActionBar(); - mViewPager = pager; - mViewPager.setAdapter(this); - mViewPager.setOnPageChangeListener(this); - } - - public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) { - TabInfo info = new TabInfo(clss, args); - tab.setTag(info); - tab.setTabListener(this); - mTabs.add(info); - mActionBar.addTab(tab); - notifyDataSetChanged(); - } - - @Override - public int getCount() { - return mTabs.size(); - } - - @Override - public Fragment getItem(int position) { - TabInfo info = mTabs.get(position); - return Fragment.instantiate(mActivity, info.clss.getName(), - info.args); - } - - @Override - public void onPageScrolled(int position, float positionOffset, - int positionOffsetPixels) { - } - - @Override - public void onPageSelected(int position) { - mActionBar.setSelectedNavigationItem(position); - } - - @Override - public void setPrimaryItem(ViewGroup container, int position, Object object) { - super.setPrimaryItem(container, position, object); - mActivity.mMultiChoiceManager.setDelegate((MultiChoiceManager.Delegate) object); - } - - @Override - public void onPageScrollStateChanged(int state) { - } - - @Override - public void onTabSelected(Tab tab, FragmentTransaction ft) { - Object tag = tab.getTag(); - for (int i = 0; i < mTabs.size(); i++) { - if (mTabs.get(i) == tag) { - mViewPager.setCurrentItem(i); - } - } - } - - @Override - public void onTabUnselected(Tab tab, FragmentTransaction ft) { - } - - @Override - public void onTabReselected(Tab tab, FragmentTransaction ft) { - } - } - - @Override - public MultiChoiceManager getMultiChoiceManager() { - return mMultiChoiceManager; - } -} diff --git a/src/com/android/photos/MultiChoiceManager.java b/src/com/android/photos/MultiChoiceManager.java deleted file mode 100644 index 49519ca63..000000000 --- a/src/com/android/photos/MultiChoiceManager.java +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.Activity; -import android.content.Context; -import android.content.Intent; -import android.net.Uri; -import android.os.AsyncTask; -import android.provider.MediaStore.Files.FileColumns; -import android.util.SparseBooleanArray; -import android.view.ActionMode; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; -import android.widget.AbsListView.MultiChoiceModeListener; -import android.widget.ShareActionProvider; -import android.widget.ShareActionProvider.OnShareTargetSelectedListener; - -import com.android.gallery3d.R; -import com.android.gallery3d.app.TrimVideo; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.filtershow.FilterShowActivity; -import com.android.gallery3d.filtershow.crop.CropActivity; -import com.android.gallery3d.util.GalleryUtils; - -import java.util.ArrayList; -import java.util.List; - -public class MultiChoiceManager implements MultiChoiceModeListener, - OnShareTargetSelectedListener, SelectionManager.SelectedUriSource { - - public interface Provider { - public MultiChoiceManager getMultiChoiceManager(); - } - - public interface Delegate { - public SparseBooleanArray getSelectedItemPositions(); - public int getSelectedItemCount(); - public int getItemMediaType(Object item); - public int getItemSupportedOperations(Object item); - public ArrayList<Uri> getSubItemUrisForItem(Object item); - public Uri getItemUri(Object item); - public Object getItemAtPosition(int position); - public Object getPathForItemAtPosition(int position); - public void deleteItemWithPath(Object itemPath); - } - - private SelectionManager mSelectionManager; - private ShareActionProvider mShareActionProvider; - private ActionMode mActionMode; - private Context mContext; - private Delegate mDelegate; - - private ArrayList<Uri> mSelectedShareableUrisArray = new ArrayList<Uri>(); - - public MultiChoiceManager(Activity activity) { - mContext = activity; - mSelectionManager = new SelectionManager(activity); - } - - public void setDelegate(Delegate delegate) { - if (mDelegate == delegate) { - return; - } - if (mActionMode != null) { - mActionMode.finish(); - } - mDelegate = delegate; - } - - @Override - public ArrayList<Uri> getSelectedShareableUris() { - return mSelectedShareableUrisArray; - } - - private void updateSelectedTitle(ActionMode mode) { - int count = mDelegate.getSelectedItemCount(); - mode.setTitle(mContext.getResources().getQuantityString( - R.plurals.number_of_items_selected, count, count)); - } - - private String getItemMimetype(Object item) { - int type = mDelegate.getItemMediaType(item); - if (type == FileColumns.MEDIA_TYPE_IMAGE) { - return GalleryUtils.MIME_TYPE_IMAGE; - } else if (type == FileColumns.MEDIA_TYPE_VIDEO) { - return GalleryUtils.MIME_TYPE_VIDEO; - } else { - return GalleryUtils.MIME_TYPE_ALL; - } - } - - @Override - public void onItemCheckedStateChanged(ActionMode mode, int position, long id, - boolean checked) { - updateSelectedTitle(mode); - Object item = mDelegate.getItemAtPosition(position); - - int supported = mDelegate.getItemSupportedOperations(item); - - if ((supported & MediaObject.SUPPORT_SHARE) > 0) { - ArrayList<Uri> subItems = mDelegate.getSubItemUrisForItem(item); - if (checked) { - mSelectedShareableUrisArray.addAll(subItems); - } else { - mSelectedShareableUrisArray.removeAll(subItems); - } - } - - mSelectionManager.onItemSelectedStateChanged(mShareActionProvider, - mDelegate.getItemMediaType(item), - supported, - checked); - updateActionItemVisibilities(mode.getMenu(), - mSelectionManager.getSupportedOperations()); - } - - private void updateActionItemVisibilities(Menu menu, int supportedOperations) { - MenuItem editItem = menu.findItem(R.id.menu_edit); - MenuItem deleteItem = menu.findItem(R.id.menu_delete); - MenuItem shareItem = menu.findItem(R.id.menu_share); - MenuItem cropItem = menu.findItem(R.id.menu_crop); - MenuItem trimItem = menu.findItem(R.id.menu_trim); - MenuItem muteItem = menu.findItem(R.id.menu_mute); - MenuItem setAsItem = menu.findItem(R.id.menu_set_as); - - editItem.setVisible((supportedOperations & MediaObject.SUPPORT_EDIT) > 0); - deleteItem.setVisible((supportedOperations & MediaObject.SUPPORT_DELETE) > 0); - shareItem.setVisible((supportedOperations & MediaObject.SUPPORT_SHARE) > 0); - cropItem.setVisible((supportedOperations & MediaObject.SUPPORT_CROP) > 0); - trimItem.setVisible((supportedOperations & MediaObject.SUPPORT_TRIM) > 0); - muteItem.setVisible((supportedOperations & MediaObject.SUPPORT_MUTE) > 0); - setAsItem.setVisible((supportedOperations & MediaObject.SUPPORT_SETAS) > 0); - } - - @Override - public boolean onCreateActionMode(ActionMode mode, Menu menu) { - mSelectionManager.setSelectedUriSource(this); - mActionMode = mode; - MenuInflater inflater = mode.getMenuInflater(); - inflater.inflate(R.menu.gallery_multiselect, menu); - MenuItem menuItem = menu.findItem(R.id.menu_share); - mShareActionProvider = (ShareActionProvider) menuItem.getActionProvider(); - mShareActionProvider.setOnShareTargetSelectedListener(this); - updateSelectedTitle(mode); - return true; - } - - @Override - public void onDestroyActionMode(ActionMode mode) { - // onDestroyActionMode gets called when the share target was selected, - // but apparently before the ArrayList is serialized in the intent - // so we can't clear the old one here. - mSelectedShareableUrisArray = new ArrayList<Uri>(); - mSelectionManager.onClearSelection(); - mSelectionManager.setSelectedUriSource(null); - mShareActionProvider = null; - mActionMode = null; - } - - @Override - public boolean onPrepareActionMode(ActionMode mode, Menu menu) { - updateSelectedTitle(mode); - return false; - } - - @Override - public boolean onShareTargetSelected(ShareActionProvider provider, Intent intent) { - mActionMode.finish(); - return false; - } - - private static class BulkDeleteTask extends AsyncTask<Void, Void, Void> { - private Delegate mDelegate; - private List<Object> mPaths; - - public BulkDeleteTask(Delegate delegate, List<Object> paths) { - mDelegate = delegate; - mPaths = paths; - } - - @Override - protected Void doInBackground(Void... ignored) { - for (Object path : mPaths) { - mDelegate.deleteItemWithPath(path); - } - return null; - } - } - - @Override - public boolean onActionItemClicked(ActionMode mode, MenuItem item) { - int actionItemId = item.getItemId(); - switch (actionItemId) { - case R.id.menu_delete: - BulkDeleteTask deleteTask = new BulkDeleteTask(mDelegate, - getPathsForSelectedItems()); - deleteTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); - mode.finish(); - return true; - case R.id.menu_edit: - case R.id.menu_crop: - case R.id.menu_trim: - case R.id.menu_mute: - case R.id.menu_set_as: - singleItemAction(getSelectedItem(), actionItemId); - mode.finish(); - return true; - default: - return false; - } - } - - private void singleItemAction(Object item, int actionItemId) { - Intent intent = new Intent(); - String mime = getItemMimetype(item); - Uri uri = mDelegate.getItemUri(item); - switch (actionItemId) { - case R.id.menu_edit: - intent.setDataAndType(uri, mime) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - .setAction(Intent.ACTION_EDIT); - mContext.startActivity(Intent.createChooser(intent, null)); - return; - case R.id.menu_crop: - intent.setDataAndType(uri, mime) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - .setAction(CropActivity.CROP_ACTION) - .setClass(mContext, FilterShowActivity.class); - mContext.startActivity(intent); - return; - case R.id.menu_trim: - intent.setData(uri) - .setClass(mContext, TrimVideo.class); - mContext.startActivity(intent); - return; - case R.id.menu_mute: - /* TODO need a way to get the file path of an item - MuteVideo muteVideo = new MuteVideo(filePath, - uri, (Activity) mContext); - muteVideo.muteInBackground(); - */ - return; - case R.id.menu_set_as: - intent.setDataAndType(uri, mime) - .setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - .setAction(Intent.ACTION_ATTACH_DATA) - .putExtra("mimeType", mime); - mContext.startActivity(Intent.createChooser( - intent, mContext.getString(R.string.set_as))); - return; - default: - return; - } - } - - private List<Object> getPathsForSelectedItems() { - List<Object> paths = new ArrayList<Object>(); - SparseBooleanArray selected = mDelegate.getSelectedItemPositions(); - for (int i = 0; i < selected.size(); i++) { - if (selected.valueAt(i)) { - paths.add(mDelegate.getPathForItemAtPosition(i)); - } - } - return paths; - } - - public Object getSelectedItem() { - if (mDelegate.getSelectedItemCount() != 1) { - return null; - } - SparseBooleanArray selected = mDelegate.getSelectedItemPositions(); - for (int i = 0; i < selected.size(); i++) { - if (selected.valueAt(i)) { - return mDelegate.getItemAtPosition(selected.keyAt(i)); - } - } - return null; - } -} diff --git a/src/com/android/photos/MultiSelectGridFragment.java b/src/com/android/photos/MultiSelectGridFragment.java deleted file mode 100644 index dda9fe443..000000000 --- a/src/com/android/photos/MultiSelectGridFragment.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.Activity; -import android.app.Fragment; -import android.os.Bundle; -import android.os.Handler; -import android.util.SparseBooleanArray; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.animation.AnimationUtils; -import android.widget.AdapterView; -import android.widget.GridView; -import android.widget.ListAdapter; -import android.widget.TextView; - -import com.android.gallery3d.R; - -public abstract class MultiSelectGridFragment extends Fragment - implements MultiChoiceManager.Delegate, AdapterView.OnItemClickListener { - - final private Handler mHandler = new Handler(); - - final private Runnable mRequestFocus = new Runnable() { - @Override - public void run() { - mGrid.focusableViewAvailable(mGrid); - } - }; - - ListAdapter mAdapter; - GridView mGrid; - TextView mEmptyView; - View mProgressContainer; - View mGridContainer; - CharSequence mEmptyText; - boolean mGridShown; - MultiChoiceManager.Provider mHost; - - public MultiSelectGridFragment() { - } - - /** - * Provide default implementation to return a simple grid view. Subclasses - * can override to replace with their own layout. If doing so, the returned - * view hierarchy <em>must</em> have a GridView whose id is - * {@link android.R.id#grid android.R.id.list} and can optionally have a - * sibling text view id {@link android.R.id#empty android.R.id.empty} that - * is to be shown when the grid is empty. - */ - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - return inflater.inflate(R.layout.multigrid_content, container, false); - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - mHost = (MultiChoiceManager.Provider) activity; - if (mGrid != null) { - mGrid.setMultiChoiceModeListener(mHost.getMultiChoiceManager()); - } - } - - @Override - public void onDetach() { - super.onDetach(); - mHost = null; - } - - /** - * Attach to grid view once the view hierarchy has been created. - */ - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - ensureGrid(); - } - - /** - * Detach from grid view. - */ - @Override - public void onDestroyView() { - mHandler.removeCallbacks(mRequestFocus); - mGrid = null; - mGridShown = false; - mEmptyView = null; - mProgressContainer = mGridContainer = null; - super.onDestroyView(); - } - - /** - * This method will be called when an item in the grid is selected. - * Subclasses should override. Subclasses can call - * getGridView().getItemAtPosition(position) if they need to access the data - * associated with the selected item. - * - * @param g The GridView where the click happened - * @param v The view that was clicked within the GridView - * @param position The position of the view in the grid - * @param id The id of the item that was clicked - */ - public void onGridItemClick(GridView g, View v, int position, long id) { - } - - /** - * Provide the cursor for the grid view. - */ - public void setAdapter(ListAdapter adapter) { - boolean hadAdapter = mAdapter != null; - mAdapter = adapter; - if (mGrid != null) { - mGrid.setAdapter(adapter); - if (!mGridShown && !hadAdapter) { - // The grid was hidden, and previously didn't have an - // adapter. It is now time to show it. - setGridShown(true, getView().getWindowToken() != null); - } - } - } - - /** - * Set the currently selected grid item to the specified position with the - * adapter's data - * - * @param position - */ - public void setSelection(int position) { - ensureGrid(); - mGrid.setSelection(position); - } - - /** - * Get the position of the currently selected grid item. - */ - public int getSelectedItemPosition() { - ensureGrid(); - return mGrid.getSelectedItemPosition(); - } - - /** - * Get the cursor row ID of the currently selected grid item. - */ - public long getSelectedItemId() { - ensureGrid(); - return mGrid.getSelectedItemId(); - } - - /** - * Get the activity's grid view widget. - */ - public GridView getGridView() { - ensureGrid(); - return mGrid; - } - - /** - * The default content for a MultiSelectGridFragment has a TextView that can - * be shown when the grid is empty. If you would like to have it shown, call - * this method to supply the text it should use. - */ - public void setEmptyText(CharSequence text) { - ensureGrid(); - if (mEmptyView == null) { - return; - } - mEmptyView.setText(text); - if (mEmptyText == null) { - mGrid.setEmptyView(mEmptyView); - } - mEmptyText = text; - } - - /** - * Control whether the grid is being displayed. You can make it not - * displayed if you are waiting for the initial data to show in it. During - * this time an indeterminate progress indicator will be shown instead. - * <p> - * Applications do not normally need to use this themselves. The default - * behavior of MultiSelectGridFragment is to start with the grid not being - * shown, only showing it once an adapter is given with - * {@link #setAdapter(ListAdapter)}. If the grid at that point had not been - * shown, when it does get shown it will be do without the user ever seeing - * the hidden state. - * - * @param shown If true, the grid view is shown; if false, the progress - * indicator. The initial value is true. - */ - public void setGridShown(boolean shown) { - setGridShown(shown, true); - } - - /** - * Like {@link #setGridShown(boolean)}, but no animation is used when - * transitioning from the previous state. - */ - public void setGridShownNoAnimation(boolean shown) { - setGridShown(shown, false); - } - - /** - * Control whether the grid is being displayed. You can make it not - * displayed if you are waiting for the initial data to show in it. During - * this time an indeterminate progress indicator will be shown instead. - * - * @param shown If true, the grid view is shown; if false, the progress - * indicator. The initial value is true. - * @param animate If true, an animation will be used to transition to the - * new state. - */ - private void setGridShown(boolean shown, boolean animate) { - ensureGrid(); - if (mProgressContainer == null) { - throw new IllegalStateException("Can't be used with a custom content view"); - } - if (mGridShown == shown) { - return; - } - mGridShown = shown; - if (shown) { - if (animate) { - mProgressContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_out)); - mGridContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_in)); - } else { - mProgressContainer.clearAnimation(); - mGridContainer.clearAnimation(); - } - mProgressContainer.setVisibility(View.GONE); - mGridContainer.setVisibility(View.VISIBLE); - } else { - if (animate) { - mProgressContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_in)); - mGridContainer.startAnimation(AnimationUtils.loadAnimation( - getActivity(), android.R.anim.fade_out)); - } else { - mProgressContainer.clearAnimation(); - mGridContainer.clearAnimation(); - } - mProgressContainer.setVisibility(View.VISIBLE); - mGridContainer.setVisibility(View.GONE); - } - } - - /** - * Get the ListAdapter associated with this activity's GridView. - */ - public ListAdapter getAdapter() { - return mGrid.getAdapter(); - } - - private void ensureGrid() { - if (mGrid != null) { - return; - } - View root = getView(); - if (root == null) { - throw new IllegalStateException("Content view not yet created"); - } - if (root instanceof GridView) { - mGrid = (GridView) root; - } else { - View empty = root.findViewById(android.R.id.empty); - if (empty != null && empty instanceof TextView) { - mEmptyView = (TextView) empty; - } - mProgressContainer = root.findViewById(R.id.progressContainer); - mGridContainer = root.findViewById(R.id.gridContainer); - View rawGridView = root.findViewById(android.R.id.list); - if (!(rawGridView instanceof GridView)) { - throw new RuntimeException( - "Content has view with id attribute 'android.R.id.list' " - + "that is not a GridView class"); - } - mGrid = (GridView) rawGridView; - if (mGrid == null) { - throw new RuntimeException( - "Your content must have a GridView whose id attribute is " + - "'android.R.id.list'"); - } - if (mEmptyView != null) { - mGrid.setEmptyView(mEmptyView); - } - } - mGridShown = true; - mGrid.setOnItemClickListener(this); - mGrid.setMultiChoiceModeListener(mHost.getMultiChoiceManager()); - if (mAdapter != null) { - ListAdapter adapter = mAdapter; - mAdapter = null; - setAdapter(adapter); - } else { - // We are starting without an adapter, so assume we won't - // have our data right away and start with the progress indicator. - if (mProgressContainer != null) { - setGridShown(false, false); - } - } - mHandler.post(mRequestFocus); - } - - @Override - public Object getItemAtPosition(int position) { - return getAdapter().getItem(position); - } - - @Override - public Object getPathForItemAtPosition(int position) { - return getPathForItem(getItemAtPosition(position)); - } - - @Override - public SparseBooleanArray getSelectedItemPositions() { - return mGrid.getCheckedItemPositions(); - } - - @Override - public int getSelectedItemCount() { - return mGrid.getCheckedItemCount(); - } - - public abstract Object getPathForItem(Object item); - - @Override - public void onItemClick(AdapterView<?> parent, View v, int position, long id) { - onGridItemClick((GridView) parent, v, position, id); - } -} diff --git a/src/com/android/photos/PhotoFragment.java b/src/com/android/photos/PhotoFragment.java deleted file mode 100644 index 3be6313f2..000000000 --- a/src/com/android/photos/PhotoFragment.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package com.android.photos; - -import android.app.Fragment; - - -public class PhotoFragment extends Fragment { - -} diff --git a/src/com/android/photos/PhotoSetFragment.java b/src/com/android/photos/PhotoSetFragment.java deleted file mode 100644 index 961fd0bf2..000000000 --- a/src/com/android/photos/PhotoSetFragment.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.LoaderManager.LoaderCallbacks; -import android.content.Context; -import android.content.Intent; -import android.content.Loader; -import android.database.Cursor; -import android.net.Uri; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.GridView; - -import com.android.gallery3d.app.Gallery; -import com.android.photos.adapters.PhotoThumbnailAdapter; -import com.android.photos.data.PhotoSetLoader; -import com.android.photos.shims.LoaderCompatShim; -import com.android.photos.shims.MediaItemsLoader; - -import java.util.ArrayList; - -public class PhotoSetFragment extends MultiSelectGridFragment implements LoaderCallbacks<Cursor> { - - private static final int LOADER_PHOTOSET = 1; - - private LoaderCompatShim<Cursor> mLoaderCompatShim; - private PhotoThumbnailAdapter mAdapter; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - Context context = getActivity(); - mAdapter = new PhotoThumbnailAdapter(context); - } - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View root = super.onCreateView(inflater, container, savedInstanceState); - getLoaderManager().initLoader(LOADER_PHOTOSET, null, this); - return root; - } - - @Override - public void onViewCreated(View view, Bundle savedInstanceState) { - super.onViewCreated(view, savedInstanceState); - // TODO: Remove once UI stabilizes - getGridView().setColumnWidth(MediaItemsLoader.getThumbnailSize()); - } - - @Override - public void onGridItemClick(GridView g, View v, int position, long id) { - if (mLoaderCompatShim == null) { - // Not fully initialized yet, discard - return; - } - Cursor item = (Cursor) getItemAtPosition(position); - Uri uri = mLoaderCompatShim.uriForItem(item); - Intent intent = new Intent(Intent.ACTION_VIEW, uri); - intent.setClass(getActivity(), Gallery.class); - startActivity(intent); - } - - @Override - public Loader<Cursor> onCreateLoader(int id, Bundle args) { - // TODO: Switch to PhotoSetLoader - MediaItemsLoader loader = new MediaItemsLoader(getActivity()); - mLoaderCompatShim = loader; - mAdapter.setDrawableFactory(mLoaderCompatShim); - return loader; - } - - @Override - public void onLoadFinished(Loader<Cursor> loader, - Cursor data) { - mAdapter.swapCursor(data); - setAdapter(mAdapter); - } - - @Override - public void onLoaderReset(Loader<Cursor> loader) { - } - - @Override - public int getItemMediaType(Object item) { - return ((Cursor) item).getInt(PhotoSetLoader.INDEX_MEDIA_TYPE); - } - - @Override - public int getItemSupportedOperations(Object item) { - return ((Cursor) item).getInt(PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS); - } - - private ArrayList<Uri> mSubItemUriTemp = new ArrayList<Uri>(1); - @Override - public ArrayList<Uri> getSubItemUrisForItem(Object item) { - mSubItemUriTemp.clear(); - mSubItemUriTemp.add(mLoaderCompatShim.uriForItem((Cursor) item)); - return mSubItemUriTemp; - } - - @Override - public void deleteItemWithPath(Object itemPath) { - mLoaderCompatShim.deleteItemWithPath(itemPath); - } - - @Override - public Uri getItemUri(Object item) { - return mLoaderCompatShim.uriForItem((Cursor) item); - } - - @Override - public Object getPathForItem(Object item) { - return mLoaderCompatShim.getPathForItem((Cursor) item); - } -} diff --git a/src/com/android/photos/SelectionManager.java b/src/com/android/photos/SelectionManager.java deleted file mode 100644 index 9bfb9be75..000000000 --- a/src/com/android/photos/SelectionManager.java +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos; - -import android.app.Activity; -import android.content.Intent; -import android.net.Uri; -import android.nfc.NfcAdapter; -import android.nfc.NfcAdapter.CreateBeamUrisCallback; -import android.nfc.NfcEvent; -import android.provider.MediaStore.Files.FileColumns; -import android.widget.ShareActionProvider; - -import com.android.gallery3d.common.ApiHelper; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.util.GalleryUtils; - -import java.util.ArrayList; - -public class SelectionManager { - private Activity mActivity; - private NfcAdapter mNfcAdapter; - private SelectedUriSource mUriSource; - private Intent mShareIntent = new Intent(); - - public interface SelectedUriSource { - public ArrayList<Uri> getSelectedShareableUris(); - } - - public SelectionManager(Activity activity) { - mActivity = activity; - if (ApiHelper.AT_LEAST_16) { - mNfcAdapter = NfcAdapter.getDefaultAdapter(mActivity); - mNfcAdapter.setBeamPushUrisCallback(new CreateBeamUrisCallback() { - @Override - public Uri[] createBeamUris(NfcEvent arg0) { - // This will have been preceded by a call to onItemSelectedStateChange - if (mCachedShareableUris == null) return null; - return mCachedShareableUris.toArray( - new Uri[mCachedShareableUris.size()]); - } - }, mActivity); - } - } - - public void setSelectedUriSource(SelectedUriSource source) { - mUriSource = source; - } - - private int mSelectedTotalCount = 0; - private int mSelectedShareableCount = 0; - private int mSelectedShareableImageCount = 0; - private int mSelectedShareableVideoCount = 0; - private int mSelectedDeletableCount = 0; - private int mSelectedEditableCount = 0; - private int mSelectedCroppableCount = 0; - private int mSelectedSetableCount = 0; - private int mSelectedTrimmableCount = 0; - private int mSelectedMuteableCount = 0; - - private ArrayList<Uri> mCachedShareableUris = null; - - public void onItemSelectedStateChanged(ShareActionProvider share, - int itemType, int itemSupportedOperations, boolean selected) { - int increment = selected ? 1 : -1; - - mSelectedTotalCount += increment; - mCachedShareableUris = null; - - if ((itemSupportedOperations & MediaObject.SUPPORT_DELETE) > 0) { - mSelectedDeletableCount += increment; - } - if ((itemSupportedOperations & MediaObject.SUPPORT_EDIT) > 0) { - mSelectedEditableCount += increment; - } - if ((itemSupportedOperations & MediaObject.SUPPORT_CROP) > 0) { - mSelectedCroppableCount += increment; - } - if ((itemSupportedOperations & MediaObject.SUPPORT_SETAS) > 0) { - mSelectedSetableCount += increment; - } - if ((itemSupportedOperations & MediaObject.SUPPORT_TRIM) > 0) { - mSelectedTrimmableCount += increment; - } - if ((itemSupportedOperations & MediaObject.SUPPORT_MUTE) > 0) { - mSelectedMuteableCount += increment; - } - if ((itemSupportedOperations & MediaObject.SUPPORT_SHARE) > 0) { - mSelectedShareableCount += increment; - if (itemType == FileColumns.MEDIA_TYPE_IMAGE) { - mSelectedShareableImageCount += increment; - } else if (itemType == FileColumns.MEDIA_TYPE_VIDEO) { - mSelectedShareableVideoCount += increment; - } - } - - mShareIntent.removeExtra(Intent.EXTRA_STREAM); - if (mSelectedShareableCount == 0) { - mShareIntent.setAction(null).setType(null); - } else if (mSelectedShareableCount >= 1) { - mCachedShareableUris = mUriSource.getSelectedShareableUris(); - if (mCachedShareableUris.size() == 0) { - mShareIntent.setAction(null).setType(null); - } else { - if (mSelectedShareableImageCount == mSelectedShareableCount) { - mShareIntent.setType(GalleryUtils.MIME_TYPE_IMAGE); - } else if (mSelectedShareableVideoCount == mSelectedShareableCount) { - mShareIntent.setType(GalleryUtils.MIME_TYPE_VIDEO); - } else { - mShareIntent.setType(GalleryUtils.MIME_TYPE_ALL); - } - if (mCachedShareableUris.size() == 1) { - mShareIntent.setAction(Intent.ACTION_SEND); - mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris.get(0)); - } else { - mShareIntent.setAction(Intent.ACTION_SEND_MULTIPLE); - mShareIntent.putExtra(Intent.EXTRA_STREAM, mCachedShareableUris); - } - } - } - share.setShareIntent(mShareIntent); - } - - public int getSupportedOperations() { - if (mSelectedTotalCount == 0) { - return 0; - } - int supported = 0; - if (mSelectedTotalCount == 1) { - if (mSelectedCroppableCount == 1) { - supported |= MediaObject.SUPPORT_CROP; - } - if (mSelectedEditableCount == 1) { - supported |= MediaObject.SUPPORT_EDIT; - } - if (mSelectedSetableCount == 1) { - supported |= MediaObject.SUPPORT_SETAS; - } - if (mSelectedTrimmableCount == 1) { - supported |= MediaObject.SUPPORT_TRIM; - } - if (mSelectedMuteableCount == 1) { - supported |= MediaObject.SUPPORT_MUTE; - } - } - if (mSelectedDeletableCount == mSelectedTotalCount) { - supported |= MediaObject.SUPPORT_DELETE; - } - if (mSelectedShareableCount > 0) { - supported |= MediaObject.SUPPORT_SHARE; - } - return supported; - } - - public void onClearSelection() { - mSelectedTotalCount = 0; - mSelectedShareableCount = 0; - mSelectedShareableImageCount = 0; - mSelectedShareableVideoCount = 0; - mSelectedDeletableCount = 0; - mSelectedEditableCount = 0; - mSelectedCroppableCount = 0; - mSelectedSetableCount = 0; - mSelectedTrimmableCount = 0; - mSelectedMuteableCount = 0; - mCachedShareableUris = null; - mShareIntent.removeExtra(Intent.EXTRA_STREAM); - mShareIntent.setAction(null).setType(null); - } -} diff --git a/src/com/android/photos/adapters/AlbumSetCursorAdapter.java b/src/com/android/photos/adapters/AlbumSetCursorAdapter.java deleted file mode 100644 index ab99cde70..000000000 --- a/src/com/android/photos/adapters/AlbumSetCursorAdapter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.adapters; - -import android.content.Context; -import android.database.Cursor; -import android.graphics.drawable.Drawable; -import android.text.format.DateFormat; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CursorAdapter; -import android.widget.ImageView; -import android.widget.ProgressBar; -import android.widget.TextView; - -import com.android.gallery3d.R; -import com.android.photos.data.AlbumSetLoader; -import com.android.photos.shims.LoaderCompatShim; - -import java.util.Date; - -public class AlbumSetCursorAdapter extends CursorAdapter { - - private LoaderCompatShim<Cursor> mDrawableFactory; - - public void setDrawableFactory(LoaderCompatShim<Cursor> factory) { - mDrawableFactory = factory; - } - - public AlbumSetCursorAdapter(Context context) { - super(context, null, false); - } - - @Override - public void bindView(View v, Context context, Cursor cursor) { - TextView titleTextView = (TextView) v.findViewById( - R.id.album_set_item_title); - titleTextView.setText(cursor.getString(AlbumSetLoader.INDEX_TITLE)); - - TextView countTextView = (TextView) v.findViewById( - R.id.album_set_item_count); - int count = cursor.getInt(AlbumSetLoader.INDEX_COUNT); - countTextView.setText(context.getResources().getQuantityString( - R.plurals.number_of_photos, count, count)); - - ImageView thumbImageView = (ImageView) v.findViewById( - R.id.album_set_item_image); - Drawable recycle = thumbImageView.getDrawable(); - Drawable drawable = mDrawableFactory.drawableForItem(cursor, recycle); - if (recycle != drawable) { - thumbImageView.setImageDrawable(drawable); - } - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - return LayoutInflater.from(context).inflate( - R.layout.album_set_item, parent, false); - } -} diff --git a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java b/src/com/android/photos/adapters/PhotoThumbnailAdapter.java deleted file mode 100644 index 1190b8c85..000000000 --- a/src/com/android/photos/adapters/PhotoThumbnailAdapter.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.adapters; - -import android.content.Context; -import android.database.Cursor; -import android.graphics.drawable.Drawable; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.CursorAdapter; -import android.widget.ImageView; - -import com.android.gallery3d.R; -import com.android.photos.data.PhotoSetLoader; -import com.android.photos.shims.LoaderCompatShim; -import com.android.photos.views.GalleryThumbnailView.GalleryThumbnailAdapter; - - -public class PhotoThumbnailAdapter extends CursorAdapter implements GalleryThumbnailAdapter { - private LayoutInflater mInflater; - private LoaderCompatShim<Cursor> mDrawableFactory; - - public PhotoThumbnailAdapter(Context context) { - super(context, null, false); - mInflater = LayoutInflater.from(context); - } - - public void setDrawableFactory(LoaderCompatShim<Cursor> factory) { - mDrawableFactory = factory; - } - - @Override - public void bindView(View view, Context context, Cursor cursor) { - ImageView iv = (ImageView) view.findViewById(R.id.thumbnail); - Drawable recycle = iv.getDrawable(); - Drawable drawable = mDrawableFactory.drawableForItem(cursor, recycle); - if (recycle != drawable) { - iv.setImageDrawable(drawable); - } - } - - @Override - public View newView(Context context, Cursor cursor, ViewGroup parent) { - View view = mInflater.inflate(R.layout.photo_set_item, parent, false); - return view; - } - - @Override - public float getIntrinsicAspectRatio(int position) { - Cursor cursor = getItem(position); - float width = cursor.getInt(PhotoSetLoader.INDEX_WIDTH); - float height = cursor.getInt(PhotoSetLoader.INDEX_HEIGHT); - return width / height; - } - - @Override - public Cursor getItem(int position) { - return (Cursor) super.getItem(position); - } -}
\ No newline at end of file diff --git a/src/com/android/photos/data/AlbumSetLoader.java b/src/com/android/photos/data/AlbumSetLoader.java deleted file mode 100644 index 940473255..000000000 --- a/src/com/android/photos/data/AlbumSetLoader.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.android.photos.data; - -import android.database.MatrixCursor; - - -public class AlbumSetLoader { - public static final int INDEX_ID = 0; - public static final int INDEX_TITLE = 1; - public static final int INDEX_TIMESTAMP = 2; - public static final int INDEX_THUMBNAIL_URI = 3; - public static final int INDEX_THUMBNAIL_WIDTH = 4; - public static final int INDEX_THUMBNAIL_HEIGHT = 5; - public static final int INDEX_COUNT_PENDING_UPLOAD = 6; - public static final int INDEX_COUNT = 7; - public static final int INDEX_SUPPORTED_OPERATIONS = 8; - - public static final String[] PROJECTION = { - "_id", - "title", - "timestamp", - "thumb_uri", - "thumb_width", - "thumb_height", - "count_pending_upload", - "_count", - "supported_operations" - }; - public static final MatrixCursor MOCK = createRandomCursor(30); - - private static MatrixCursor createRandomCursor(int count) { - MatrixCursor c = new MatrixCursor(PROJECTION, count); - for (int i = 0; i < count; i++) { - c.addRow(createRandomRow()); - } - return c; - } - - private static Object[] createRandomRow() { - double random = Math.random(); - int id = (int) (500 * random); - Object[] row = { - id, - "Fun times " + id, - (long) (System.currentTimeMillis() * random), - null, - 0, - 0, - (random < .3 ? 1 : 0), - 1, - 0 - }; - return row; - } -}
\ No newline at end of file diff --git a/src/com/android/photos/data/BitmapDecoder.java b/src/com/android/photos/data/BitmapDecoder.java deleted file mode 100644 index 0671e73ca..000000000 --- a/src/com/android/photos/data/BitmapDecoder.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.graphics.Bitmap; -import android.graphics.Bitmap.Config; -import android.graphics.BitmapFactory; -import android.graphics.BitmapFactory.Options; -import android.util.Log; -import android.util.Pools.Pool; -import android.util.Pools.SynchronizedPool; - -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - -/** - * BitmapDecoder keeps a pool of temporary storage to reuse for decoding - * bitmaps. It also simplifies the multi-stage decoding required to efficiently - * use GalleryBitmapPool. The static methods decode and decodeFile can be used - * to decode a bitmap from GalleryBitmapPool. The bitmap may be returned - * directly to GalleryBitmapPool or use the put method here when the bitmap is - * ready to be recycled. - */ -public class BitmapDecoder { - private static final String TAG = BitmapDecoder.class.getSimpleName(); - private static final int POOL_SIZE = 4; - private static final int TEMP_STORAGE_SIZE_BYTES = 16 * 1024; - private static final int HEADER_MAX_SIZE = 128 * 1024; - private static final int NO_SCALING = -1; - - private static final Pool<BitmapFactory.Options> sOptions = - new SynchronizedPool<BitmapFactory.Options>(POOL_SIZE); - - private interface Decoder<T> { - Bitmap decode(T input, BitmapFactory.Options options); - - boolean decodeBounds(T input, BitmapFactory.Options options); - } - - private static abstract class OnlyDecode<T> implements Decoder<T> { - @Override - public boolean decodeBounds(T input, BitmapFactory.Options options) { - decode(input, options); - return true; - } - } - - private static final Decoder<InputStream> sStreamDecoder = new Decoder<InputStream>() { - @Override - public Bitmap decode(InputStream is, Options options) { - return BitmapFactory.decodeStream(is, null, options); - } - - @Override - public boolean decodeBounds(InputStream is, Options options) { - is.mark(HEADER_MAX_SIZE); - BitmapFactory.decodeStream(is, null, options); - try { - is.reset(); - return true; - } catch (IOException e) { - Log.e(TAG, "Could not decode stream to bitmap", e); - return false; - } - } - }; - - private static final Decoder<String> sFileDecoder = new OnlyDecode<String>() { - @Override - public Bitmap decode(String filePath, Options options) { - return BitmapFactory.decodeFile(filePath, options); - } - }; - - private static final Decoder<byte[]> sByteArrayDecoder = new OnlyDecode<byte[]>() { - @Override - public Bitmap decode(byte[] data, Options options) { - return BitmapFactory.decodeByteArray(data, 0, data.length, options); - } - }; - - private static <T> Bitmap delegateDecode(Decoder<T> decoder, T input, int width, int height) { - BitmapFactory.Options options = getOptions(); - GalleryBitmapPool pool = GalleryBitmapPool.getInstance(); - try { - options.inJustDecodeBounds = true; - if (!decoder.decodeBounds(input, options)) { - return null; - } - options.inJustDecodeBounds = false; - Bitmap reuseBitmap = null; - if (width != NO_SCALING && options.outWidth >= width && options.outHeight >= height) { - setScaling(options, width, height); - } else { - reuseBitmap = pool.get(options.outWidth, options.outHeight); - } - options.inBitmap = reuseBitmap; - Bitmap decodedBitmap = decoder.decode(input, options); - if (reuseBitmap != null && decodedBitmap != reuseBitmap) { - pool.put(reuseBitmap); - } - return decodedBitmap; - } catch (IllegalArgumentException e) { - if (options.inBitmap == null) { - throw e; - } - pool.put(options.inBitmap); - options.inBitmap = null; - return decoder.decode(input, options); - } finally { - options.inBitmap = null; - options.inJustDecodeBounds = false; - sOptions.release(options); - } - } - - public static Bitmap decode(InputStream in) { - try { - if (!in.markSupported()) { - in = new BufferedInputStream(in); - } - return delegateDecode(sStreamDecoder, in, NO_SCALING, NO_SCALING); - } finally { - Utils.closeSilently(in); - } - } - - public static Bitmap decode(File file) { - return decodeFile(file.getPath()); - } - - public static Bitmap decodeFile(String path) { - return delegateDecode(sFileDecoder, path, NO_SCALING, NO_SCALING); - } - - public static Bitmap decodeByteArray(byte[] data) { - return delegateDecode(sByteArrayDecoder, data, NO_SCALING, NO_SCALING); - } - - public static void put(Bitmap bitmap) { - GalleryBitmapPool.getInstance().put(bitmap); - } - - /** - * Decodes to a specific size. If the dimensions of the image don't match - * width x height, the resulting image will be in the proportions of the - * decoded image, but will be scaled to fill the dimensions. For example, if - * width and height are 10x10 and the image is 200x100, the resulting image - * will be scaled/sampled to 20x10. - */ - public static Bitmap decodeFile(String path, int width, int height) { - return delegateDecode(sFileDecoder, path, width, height); - } - - /** @see #decodeFile(String, int, int) */ - public static Bitmap decodeByteArray(byte[] data, int width, int height) { - return delegateDecode(sByteArrayDecoder, data, width, height); - } - - /** @see #decodeFile(String, int, int) */ - public static Bitmap decode(InputStream in, int width, int height) { - try { - if (!in.markSupported()) { - in = new BufferedInputStream(in); - } - return delegateDecode(sStreamDecoder, in, width, height); - } finally { - Utils.closeSilently(in); - } - } - - private static BitmapFactory.Options getOptions() { - BitmapFactory.Options opts = sOptions.acquire(); - if (opts == null) { - opts = new BitmapFactory.Options(); - opts.inMutable = true; - opts.inPreferredConfig = Config.ARGB_8888; - opts.inTempStorage = new byte[TEMP_STORAGE_SIZE_BYTES]; - } - opts.inSampleSize = 1; - opts.inDensity = 1; - opts.inTargetDensity = 1; - - return opts; - } - - // Sets the options to sample then scale the image so that the image's - // minimum dimension will match side. - private static void setScaling(BitmapFactory.Options options, int width, int height) { - float widthScale = ((float)options.outWidth)/ width; - float heightScale = ((float) options.outHeight)/height; - int side = (widthScale < heightScale) ? width : height; - options.inSampleSize = BitmapUtils.computeSampleSize(options.outWidth, options.outHeight, - side, BitmapUtils.UNCONSTRAINED); - int constraint; - if (options.outWidth < options.outHeight) { - // Width is the constraint. Scale so that width = side. - constraint = options.outWidth; - } else { - // Height is the constraint. Scale so that height = side. - constraint = options.outHeight; - } - options.inDensity = constraint / options.inSampleSize; - options.inTargetDensity = side; - } -} diff --git a/src/com/android/photos/data/FileRetriever.java b/src/com/android/photos/data/FileRetriever.java deleted file mode 100644 index eb7686ef6..000000000 --- a/src/com/android/photos/data/FileRetriever.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.graphics.Bitmap; -import android.media.ExifInterface; -import android.net.Uri; -import android.util.Log; -import android.webkit.MimeTypeMap; - -import com.android.gallery3d.common.BitmapUtils; - -import java.io.File; -import java.io.IOException; - -public class FileRetriever implements MediaRetriever { - private static final String TAG = FileRetriever.class.getSimpleName(); - - @Override - public File getLocalFile(Uri contentUri) { - return new File(contentUri.getPath()); - } - - @Override - public MediaSize getFastImageSize(Uri contentUri, MediaSize size) { - if (isVideo(contentUri)) { - return null; - } - return MediaSize.TemporaryThumbnail; - } - - @Override - public byte[] getTemporaryImage(Uri contentUri, MediaSize fastImageSize) { - - try { - ExifInterface exif = new ExifInterface(contentUri.getPath()); - if (exif.hasThumbnail()) { - return exif.getThumbnail(); - } - } catch (IOException e) { - Log.w(TAG, "Unable to load exif for " + contentUri); - } - return null; - } - - @Override - public boolean getMedia(Uri contentUri, MediaSize imageSize, File tempFile) { - if (imageSize == MediaSize.Original) { - return false; // getLocalFile should always return the original. - } - if (imageSize == MediaSize.Thumbnail) { - File preview = MediaCache.getInstance().getCachedFile(contentUri, MediaSize.Preview); - if (preview != null) { - // Just downsample the preview, it is faster. - return MediaCacheUtils.downsample(preview, imageSize, tempFile); - } - } - File highRes = new File(contentUri.getPath()); - boolean success; - if (!isVideo(contentUri)) { - success = MediaCacheUtils.downsample(highRes, imageSize, tempFile); - } else { - // Video needs to extract the bitmap. - Bitmap bitmap = BitmapUtils.createVideoThumbnail(highRes.getPath()); - if (bitmap == null) { - return false; - } else if (imageSize == MediaSize.Thumbnail - && !MediaCacheUtils.needsDownsample(bitmap, MediaSize.Preview) - && MediaCacheUtils.writeToFile(bitmap, tempFile)) { - // Opportunistically save preview - MediaCache mediaCache = MediaCache.getInstance(); - mediaCache.insertIntoCache(contentUri, MediaSize.Preview, tempFile); - } - // Now scale the image - success = MediaCacheUtils.downsample(bitmap, imageSize, tempFile); - } - return success; - } - - @Override - public Uri normalizeUri(Uri contentUri, MediaSize size) { - return contentUri; - } - - @Override - public MediaSize normalizeMediaSize(Uri contentUri, MediaSize size) { - return size; - } - - private static boolean isVideo(Uri uri) { - MimeTypeMap mimeTypeMap = MimeTypeMap.getSingleton(); - String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString()); - String mimeType = mimeTypeMap.getMimeTypeFromExtension(extension); - return (mimeType != null && mimeType.startsWith("video/")); - } -} diff --git a/src/com/android/photos/data/GalleryBitmapPool.java b/src/com/android/photos/data/GalleryBitmapPool.java deleted file mode 100644 index 390a0d42f..000000000 --- a/src/com/android/photos/data/GalleryBitmapPool.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.data; - -import android.graphics.Bitmap; -import android.graphics.Point; -import android.util.Pools.Pool; -import android.util.Pools.SynchronizedPool; - -import com.android.photos.data.SparseArrayBitmapPool.Node; - -/** - * Pool allowing the efficient reuse of bitmaps in order to avoid long - * garbage collection pauses. - */ -public class GalleryBitmapPool { - - private static final int CAPACITY_BYTES = 20971520; - - // We found that Gallery uses bitmaps that are either square (for example, - // tiles of large images or square thumbnails), match one of the common - // photo aspect ratios (4x3, 3x2, or 16x9), or, less commonly, are of some - // other aspect ratio. Taking advantage of this information, we use 3 - // SparseArrayBitmapPool instances to back the GalleryBitmapPool, which affords - // O(1) lookups for square bitmaps, and average-case - but *not* asymptotically - - // O(1) lookups for common photo aspect ratios and other miscellaneous aspect - // ratios. Beware of the pathological case where there are many bitmaps added - // to the pool with different non-square aspect ratios but the same width, as - // performance will degrade and the average case lookup will approach - // O(# of different aspect ratios). - private static final int POOL_INDEX_NONE = -1; - private static final int POOL_INDEX_SQUARE = 0; - private static final int POOL_INDEX_PHOTO = 1; - private static final int POOL_INDEX_MISC = 2; - - private static final Point[] COMMON_PHOTO_ASPECT_RATIOS = - { new Point(4, 3), new Point(3, 2), new Point(16, 9) }; - - private int mCapacityBytes; - private SparseArrayBitmapPool [] mPools; - private Pool<Node> mSharedNodePool = new SynchronizedPool<Node>(128); - - private GalleryBitmapPool(int capacityBytes) { - mPools = new SparseArrayBitmapPool[3]; - mPools[POOL_INDEX_SQUARE] = new SparseArrayBitmapPool(capacityBytes / 3, mSharedNodePool); - mPools[POOL_INDEX_PHOTO] = new SparseArrayBitmapPool(capacityBytes / 3, mSharedNodePool); - mPools[POOL_INDEX_MISC] = new SparseArrayBitmapPool(capacityBytes / 3, mSharedNodePool); - mCapacityBytes = capacityBytes; - } - - private static GalleryBitmapPool sInstance = new GalleryBitmapPool(CAPACITY_BYTES); - - public static GalleryBitmapPool getInstance() { - return sInstance; - } - - private SparseArrayBitmapPool getPoolForDimensions(int width, int height) { - int index = getPoolIndexForDimensions(width, height); - if (index == POOL_INDEX_NONE) { - return null; - } else { - return mPools[index]; - } - } - - private int getPoolIndexForDimensions(int width, int height) { - if (width <= 0 || height <= 0) { - return POOL_INDEX_NONE; - } - if (width == height) { - return POOL_INDEX_SQUARE; - } - int min, max; - if (width > height) { - min = height; - max = width; - } else { - min = width; - max = height; - } - for (Point ar : COMMON_PHOTO_ASPECT_RATIOS) { - if (min * ar.x == max * ar.y) { - return POOL_INDEX_PHOTO; - } - } - return POOL_INDEX_MISC; - } - - /** - * @return Capacity of the pool in bytes. - */ - public synchronized int getCapacity() { - return mCapacityBytes; - } - - /** - * @return Approximate total size in bytes of the bitmaps stored in the pool. - */ - public int getSize() { - // Note that this only returns an approximate size, since multiple threads - // might be getting and putting Bitmaps from the pool and we lock at the - // sub-pool level to avoid unnecessary blocking. - int total = 0; - for (SparseArrayBitmapPool p : mPools) { - total += p.getSize(); - } - return total; - } - - /** - * @return Bitmap from the pool with the desired height/width or null if none available. - */ - public Bitmap get(int width, int height) { - SparseArrayBitmapPool pool = getPoolForDimensions(width, height); - if (pool == null) { - return null; - } else { - return pool.get(width, height); - } - } - - /** - * Adds the given bitmap to the pool. - * @return Whether the bitmap was added to the pool. - */ - public boolean put(Bitmap b) { - if (b == null || b.getConfig() != Bitmap.Config.ARGB_8888) { - return false; - } - SparseArrayBitmapPool pool = getPoolForDimensions(b.getWidth(), b.getHeight()); - if (pool == null) { - b.recycle(); - return false; - } else { - return pool.put(b); - } - } - - /** - * Empty the pool, recycling all the bitmaps currently in it. - */ - public void clear() { - for (SparseArrayBitmapPool p : mPools) { - p.clear(); - } - } -} diff --git a/src/com/android/photos/data/MediaCache.java b/src/com/android/photos/data/MediaCache.java deleted file mode 100644 index 0952a4017..000000000 --- a/src/com/android/photos/data/MediaCache.java +++ /dev/null @@ -1,676 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.net.Uri; -import android.os.Environment; -import android.util.Log; - -import com.android.photos.data.MediaCacheDatabase.Action; -import com.android.photos.data.MediaRetriever.MediaSize; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Queue; - -/** - * MediaCache keeps a cache of images, videos, thumbnails and previews. Calls to - * retrieve a specific media item are executed asynchronously. The caller has an - * option to receive a notification for lower resolution images that happen to - * be available prior to the one requested. - * <p> - * When an media item has been retrieved, the notification for it is called on a - * separate notifier thread. This thread should not be held for a long time so - * that other notifications may happen. - * </p> - * <p> - * Media items are uniquely identified by their content URIs. Each - * scheme/authority can offer its own MediaRetriever, running in its own thread. - * </p> - * <p> - * The MediaCache is an LRU cache, but does not allow the thumbnail cache to - * drop below a minimum size. This prevents browsing through original images to - * wipe out the thumbnails. - * </p> - */ -public class MediaCache { - static final String TAG = MediaCache.class.getSimpleName(); - /** Subdirectory containing the image cache. */ - static final String IMAGE_CACHE_SUBDIR = "image_cache"; - /** File name extension to use for cached images. */ - static final String IMAGE_EXTENSION = ".cache"; - /** File name extension to use for temporary cached images while retrieving. */ - static final String TEMP_IMAGE_EXTENSION = ".temp"; - - public static interface ImageReady { - void imageReady(InputStream bitmapInputStream); - } - - public static interface OriginalReady { - void originalReady(File originalFile); - } - - /** A Thread for each MediaRetriever */ - private class ProcessQueue extends Thread { - private Queue<ProcessingJob> mQueue; - - public ProcessQueue(Queue<ProcessingJob> queue) { - mQueue = queue; - } - - @Override - public void run() { - while (mRunning) { - ProcessingJob status; - synchronized (mQueue) { - while (mQueue.isEmpty()) { - try { - mQueue.wait(); - } catch (InterruptedException e) { - if (!mRunning) { - return; - } - Log.w(TAG, "Unexpected interruption", e); - } - } - status = mQueue.remove(); - } - processTask(status); - } - } - }; - - private interface NotifyReady { - void notifyReady(); - - void setFile(File file) throws FileNotFoundException; - - boolean isPrefetch(); - } - - private static class NotifyOriginalReady implements NotifyReady { - private final OriginalReady mCallback; - private File mFile; - - public NotifyOriginalReady(OriginalReady callback) { - mCallback = callback; - } - - @Override - public void notifyReady() { - if (mCallback != null) { - mCallback.originalReady(mFile); - } - } - - @Override - public void setFile(File file) { - mFile = file; - } - - @Override - public boolean isPrefetch() { - return mCallback == null; - } - } - - private static class NotifyImageReady implements NotifyReady { - private final ImageReady mCallback; - private InputStream mInputStream; - - public NotifyImageReady(ImageReady callback) { - mCallback = callback; - } - - @Override - public void notifyReady() { - if (mCallback != null) { - mCallback.imageReady(mInputStream); - } - } - - @Override - public void setFile(File file) throws FileNotFoundException { - mInputStream = new FileInputStream(file); - } - - public void setBytes(byte[] bytes) { - mInputStream = new ByteArrayInputStream(bytes); - } - - @Override - public boolean isPrefetch() { - return mCallback == null; - } - } - - /** A media item to be retrieved and its notifications. */ - private static class ProcessingJob { - public ProcessingJob(Uri uri, MediaSize size, NotifyReady complete, - NotifyImageReady lowResolution) { - this.contentUri = uri; - this.size = size; - this.complete = complete; - this.lowResolution = lowResolution; - } - public Uri contentUri; - public MediaSize size; - public NotifyImageReady lowResolution; - public NotifyReady complete; - } - - private boolean mRunning = true; - private static MediaCache sInstance; - private File mCacheDir; - private Context mContext; - private Queue<NotifyReady> mCallbacks = new LinkedList<NotifyReady>(); - private Map<String, MediaRetriever> mRetrievers = new HashMap<String, MediaRetriever>(); - private Map<String, List<ProcessingJob>> mTasks = new HashMap<String, List<ProcessingJob>>(); - private List<ProcessQueue> mProcessingThreads = new ArrayList<ProcessQueue>(); - private MediaCacheDatabase mDatabaseHelper; - private long mTempImageNumber = 1; - private Object mTempImageNumberLock = new Object(); - - private long mMaxCacheSize = 40 * 1024 * 1024; // 40 MB - private long mMinThumbCacheSize = 4 * 1024 * 1024; // 4 MB - private long mCacheSize = -1; - private long mThumbCacheSize = -1; - private Object mCacheSizeLock = new Object(); - - private Action mNotifyCachedLowResolution = new Action() { - @Override - public void execute(Uri uri, long id, MediaSize size, Object parameter) { - ProcessingJob job = (ProcessingJob) parameter; - File file = createCacheImagePath(id); - addNotification(job.lowResolution, file); - } - }; - - private Action mMoveTempToCache = new Action() { - @Override - public void execute(Uri uri, long id, MediaSize size, Object parameter) { - File tempFile = (File) parameter; - File cacheFile = createCacheImagePath(id); - tempFile.renameTo(cacheFile); - } - }; - - private Action mDeleteFile = new Action() { - @Override - public void execute(Uri uri, long id, MediaSize size, Object parameter) { - File file = createCacheImagePath(id); - file.delete(); - synchronized (mCacheSizeLock) { - if (mCacheSize != -1) { - long length = (Long) parameter; - mCacheSize -= length; - if (size == MediaSize.Thumbnail) { - mThumbCacheSize -= length; - } - } - } - } - }; - - /** The thread used to make ImageReady and OriginalReady callbacks. */ - private Thread mProcessNotifications = new Thread() { - @Override - public void run() { - while (mRunning) { - NotifyReady notifyImage; - synchronized (mCallbacks) { - while (mCallbacks.isEmpty()) { - try { - mCallbacks.wait(); - } catch (InterruptedException e) { - if (!mRunning) { - return; - } - Log.w(TAG, "Unexpected Interruption, continuing"); - } - } - notifyImage = mCallbacks.remove(); - } - - notifyImage.notifyReady(); - } - } - }; - - public static synchronized void initialize(Context context) { - if (sInstance == null) { - sInstance = new MediaCache(context); - MediaCacheUtils.initialize(context); - } - } - - public static MediaCache getInstance() { - return sInstance; - } - - public static synchronized void shutdown() { - sInstance.mRunning = false; - sInstance.mProcessNotifications.interrupt(); - for (ProcessQueue processingThread : sInstance.mProcessingThreads) { - processingThread.interrupt(); - } - sInstance = null; - } - - private MediaCache(Context context) { - mDatabaseHelper = new MediaCacheDatabase(context); - mProcessNotifications.start(); - mContext = context; - } - - // This is used for testing. - public void setCacheDir(File cacheDir) { - cacheDir.mkdirs(); - mCacheDir = cacheDir; - } - - public File getCacheDir() { - synchronized (mContext) { - if (mCacheDir == null) { - String state = Environment.getExternalStorageState(); - File baseDir; - if (Environment.MEDIA_MOUNTED.equals(state)) { - baseDir = mContext.getExternalCacheDir(); - } else { - // Stored in internal cache - baseDir = mContext.getCacheDir(); - } - mCacheDir = new File(baseDir, IMAGE_CACHE_SUBDIR); - mCacheDir.mkdirs(); - } - return mCacheDir; - } - } - - /** - * Invalidates all cached images related to a given contentUri. This call - * doesn't complete until the images have been removed from the cache. - */ - public void invalidate(Uri contentUri) { - mDatabaseHelper.delete(contentUri, mDeleteFile); - } - - public void clearCacheDir() { - File[] cachedFiles = getCacheDir().listFiles(); - if (cachedFiles != null) { - for (File cachedFile : cachedFiles) { - cachedFile.delete(); - } - } - } - - /** - * Add a MediaRetriever for a Uri scheme and authority. This MediaRetriever - * will be granted its own thread for retrieving images. - */ - public void addRetriever(String scheme, String authority, MediaRetriever retriever) { - String differentiator = getDifferentiator(scheme, authority); - synchronized (mRetrievers) { - mRetrievers.put(differentiator, retriever); - } - synchronized (mTasks) { - LinkedList<ProcessingJob> queue = new LinkedList<ProcessingJob>(); - mTasks.put(differentiator, queue); - new ProcessQueue(queue).start(); - } - } - - /** - * Retrieves a thumbnail. complete will be called when the thumbnail is - * available. If lowResolution is not null and a lower resolution thumbnail - * is available before the thumbnail, lowResolution will be called prior to - * complete. All callbacks will be made on a thread other than the calling - * thread. - * - * @param contentUri The URI for the full resolution image to search for. - * @param complete Callback for when the image has been retrieved. - * @param lowResolution If not null and a lower resolution image is - * available prior to retrieving the thumbnail, this will be - * called with the low resolution bitmap. - */ - public void retrieveThumbnail(Uri contentUri, ImageReady complete, ImageReady lowResolution) { - addTask(contentUri, complete, lowResolution, MediaSize.Thumbnail); - } - - /** - * Retrieves a preview. complete will be called when the preview is - * available. If lowResolution is not null and a lower resolution preview is - * available before the preview, lowResolution will be called prior to - * complete. All callbacks will be made on a thread other than the calling - * thread. - * - * @param contentUri The URI for the full resolution image to search for. - * @param complete Callback for when the image has been retrieved. - * @param lowResolution If not null and a lower resolution image is - * available prior to retrieving the preview, this will be called - * with the low resolution bitmap. - */ - public void retrievePreview(Uri contentUri, ImageReady complete, ImageReady lowResolution) { - addTask(contentUri, complete, lowResolution, MediaSize.Preview); - } - - /** - * Retrieves the original image or video. complete will be called when the - * media is available on the local file system. If lowResolution is not null - * and a lower resolution preview is available before the original, - * lowResolution will be called prior to complete. All callbacks will be - * made on a thread other than the calling thread. - * - * @param contentUri The URI for the full resolution image to search for. - * @param complete Callback for when the image has been retrieved. - * @param lowResolution If not null and a lower resolution image is - * available prior to retrieving the preview, this will be called - * with the low resolution bitmap. - */ - public void retrieveOriginal(Uri contentUri, OriginalReady complete, ImageReady lowResolution) { - File localFile = getLocalFile(contentUri); - if (localFile != null) { - addNotification(new NotifyOriginalReady(complete), localFile); - } else { - NotifyImageReady notifyLowResolution = (lowResolution == null) ? null - : new NotifyImageReady(lowResolution); - addTask(contentUri, new NotifyOriginalReady(complete), notifyLowResolution, - MediaSize.Original); - } - } - - /** - * Looks for an already cached media at a specific size. - * - * @param contentUri The original media item content URI - * @param size The target size to search for in the cache - * @return The cached file location or null if it is not cached. - */ - public File getCachedFile(Uri contentUri, MediaSize size) { - Long cachedId = mDatabaseHelper.getCached(contentUri, size); - File file = null; - if (cachedId != null) { - file = createCacheImagePath(cachedId); - if (!file.exists()) { - mDatabaseHelper.delete(contentUri, size, mDeleteFile); - file = null; - } - } - return file; - } - - /** - * Inserts a media item into the cache. - * - * @param contentUri The original media item URI. - * @param size The size of the media item to store in the cache. - * @param tempFile The temporary file where the image is stored. This file - * will no longer exist after executing this method. - * @return The new location, in the cache, of the media item or null if it - * wasn't possible to move into the cache. - */ - public File insertIntoCache(Uri contentUri, MediaSize size, File tempFile) { - long fileSize = tempFile.length(); - if (fileSize == 0) { - return null; - } - File cacheFile = null; - SQLiteDatabase db = mDatabaseHelper.getWritableDatabase(); - // Ensure that this step is atomic - db.beginTransaction(); - try { - Long id = mDatabaseHelper.getCached(contentUri, size); - if (id != null) { - cacheFile = createCacheImagePath(id); - if (tempFile.renameTo(cacheFile)) { - mDatabaseHelper.updateLength(id, fileSize); - } else { - Log.w(TAG, "Could not update cached file with " + tempFile); - tempFile.delete(); - cacheFile = null; - } - } else { - ensureFreeCacheSpace(tempFile.length(), size); - id = mDatabaseHelper.insert(contentUri, size, mMoveTempToCache, tempFile); - cacheFile = createCacheImagePath(id); - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - return cacheFile; - } - - /** - * For testing purposes. - */ - public void setMaxCacheSize(long maxCacheSize) { - synchronized (mCacheSizeLock) { - mMaxCacheSize = maxCacheSize; - mMinThumbCacheSize = mMaxCacheSize / 10; - mCacheSize = -1; - mThumbCacheSize = -1; - } - } - - private File createCacheImagePath(long id) { - return new File(getCacheDir(), String.valueOf(id) + IMAGE_EXTENSION); - } - - private void addTask(Uri contentUri, ImageReady complete, ImageReady lowResolution, - MediaSize size) { - NotifyReady notifyComplete = new NotifyImageReady(complete); - NotifyImageReady notifyLowResolution = null; - if (lowResolution != null) { - notifyLowResolution = new NotifyImageReady(lowResolution); - } - addTask(contentUri, notifyComplete, notifyLowResolution, size); - } - - private void addTask(Uri contentUri, NotifyReady complete, NotifyImageReady lowResolution, - MediaSize size) { - MediaRetriever retriever = getMediaRetriever(contentUri); - Uri uri = retriever.normalizeUri(contentUri, size); - if (uri == null) { - throw new IllegalArgumentException("No MediaRetriever for " + contentUri); - } - size = retriever.normalizeMediaSize(uri, size); - - File cachedFile = getCachedFile(uri, size); - if (cachedFile != null) { - addNotification(complete, cachedFile); - return; - } - String differentiator = getDifferentiator(uri.getScheme(), uri.getAuthority()); - synchronized (mTasks) { - List<ProcessingJob> tasks = mTasks.get(differentiator); - if (tasks == null) { - throw new IllegalArgumentException("Cannot find retriever for: " + uri); - } - synchronized (tasks) { - ProcessingJob job = new ProcessingJob(uri, size, complete, lowResolution); - if (complete.isPrefetch()) { - tasks.add(job); - } else { - int index = tasks.size() - 1; - while (index >= 0 && tasks.get(index).complete.isPrefetch()) { - index--; - } - tasks.add(index + 1, job); - } - tasks.notifyAll(); - } - } - } - - private MediaRetriever getMediaRetriever(Uri uri) { - String differentiator = getDifferentiator(uri.getScheme(), uri.getAuthority()); - MediaRetriever retriever; - synchronized (mRetrievers) { - retriever = mRetrievers.get(differentiator); - } - if (retriever == null) { - throw new IllegalArgumentException("No MediaRetriever for " + uri); - } - return retriever; - } - - private File getLocalFile(Uri uri) { - MediaRetriever retriever = getMediaRetriever(uri); - File localFile = null; - if (retriever != null) { - localFile = retriever.getLocalFile(uri); - } - return localFile; - } - - private MediaSize getFastImageSize(Uri uri, MediaSize size) { - MediaRetriever retriever = getMediaRetriever(uri); - return retriever.getFastImageSize(uri, size); - } - - private boolean isFastImageBetter(MediaSize fastImageType, MediaSize size) { - if (fastImageType == null) { - return false; - } - if (size == null) { - return true; - } - return fastImageType.isBetterThan(size); - } - - private byte[] getTemporaryImage(Uri uri, MediaSize fastImageType) { - MediaRetriever retriever = getMediaRetriever(uri); - return retriever.getTemporaryImage(uri, fastImageType); - } - - private void processTask(ProcessingJob job) { - File cachedFile = getCachedFile(job.contentUri, job.size); - if (cachedFile != null) { - addNotification(job.complete, cachedFile); - return; - } - - boolean hasLowResolution = job.lowResolution != null; - if (hasLowResolution) { - MediaSize cachedSize = mDatabaseHelper.executeOnBestCached(job.contentUri, job.size, - mNotifyCachedLowResolution); - MediaSize fastImageSize = getFastImageSize(job.contentUri, job.size); - if (isFastImageBetter(fastImageSize, cachedSize)) { - if (fastImageSize.isTemporary()) { - byte[] bytes = getTemporaryImage(job.contentUri, fastImageSize); - if (bytes != null) { - addNotification(job.lowResolution, bytes); - } - } else { - File lowFile = getMedia(job.contentUri, fastImageSize); - if (lowFile != null) { - addNotification(job.lowResolution, lowFile); - } - } - } - } - - // Now get the full size desired - File fullSizeFile = getMedia(job.contentUri, job.size); - if (fullSizeFile != null) { - addNotification(job.complete, fullSizeFile); - } - } - - private void addNotification(NotifyReady callback, File file) { - try { - callback.setFile(file); - synchronized (mCallbacks) { - mCallbacks.add(callback); - mCallbacks.notifyAll(); - } - } catch (FileNotFoundException e) { - Log.e(TAG, "Unable to read file " + file, e); - } - } - - private void addNotification(NotifyImageReady callback, byte[] bytes) { - callback.setBytes(bytes); - synchronized (mCallbacks) { - mCallbacks.add(callback); - mCallbacks.notifyAll(); - } - } - - private File getMedia(Uri uri, MediaSize size) { - long imageNumber; - synchronized (mTempImageNumberLock) { - imageNumber = mTempImageNumber++; - } - File tempFile = new File(getCacheDir(), String.valueOf(imageNumber) + TEMP_IMAGE_EXTENSION); - MediaRetriever retriever = getMediaRetriever(uri); - boolean retrieved = retriever.getMedia(uri, size, tempFile); - File cachedFile = null; - if (retrieved) { - ensureFreeCacheSpace(tempFile.length(), size); - long id = mDatabaseHelper.insert(uri, size, mMoveTempToCache, tempFile); - cachedFile = createCacheImagePath(id); - } - return cachedFile; - } - - private static String getDifferentiator(String scheme, String authority) { - if (authority == null) { - return scheme; - } - StringBuilder differentiator = new StringBuilder(scheme); - differentiator.append(':'); - differentiator.append(authority); - return differentiator.toString(); - } - - private void ensureFreeCacheSpace(long size, MediaSize mediaSize) { - synchronized (mCacheSizeLock) { - if (mCacheSize == -1 || mThumbCacheSize == -1) { - mCacheSize = mDatabaseHelper.getCacheSize(); - mThumbCacheSize = mDatabaseHelper.getThumbnailCacheSize(); - if (mCacheSize == -1 || mThumbCacheSize == -1) { - Log.e(TAG, "Can't determine size of the image cache"); - return; - } - } - mCacheSize += size; - if (mediaSize == MediaSize.Thumbnail) { - mThumbCacheSize += size; - } - if (mCacheSize > mMaxCacheSize) { - shrinkCacheLocked(); - } - } - } - - private void shrinkCacheLocked() { - long deleteSize = mMinThumbCacheSize; - boolean includeThumbnails = (mThumbCacheSize - deleteSize) > mMinThumbCacheSize; - mDatabaseHelper.deleteOldCached(includeThumbnails, deleteSize, mDeleteFile); - } -} diff --git a/src/com/android/photos/data/MediaCacheDatabase.java b/src/com/android/photos/data/MediaCacheDatabase.java deleted file mode 100644 index c92ac0fdf..000000000 --- a/src/com/android/photos/data/MediaCacheDatabase.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.content.ContentValues; -import android.content.Context; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.net.Uri; -import android.provider.BaseColumns; - -import com.android.photos.data.MediaRetriever.MediaSize; - -import java.io.File; - -class MediaCacheDatabase extends SQLiteOpenHelper { - public static final int DB_VERSION = 1; - public static final String DB_NAME = "mediacache.db"; - - /** Internal database table used for the media cache */ - public static final String TABLE = "media_cache"; - - private static interface Columns extends BaseColumns { - /** The Content URI of the original image. */ - public static final String URI = "uri"; - /** MediaSize.getValue() values. */ - public static final String MEDIA_SIZE = "media_size"; - /** The last time this image was queried. */ - public static final String LAST_ACCESS = "last_access"; - /** The image size in bytes. */ - public static final String SIZE_IN_BYTES = "size"; - } - - static interface Action { - void execute(Uri uri, long id, MediaSize size, Object parameter); - } - - private static final String[] PROJECTION_ID = { - Columns._ID, - }; - - private static final String[] PROJECTION_CACHED = { - Columns._ID, Columns.MEDIA_SIZE, Columns.SIZE_IN_BYTES, - }; - - private static final String[] PROJECTION_CACHE_SIZE = { - "SUM(" + Columns.SIZE_IN_BYTES + ")" - }; - - private static final String[] PROJECTION_DELETE_OLD = { - Columns._ID, Columns.URI, Columns.MEDIA_SIZE, Columns.SIZE_IN_BYTES, Columns.LAST_ACCESS, - }; - - public static final String CREATE_TABLE = "CREATE TABLE " + TABLE + "(" - + Columns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " - + Columns.URI + " TEXT NOT NULL," - + Columns.MEDIA_SIZE + " INTEGER NOT NULL," - + Columns.LAST_ACCESS + " INTEGER NOT NULL," - + Columns.SIZE_IN_BYTES + " INTEGER NOT NULL," - + "UNIQUE(" + Columns.URI + ", " + Columns.MEDIA_SIZE + "))"; - - public static final String DROP_TABLE = "DROP TABLE IF EXISTS " + TABLE; - - public static final String WHERE_THUMBNAIL = Columns.MEDIA_SIZE + " = " - + MediaSize.Thumbnail.getValue(); - - public static final String WHERE_NOT_THUMBNAIL = Columns.MEDIA_SIZE + " <> " - + MediaSize.Thumbnail.getValue(); - - public static final String WHERE_CLEAR_CACHE = Columns.LAST_ACCESS + " <= ?"; - - public static final String WHERE_CLEAR_CACHE_LARGE = WHERE_CLEAR_CACHE + " AND " - + WHERE_NOT_THUMBNAIL; - - static class QueryCacheResults { - public QueryCacheResults(long id, int sizeVal) { - this.id = id; - this.size = MediaSize.fromInteger(sizeVal); - } - public long id; - public MediaSize size; - } - - public MediaCacheDatabase(Context context) { - super(context, DB_NAME, null, DB_VERSION); - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL(CREATE_TABLE); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - db.execSQL(DROP_TABLE); - onCreate(db); - MediaCache.getInstance().clearCacheDir(); - } - - public Long getCached(Uri uri, MediaSize size) { - String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " = ?"; - SQLiteDatabase db = getWritableDatabase(); - String[] whereArgs = { - uri.toString(), String.valueOf(size.getValue()), - }; - Cursor cursor = db.query(TABLE, PROJECTION_ID, where, whereArgs, null, null, null); - Long id = null; - if (cursor.moveToNext()) { - id = cursor.getLong(0); - } - cursor.close(); - if (id != null) { - String[] updateArgs = { - id.toString() - }; - ContentValues values = new ContentValues(); - values.put(Columns.LAST_ACCESS, System.currentTimeMillis()); - db.beginTransaction(); - try { - db.update(TABLE, values, Columns._ID + " = ?", updateArgs); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - return id; - } - - public MediaSize executeOnBestCached(Uri uri, MediaSize size, Action action) { - String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " < ?"; - String orderBy = Columns.MEDIA_SIZE + " DESC"; - SQLiteDatabase db = getReadableDatabase(); - String[] whereArgs = { - uri.toString(), String.valueOf(size.getValue()), - }; - Cursor cursor = db.query(TABLE, PROJECTION_CACHED, where, whereArgs, null, null, orderBy); - MediaSize bestSize = null; - if (cursor.moveToNext()) { - long id = cursor.getLong(0); - bestSize = MediaSize.fromInteger(cursor.getInt(1)); - long fileSize = cursor.getLong(2); - action.execute(uri, id, bestSize, fileSize); - } - cursor.close(); - return bestSize; - } - - public long insert(Uri uri, MediaSize size, Action action, File tempFile) { - SQLiteDatabase db = getWritableDatabase(); - db.beginTransaction(); - try { - ContentValues values = new ContentValues(); - values.put(Columns.LAST_ACCESS, System.currentTimeMillis()); - values.put(Columns.MEDIA_SIZE, size.getValue()); - values.put(Columns.URI, uri.toString()); - values.put(Columns.SIZE_IN_BYTES, tempFile.length()); - long id = db.insert(TABLE, null, values); - if (id != -1) { - action.execute(uri, id, size, tempFile); - db.setTransactionSuccessful(); - } - return id; - } finally { - db.endTransaction(); - } - } - - public void updateLength(long id, long fileSize) { - ContentValues values = new ContentValues(); - values.put(Columns.SIZE_IN_BYTES, fileSize); - String[] whereArgs = { - String.valueOf(id) - }; - SQLiteDatabase db = getWritableDatabase(); - db.beginTransaction(); - try { - db.update(TABLE, values, Columns._ID + " = ?", whereArgs); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - public void delete(Uri uri, MediaSize size, Action action) { - String where = Columns.URI + " = ? AND " + Columns.MEDIA_SIZE + " = ?"; - String[] whereArgs = { - uri.toString(), String.valueOf(size.getValue()), - }; - deleteRows(uri, where, whereArgs, action); - } - - public void delete(Uri uri, Action action) { - String where = Columns.URI + " = ?"; - String[] whereArgs = { - uri.toString() - }; - deleteRows(uri, where, whereArgs, action); - } - - private void deleteRows(Uri uri, String where, String[] whereArgs, Action action) { - SQLiteDatabase db = getWritableDatabase(); - // Make this an atomic operation - db.beginTransaction(); - Cursor cursor = db.query(TABLE, PROJECTION_CACHED, where, whereArgs, null, null, null); - while (cursor.moveToNext()) { - long id = cursor.getLong(0); - MediaSize size = MediaSize.fromInteger(cursor.getInt(1)); - long length = cursor.getLong(2); - action.execute(uri, id, size, length); - } - cursor.close(); - try { - db.delete(TABLE, where, whereArgs); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - public void deleteOldCached(boolean includeThumbnails, long deleteSize, Action action) { - String where = includeThumbnails ? null : WHERE_NOT_THUMBNAIL; - long lastAccess = 0; - SQLiteDatabase db = getWritableDatabase(); - db.beginTransaction(); - try { - Cursor cursor = db.query(TABLE, PROJECTION_DELETE_OLD, where, null, null, null, - Columns.LAST_ACCESS); - while (cursor.moveToNext()) { - long id = cursor.getLong(0); - String uri = cursor.getString(1); - MediaSize size = MediaSize.fromInteger(cursor.getInt(2)); - long length = cursor.getLong(3); - long imageLastAccess = cursor.getLong(4); - - if (imageLastAccess != lastAccess && deleteSize < 0) { - break; // We've deleted enough. - } - lastAccess = imageLastAccess; - action.execute(Uri.parse(uri), id, size, length); - deleteSize -= length; - } - cursor.close(); - String[] whereArgs = { - String.valueOf(lastAccess), - }; - String whereDelete = includeThumbnails ? WHERE_CLEAR_CACHE : WHERE_CLEAR_CACHE_LARGE; - db.delete(TABLE, whereDelete, whereArgs); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - public long getCacheSize() { - return getCacheSize(null); - } - - public long getThumbnailCacheSize() { - return getCacheSize(WHERE_THUMBNAIL); - } - - private long getCacheSize(String where) { - SQLiteDatabase db = getReadableDatabase(); - Cursor cursor = db.query(TABLE, PROJECTION_CACHE_SIZE, where, null, null, null, null); - long size = -1; - if (cursor.moveToNext()) { - size = cursor.getLong(0); - } - cursor.close(); - return size; - } -} diff --git a/src/com/android/photos/data/MediaCacheUtils.java b/src/com/android/photos/data/MediaCacheUtils.java deleted file mode 100644 index e3ccd1402..000000000 --- a/src/com/android/photos/data/MediaCacheUtils.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.content.Context; -import android.content.res.Resources; -import android.graphics.Bitmap; -import android.graphics.Bitmap.CompressFormat; -import android.graphics.BitmapFactory; -import android.util.Log; -import android.util.Pools.SimplePool; -import android.util.Pools.SynchronizedPool; - -import com.android.gallery3d.R; -import com.android.gallery3d.common.BitmapUtils; -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.data.DecodeUtils; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.util.ThreadPool.CancelListener; -import com.android.gallery3d.util.ThreadPool.JobContext; -import com.android.photos.data.MediaRetriever.MediaSize; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -public class MediaCacheUtils { - private static final String TAG = MediaCacheUtils.class.getSimpleName(); - private static int QUALITY = 80; - private static final int BUFFER_SIZE = 4096; - private static final SimplePool<byte[]> mBufferPool = new SynchronizedPool<byte[]>(5); - - private static final JobContext sJobStub = new JobContext() { - - @Override - public boolean isCancelled() { - return false; - } - - @Override - public void setCancelListener(CancelListener listener) { - } - - @Override - public boolean setMode(int mode) { - return true; - } - }; - - private static int mTargetThumbnailSize; - private static int mTargetPreviewSize; - - public static void initialize(Context context) { - Resources resources = context.getResources(); - mTargetThumbnailSize = resources.getDimensionPixelSize(R.dimen.size_thumbnail); - mTargetPreviewSize = resources.getDimensionPixelSize(R.dimen.size_preview); - } - - public static int getTargetSize(MediaSize size) { - return (size == MediaSize.Thumbnail) ? mTargetThumbnailSize : mTargetPreviewSize; - } - - public static boolean downsample(File inBitmap, MediaSize targetSize, File outBitmap) { - if (MediaSize.Original == targetSize) { - return false; // MediaCache should use the local path for this. - } - int size = getTargetSize(targetSize); - BitmapFactory.Options options = new BitmapFactory.Options(); - options.inPreferredConfig = Bitmap.Config.ARGB_8888; - // TODO: remove unnecessary job context from DecodeUtils. - Bitmap bitmap = DecodeUtils.decodeThumbnail(sJobStub, inBitmap.getPath(), options, size, - MediaItem.TYPE_THUMBNAIL); - boolean success = (bitmap != null); - if (success) { - success = writeAndRecycle(bitmap, outBitmap); - } - return success; - } - - public static boolean downsample(Bitmap inBitmap, MediaSize size, File outBitmap) { - if (MediaSize.Original == size) { - return false; // MediaCache should use the local path for this. - } - int targetSize = getTargetSize(size); - boolean success; - if (!needsDownsample(inBitmap, size)) { - success = writeAndRecycle(inBitmap, outBitmap); - } else { - float maxDimension = Math.max(inBitmap.getWidth(), inBitmap.getHeight()); - float scale = targetSize / maxDimension; - int targetWidth = Math.round(scale * inBitmap.getWidth()); - int targetHeight = Math.round(scale * inBitmap.getHeight()); - Bitmap scaled = Bitmap.createScaledBitmap(inBitmap, targetWidth, targetHeight, false); - success = writeAndRecycle(scaled, outBitmap); - inBitmap.recycle(); - } - return success; - } - - public static boolean extractImageFromVideo(File inVideo, File outBitmap) { - Bitmap bitmap = BitmapUtils.createVideoThumbnail(inVideo.getPath()); - return writeAndRecycle(bitmap, outBitmap); - } - - public static boolean needsDownsample(Bitmap bitmap, MediaSize size) { - if (size == MediaSize.Original) { - return false; - } - int targetSize = getTargetSize(size); - int maxDimension = Math.max(bitmap.getWidth(), bitmap.getHeight()); - return maxDimension > (targetSize * 4 / 3); - } - - public static boolean writeAndRecycle(Bitmap bitmap, File outBitmap) { - boolean success = writeToFile(bitmap, outBitmap); - bitmap.recycle(); - return success; - } - - public static boolean writeToFile(Bitmap bitmap, File outBitmap) { - boolean success = false; - try { - FileOutputStream out = new FileOutputStream(outBitmap); - success = bitmap.compress(CompressFormat.JPEG, QUALITY, out); - out.close(); - } catch (IOException e) { - Log.w(TAG, "Couldn't write bitmap to cache", e); - // success is already false - } - return success; - } - - public static int copyStream(InputStream in, OutputStream out) throws IOException { - byte[] buffer = mBufferPool.acquire(); - if (buffer == null) { - buffer = new byte[BUFFER_SIZE]; - } - try { - int totalWritten = 0; - int bytesRead; - while ((bytesRead = in.read(buffer)) >= 0) { - out.write(buffer, 0, bytesRead); - totalWritten += bytesRead; - } - return totalWritten; - } finally { - Utils.closeSilently(in); - Utils.closeSilently(out); - mBufferPool.release(buffer); - } - } -} diff --git a/src/com/android/photos/data/MediaRetriever.java b/src/com/android/photos/data/MediaRetriever.java deleted file mode 100644 index f383e5ffa..000000000 --- a/src/com/android/photos/data/MediaRetriever.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.data; - -import android.net.Uri; - -import java.io.File; - -public interface MediaRetriever { - public enum MediaSize { - TemporaryThumbnail(5), Thumbnail(10), TemporaryPreview(15), Preview(20), Original(30); - - private final int mValue; - - private MediaSize(int value) { - mValue = value; - } - - public int getValue() { - return mValue; - } - - static MediaSize fromInteger(int value) { - switch (value) { - case 10: - return MediaSize.Thumbnail; - case 20: - return MediaSize.Preview; - case 30: - return MediaSize.Original; - default: - throw new IllegalArgumentException(); - } - } - - public boolean isBetterThan(MediaSize that) { - return mValue > that.mValue; - } - - public boolean isTemporary() { - return this == TemporaryThumbnail || this == TemporaryPreview; - } - } - - /** - * Returns the local File for the given Uri. If the image is not stored - * locally, null should be returned. The image should not be retrieved if it - * isn't already available. - * - * @param contentUri The media URI to search for. - * @return The local File of the image if it is available or null if it - * isn't. - */ - File getLocalFile(Uri contentUri); - - /** - * Returns the fast access image type for a given image size, if supported. - * This image should be smaller than size and should be quick to retrieve. - * It does not have to obey the expected aspect ratio. - * - * @param contentUri The original media Uri. - * @param size The target size to search for a fast-access image. - * @return The fast image type supported for the given image size or null of - * no fast image is supported. - */ - MediaSize getFastImageSize(Uri contentUri, MediaSize size); - - /** - * Returns a byte array containing the contents of the fast temporary image - * for a given image size. For example, a thumbnail may be smaller or of a - * different aspect ratio than the generated thumbnail. - * - * @param contentUri The original media Uri. - * @param temporarySize The target media size. Guaranteed to be a MediaSize - * for which isTemporary() returns true. - * @return A byte array of contents for for the given contentUri and - * fastImageType. null can be retrieved if the quick retrieval - * fails. - */ - byte[] getTemporaryImage(Uri contentUri, MediaSize temporarySize); - - /** - * Retrieves an image and saves it to a file. - * - * @param contentUri The original media Uri. - * @param size The target media size. - * @param tempFile The file to write the bitmap to. - * @return <code>true</code> on success. - */ - boolean getMedia(Uri contentUri, MediaSize imageSize, File tempFile); - - /** - * Normalizes a URI that may have additional parameters. It is fine to - * return contentUri. This is executed on the calling thread, so it must be - * a fast access operation and cannot depend, for example, on I/O. - * - * @param contentUri The URI to normalize - * @param size The size of the image being requested - * @return The normalized URI representation of contentUri. - */ - Uri normalizeUri(Uri contentUri, MediaSize size); - - /** - * Normalize the MediaSize for a given URI. Typically the size returned - * would be the passed-in size. Some URIs may only have one size used and - * should be treaded as Thumbnails, for example. This is executed on the - * calling thread, so it must be a fast access operation and cannot depend, - * for example, on I/O. - * - * @param contentUri The URI for the size being normalized. - * @param size The size to be normalized. - * @return The normalized size of the given URI. - */ - MediaSize normalizeMediaSize(Uri contentUri, MediaSize size); -} diff --git a/src/com/android/photos/data/NotificationWatcher.java b/src/com/android/photos/data/NotificationWatcher.java deleted file mode 100644 index 9041c236f..000000000 --- a/src/com/android/photos/data/NotificationWatcher.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.net.Uri; - -import com.android.photos.data.PhotoProvider.ChangeNotification; - -import java.util.ArrayList; - -/** - * Used for capturing notifications from PhotoProvider without relying on - * ContentResolver. MockContentResolver does not allow sending notification to - * ContentObservers, so PhotoProvider allows this alternative for testing. - */ -public class NotificationWatcher implements ChangeNotification { - private ArrayList<Uri> mUris = new ArrayList<Uri>(); - private boolean mSyncToNetwork = false; - - @Override - public void notifyChange(Uri uri, boolean syncToNetwork) { - mUris.add(uri); - mSyncToNetwork = mSyncToNetwork || syncToNetwork; - } - - public boolean isNotified(Uri uri) { - return mUris.contains(uri); - } - - public int notificationCount() { - return mUris.size(); - } - - public boolean syncToNetwork() { - return mSyncToNetwork; - } - - public void reset() { - mUris.clear(); - mSyncToNetwork = false; - } -} diff --git a/src/com/android/photos/data/PhotoDatabase.java b/src/com/android/photos/data/PhotoDatabase.java deleted file mode 100644 index 0c7b22730..000000000 --- a/src/com/android/photos/data/PhotoDatabase.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.content.Context; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; - -import com.android.photos.data.PhotoProvider.Accounts; -import com.android.photos.data.PhotoProvider.Albums; -import com.android.photos.data.PhotoProvider.Metadata; -import com.android.photos.data.PhotoProvider.Photos; - -import java.util.ArrayList; -import java.util.List; - -/** - * Used in PhotoProvider to create and access the database containing - * information about photo and video information stored on the server. - */ -public class PhotoDatabase extends SQLiteOpenHelper { - @SuppressWarnings("unused") - private static final String TAG = PhotoDatabase.class.getSimpleName(); - static final int DB_VERSION = 3; - - private static final String SQL_CREATE_TABLE = "CREATE TABLE "; - - private static final String[][] CREATE_PHOTO = { - { Photos._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" }, - // Photos.ACCOUNT_ID is a foreign key to Accounts._ID - { Photos.ACCOUNT_ID, "INTEGER NOT NULL" }, - { Photos.WIDTH, "INTEGER NOT NULL" }, - { Photos.HEIGHT, "INTEGER NOT NULL" }, - { Photos.DATE_TAKEN, "INTEGER NOT NULL" }, - // Photos.ALBUM_ID is a foreign key to Albums._ID - { Photos.ALBUM_ID, "INTEGER" }, - { Photos.MIME_TYPE, "TEXT NOT NULL" }, - { Photos.TITLE, "TEXT" }, - { Photos.DATE_MODIFIED, "INTEGER" }, - { Photos.ROTATION, "INTEGER" }, - }; - - private static final String[][] CREATE_ALBUM = { - { Albums._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" }, - // Albums.ACCOUNT_ID is a foreign key to Accounts._ID - { Albums.ACCOUNT_ID, "INTEGER NOT NULL" }, - // Albums.PARENT_ID is a foreign key to Albums._ID - { Albums.PARENT_ID, "INTEGER" }, - { Albums.ALBUM_TYPE, "TEXT" }, - { Albums.VISIBILITY, "INTEGER NOT NULL" }, - { Albums.LOCATION_STRING, "TEXT" }, - { Albums.TITLE, "TEXT NOT NULL" }, - { Albums.SUMMARY, "TEXT" }, - { Albums.DATE_PUBLISHED, "INTEGER" }, - { Albums.DATE_MODIFIED, "INTEGER" }, - createUniqueConstraint(Albums.PARENT_ID, Albums.TITLE), - }; - - private static final String[][] CREATE_METADATA = { - { Metadata._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" }, - // Metadata.PHOTO_ID is a foreign key to Photos._ID - { Metadata.PHOTO_ID, "INTEGER NOT NULL" }, - { Metadata.KEY, "TEXT NOT NULL" }, - { Metadata.VALUE, "TEXT NOT NULL" }, - createUniqueConstraint(Metadata.PHOTO_ID, Metadata.KEY), - }; - - private static final String[][] CREATE_ACCOUNT = { - { Accounts._ID, "INTEGER PRIMARY KEY AUTOINCREMENT" }, - { Accounts.ACCOUNT_NAME, "TEXT UNIQUE NOT NULL" }, - }; - - @Override - public void onCreate(SQLiteDatabase db) { - createTable(db, Accounts.TABLE, getAccountTableDefinition()); - createTable(db, Albums.TABLE, getAlbumTableDefinition()); - createTable(db, Photos.TABLE, getPhotoTableDefinition()); - createTable(db, Metadata.TABLE, getMetadataTableDefinition()); - } - - public PhotoDatabase(Context context, String dbName, int dbVersion) { - super(context, dbName, null, dbVersion); - } - - public PhotoDatabase(Context context, String dbName) { - super(context, dbName, null, DB_VERSION); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - recreate(db); - } - - @Override - public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { - recreate(db); - } - - private void recreate(SQLiteDatabase db) { - dropTable(db, Metadata.TABLE); - dropTable(db, Photos.TABLE); - dropTable(db, Albums.TABLE); - dropTable(db, Accounts.TABLE); - onCreate(db); - } - - protected List<String[]> getAlbumTableDefinition() { - return tableCreationStrings(CREATE_ALBUM); - } - - protected List<String[]> getPhotoTableDefinition() { - return tableCreationStrings(CREATE_PHOTO); - } - - protected List<String[]> getMetadataTableDefinition() { - return tableCreationStrings(CREATE_METADATA); - } - - protected List<String[]> getAccountTableDefinition() { - return tableCreationStrings(CREATE_ACCOUNT); - } - - protected static void createTable(SQLiteDatabase db, String table, List<String[]> columns) { - StringBuilder create = new StringBuilder(SQL_CREATE_TABLE); - create.append(table).append('('); - boolean first = true; - for (String[] column : columns) { - if (!first) { - create.append(','); - } - first = false; - for (String val: column) { - create.append(val).append(' '); - } - } - create.append(')'); - db.beginTransaction(); - try { - db.execSQL(create.toString()); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - protected static String[] createUniqueConstraint(String column1, String column2) { - return new String[] { - "UNIQUE(", column1, ",", column2, ")" - }; - } - - protected static List<String[]> tableCreationStrings(String[][] createTable) { - ArrayList<String[]> create = new ArrayList<String[]>(createTable.length); - for (String[] line: createTable) { - create.add(line); - } - return create; - } - - protected static void addToTable(List<String[]> createTable, String[][] columns, String[][] constraints) { - if (columns != null) { - for (String[] column: columns) { - createTable.add(0, column); - } - } - if (constraints != null) { - for (String[] constraint: constraints) { - createTable.add(constraint); - } - } - } - - protected static void dropTable(SQLiteDatabase db, String table) { - db.beginTransaction(); - try { - db.execSQL("drop table if exists " + table); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } -} diff --git a/src/com/android/photos/data/PhotoProvider.java b/src/com/android/photos/data/PhotoProvider.java deleted file mode 100644 index d4310ca95..000000000 --- a/src/com/android/photos/data/PhotoProvider.java +++ /dev/null @@ -1,536 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.photos.data; - -import android.content.ContentResolver; -import android.content.ContentUris; -import android.content.ContentValues; -import android.content.Context; -import android.content.UriMatcher; -import android.database.Cursor; -import android.database.DatabaseUtils; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.database.sqlite.SQLiteQueryBuilder; -import android.media.ExifInterface; -import android.net.Uri; -import android.os.CancellationSignal; -import android.provider.BaseColumns; - -import com.android.gallery3d.common.ApiHelper; - -import java.util.List; - -/** - * A provider that gives access to photo and video information for media stored - * on the server. Only media that is or will be put on the server will be - * accessed by this provider. Use Photos.CONTENT_URI to query all photos and - * videos. Use Albums.CONTENT_URI to query all albums. Use Metadata.CONTENT_URI - * to query metadata about a photo or video, based on the ID of the media. Use - * ImageCache.THUMBNAIL_CONTENT_URI, ImageCache.PREVIEW_CONTENT_URI, or - * ImageCache.ORIGINAL_CONTENT_URI to query the path of the thumbnail, preview, - * or original-sized image respectfully. <br/> - * To add or update metadata, use the update function rather than insert. All - * values for the metadata must be in the ContentValues, even if they are also - * in the selection. The selection and selectionArgs are not used when updating - * metadata. If the metadata values are null, the row will be deleted. - */ -public class PhotoProvider extends SQLiteContentProvider { - @SuppressWarnings("unused") - private static final String TAG = PhotoProvider.class.getSimpleName(); - - protected static final String DB_NAME = "photo.db"; - public static final String AUTHORITY = PhotoProviderAuthority.AUTHORITY; - static final Uri BASE_CONTENT_URI = new Uri.Builder().scheme("content").authority(AUTHORITY) - .build(); - - // Used to allow mocking out the change notification because - // MockContextResolver disallows system-wide notification. - public static interface ChangeNotification { - void notifyChange(Uri uri, boolean syncToNetwork); - } - - /** - * Contains columns that can be accessed via Accounts.CONTENT_URI - */ - public static interface Accounts extends BaseColumns { - /** - * Internal database table used for account information - */ - public static final String TABLE = "accounts"; - /** - * Content URI for account information - */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); - /** - * User name for this account. - */ - public static final String ACCOUNT_NAME = "name"; - } - - /** - * Contains columns that can be accessed via Photos.CONTENT_URI. - */ - public static interface Photos extends BaseColumns { - /** - * The image_type query parameter required for requesting a specific - * size of image. - */ - public static final String MEDIA_SIZE_QUERY_PARAMETER = "media_size"; - - /** Internal database table used for basic photo information. */ - public static final String TABLE = "photos"; - /** Content URI for basic photo and video information. */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); - - /** Long foreign key to Accounts._ID */ - public static final String ACCOUNT_ID = "account_id"; - /** Column name for the width of the original image. Integer value. */ - public static final String WIDTH = "width"; - /** Column name for the height of the original image. Integer value. */ - public static final String HEIGHT = "height"; - /** - * Column name for the date that the original image was taken. Long - * value indicating the milliseconds since epoch in the GMT time zone. - */ - public static final String DATE_TAKEN = "date_taken"; - /** - * Column name indicating the long value of the album id that this image - * resides in. Will be NULL if it it has not been uploaded to the - * server. - */ - public static final String ALBUM_ID = "album_id"; - /** The column name for the mime-type String. */ - public static final String MIME_TYPE = "mime_type"; - /** The title of the photo. String value. */ - public static final String TITLE = "title"; - /** The date the photo entry was last updated. Long value. */ - public static final String DATE_MODIFIED = "date_modified"; - /** - * The rotation of the photo in degrees, if rotation has not already - * been applied. Integer value. - */ - public static final String ROTATION = "rotation"; - } - - /** - * Contains columns and Uri for accessing album information. - */ - public static interface Albums extends BaseColumns { - /** Internal database table used album information. */ - public static final String TABLE = "albums"; - /** Content URI for album information. */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); - - /** Long foreign key to Accounts._ID */ - public static final String ACCOUNT_ID = "account_id"; - /** Parent directory or null if this is in the root. */ - public static final String PARENT_ID = "parent_id"; - /** The type of album. Non-null, if album is auto-generated. String value. */ - public static final String ALBUM_TYPE = "album_type"; - /** - * Column name for the visibility level of the album. Can be any of the - * VISIBILITY_* values. - */ - public static final String VISIBILITY = "visibility"; - /** The user-specified location associated with the album. String value. */ - public static final String LOCATION_STRING = "location_string"; - /** The title of the album. String value. */ - public static final String TITLE = "title"; - /** A short summary of the contents of the album. String value. */ - public static final String SUMMARY = "summary"; - /** The date the album was created. Long value */ - public static final String DATE_PUBLISHED = "date_published"; - /** The date the album entry was last updated. Long value. */ - public static final String DATE_MODIFIED = "date_modified"; - - // Privacy values for Albums.VISIBILITY - public static final int VISIBILITY_PRIVATE = 1; - public static final int VISIBILITY_SHARED = 2; - public static final int VISIBILITY_PUBLIC = 3; - } - - /** - * Contains columns and Uri for accessing photo and video metadata - */ - public static interface Metadata extends BaseColumns { - /** Internal database table used metadata information. */ - public static final String TABLE = "metadata"; - /** Content URI for photo and video metadata. */ - public static final Uri CONTENT_URI = Uri.withAppendedPath(BASE_CONTENT_URI, TABLE); - /** Foreign key to photo_id. Long value. */ - public static final String PHOTO_ID = "photo_id"; - /** Metadata key. String value */ - public static final String KEY = "key"; - /** - * Metadata value. Type is based on key. - */ - public static final String VALUE = "value"; - - /** A short summary of the photo. String value. */ - public static final String KEY_SUMMARY = "summary"; - /** The date the photo was added. Long value. */ - public static final String KEY_PUBLISHED = "date_published"; - /** The date the photo was last updated. Long value. */ - public static final String KEY_DATE_UPDATED = "date_updated"; - /** The size of the photo is bytes. Integer value. */ - public static final String KEY_SIZE_IN_BTYES = "size"; - /** The latitude associated with the photo. Double value. */ - public static final String KEY_LATITUDE = "latitude"; - /** The longitude associated with the photo. Double value. */ - public static final String KEY_LONGITUDE = "longitude"; - - /** The make of the camera used. String value. */ - public static final String KEY_EXIF_MAKE = ExifInterface.TAG_MAKE; - /** The model of the camera used. String value. */ - public static final String KEY_EXIF_MODEL = ExifInterface.TAG_MODEL;; - /** The exposure time used. Float value. */ - public static final String KEY_EXIF_EXPOSURE = ExifInterface.TAG_EXPOSURE_TIME; - /** Whether the flash was used. Boolean value. */ - public static final String KEY_EXIF_FLASH = ExifInterface.TAG_FLASH; - /** The focal length used. Float value. */ - public static final String KEY_EXIF_FOCAL_LENGTH = ExifInterface.TAG_FOCAL_LENGTH; - /** The fstop value used. Float value. */ - public static final String KEY_EXIF_FSTOP = ExifInterface.TAG_APERTURE; - /** The ISO equivalent value used. Integer value. */ - public static final String KEY_EXIF_ISO = ExifInterface.TAG_ISO; - } - - // SQL used within this class. - protected static final String WHERE_ID = BaseColumns._ID + " = ?"; - protected static final String WHERE_METADATA_ID = Metadata.PHOTO_ID + " = ? AND " - + Metadata.KEY + " = ?"; - - protected static final String SELECT_ALBUM_ID = "SELECT " + Albums._ID + " FROM " - + Albums.TABLE; - protected static final String SELECT_PHOTO_ID = "SELECT " + Photos._ID + " FROM " - + Photos.TABLE; - protected static final String SELECT_PHOTO_COUNT = "SELECT COUNT(*) FROM " + Photos.TABLE; - protected static final String DELETE_PHOTOS = "DELETE FROM " + Photos.TABLE; - protected static final String DELETE_METADATA = "DELETE FROM " + Metadata.TABLE; - protected static final String SELECT_METADATA_COUNT = "SELECT COUNT(*) FROM " + Metadata.TABLE; - protected static final String WHERE = " WHERE "; - protected static final String IN = " IN "; - protected static final String NESTED_SELECT_START = "("; - protected static final String NESTED_SELECT_END = ")"; - protected static final String[] PROJECTION_COUNT = { - "COUNT(*)" - }; - - /** - * For selecting the mime-type for an image. - */ - private static final String[] PROJECTION_MIME_TYPE = { - Photos.MIME_TYPE, - }; - - protected static final String[] BASE_COLUMNS_ID = { - BaseColumns._ID, - }; - - protected ChangeNotification mNotifier = null; - protected static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH); - - protected static final int MATCH_PHOTO = 1; - protected static final int MATCH_PHOTO_ID = 2; - protected static final int MATCH_ALBUM = 3; - protected static final int MATCH_ALBUM_ID = 4; - protected static final int MATCH_METADATA = 5; - protected static final int MATCH_METADATA_ID = 6; - protected static final int MATCH_ACCOUNT = 7; - protected static final int MATCH_ACCOUNT_ID = 8; - - static { - sUriMatcher.addURI(AUTHORITY, Photos.TABLE, MATCH_PHOTO); - // match against Photos._ID - sUriMatcher.addURI(AUTHORITY, Photos.TABLE + "/#", MATCH_PHOTO_ID); - sUriMatcher.addURI(AUTHORITY, Albums.TABLE, MATCH_ALBUM); - // match against Albums._ID - sUriMatcher.addURI(AUTHORITY, Albums.TABLE + "/#", MATCH_ALBUM_ID); - sUriMatcher.addURI(AUTHORITY, Metadata.TABLE, MATCH_METADATA); - // match against metadata/<Metadata._ID> - sUriMatcher.addURI(AUTHORITY, Metadata.TABLE + "/#", MATCH_METADATA_ID); - sUriMatcher.addURI(AUTHORITY, Accounts.TABLE, MATCH_ACCOUNT); - // match against Accounts._ID - sUriMatcher.addURI(AUTHORITY, Accounts.TABLE + "/#", MATCH_ACCOUNT_ID); - } - - @Override - public int deleteInTransaction(Uri uri, String selection, String[] selectionArgs, - boolean callerIsSyncAdapter) { - int match = matchUri(uri); - selection = addIdToSelection(match, selection); - selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs); - return deleteCascade(uri, match, selection, selectionArgs); - } - - @Override - public String getType(Uri uri) { - Cursor cursor = query(uri, PROJECTION_MIME_TYPE, null, null, null); - String mimeType = null; - if (cursor.moveToNext()) { - mimeType = cursor.getString(0); - } - cursor.close(); - return mimeType; - } - - @Override - public Uri insertInTransaction(Uri uri, ContentValues values, boolean callerIsSyncAdapter) { - int match = matchUri(uri); - validateMatchTable(match); - String table = getTableFromMatch(match, uri); - SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); - Uri insertedUri = null; - long id = db.insert(table, null, values); - if (id != -1) { - // uri already matches the table. - insertedUri = ContentUris.withAppendedId(uri, id); - postNotifyUri(insertedUri); - } - return insertedUri; - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder) { - return query(uri, projection, selection, selectionArgs, sortOrder, null); - } - - @Override - public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, - String sortOrder, CancellationSignal cancellationSignal) { - projection = replaceCount(projection); - int match = matchUri(uri); - selection = addIdToSelection(match, selection); - selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs); - String table = getTableFromMatch(match, uri); - Cursor c = query(table, projection, selection, selectionArgs, sortOrder, cancellationSignal); - if (c != null) { - c.setNotificationUri(getContext().getContentResolver(), uri); - } - return c; - } - - @Override - public int updateInTransaction(Uri uri, ContentValues values, String selection, - String[] selectionArgs, boolean callerIsSyncAdapter) { - int match = matchUri(uri); - int rowsUpdated = 0; - SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); - if (match == MATCH_METADATA) { - rowsUpdated = modifyMetadata(db, values); - } else { - selection = addIdToSelection(match, selection); - selectionArgs = addIdToSelectionArgs(match, uri, selectionArgs); - String table = getTableFromMatch(match, uri); - rowsUpdated = db.update(table, values, selection, selectionArgs); - } - postNotifyUri(uri); - return rowsUpdated; - } - - public void setMockNotification(ChangeNotification notification) { - mNotifier = notification; - } - - protected static String addIdToSelection(int match, String selection) { - String where; - switch (match) { - case MATCH_PHOTO_ID: - case MATCH_ALBUM_ID: - case MATCH_METADATA_ID: - where = WHERE_ID; - break; - default: - return selection; - } - return DatabaseUtils.concatenateWhere(selection, where); - } - - protected static String[] addIdToSelectionArgs(int match, Uri uri, String[] selectionArgs) { - String[] whereArgs; - switch (match) { - case MATCH_PHOTO_ID: - case MATCH_ALBUM_ID: - case MATCH_METADATA_ID: - whereArgs = new String[] { - uri.getPathSegments().get(1), - }; - break; - default: - return selectionArgs; - } - return DatabaseUtils.appendSelectionArgs(selectionArgs, whereArgs); - } - - protected static String[] addMetadataKeysToSelectionArgs(String[] selectionArgs, Uri uri) { - List<String> segments = uri.getPathSegments(); - String[] additionalArgs = { - segments.get(1), - segments.get(2), - }; - - return DatabaseUtils.appendSelectionArgs(selectionArgs, additionalArgs); - } - - protected static String getTableFromMatch(int match, Uri uri) { - String table; - switch (match) { - case MATCH_PHOTO: - case MATCH_PHOTO_ID: - table = Photos.TABLE; - break; - case MATCH_ALBUM: - case MATCH_ALBUM_ID: - table = Albums.TABLE; - break; - case MATCH_METADATA: - case MATCH_METADATA_ID: - table = Metadata.TABLE; - break; - case MATCH_ACCOUNT: - case MATCH_ACCOUNT_ID: - table = Accounts.TABLE; - break; - default: - throw unknownUri(uri); - } - return table; - } - - @Override - public SQLiteOpenHelper getDatabaseHelper(Context context) { - return new PhotoDatabase(context, DB_NAME); - } - - private int modifyMetadata(SQLiteDatabase db, ContentValues values) { - int rowCount; - if (values.get(Metadata.VALUE) == null) { - String[] selectionArgs = { - values.getAsString(Metadata.PHOTO_ID), values.getAsString(Metadata.KEY), - }; - rowCount = db.delete(Metadata.TABLE, WHERE_METADATA_ID, selectionArgs); - } else { - long rowId = db.replace(Metadata.TABLE, null, values); - rowCount = (rowId == -1) ? 0 : 1; - } - return rowCount; - } - - private int matchUri(Uri uri) { - int match = sUriMatcher.match(uri); - if (match == UriMatcher.NO_MATCH) { - throw unknownUri(uri); - } - return match; - } - - @Override - protected void notifyChange(ContentResolver resolver, Uri uri, boolean syncToNetwork) { - if (mNotifier != null) { - mNotifier.notifyChange(uri, syncToNetwork); - } else { - super.notifyChange(resolver, uri, syncToNetwork); - } - } - - protected static IllegalArgumentException unknownUri(Uri uri) { - return new IllegalArgumentException("Unknown Uri format: " + uri); - } - - protected static String nestWhere(String matchColumn, String table, String nestedWhere) { - String query = SQLiteQueryBuilder.buildQueryString(false, table, BASE_COLUMNS_ID, - nestedWhere, null, null, null, null); - return matchColumn + IN + NESTED_SELECT_START + query + NESTED_SELECT_END; - } - - protected static String metadataSelectionFromPhotos(String where) { - return nestWhere(Metadata.PHOTO_ID, Photos.TABLE, where); - } - - protected static String photoSelectionFromAlbums(String where) { - return nestWhere(Photos.ALBUM_ID, Albums.TABLE, where); - } - - protected static String photoSelectionFromAccounts(String where) { - return nestWhere(Photos.ACCOUNT_ID, Accounts.TABLE, where); - } - - protected static String albumSelectionFromAccounts(String where) { - return nestWhere(Albums.ACCOUNT_ID, Accounts.TABLE, where); - } - - protected int deleteCascade(Uri uri, int match, String selection, String[] selectionArgs) { - switch (match) { - case MATCH_PHOTO: - case MATCH_PHOTO_ID: - deleteCascade(Metadata.CONTENT_URI, MATCH_METADATA, - metadataSelectionFromPhotos(selection), selectionArgs); - break; - case MATCH_ALBUM: - case MATCH_ALBUM_ID: - deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO, - photoSelectionFromAlbums(selection), selectionArgs); - break; - case MATCH_ACCOUNT: - case MATCH_ACCOUNT_ID: - deleteCascade(Photos.CONTENT_URI, MATCH_PHOTO, - photoSelectionFromAccounts(selection), selectionArgs); - deleteCascade(Albums.CONTENT_URI, MATCH_ALBUM, - albumSelectionFromAccounts(selection), selectionArgs); - break; - } - SQLiteDatabase db = getDatabaseHelper().getWritableDatabase(); - String table = getTableFromMatch(match, uri); - int deleted = db.delete(table, selection, selectionArgs); - if (deleted > 0) { - postNotifyUri(uri); - } - return deleted; - } - - private static void validateMatchTable(int match) { - switch (match) { - case MATCH_PHOTO: - case MATCH_ALBUM: - case MATCH_METADATA: - case MATCH_ACCOUNT: - break; - default: - throw new IllegalArgumentException("Operation not allowed on an existing row."); - } - } - - protected Cursor query(String table, String[] columns, String selection, - String[] selectionArgs, String orderBy, CancellationSignal cancellationSignal) { - SQLiteDatabase db = getDatabaseHelper().getReadableDatabase(); - if (ApiHelper.HAS_CANCELLATION_SIGNAL) { - return db.query(false, table, columns, selection, selectionArgs, null, null, - orderBy, null, cancellationSignal); - } else { - return db.query(table, columns, selection, selectionArgs, null, null, orderBy); - } - } - - protected static String[] replaceCount(String[] projection) { - if (projection != null && projection.length == 1 - && BaseColumns._COUNT.equals(projection[0])) { - return PROJECTION_COUNT; - } - return projection; - } -} diff --git a/src/com/android/photos/data/PhotoSetLoader.java b/src/com/android/photos/data/PhotoSetLoader.java deleted file mode 100644 index 56c82c4a9..000000000 --- a/src/com/android/photos/data/PhotoSetLoader.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.data; - -import android.content.Context; -import android.content.CursorLoader; -import android.database.ContentObserver; -import android.database.Cursor; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.provider.MediaStore; -import android.provider.MediaStore.Files; -import android.provider.MediaStore.Files.FileColumns; - -import com.android.photos.drawables.DataUriThumbnailDrawable; -import com.android.photos.shims.LoaderCompatShim; - -import java.util.ArrayList; - -public class PhotoSetLoader extends CursorLoader implements LoaderCompatShim<Cursor> { - - public static final String SUPPORTED_OPERATIONS = "supported_operations"; - - private static final Uri CONTENT_URI = Files.getContentUri("external"); - public static final String[] PROJECTION = new String[] { - FileColumns._ID, - FileColumns.DATA, - FileColumns.WIDTH, - FileColumns.HEIGHT, - FileColumns.DATE_ADDED, - FileColumns.MEDIA_TYPE, - SUPPORTED_OPERATIONS, - }; - - private static final String SORT_ORDER = FileColumns.DATE_ADDED + " DESC"; - private static final String SELECTION = - FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_IMAGE - + " OR " - + FileColumns.MEDIA_TYPE + " == " + FileColumns.MEDIA_TYPE_VIDEO; - - public static final int INDEX_ID = 0; - public static final int INDEX_DATA = 1; - public static final int INDEX_WIDTH = 2; - public static final int INDEX_HEIGHT = 3; - public static final int INDEX_DATE_ADDED = 4; - public static final int INDEX_MEDIA_TYPE = 5; - public static final int INDEX_SUPPORTED_OPERATIONS = 6; - - private static final Uri GLOBAL_CONTENT_URI = Uri.parse("content://" + MediaStore.AUTHORITY + "/external/"); - private final ContentObserver mGlobalObserver = new ForceLoadContentObserver(); - - public PhotoSetLoader(Context context) { - super(context, CONTENT_URI, PROJECTION, SELECTION, null, SORT_ORDER); - } - - @Override - protected void onStartLoading() { - super.onStartLoading(); - getContext().getContentResolver().registerContentObserver(GLOBAL_CONTENT_URI, - true, mGlobalObserver); - } - - @Override - protected void onReset() { - super.onReset(); - getContext().getContentResolver().unregisterContentObserver(mGlobalObserver); - } - - @Override - public Drawable drawableForItem(Cursor item, Drawable recycle) { - DataUriThumbnailDrawable drawable = null; - if (recycle == null || !(recycle instanceof DataUriThumbnailDrawable)) { - drawable = new DataUriThumbnailDrawable(); - } else { - drawable = (DataUriThumbnailDrawable) recycle; - } - drawable.setImage(item.getString(INDEX_DATA), - item.getInt(INDEX_WIDTH), item.getInt(INDEX_HEIGHT)); - return drawable; - } - - @Override - public Uri uriForItem(Cursor item) { - return null; - } - - @Override - public ArrayList<Uri> urisForSubItems(Cursor item) { - return null; - } - - @Override - public void deleteItemWithPath(Object path) { - - } - - @Override - public Object getPathForItem(Cursor item) { - return null; - } -} diff --git a/src/com/android/photos/data/SQLiteContentProvider.java b/src/com/android/photos/data/SQLiteContentProvider.java deleted file mode 100644 index daffa6e79..000000000 --- a/src/com/android/photos/data/SQLiteContentProvider.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - */ - -package com.android.photos.data; - -import android.content.ContentProvider; -import android.content.ContentProviderOperation; -import android.content.ContentProviderResult; -import android.content.ContentResolver; -import android.content.ContentValues; -import android.content.Context; -import android.content.OperationApplicationException; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.net.Uri; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Set; - -/** - * General purpose {@link ContentProvider} base class that uses SQLiteDatabase - * for storage. - */ -public abstract class SQLiteContentProvider extends ContentProvider { - - @SuppressWarnings("unused") - private static final String TAG = "SQLiteContentProvider"; - - private SQLiteOpenHelper mOpenHelper; - private Set<Uri> mChangedUris; - - private final ThreadLocal<Boolean> mApplyingBatch = new ThreadLocal<Boolean>(); - private static final int SLEEP_AFTER_YIELD_DELAY = 4000; - - /** - * Maximum number of operations allowed in a batch between yield points. - */ - private static final int MAX_OPERATIONS_PER_YIELD_POINT = 500; - - @Override - public boolean onCreate() { - Context context = getContext(); - mOpenHelper = getDatabaseHelper(context); - mChangedUris = new HashSet<Uri>(); - return true; - } - - @Override - public void shutdown() { - getDatabaseHelper().close(); - } - - /** - * Returns a {@link SQLiteOpenHelper} that can open the database. - */ - public abstract SQLiteOpenHelper getDatabaseHelper(Context context); - - /** - * The equivalent of the {@link #insert} method, but invoked within a - * transaction. - */ - public abstract Uri insertInTransaction(Uri uri, ContentValues values, - boolean callerIsSyncAdapter); - - /** - * The equivalent of the {@link #update} method, but invoked within a - * transaction. - */ - public abstract int updateInTransaction(Uri uri, ContentValues values, String selection, - String[] selectionArgs, boolean callerIsSyncAdapter); - - /** - * The equivalent of the {@link #delete} method, but invoked within a - * transaction. - */ - public abstract int deleteInTransaction(Uri uri, String selection, String[] selectionArgs, - boolean callerIsSyncAdapter); - - /** - * Call this to add a URI to the list of URIs to be notified when the - * transaction is committed. - */ - protected void postNotifyUri(Uri uri) { - synchronized (mChangedUris) { - mChangedUris.add(uri); - } - } - - public boolean isCallerSyncAdapter(Uri uri) { - return false; - } - - public SQLiteOpenHelper getDatabaseHelper() { - return mOpenHelper; - } - - private boolean applyingBatch() { - return mApplyingBatch.get() != null && mApplyingBatch.get(); - } - - @Override - public Uri insert(Uri uri, ContentValues values) { - Uri result = null; - boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); - boolean applyingBatch = applyingBatch(); - if (!applyingBatch) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - result = insertInTransaction(uri, values, callerIsSyncAdapter); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - onEndTransaction(callerIsSyncAdapter); - } else { - result = insertInTransaction(uri, values, callerIsSyncAdapter); - } - return result; - } - - @Override - public int bulkInsert(Uri uri, ContentValues[] values) { - int numValues = values.length; - boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - for (int i = 0; i < numValues; i++) { - @SuppressWarnings("unused") - Uri result = insertInTransaction(uri, values[i], callerIsSyncAdapter); - db.yieldIfContendedSafely(); - } - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - onEndTransaction(callerIsSyncAdapter); - return numValues; - } - - @Override - public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) { - int count = 0; - boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); - boolean applyingBatch = applyingBatch(); - if (!applyingBatch) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - count = updateInTransaction(uri, values, selection, selectionArgs, - callerIsSyncAdapter); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - onEndTransaction(callerIsSyncAdapter); - } else { - count = updateInTransaction(uri, values, selection, selectionArgs, callerIsSyncAdapter); - } - - return count; - } - - @Override - public int delete(Uri uri, String selection, String[] selectionArgs) { - int count = 0; - boolean callerIsSyncAdapter = isCallerSyncAdapter(uri); - boolean applyingBatch = applyingBatch(); - if (!applyingBatch) { - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - - onEndTransaction(callerIsSyncAdapter); - } else { - count = deleteInTransaction(uri, selection, selectionArgs, callerIsSyncAdapter); - } - return count; - } - - @Override - public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations) - throws OperationApplicationException { - int ypCount = 0; - int opCount = 0; - boolean callerIsSyncAdapter = false; - SQLiteDatabase db = mOpenHelper.getWritableDatabase(); - db.beginTransaction(); - try { - mApplyingBatch.set(true); - final int numOperations = operations.size(); - final ContentProviderResult[] results = new ContentProviderResult[numOperations]; - for (int i = 0; i < numOperations; i++) { - if (++opCount >= MAX_OPERATIONS_PER_YIELD_POINT) { - throw new OperationApplicationException( - "Too many content provider operations between yield points. " - + "The maximum number of operations per yield point is " - + MAX_OPERATIONS_PER_YIELD_POINT, ypCount); - } - final ContentProviderOperation operation = operations.get(i); - if (!callerIsSyncAdapter && isCallerSyncAdapter(operation.getUri())) { - callerIsSyncAdapter = true; - } - if (i > 0 && operation.isYieldAllowed()) { - opCount = 0; - if (db.yieldIfContendedSafely(SLEEP_AFTER_YIELD_DELAY)) { - ypCount++; - } - } - results[i] = operation.apply(this, results, i); - } - db.setTransactionSuccessful(); - return results; - } finally { - mApplyingBatch.set(false); - db.endTransaction(); - onEndTransaction(callerIsSyncAdapter); - } - } - - protected Set<Uri> onEndTransaction(boolean callerIsSyncAdapter) { - Set<Uri> changed; - synchronized (mChangedUris) { - changed = new HashSet<Uri>(mChangedUris); - mChangedUris.clear(); - } - ContentResolver resolver = getContext().getContentResolver(); - for (Uri uri : changed) { - boolean syncToNetwork = !callerIsSyncAdapter && syncToNetwork(uri); - notifyChange(resolver, uri, syncToNetwork); - } - return changed; - } - - protected void notifyChange(ContentResolver resolver, Uri uri, boolean syncToNetwork) { - resolver.notifyChange(uri, null, syncToNetwork); - } - - protected boolean syncToNetwork(Uri uri) { - return false; - } -}
\ No newline at end of file diff --git a/src/com/android/photos/data/SparseArrayBitmapPool.java b/src/com/android/photos/data/SparseArrayBitmapPool.java deleted file mode 100644 index 95e10267b..000000000 --- a/src/com/android/photos/data/SparseArrayBitmapPool.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.data; - -import android.graphics.Bitmap; -import android.util.SparseArray; - -import android.util.Pools.Pool; -import android.util.Pools.SimplePool; - -/** - * Bitmap pool backed by a sparse array indexing linked lists of bitmaps - * sharing the same width. Performance will degrade if using this to store - * many bitmaps with the same width but many different heights. - */ -public class SparseArrayBitmapPool { - - private int mCapacityBytes; - private SparseArray<Node> mStore = new SparseArray<Node>(); - private int mSizeBytes = 0; - - private Pool<Node> mNodePool; - private Node mPoolNodesHead = null; - private Node mPoolNodesTail = null; - - protected static class Node { - Bitmap bitmap; - - // Each node is part of two doubly linked lists: - // - A pool-level list (accessed by mPoolNodesHead and mPoolNodesTail) - // that is used for FIFO eviction of nodes when the pool gets full. - // - A bucket-level list for each index of the sparse array, so that - // each index can store more than one item. - Node prevInBucket; - Node nextInBucket; - Node nextInPool; - Node prevInPool; - } - - /** - * @param capacityBytes Maximum capacity of the pool in bytes. - * @param nodePool Shared pool to use for recycling linked list nodes, or null. - */ - public SparseArrayBitmapPool(int capacityBytes, Pool<Node> nodePool) { - mCapacityBytes = capacityBytes; - if (nodePool == null) { - mNodePool = new SimplePool<Node>(32); - } else { - mNodePool = nodePool; - } - } - - /** - * Set the maximum capacity of the pool, and if necessary trim it down to size. - */ - public synchronized void setCapacity(int capacityBytes) { - mCapacityBytes = capacityBytes; - - // No-op unless current size exceeds the new capacity. - freeUpCapacity(0); - } - - private void freeUpCapacity(int bytesNeeded) { - int targetSize = mCapacityBytes - bytesNeeded; - // Repeatedly remove the oldest node until we have freed up at least bytesNeeded. - while (mPoolNodesTail != null && mSizeBytes > targetSize) { - unlinkAndRecycleNode(mPoolNodesTail, true); - } - } - - private void unlinkAndRecycleNode(Node n, boolean recycleBitmap) { - // Unlink the node from its sparse array bucket list. - if (n.prevInBucket != null) { - // This wasn't the head, update the previous node. - n.prevInBucket.nextInBucket = n.nextInBucket; - } else { - // This was the head of the bucket, replace it with the next node. - mStore.put(n.bitmap.getWidth(), n.nextInBucket); - } - if (n.nextInBucket != null) { - // This wasn't the tail, update the next node. - n.nextInBucket.prevInBucket = n.prevInBucket; - } - - // Unlink the node from the pool-wide list. - if (n.prevInPool != null) { - // This wasn't the head, update the previous node. - n.prevInPool.nextInPool = n.nextInPool; - } else { - // This was the head of the pool-wide list, update the head pointer. - mPoolNodesHead = n.nextInPool; - } - if (n.nextInPool != null) { - // This wasn't the tail, update the next node. - n.nextInPool.prevInPool = n.prevInPool; - } else { - // This was the tail, update the tail pointer. - mPoolNodesTail = n.prevInPool; - } - - // Recycle the node. - n.nextInBucket = null; - n.nextInPool = null; - n.prevInBucket = null; - n.prevInPool = null; - mSizeBytes -= n.bitmap.getByteCount(); - if (recycleBitmap) n.bitmap.recycle(); - n.bitmap = null; - mNodePool.release(n); - } - - /** - * @return Capacity of the pool in bytes. - */ - public synchronized int getCapacity() { - return mCapacityBytes; - } - - /** - * @return Total size in bytes of the bitmaps stored in the pool. - */ - public synchronized int getSize() { - return mSizeBytes; - } - - /** - * @return Bitmap from the pool with the desired height/width or null if none available. - */ - public synchronized Bitmap get(int width, int height) { - Node cur = mStore.get(width); - - // Traverse the list corresponding to the width bucket in the - // sparse array, and unlink and return the first bitmap that - // also has the correct height. - while (cur != null) { - if (cur.bitmap.getHeight() == height) { - Bitmap b = cur.bitmap; - unlinkAndRecycleNode(cur, false); - return b; - } - cur = cur.nextInBucket; - } - return null; - } - - /** - * Adds the given bitmap to the pool. - * @return Whether the bitmap was added to the pool. - */ - public synchronized boolean put(Bitmap b) { - if (b == null) { - return false; - } - - // Ensure there is enough room to contain the new bitmap. - int bytes = b.getByteCount(); - freeUpCapacity(bytes); - - Node newNode = mNodePool.acquire(); - if (newNode == null) { - newNode = new Node(); - } - newNode.bitmap = b; - - // We append to the head, and freeUpCapacity clears from the tail, - // resulting in FIFO eviction. - newNode.prevInBucket = null; - newNode.prevInPool = null; - newNode.nextInPool = mPoolNodesHead; - mPoolNodesHead = newNode; - - // Insert the node into its appropriate bucket based on width. - int key = b.getWidth(); - newNode.nextInBucket = mStore.get(key); - if (newNode.nextInBucket != null) { - // The bucket already had nodes, update the old head. - newNode.nextInBucket.prevInBucket = newNode; - } - mStore.put(key, newNode); - - if (newNode.nextInPool == null) { - // This is the only node in the list, update the tail pointer. - mPoolNodesTail = newNode; - } else { - newNode.nextInPool.prevInPool = newNode; - } - mSizeBytes += bytes; - return true; - } - - /** - * Empty the pool, recycling all the bitmaps currently in it. - */ - public synchronized void clear() { - // Clearing is equivalent to ensuring all the capacity is available. - freeUpCapacity(mCapacityBytes); - } -} diff --git a/src/com/android/photos/drawables/AutoThumbnailDrawable.java b/src/com/android/photos/drawables/AutoThumbnailDrawable.java deleted file mode 100644 index b51b6709f..000000000 --- a/src/com/android/photos/drawables/AutoThumbnailDrawable.java +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.drawables; - -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; -import android.util.Log; - -import com.android.photos.data.GalleryBitmapPool; - -import java.io.InputStream; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public abstract class AutoThumbnailDrawable<T> extends Drawable { - - private static final String TAG = "AutoThumbnailDrawable"; - - private static ExecutorService sThreadPool = Executors.newSingleThreadExecutor(); - private static GalleryBitmapPool sBitmapPool = GalleryBitmapPool.getInstance(); - private static byte[] sTempStorage = new byte[64 * 1024]; - - // UI thread only - private Paint mPaint = new Paint(); - private Matrix mDrawMatrix = new Matrix(); - - // Decoder thread only - private BitmapFactory.Options mOptions = new BitmapFactory.Options(); - - // Shared, guarded by mLock - private Object mLock = new Object(); - private Bitmap mBitmap; - protected T mData; - private boolean mIsQueued; - private int mImageWidth, mImageHeight; - private Rect mBounds = new Rect(); - private int mSampleSize = 1; - - public AutoThumbnailDrawable() { - mPaint.setAntiAlias(true); - mPaint.setFilterBitmap(true); - mDrawMatrix.reset(); - mOptions.inTempStorage = sTempStorage; - } - - protected abstract byte[] getPreferredImageBytes(T data); - protected abstract InputStream getFallbackImageStream(T data); - protected abstract boolean dataChangedLocked(T data); - - public void setImage(T data, int width, int height) { - if (!dataChangedLocked(data)) return; - synchronized (mLock) { - mImageWidth = width; - mImageHeight = height; - mData = data; - setBitmapLocked(null); - refreshSampleSizeLocked(); - } - invalidateSelf(); - } - - private void setBitmapLocked(Bitmap b) { - if (b == mBitmap) { - return; - } - if (mBitmap != null) { - sBitmapPool.put(mBitmap); - } - mBitmap = b; - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - synchronized (mLock) { - mBounds.set(bounds); - if (mBounds.isEmpty()) { - mBitmap = null; - } else { - refreshSampleSizeLocked(); - updateDrawMatrixLocked(); - } - } - invalidateSelf(); - } - - @Override - public void draw(Canvas canvas) { - if (mBitmap != null) { - canvas.save(); - canvas.clipRect(mBounds); - canvas.concat(mDrawMatrix); - canvas.drawBitmap(mBitmap, 0, 0, mPaint); - canvas.restore(); - } else { - // TODO: Draw placeholder...? - } - } - - private void updateDrawMatrixLocked() { - if (mBitmap == null || mBounds.isEmpty()) { - mDrawMatrix.reset(); - return; - } - - float scale; - float dx = 0, dy = 0; - - int dwidth = mBitmap.getWidth(); - int dheight = mBitmap.getHeight(); - int vwidth = mBounds.width(); - int vheight = mBounds.height(); - - // Calculates a matrix similar to ScaleType.CENTER_CROP - if (dwidth * vheight > vwidth * dheight) { - scale = (float) vheight / (float) dheight; - dx = (vwidth - dwidth * scale) * 0.5f; - } else { - scale = (float) vwidth / (float) dwidth; - dy = (vheight - dheight * scale) * 0.5f; - } - if (scale < .8f) { - Log.w(TAG, "sample size was too small! Overdrawing! " + scale + ", " + mSampleSize); - } else if (scale > 1.5f) { - Log.w(TAG, "Potential quality loss! " + scale + ", " + mSampleSize); - } - - mDrawMatrix.setScale(scale, scale); - mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); - } - - private int calculateSampleSizeLocked(int dwidth, int dheight) { - float scale; - - int vwidth = mBounds.width(); - int vheight = mBounds.height(); - - // Inverse of updateDrawMatrixLocked - if (dwidth * vheight > vwidth * dheight) { - scale = (float) dheight / (float) vheight; - } else { - scale = (float) dwidth / (float) vwidth; - } - int result = Math.round(scale); - return result > 0 ? result : 1; - } - - private void refreshSampleSizeLocked() { - if (mBounds.isEmpty() || mImageWidth == 0 || mImageHeight == 0) { - return; - } - - int sampleSize = calculateSampleSizeLocked(mImageWidth, mImageHeight); - if (sampleSize != mSampleSize || mBitmap == null) { - mSampleSize = sampleSize; - loadBitmapLocked(); - } - } - - private void loadBitmapLocked() { - if (!mIsQueued && !mBounds.isEmpty()) { - unscheduleSelf(mUpdateBitmap); - sThreadPool.execute(mLoadBitmap); - mIsQueued = true; - } - } - - public float getAspectRatio() { - return (float) mImageWidth / (float) mImageHeight; - } - - @Override - public int getIntrinsicWidth() { - return -1; - } - - @Override - public int getIntrinsicHeight() { - return -1; - } - - @Override - public int getOpacity() { - Bitmap bm = mBitmap; - return (bm == null || bm.hasAlpha() || mPaint.getAlpha() < 255) ? - PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; - } - - @Override - public void setAlpha(int alpha) { - int oldAlpha = mPaint.getAlpha(); - if (alpha != oldAlpha) { - mPaint.setAlpha(alpha); - invalidateSelf(); - } - } - - @Override - public void setColorFilter(ColorFilter cf) { - mPaint.setColorFilter(cf); - invalidateSelf(); - } - - private final Runnable mLoadBitmap = new Runnable() { - @Override - public void run() { - T data; - synchronized (mLock) { - data = mData; - } - int preferredSampleSize = 1; - byte[] preferred = getPreferredImageBytes(data); - boolean hasPreferred = (preferred != null && preferred.length > 0); - if (hasPreferred) { - mOptions.inJustDecodeBounds = true; - BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions); - mOptions.inJustDecodeBounds = false; - } - int sampleSize, width, height; - synchronized (mLock) { - if (dataChangedLocked(data)) { - return; - } - width = mImageWidth; - height = mImageHeight; - if (hasPreferred) { - preferredSampleSize = calculateSampleSizeLocked( - mOptions.outWidth, mOptions.outHeight); - } - sampleSize = calculateSampleSizeLocked(width, height); - mIsQueued = false; - } - Bitmap b = null; - InputStream is = null; - try { - if (hasPreferred) { - mOptions.inSampleSize = preferredSampleSize; - mOptions.inBitmap = sBitmapPool.get( - mOptions.outWidth / preferredSampleSize, - mOptions.outHeight / preferredSampleSize); - b = BitmapFactory.decodeByteArray(preferred, 0, preferred.length, mOptions); - if (mOptions.inBitmap != null && b != mOptions.inBitmap) { - sBitmapPool.put(mOptions.inBitmap); - mOptions.inBitmap = null; - } - } - if (b == null) { - is = getFallbackImageStream(data); - mOptions.inSampleSize = sampleSize; - mOptions.inBitmap = sBitmapPool.get(width / sampleSize, height / sampleSize); - b = BitmapFactory.decodeStream(is, null, mOptions); - if (mOptions.inBitmap != null && b != mOptions.inBitmap) { - sBitmapPool.put(mOptions.inBitmap); - mOptions.inBitmap = null; - } - } - } catch (Exception e) { - Log.d(TAG, "Failed to fetch bitmap", e); - return; - } finally { - try { - if (is != null) { - is.close(); - } - } catch (Exception e) {} - if (b != null) { - synchronized (mLock) { - if (!dataChangedLocked(data)) { - setBitmapLocked(b); - scheduleSelf(mUpdateBitmap, 0); - } - } - } - } - } - }; - - private final Runnable mUpdateBitmap = new Runnable() { - @Override - public void run() { - synchronized (AutoThumbnailDrawable.this) { - updateDrawMatrixLocked(); - invalidateSelf(); - } - } - }; - -} diff --git a/src/com/android/photos/drawables/DataUriThumbnailDrawable.java b/src/com/android/photos/drawables/DataUriThumbnailDrawable.java deleted file mode 100644 index c83b0c8fa..000000000 --- a/src/com/android/photos/drawables/DataUriThumbnailDrawable.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.drawables; - -import android.media.ExifInterface; -import android.text.TextUtils; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; - -public class DataUriThumbnailDrawable extends AutoThumbnailDrawable<String> { - - @Override - protected byte[] getPreferredImageBytes(String data) { - byte[] thumbnail = null; - try { - ExifInterface exif = new ExifInterface(data); - if (exif.hasThumbnail()) { - thumbnail = exif.getThumbnail(); - } - } catch (IOException e) { } - return thumbnail; - } - - @Override - protected InputStream getFallbackImageStream(String data) { - try { - return new FileInputStream(data); - } catch (FileNotFoundException e) { - return null; - } - } - - @Override - protected boolean dataChangedLocked(String data) { - return !TextUtils.equals(mData, data); - } -} diff --git a/src/com/android/photos/shims/BitmapJobDrawable.java b/src/com/android/photos/shims/BitmapJobDrawable.java deleted file mode 100644 index 32dbc8078..000000000 --- a/src/com/android/photos/shims/BitmapJobDrawable.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.shims; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.ColorFilter; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.PixelFormat; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; - -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.ui.BitmapLoader; -import com.android.gallery3d.util.Future; -import com.android.gallery3d.util.FutureListener; -import com.android.gallery3d.util.ThreadPool; -import com.android.photos.data.GalleryBitmapPool; - - -public class BitmapJobDrawable extends Drawable implements Runnable { - - private ThumbnailLoader mLoader; - private MediaItem mItem; - private Bitmap mBitmap; - private Paint mPaint = new Paint(); - private Matrix mDrawMatrix = new Matrix(); - private int mRotation = 0; - - public BitmapJobDrawable() { - } - - public void setMediaItem(MediaItem item) { - if (mItem == item) return; - - if (mLoader != null) { - mLoader.cancelLoad(); - } - mItem = item; - if (mBitmap != null) { - GalleryBitmapPool.getInstance().put(mBitmap); - mBitmap = null; - } - if (mItem != null) { - // TODO: Figure out why ThumbnailLoader doesn't like to be re-used - mLoader = new ThumbnailLoader(this); - mLoader.startLoad(); - mRotation = mItem.getRotation(); - } - invalidateSelf(); - } - - @Override - public void run() { - Bitmap bitmap = mLoader.getBitmap(); - if (bitmap != null) { - mBitmap = bitmap; - updateDrawMatrix(); - } - } - - @Override - protected void onBoundsChange(Rect bounds) { - super.onBoundsChange(bounds); - updateDrawMatrix(); - } - - @Override - public void draw(Canvas canvas) { - Rect bounds = getBounds(); - if (mBitmap != null) { - canvas.save(); - canvas.clipRect(bounds); - canvas.concat(mDrawMatrix); - canvas.rotate(mRotation, bounds.centerX(), bounds.centerY()); - canvas.drawBitmap(mBitmap, 0, 0, mPaint); - canvas.restore(); - } else { - mPaint.setColor(0xFFCCCCCC); - canvas.drawRect(bounds, mPaint); - } - } - - private void updateDrawMatrix() { - Rect bounds = getBounds(); - if (mBitmap == null || bounds.isEmpty()) { - mDrawMatrix.reset(); - return; - } - - float scale; - float dx = 0, dy = 0; - - int dwidth = mBitmap.getWidth(); - int dheight = mBitmap.getHeight(); - int vwidth = bounds.width(); - int vheight = bounds.height(); - - // Calculates a matrix similar to ScaleType.CENTER_CROP - if (dwidth * vheight > vwidth * dheight) { - scale = (float) vheight / (float) dheight; - dx = (vwidth - dwidth * scale) * 0.5f; - } else { - scale = (float) vwidth / (float) dwidth; - dy = (vheight - dheight * scale) * 0.5f; - } - - mDrawMatrix.setScale(scale, scale); - mDrawMatrix.postTranslate((int) (dx + 0.5f), (int) (dy + 0.5f)); - invalidateSelf(); - } - - @Override - public int getIntrinsicWidth() { - return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); - } - - @Override - public int getIntrinsicHeight() { - return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); - } - - @Override - public int getOpacity() { - Bitmap bm = mBitmap; - return (bm == null || bm.hasAlpha() || mPaint.getAlpha() < 255) ? - PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE; - } - - @Override - public void setAlpha(int alpha) { - int oldAlpha = mPaint.getAlpha(); - if (alpha != oldAlpha) { - mPaint.setAlpha(alpha); - invalidateSelf(); - } - } - - @Override - public void setColorFilter(ColorFilter cf) { - mPaint.setColorFilter(cf); - invalidateSelf(); - } - - private static class ThumbnailLoader extends BitmapLoader { - private static final ThreadPool sThreadPool = new ThreadPool(0, 2); - private BitmapJobDrawable mParent; - - public ThumbnailLoader(BitmapJobDrawable parent) { - mParent = parent; - } - - @Override - protected Future<Bitmap> submitBitmapTask(FutureListener<Bitmap> l) { - return sThreadPool.submit( - mParent.mItem.requestImage(MediaItem.TYPE_MICROTHUMBNAIL), this); - } - - @Override - protected void onLoadComplete(Bitmap bitmap) { - mParent.scheduleSelf(mParent, 0); - } - } - -} diff --git a/src/com/android/photos/shims/LoaderCompatShim.java b/src/com/android/photos/shims/LoaderCompatShim.java deleted file mode 100644 index d5bf710de..000000000 --- a/src/com/android/photos/shims/LoaderCompatShim.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.shims; - -import android.graphics.drawable.Drawable; -import android.net.Uri; - -import java.util.ArrayList; - - -public interface LoaderCompatShim<T> { - Drawable drawableForItem(T item, Drawable recycle); - Uri uriForItem(T item); - ArrayList<Uri> urisForSubItems(T item); - void deleteItemWithPath(Object path); - Object getPathForItem(T item); -} diff --git a/src/com/android/photos/shims/MediaItemsLoader.java b/src/com/android/photos/shims/MediaItemsLoader.java deleted file mode 100644 index 6142355a9..000000000 --- a/src/com/android/photos/shims/MediaItemsLoader.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.shims; - -import android.content.AsyncTaskLoader; -import android.content.Context; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.provider.MediaStore.Files.FileColumns; -import android.util.SparseArray; - -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.MediaSet.ItemConsumer; -import com.android.gallery3d.data.MediaSet.SyncListener; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.util.Future; -import com.android.photos.data.PhotoSetLoader; - -import java.util.ArrayList; - -/** - * Returns all MediaItems in a MediaSet, wrapping them in a cursor to appear - * like a PhotoSetLoader - */ -public class MediaItemsLoader extends AsyncTaskLoader<Cursor> implements LoaderCompatShim<Cursor> { - - private static final SyncListener sNullListener = new SyncListener() { - @Override - public void onSyncDone(MediaSet mediaSet, int resultCode) { - } - }; - - private final MediaSet mMediaSet; - private final DataManager mDataManager; - private Future<Integer> mSyncTask = null; - private ContentListener mObserver = new ContentListener() { - @Override - public void onContentDirty() { - onContentChanged(); - } - }; - private SparseArray<MediaItem> mMediaItems; - - public MediaItemsLoader(Context context) { - super(context); - mDataManager = DataManager.from(context); - String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL); - mMediaSet = mDataManager.getMediaSet(path); - } - - public MediaItemsLoader(Context context, String parentPath) { - super(context); - mDataManager = DataManager.from(getContext()); - mMediaSet = mDataManager.getMediaSet(parentPath); - } - - @Override - protected void onStartLoading() { - super.onStartLoading(); - mMediaSet.addContentListener(mObserver); - mSyncTask = mMediaSet.requestSync(sNullListener); - forceLoad(); - } - - @Override - protected boolean onCancelLoad() { - if (mSyncTask != null) { - mSyncTask.cancel(); - mSyncTask = null; - } - return super.onCancelLoad(); - } - - @Override - protected void onStopLoading() { - super.onStopLoading(); - cancelLoad(); - mMediaSet.removeContentListener(mObserver); - } - - @Override - protected void onReset() { - super.onReset(); - onStopLoading(); - } - - @Override - public Cursor loadInBackground() { - // TODO: This probably doesn't work - mMediaSet.reload(); - final MatrixCursor cursor = new MatrixCursor(PhotoSetLoader.PROJECTION); - final Object[] row = new Object[PhotoSetLoader.PROJECTION.length]; - final SparseArray<MediaItem> mediaItems = new SparseArray<MediaItem>(); - mMediaSet.enumerateTotalMediaItems(new ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - row[PhotoSetLoader.INDEX_ID] = index; - row[PhotoSetLoader.INDEX_DATA] = item.getContentUri().toString(); - row[PhotoSetLoader.INDEX_DATE_ADDED] = item.getDateInMs(); - row[PhotoSetLoader.INDEX_HEIGHT] = item.getHeight(); - row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth(); - row[PhotoSetLoader.INDEX_WIDTH] = item.getWidth(); - int rawMediaType = item.getMediaType(); - int mappedMediaType = FileColumns.MEDIA_TYPE_NONE; - if (rawMediaType == MediaItem.MEDIA_TYPE_IMAGE) { - mappedMediaType = FileColumns.MEDIA_TYPE_IMAGE; - } else if (rawMediaType == MediaItem.MEDIA_TYPE_VIDEO) { - mappedMediaType = FileColumns.MEDIA_TYPE_VIDEO; - } - row[PhotoSetLoader.INDEX_MEDIA_TYPE] = mappedMediaType; - row[PhotoSetLoader.INDEX_SUPPORTED_OPERATIONS] = - item.getSupportedOperations(); - cursor.addRow(row); - mediaItems.append(index, item); - } - }); - synchronized (mMediaSet) { - mMediaItems = mediaItems; - } - return cursor; - } - - @Override - public Drawable drawableForItem(Cursor item, Drawable recycle) { - BitmapJobDrawable drawable = null; - if (recycle == null || !(recycle instanceof BitmapJobDrawable)) { - drawable = new BitmapJobDrawable(); - } else { - drawable = (BitmapJobDrawable) recycle; - } - int index = item.getInt(PhotoSetLoader.INDEX_ID); - drawable.setMediaItem(mMediaItems.get(index)); - return drawable; - } - - public static int getThumbnailSize() { - return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); - } - - @Override - public Uri uriForItem(Cursor item) { - int index = item.getInt(PhotoSetLoader.INDEX_ID); - MediaItem mi = mMediaItems.get(index); - return mi == null ? null : mi.getContentUri(); - } - - @Override - public ArrayList<Uri> urisForSubItems(Cursor item) { - return null; - } - - @Override - public void deleteItemWithPath(Object path) { - MediaObject o = mDataManager.getMediaObject((Path) path); - if (o != null) { - o.delete(); - } - } - - @Override - public Object getPathForItem(Cursor item) { - int index = item.getInt(PhotoSetLoader.INDEX_ID); - MediaItem mi = mMediaItems.get(index); - if (mi != null) { - return mi.getPath(); - } - return null; - } - -} diff --git a/src/com/android/photos/shims/MediaSetLoader.java b/src/com/android/photos/shims/MediaSetLoader.java deleted file mode 100644 index 9093bc139..000000000 --- a/src/com/android/photos/shims/MediaSetLoader.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.shims; - -import android.content.AsyncTaskLoader; -import android.content.Context; -import android.database.Cursor; -import android.database.MatrixCursor; -import android.graphics.drawable.Drawable; -import android.net.Uri; - -import com.android.gallery3d.data.ContentListener; -import com.android.gallery3d.data.DataManager; -import com.android.gallery3d.data.MediaItem; -import com.android.gallery3d.data.MediaObject; -import com.android.gallery3d.data.MediaSet; -import com.android.gallery3d.data.Path; -import com.android.gallery3d.data.MediaSet.SyncListener; -import com.android.gallery3d.util.Future; -import com.android.photos.data.AlbumSetLoader; - -import java.util.ArrayList; - -/** - * Returns all MediaSets in a MediaSet, wrapping them in a cursor to appear - * like a AlbumSetLoader. - */ -public class MediaSetLoader extends AsyncTaskLoader<Cursor> implements LoaderCompatShim<Cursor>{ - - private static final SyncListener sNullListener = new SyncListener() { - @Override - public void onSyncDone(MediaSet mediaSet, int resultCode) { - } - }; - - private final MediaSet mMediaSet; - private final DataManager mDataManager; - private Future<Integer> mSyncTask = null; - private ContentListener mObserver = new ContentListener() { - @Override - public void onContentDirty() { - onContentChanged(); - } - }; - - private ArrayList<MediaItem> mCoverItems; - - public MediaSetLoader(Context context) { - super(context); - mDataManager = DataManager.from(context); - String path = mDataManager.getTopSetPath(DataManager.INCLUDE_ALL); - mMediaSet = mDataManager.getMediaSet(path); - } - - public MediaSetLoader(Context context, String path) { - super(context); - mDataManager = DataManager.from(getContext()); - mMediaSet = mDataManager.getMediaSet(path); - } - - @Override - protected void onStartLoading() { - super.onStartLoading(); - mMediaSet.addContentListener(mObserver); - mSyncTask = mMediaSet.requestSync(sNullListener); - forceLoad(); - } - - @Override - protected boolean onCancelLoad() { - if (mSyncTask != null) { - mSyncTask.cancel(); - mSyncTask = null; - } - return super.onCancelLoad(); - } - - @Override - protected void onStopLoading() { - super.onStopLoading(); - cancelLoad(); - mMediaSet.removeContentListener(mObserver); - } - - @Override - protected void onReset() { - super.onReset(); - onStopLoading(); - } - - @Override - public Cursor loadInBackground() { - // TODO: This probably doesn't work - mMediaSet.reload(); - final MatrixCursor cursor = new MatrixCursor(AlbumSetLoader.PROJECTION); - final Object[] row = new Object[AlbumSetLoader.PROJECTION.length]; - int count = mMediaSet.getSubMediaSetCount(); - ArrayList<MediaItem> coverItems = new ArrayList<MediaItem>(count); - for (int i = 0; i < count; i++) { - MediaSet m = mMediaSet.getSubMediaSet(i); - m.reload(); - row[AlbumSetLoader.INDEX_ID] = i; - row[AlbumSetLoader.INDEX_TITLE] = m.getName(); - row[AlbumSetLoader.INDEX_COUNT] = m.getMediaItemCount(); - row[AlbumSetLoader.INDEX_SUPPORTED_OPERATIONS] = m.getSupportedOperations(); - MediaItem coverItem = m.getCoverMediaItem(); - if (coverItem != null) { - row[AlbumSetLoader.INDEX_TIMESTAMP] = coverItem.getDateInMs(); - } - coverItems.add(coverItem); - cursor.addRow(row); - } - synchronized (mMediaSet) { - mCoverItems = coverItems; - } - return cursor; - } - - @Override - public Drawable drawableForItem(Cursor item, Drawable recycle) { - BitmapJobDrawable drawable = null; - if (recycle == null || !(recycle instanceof BitmapJobDrawable)) { - drawable = new BitmapJobDrawable(); - } else { - drawable = (BitmapJobDrawable) recycle; - } - int index = item.getInt(AlbumSetLoader.INDEX_ID); - drawable.setMediaItem(mCoverItems.get(index)); - return drawable; - } - - public static int getThumbnailSize() { - return MediaItem.getTargetSize(MediaItem.TYPE_MICROTHUMBNAIL); - } - - @Override - public Uri uriForItem(Cursor item) { - int index = item.getInt(AlbumSetLoader.INDEX_ID); - MediaSet ms = mMediaSet.getSubMediaSet(index); - return ms == null ? null : ms.getContentUri(); - } - - @Override - public ArrayList<Uri> urisForSubItems(Cursor item) { - int index = item.getInt(AlbumSetLoader.INDEX_ID); - MediaSet ms = mMediaSet.getSubMediaSet(index); - if (ms == null) return null; - final ArrayList<Uri> result = new ArrayList<Uri>(); - ms.enumerateMediaItems(new MediaSet.ItemConsumer() { - @Override - public void consume(int index, MediaItem item) { - if (item != null) { - result.add(item.getContentUri()); - } - } - }); - return result; - } - - @Override - public void deleteItemWithPath(Object path) { - MediaObject o = mDataManager.getMediaObject((Path) path); - if (o != null) { - o.delete(); - } - } - - @Override - public Object getPathForItem(Cursor item) { - int index = item.getInt(AlbumSetLoader.INDEX_ID); - MediaSet ms = mMediaSet.getSubMediaSet(index); - if (ms != null) { - return ms.getPath(); - } - return null; - } -} diff --git a/src/com/android/photos/views/BlockingGLTextureView.java b/src/com/android/photos/views/BlockingGLTextureView.java deleted file mode 100644 index 8a0505185..000000000 --- a/src/com/android/photos/views/BlockingGLTextureView.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.views; - -import android.content.Context; -import android.graphics.SurfaceTexture; -import android.opengl.GLSurfaceView.Renderer; -import android.opengl.GLUtils; -import android.util.Log; -import android.view.TextureView; -import android.view.TextureView.SurfaceTextureListener; - -import javax.microedition.khronos.egl.EGL10; -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.egl.EGLContext; -import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLSurface; -import javax.microedition.khronos.opengles.GL10; - -/** - * A TextureView that supports blocking rendering for synchronous drawing - */ -public class BlockingGLTextureView extends TextureView - implements SurfaceTextureListener { - - private RenderThread mRenderThread; - - public BlockingGLTextureView(Context context) { - super(context); - setSurfaceTextureListener(this); - } - - public void setRenderer(Renderer renderer) { - if (mRenderThread != null) { - throw new IllegalArgumentException("Renderer already set"); - } - mRenderThread = new RenderThread(renderer); - } - - public void render() { - mRenderThread.render(); - } - - public void destroy() { - if (mRenderThread != null) { - mRenderThread.finish(); - mRenderThread = null; - } - } - - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, - int height) { - mRenderThread.setSurface(surface); - mRenderThread.setSize(width, height); - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, - int height) { - mRenderThread.setSize(width, height); - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - if (mRenderThread != null) { - mRenderThread.setSurface(null); - } - return false; - } - - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { - } - - @Override - protected void finalize() throws Throwable { - try { - destroy(); - } catch (Throwable t) { - // Ignore - } - super.finalize(); - } - - /** - * An EGL helper class. - */ - - private static class EglHelper { - private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098; - private static final int EGL_OPENGL_ES2_BIT = 4; - - EGL10 mEgl; - EGLDisplay mEglDisplay; - EGLSurface mEglSurface; - EGLConfig mEglConfig; - EGLContext mEglContext; - - private EGLConfig chooseEglConfig() { - int[] configsCount = new int[1]; - EGLConfig[] configs = new EGLConfig[1]; - int[] configSpec = getConfig(); - if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) { - throw new IllegalArgumentException("eglChooseConfig failed " + - GLUtils.getEGLErrorString(mEgl.eglGetError())); - } else if (configsCount[0] > 0) { - return configs[0]; - } - return null; - } - - private static int[] getConfig() { - return new int[] { - EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL10.EGL_RED_SIZE, 8, - EGL10.EGL_GREEN_SIZE, 8, - EGL10.EGL_BLUE_SIZE, 8, - EGL10.EGL_ALPHA_SIZE, 8, - EGL10.EGL_DEPTH_SIZE, 0, - EGL10.EGL_STENCIL_SIZE, 0, - EGL10.EGL_NONE - }; - } - - EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) { - int[] attribList = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE }; - return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attribList); - } - - /** - * Initialize EGL for a given configuration spec. - */ - public void start() { - /* - * Get an EGL instance - */ - mEgl = (EGL10) EGLContext.getEGL(); - - /* - * Get to the default display. - */ - mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY); - - if (mEglDisplay == EGL10.EGL_NO_DISPLAY) { - throw new RuntimeException("eglGetDisplay failed"); - } - - /* - * We can now initialize EGL for that display - */ - int[] version = new int[2]; - if (!mEgl.eglInitialize(mEglDisplay, version)) { - throw new RuntimeException("eglInitialize failed"); - } - mEglConfig = chooseEglConfig(); - - /* - * Create an EGL context. We want to do this as rarely as we can, because an - * EGL context is a somewhat heavy object. - */ - mEglContext = createContext(mEgl, mEglDisplay, mEglConfig); - - if (mEglContext == null || mEglContext == EGL10.EGL_NO_CONTEXT) { - mEglContext = null; - throwEglException("createContext"); - } - - mEglSurface = null; - } - - /** - * Create an egl surface for the current SurfaceTexture surface. If a surface - * already exists, destroy it before creating the new surface. - * - * @return true if the surface was created successfully. - */ - public boolean createSurface(SurfaceTexture surface) { - /* - * Check preconditions. - */ - if (mEgl == null) { - throw new RuntimeException("egl not initialized"); - } - if (mEglDisplay == null) { - throw new RuntimeException("eglDisplay not initialized"); - } - if (mEglConfig == null) { - throw new RuntimeException("mEglConfig not initialized"); - } - - /* - * The window size has changed, so we need to create a new - * surface. - */ - destroySurfaceImp(); - - /* - * Create an EGL surface we can render into. - */ - if (surface != null) { - mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surface, null); - } else { - mEglSurface = null; - } - - if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) { - int error = mEgl.eglGetError(); - if (error == EGL10.EGL_BAD_NATIVE_WINDOW) { - Log.e("EglHelper", "createWindowSurface returned EGL_BAD_NATIVE_WINDOW."); - } - return false; - } - - /* - * Before we can issue GL commands, we need to make sure - * the context is current and bound to a surface. - */ - if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) { - /* - * Could not make the context current, probably because the underlying - * SurfaceView surface has been destroyed. - */ - logEglErrorAsWarning("EGLHelper", "eglMakeCurrent", mEgl.eglGetError()); - return false; - } - - return true; - } - - /** - * Create a GL object for the current EGL context. - */ - public GL10 createGL() { - return (GL10) mEglContext.getGL(); - } - - /** - * Display the current render surface. - * @return the EGL error code from eglSwapBuffers. - */ - public int swap() { - if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) { - return mEgl.eglGetError(); - } - return EGL10.EGL_SUCCESS; - } - - public void destroySurface() { - destroySurfaceImp(); - } - - private void destroySurfaceImp() { - if (mEglSurface != null && mEglSurface != EGL10.EGL_NO_SURFACE) { - mEgl.eglMakeCurrent(mEglDisplay, EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_SURFACE, - EGL10.EGL_NO_CONTEXT); - mEgl.eglDestroySurface(mEglDisplay, mEglSurface); - mEglSurface = null; - } - } - - public void finish() { - if (mEglContext != null) { - mEgl.eglDestroyContext(mEglDisplay, mEglContext); - mEglContext = null; - } - if (mEglDisplay != null) { - mEgl.eglTerminate(mEglDisplay); - mEglDisplay = null; - } - } - - private void throwEglException(String function) { - throwEglException(function, mEgl.eglGetError()); - } - - public static void throwEglException(String function, int error) { - String message = formatEglError(function, error); - throw new RuntimeException(message); - } - - public static void logEglErrorAsWarning(String tag, String function, int error) { - Log.w(tag, formatEglError(function, error)); - } - - public static String formatEglError(String function, int error) { - return function + " failed: " + error; - } - - } - - private static class RenderThread extends Thread { - private static final int INVALID = -1; - private static final int RENDER = 1; - private static final int CHANGE_SURFACE = 2; - private static final int RESIZE_SURFACE = 3; - private static final int FINISH = 4; - - private EglHelper mEglHelper = new EglHelper(); - - private Object mLock = new Object(); - private int mExecMsgId = INVALID; - private SurfaceTexture mSurface; - private Renderer mRenderer; - private int mWidth, mHeight; - - private boolean mFinished = false; - private GL10 mGL; - - public RenderThread(Renderer renderer) { - super("RenderThread"); - mRenderer = renderer; - start(); - } - - private void checkRenderer() { - if (mRenderer == null) { - throw new IllegalArgumentException("Renderer is null!"); - } - } - - private void checkSurface() { - if (mSurface == null) { - throw new IllegalArgumentException("surface is null!"); - } - } - - public void setSurface(SurfaceTexture surface) { - // If the surface is null we're being torn down, don't need a - // renderer then - if (surface != null) { - checkRenderer(); - } - mSurface = surface; - exec(CHANGE_SURFACE); - } - - public void setSize(int width, int height) { - checkRenderer(); - checkSurface(); - mWidth = width; - mHeight = height; - exec(RESIZE_SURFACE); - } - - public void render() { - checkRenderer(); - if (mSurface != null) { - exec(RENDER); - mSurface.updateTexImage(); - } - } - - public void finish() { - mSurface = null; - exec(FINISH); - try { - join(); - } catch (InterruptedException e) { - // Ignore - } - } - - private void exec(int msgid) { - synchronized (mLock) { - if (mExecMsgId != INVALID) { - throw new IllegalArgumentException( - "Message already set - multithreaded access?"); - } - mExecMsgId = msgid; - mLock.notify(); - try { - mLock.wait(); - } catch (InterruptedException e) { - // Ignore - } - } - } - - private void handleMessageLocked(int what) { - switch (what) { - case CHANGE_SURFACE: - if (mEglHelper.createSurface(mSurface)) { - mGL = mEglHelper.createGL(); - mRenderer.onSurfaceCreated(mGL, mEglHelper.mEglConfig); - } - break; - case RESIZE_SURFACE: - mRenderer.onSurfaceChanged(mGL, mWidth, mHeight); - break; - case RENDER: - mRenderer.onDrawFrame(mGL); - mEglHelper.swap(); - break; - case FINISH: - mEglHelper.destroySurface(); - mEglHelper.finish(); - mFinished = true; - break; - } - } - - @Override - public void run() { - synchronized (mLock) { - mEglHelper.start(); - while (!mFinished) { - while (mExecMsgId == INVALID) { - try { - mLock.wait(); - } catch (InterruptedException e) { - // Ignore - } - } - handleMessageLocked(mExecMsgId); - mExecMsgId = INVALID; - mLock.notify(); - } - mExecMsgId = FINISH; - } - } - } -} diff --git a/src/com/android/photos/views/GalleryThumbnailView.java b/src/com/android/photos/views/GalleryThumbnailView.java deleted file mode 100644 index e5dd6f2ff..000000000 --- a/src/com/android/photos/views/GalleryThumbnailView.java +++ /dev/null @@ -1,883 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.views; - -import android.content.Context; -import android.content.res.TypedArray; -import android.database.DataSetObserver; -import android.graphics.Canvas; -import android.support.v4.view.MotionEventCompat; -import android.support.v4.view.VelocityTrackerCompat; -import android.support.v4.view.ViewCompat; -import android.support.v4.widget.EdgeEffectCompat; -import android.util.AttributeSet; -import android.util.Log; -import android.util.SparseArray; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; -import android.view.ViewConfiguration; -import android.view.ViewGroup; -import android.widget.ListAdapter; -import android.widget.OverScroller; - -import java.util.ArrayList; - -public class GalleryThumbnailView extends ViewGroup { - - public interface GalleryThumbnailAdapter extends ListAdapter { - /** - * @param position Position to get the intrinsic aspect ratio for - * @return width / height - */ - float getIntrinsicAspectRatio(int position); - } - - private static final String TAG = "GalleryThumbnailView"; - private static final float ASPECT_RATIO = (float) Math.sqrt(1.5f); - private static final int LAND_UNITS = 2; - private static final int PORT_UNITS = 3; - - private GalleryThumbnailAdapter mAdapter; - - private final RecycleBin mRecycler = new RecycleBin(); - - private final AdapterDataSetObserver mObserver = new AdapterDataSetObserver(); - - private boolean mDataChanged; - private int mOldItemCount; - private int mItemCount; - private boolean mHasStableIds; - - private int mFirstPosition; - - private boolean mPopulating; - private boolean mInLayout; - - private int mTouchSlop; - private int mMaximumVelocity; - private int mFlingVelocity; - private float mLastTouchX; - private float mTouchRemainderX; - private int mActivePointerId; - - private static final int TOUCH_MODE_IDLE = 0; - private static final int TOUCH_MODE_DRAGGING = 1; - private static final int TOUCH_MODE_FLINGING = 2; - - private int mTouchMode; - private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); - private final OverScroller mScroller; - - private final EdgeEffectCompat mLeftEdge; - private final EdgeEffectCompat mRightEdge; - - private int mLargeColumnWidth; - private int mSmallColumnWidth; - private int mLargeColumnUnitCount = 8; - private int mSmallColumnUnitCount = 10; - - public GalleryThumbnailView(Context context) { - this(context, null); - } - - public GalleryThumbnailView(Context context, AttributeSet attrs) { - this(context, attrs, 0); - } - - public GalleryThumbnailView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - - final ViewConfiguration vc = ViewConfiguration.get(context); - mTouchSlop = vc.getScaledTouchSlop(); - mMaximumVelocity = vc.getScaledMaximumFlingVelocity(); - mFlingVelocity = vc.getScaledMinimumFlingVelocity(); - mScroller = new OverScroller(context); - - mLeftEdge = new EdgeEffectCompat(context); - mRightEdge = new EdgeEffectCompat(context); - setWillNotDraw(false); - setClipToPadding(false); - } - - @Override - public void requestLayout() { - if (!mPopulating) { - super.requestLayout(); - } - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - int widthSize = MeasureSpec.getSize(widthMeasureSpec); - int heightSize = MeasureSpec.getSize(heightMeasureSpec); - - if (widthMode != MeasureSpec.EXACTLY) { - Log.e(TAG, "onMeasure: must have an exact width or match_parent! " + - "Using fallback spec of EXACTLY " + widthSize); - } - if (heightMode != MeasureSpec.EXACTLY) { - Log.e(TAG, "onMeasure: must have an exact height or match_parent! " + - "Using fallback spec of EXACTLY " + heightSize); - } - - setMeasuredDimension(widthSize, heightSize); - - float portSpaces = mLargeColumnUnitCount / PORT_UNITS; - float height = getMeasuredHeight() / portSpaces; - mLargeColumnWidth = (int) (height / ASPECT_RATIO); - portSpaces++; - height = getMeasuredHeight() / portSpaces; - mSmallColumnWidth = (int) (height / ASPECT_RATIO); - } - - @Override - protected void onLayout(boolean changed, int l, int t, int r, int b) { - mInLayout = true; - populate(); - mInLayout = false; - - final int width = r - l; - final int height = b - t; - mLeftEdge.setSize(width, height); - mRightEdge.setSize(width, height); - } - - private void populate() { - if (getWidth() == 0 || getHeight() == 0) { - return; - } - - // TODO: Handle size changing -// final int colCount = mColCount; -// if (mItemTops == null || mItemTops.length != colCount) { -// mItemTops = new int[colCount]; -// mItemBottoms = new int[colCount]; -// final int top = getPaddingTop(); -// final int offset = top + Math.min(mRestoreOffset, 0); -// Arrays.fill(mItemTops, offset); -// Arrays.fill(mItemBottoms, offset); -// mLayoutRecords.clear(); -// if (mInLayout) { -// removeAllViewsInLayout(); -// } else { -// removeAllViews(); -// } -// mRestoreOffset = 0; -// } - - mPopulating = true; - layoutChildren(mDataChanged); - fillRight(mFirstPosition + getChildCount(), 0); - fillLeft(mFirstPosition - 1, 0); - mPopulating = false; - mDataChanged = false; - } - - final void layoutChildren(boolean queryAdapter) { -// TODO -// final int childCount = getChildCount(); -// for (int i = 0; i < childCount; i++) { -// View child = getChildAt(i); -// -// if (child.isLayoutRequested()) { -// final int widthSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredWidth(), MeasureSpec.EXACTLY); -// final int heightSpec = MeasureSpec.makeMeasureSpec(child.getMeasuredHeight(), MeasureSpec.EXACTLY); -// child.measure(widthSpec, heightSpec); -// child.layout(child.getLeft(), child.getTop(), child.getRight(), child.getBottom()); -// } -// -// int childTop = mItemBottoms[col] > Integer.MIN_VALUE ? -// mItemBottoms[col] + mItemMargin : child.getTop(); -// if (span > 1) { -// int lowest = childTop; -// for (int j = col + 1; j < col + span; j++) { -// final int bottom = mItemBottoms[j] + mItemMargin; -// if (bottom > lowest) { -// lowest = bottom; -// } -// } -// childTop = lowest; -// } -// final int childHeight = child.getMeasuredHeight(); -// final int childBottom = childTop + childHeight; -// final int childLeft = paddingLeft + col * (colWidth + itemMargin); -// final int childRight = childLeft + child.getMeasuredWidth(); -// child.layout(childLeft, childTop, childRight, childBottom); -// } - } - - /** - * Obtain the view and add it to our list of children. The view can be made - * fresh, converted from an unused view, or used as is if it was in the - * recycle bin. - * - * @param startPosition Logical position in the list to start from - * @param x Left or right edge of the view to add - * @param forward If true, align left edge to x and increase position. - * If false, align right edge to x and decrease position. - * @return Number of views added - */ - private int makeAndAddColumn(int startPosition, int x, boolean forward) { - int columnWidth = mLargeColumnWidth; - int addViews = 0; - for (int remaining = mLargeColumnUnitCount, i = 0; - remaining > 0 && startPosition + i >= 0 && startPosition + i < mItemCount; - i += forward ? 1 : -1, addViews++) { - if (mAdapter.getIntrinsicAspectRatio(startPosition + i) >= 1f) { - // landscape - remaining -= LAND_UNITS; - } else { - // portrait - remaining -= PORT_UNITS; - if (remaining < 0) { - remaining += (mSmallColumnUnitCount - mLargeColumnUnitCount); - columnWidth = mSmallColumnWidth; - } - } - } - int nextTop = 0; - for (int i = 0; i < addViews; i++) { - int position = startPosition + (forward ? i : -i); - View child = obtainView(position, null); - if (child.getParent() != this) { - if (mInLayout) { - addViewInLayout(child, forward ? -1 : 0, child.getLayoutParams()); - } else { - addView(child, forward ? -1 : 0); - } - } - int heightSize = (int) (.5f + (mAdapter.getIntrinsicAspectRatio(position) >= 1f - ? columnWidth / ASPECT_RATIO - : columnWidth * ASPECT_RATIO)); - int heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); - int widthSpec = MeasureSpec.makeMeasureSpec(columnWidth, MeasureSpec.EXACTLY); - child.measure(widthSpec, heightSpec); - int childLeft = forward ? x : x - columnWidth; - child.layout(childLeft, nextTop, childLeft + columnWidth, nextTop + heightSize); - nextTop += heightSize; - } - return addViews; - } - - @Override - public boolean onInterceptTouchEvent(MotionEvent ev) { - mVelocityTracker.addMovement(ev); - final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; - switch (action) { - case MotionEvent.ACTION_DOWN: - mVelocityTracker.clear(); - mScroller.abortAnimation(); - mLastTouchX = ev.getX(); - mActivePointerId = MotionEventCompat.getPointerId(ev, 0); - mTouchRemainderX = 0; - if (mTouchMode == TOUCH_MODE_FLINGING) { - // Catch! - mTouchMode = TOUCH_MODE_DRAGGING; - return true; - } - break; - - case MotionEvent.ACTION_MOVE: { - final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId); - if (index < 0) { - Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " + - mActivePointerId + " - did StaggeredGridView receive an inconsistent " + - "event stream?"); - return false; - } - final float x = MotionEventCompat.getX(ev, index); - final float dx = x - mLastTouchX + mTouchRemainderX; - final int deltaY = (int) dx; - mTouchRemainderX = dx - deltaY; - - if (Math.abs(dx) > mTouchSlop) { - mTouchMode = TOUCH_MODE_DRAGGING; - return true; - } - } - } - - return false; - } - - @Override - public boolean onTouchEvent(MotionEvent ev) { - mVelocityTracker.addMovement(ev); - final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; - switch (action) { - case MotionEvent.ACTION_DOWN: - mVelocityTracker.clear(); - mScroller.abortAnimation(); - mLastTouchX = ev.getX(); - mActivePointerId = MotionEventCompat.getPointerId(ev, 0); - mTouchRemainderX = 0; - break; - - case MotionEvent.ACTION_MOVE: { - final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId); - if (index < 0) { - Log.e(TAG, "onInterceptTouchEvent could not find pointer with id " + - mActivePointerId + " - did StaggeredGridView receive an inconsistent " + - "event stream?"); - return false; - } - final float x = MotionEventCompat.getX(ev, index); - final float dx = x - mLastTouchX + mTouchRemainderX; - final int deltaX = (int) dx; - mTouchRemainderX = dx - deltaX; - - if (Math.abs(dx) > mTouchSlop) { - mTouchMode = TOUCH_MODE_DRAGGING; - } - - if (mTouchMode == TOUCH_MODE_DRAGGING) { - mLastTouchX = x; - - if (!trackMotionScroll(deltaX, true)) { - // Break fling velocity if we impacted an edge. - mVelocityTracker.clear(); - } - } - } break; - - case MotionEvent.ACTION_CANCEL: - mTouchMode = TOUCH_MODE_IDLE; - break; - - case MotionEvent.ACTION_UP: { - mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity); - final float velocity = VelocityTrackerCompat.getXVelocity(mVelocityTracker, - mActivePointerId); - if (Math.abs(velocity) > mFlingVelocity) { // TODO - mTouchMode = TOUCH_MODE_FLINGING; - mScroller.fling(0, 0, (int) velocity, 0, - Integer.MIN_VALUE, Integer.MAX_VALUE, 0, 0); - mLastTouchX = 0; - ViewCompat.postInvalidateOnAnimation(this); - } else { - mTouchMode = TOUCH_MODE_IDLE; - } - - } break; - } - return true; - } - - /** - * - * @param deltaX Pixels that content should move by - * @return true if the movement completed, false if it was stopped prematurely. - */ - private boolean trackMotionScroll(int deltaX, boolean allowOverScroll) { - final boolean contentFits = contentFits(); - final int allowOverhang = Math.abs(deltaX); - - final int overScrolledBy; - final int movedBy; - if (!contentFits) { - final int overhang; - final boolean up; - mPopulating = true; - if (deltaX > 0) { - overhang = fillLeft(mFirstPosition - 1, allowOverhang); - up = true; - } else { - overhang = fillRight(mFirstPosition + getChildCount(), allowOverhang); - up = false; - } - movedBy = Math.min(overhang, allowOverhang); - offsetChildren(up ? movedBy : -movedBy); - recycleOffscreenViews(); - mPopulating = false; - overScrolledBy = allowOverhang - overhang; - } else { - overScrolledBy = allowOverhang; - movedBy = 0; - } - - if (allowOverScroll) { - final int overScrollMode = ViewCompat.getOverScrollMode(this); - - if (overScrollMode == ViewCompat.OVER_SCROLL_ALWAYS || - (overScrollMode == ViewCompat.OVER_SCROLL_IF_CONTENT_SCROLLS && !contentFits)) { - - if (overScrolledBy > 0) { - EdgeEffectCompat edge = deltaX > 0 ? mLeftEdge : mRightEdge; - edge.onPull((float) Math.abs(deltaX) / getWidth()); - ViewCompat.postInvalidateOnAnimation(this); - } - } - } - - return deltaX == 0 || movedBy != 0; - } - - /** - * Important: this method will leave offscreen views attached if they - * are required to maintain the invariant that child view with index i - * is always the view corresponding to position mFirstPosition + i. - */ - private void recycleOffscreenViews() { - final int height = getHeight(); - final int clearAbove = 0; - final int clearBelow = height; - for (int i = getChildCount() - 1; i >= 0; i--) { - final View child = getChildAt(i); - if (child.getTop() <= clearBelow) { - // There may be other offscreen views, but we need to maintain - // the invariant documented above. - break; - } - - if (mInLayout) { - removeViewsInLayout(i, 1); - } else { - removeViewAt(i); - } - - mRecycler.addScrap(child); - } - - while (getChildCount() > 0) { - final View child = getChildAt(0); - if (child.getBottom() >= clearAbove) { - // There may be other offscreen views, but we need to maintain - // the invariant documented above. - break; - } - - if (mInLayout) { - removeViewsInLayout(0, 1); - } else { - removeViewAt(0); - } - - mRecycler.addScrap(child); - mFirstPosition++; - } - } - - final void offsetChildren(int offset) { - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - final View child = getChildAt(i); - child.layout(child.getLeft() + offset, child.getTop(), - child.getRight() + offset, child.getBottom()); - } - } - - private boolean contentFits() { - final int childCount = getChildCount(); - if (childCount == 0) return true; - if (childCount != mItemCount) return false; - - return getChildAt(0).getLeft() >= getPaddingLeft() && - getChildAt(childCount - 1).getRight() <= getWidth() - getPaddingRight(); - } - - private void recycleAllViews() { - for (int i = 0; i < getChildCount(); i++) { - mRecycler.addScrap(getChildAt(i)); - } - - if (mInLayout) { - removeAllViewsInLayout(); - } else { - removeAllViews(); - } - } - - private int fillRight(int pos, int overhang) { - int end = (getRight() - getLeft()) + overhang; - - int nextLeft = getChildCount() == 0 ? 0 : getChildAt(getChildCount() - 1).getRight(); - while (nextLeft < end && pos < mItemCount) { - pos += makeAndAddColumn(pos, nextLeft, true); - nextLeft = getChildAt(getChildCount() - 1).getRight(); - } - final int gridRight = getWidth() - getPaddingRight(); - return getChildAt(getChildCount() - 1).getRight() - gridRight; - } - - private int fillLeft(int pos, int overhang) { - int end = getPaddingLeft() - overhang; - - int nextRight = getChildAt(0).getLeft(); - while (nextRight > end && pos >= 0) { - pos -= makeAndAddColumn(pos, nextRight, false); - nextRight = getChildAt(0).getLeft(); - } - - mFirstPosition = pos + 1; - return getPaddingLeft() - getChildAt(0).getLeft(); - } - - @Override - public void computeScroll() { - if (mScroller.computeScrollOffset()) { - final int x = mScroller.getCurrX(); - final int dx = (int) (x - mLastTouchX); - mLastTouchX = x; - final boolean stopped = !trackMotionScroll(dx, false); - - if (!stopped && !mScroller.isFinished()) { - ViewCompat.postInvalidateOnAnimation(this); - } else { - if (stopped) { - final int overScrollMode = ViewCompat.getOverScrollMode(this); - if (overScrollMode != ViewCompat.OVER_SCROLL_NEVER) { - final EdgeEffectCompat edge; - if (dx > 0) { - edge = mLeftEdge; - } else { - edge = mRightEdge; - } - edge.onAbsorb(Math.abs((int) mScroller.getCurrVelocity())); - ViewCompat.postInvalidateOnAnimation(this); - } - mScroller.abortAnimation(); - } - mTouchMode = TOUCH_MODE_IDLE; - } - } - } - - @Override - public void draw(Canvas canvas) { - super.draw(canvas); - - if (!mLeftEdge.isFinished()) { - final int restoreCount = canvas.save(); - final int height = getHeight() - getPaddingTop() - getPaddingBottom(); - - canvas.rotate(270); - canvas.translate(-height + getPaddingTop(), 0); - mLeftEdge.setSize(height, getWidth()); - if (mLeftEdge.draw(canvas)) { - postInvalidateOnAnimation(); - } - canvas.restoreToCount(restoreCount); - } - if (!mRightEdge.isFinished()) { - final int restoreCount = canvas.save(); - final int width = getWidth(); - final int height = getHeight() - getPaddingTop() - getPaddingBottom(); - - canvas.rotate(90); - canvas.translate(-getPaddingTop(), width); - mRightEdge.setSize(height, width); - if (mRightEdge.draw(canvas)) { - postInvalidateOnAnimation(); - } - canvas.restoreToCount(restoreCount); - } - } - - /** - * Obtain a populated view from the adapter. If optScrap is non-null and is not - * reused it will be placed in the recycle bin. - * - * @param position position to get view for - * @param optScrap Optional scrap view; will be reused if possible - * @return A new view, a recycled view from mRecycler, or optScrap - */ - private final View obtainView(int position, View optScrap) { - View view = mRecycler.getTransientStateView(position); - if (view != null) { - return view; - } - - // Reuse optScrap if it's of the right type (and not null) - final int optType = optScrap != null ? - ((LayoutParams) optScrap.getLayoutParams()).viewType : -1; - final int positionViewType = mAdapter.getItemViewType(position); - final View scrap = optType == positionViewType ? - optScrap : mRecycler.getScrapView(positionViewType); - - view = mAdapter.getView(position, scrap, this); - - if (view != scrap && scrap != null) { - // The adapter didn't use it; put it back. - mRecycler.addScrap(scrap); - } - - ViewGroup.LayoutParams lp = view.getLayoutParams(); - - if (view.getParent() != this) { - if (lp == null) { - lp = generateDefaultLayoutParams(); - } else if (!checkLayoutParams(lp)) { - lp = generateLayoutParams(lp); - } - view.setLayoutParams(lp); - } - - final LayoutParams sglp = (LayoutParams) lp; - sglp.position = position; - sglp.viewType = positionViewType; - - return view; - } - - public GalleryThumbnailAdapter getAdapter() { - return mAdapter; - } - - public void setAdapter(GalleryThumbnailAdapter adapter) { - if (mAdapter != null) { - mAdapter.unregisterDataSetObserver(mObserver); - } - // TODO: If the new adapter says that there are stable IDs, remove certain layout records - // and onscreen views if they have changed instead of removing all of the state here. - clearAllState(); - mAdapter = adapter; - mDataChanged = true; - mOldItemCount = mItemCount = adapter != null ? adapter.getCount() : 0; - if (adapter != null) { - adapter.registerDataSetObserver(mObserver); - mRecycler.setViewTypeCount(adapter.getViewTypeCount()); - mHasStableIds = adapter.hasStableIds(); - } else { - mHasStableIds = false; - } - populate(); - } - - /** - * Clear all state because the grid will be used for a completely different set of data. - */ - private void clearAllState() { - // Clear all layout records and views - removeAllViews(); - - // Reset to the top of the grid - mFirstPosition = 0; - - // Clear recycler because there could be different view types now - mRecycler.clear(); - } - - @Override - protected LayoutParams generateDefaultLayoutParams() { - return new LayoutParams(LayoutParams.WRAP_CONTENT); - } - - @Override - protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { - return new LayoutParams(lp); - } - - @Override - protected boolean checkLayoutParams(ViewGroup.LayoutParams lp) { - return lp instanceof LayoutParams; - } - - @Override - public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { - return new LayoutParams(getContext(), attrs); - } - - public static class LayoutParams extends ViewGroup.LayoutParams { - private static final int[] LAYOUT_ATTRS = new int[] { - android.R.attr.layout_span - }; - - private static final int SPAN_INDEX = 0; - - /** - * The number of columns this item should span - */ - public int span = 1; - - /** - * Item position this view represents - */ - int position; - - /** - * Type of this view as reported by the adapter - */ - int viewType; - - /** - * The column this view is occupying - */ - int column; - - /** - * The stable ID of the item this view displays - */ - long id = -1; - - public LayoutParams(int height) { - super(MATCH_PARENT, height); - - if (this.height == MATCH_PARENT) { - Log.w(TAG, "Constructing LayoutParams with height MATCH_PARENT - " + - "impossible! Falling back to WRAP_CONTENT"); - this.height = WRAP_CONTENT; - } - } - - public LayoutParams(Context c, AttributeSet attrs) { - super(c, attrs); - - if (this.width != MATCH_PARENT) { - Log.w(TAG, "Inflation setting LayoutParams width to " + this.width + - " - must be MATCH_PARENT"); - this.width = MATCH_PARENT; - } - if (this.height == MATCH_PARENT) { - Log.w(TAG, "Inflation setting LayoutParams height to MATCH_PARENT - " + - "impossible! Falling back to WRAP_CONTENT"); - this.height = WRAP_CONTENT; - } - - TypedArray a = c.obtainStyledAttributes(attrs, LAYOUT_ATTRS); - span = a.getInteger(SPAN_INDEX, 1); - a.recycle(); - } - - public LayoutParams(ViewGroup.LayoutParams other) { - super(other); - - if (this.width != MATCH_PARENT) { - Log.w(TAG, "Constructing LayoutParams with width " + this.width + - " - must be MATCH_PARENT"); - this.width = MATCH_PARENT; - } - if (this.height == MATCH_PARENT) { - Log.w(TAG, "Constructing LayoutParams with height MATCH_PARENT - " + - "impossible! Falling back to WRAP_CONTENT"); - this.height = WRAP_CONTENT; - } - } - } - - private class RecycleBin { - private ArrayList<View>[] mScrapViews; - private int mViewTypeCount; - private int mMaxScrap; - - private SparseArray<View> mTransientStateViews; - - public void setViewTypeCount(int viewTypeCount) { - if (viewTypeCount < 1) { - throw new IllegalArgumentException("Must have at least one view type (" + - viewTypeCount + " types reported)"); - } - if (viewTypeCount == mViewTypeCount) { - return; - } - - ArrayList<View>[] scrapViews = new ArrayList[viewTypeCount]; - for (int i = 0; i < viewTypeCount; i++) { - scrapViews[i] = new ArrayList<View>(); - } - mViewTypeCount = viewTypeCount; - mScrapViews = scrapViews; - } - - public void clear() { - final int typeCount = mViewTypeCount; - for (int i = 0; i < typeCount; i++) { - mScrapViews[i].clear(); - } - if (mTransientStateViews != null) { - mTransientStateViews.clear(); - } - } - - public void clearTransientViews() { - if (mTransientStateViews != null) { - mTransientStateViews.clear(); - } - } - - public void addScrap(View v) { - final LayoutParams lp = (LayoutParams) v.getLayoutParams(); - if (ViewCompat.hasTransientState(v)) { - if (mTransientStateViews == null) { - mTransientStateViews = new SparseArray<View>(); - } - mTransientStateViews.put(lp.position, v); - return; - } - - final int childCount = getChildCount(); - if (childCount > mMaxScrap) { - mMaxScrap = childCount; - } - - ArrayList<View> scrap = mScrapViews[lp.viewType]; - if (scrap.size() < mMaxScrap) { - scrap.add(v); - } - } - - public View getTransientStateView(int position) { - if (mTransientStateViews == null) { - return null; - } - - final View result = mTransientStateViews.get(position); - if (result != null) { - mTransientStateViews.remove(position); - } - return result; - } - - public View getScrapView(int type) { - ArrayList<View> scrap = mScrapViews[type]; - if (scrap.isEmpty()) { - return null; - } - - final int index = scrap.size() - 1; - final View result = scrap.get(index); - scrap.remove(index); - return result; - } - } - - private class AdapterDataSetObserver extends DataSetObserver { - @Override - public void onChanged() { - mDataChanged = true; - mOldItemCount = mItemCount; - mItemCount = mAdapter.getCount(); - - // TODO: Consider matching these back up if we have stable IDs. - mRecycler.clearTransientViews(); - - if (!mHasStableIds) { - recycleAllViews(); - } - - // TODO: consider repopulating in a deferred runnable instead - // (so that successive changes may still be batched) - requestLayout(); - } - - @Override - public void onInvalidated() { - } - } -} diff --git a/src/com/android/photos/views/HeaderGridView.java b/src/com/android/photos/views/HeaderGridView.java deleted file mode 100644 index 45a5eaf73..000000000 --- a/src/com/android/photos/views/HeaderGridView.java +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.views; - -import android.content.Context; -import android.database.DataSetObservable; -import android.database.DataSetObserver; -import android.util.AttributeSet; -import android.view.View; -import android.view.ViewGroup; -import android.widget.AdapterView; -import android.widget.Filter; -import android.widget.Filterable; -import android.widget.FrameLayout; -import android.widget.GridView; -import android.widget.ListAdapter; -import android.widget.WrapperListAdapter; - -import java.util.ArrayList; - -/** - * A {@link GridView} that supports adding header rows in a - * very similar way to {@link ListView}. - * See {@link HeaderGridView#addHeaderView(View, Object, boolean)} - */ -public class HeaderGridView extends GridView { - private static final String TAG = "HeaderGridView"; - - /** - * A class that represents a fixed view in a list, for example a header at the top - * or a footer at the bottom. - */ - private static class FixedViewInfo { - /** The view to add to the grid */ - public View view; - public ViewGroup viewContainer; - /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */ - public Object data; - /** <code>true</code> if the fixed view should be selectable in the grid */ - public boolean isSelectable; - } - - private ArrayList<FixedViewInfo> mHeaderViewInfos = new ArrayList<FixedViewInfo>(); - - private void initHeaderGridView() { - super.setClipChildren(false); - } - - public HeaderGridView(Context context) { - super(context); - initHeaderGridView(); - } - - public HeaderGridView(Context context, AttributeSet attrs) { - super(context, attrs); - initHeaderGridView(); - } - - public HeaderGridView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - initHeaderGridView(); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - ListAdapter adapter = getAdapter(); - if (adapter != null && adapter instanceof HeaderViewGridAdapter) { - ((HeaderViewGridAdapter) adapter).setNumColumns(getNumColumns()); - } - } - - @Override - public void setClipChildren(boolean clipChildren) { - // Ignore, since the header rows depend on not being clipped - } - - /** - * Add a fixed view to appear at the top of the grid. If addHeaderView is - * called more than once, the views will appear in the order they were - * added. Views added using this call can take focus if they want. - * <p> - * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap - * the supplied cursor with one that will also account for header views. - * - * @param v The view to add. - * @param data Data to associate with this view - * @param isSelectable whether the item is selectable - */ - public void addHeaderView(View v, Object data, boolean isSelectable) { - ListAdapter adapter = getAdapter(); - - if (adapter != null && ! (adapter instanceof HeaderViewGridAdapter)) { - throw new IllegalStateException( - "Cannot add header view to grid -- setAdapter has already been called."); - } - - FixedViewInfo info = new FixedViewInfo(); - FrameLayout fl = new FullWidthFixedViewLayout(getContext()); - fl.addView(v); - info.view = v; - info.viewContainer = fl; - info.data = data; - info.isSelectable = isSelectable; - mHeaderViewInfos.add(info); - - // in the case of re-adding a header view, or adding one later on, - // we need to notify the observer - if (adapter != null) { - ((HeaderViewGridAdapter) adapter).notifyDataSetChanged(); - } - } - - /** - * Add a fixed view to appear at the top of the grid. If addHeaderView is - * called more than once, the views will appear in the order they were - * added. Views added using this call can take focus if they want. - * <p> - * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap - * the supplied cursor with one that will also account for header views. - * - * @param v The view to add. - */ - public void addHeaderView(View v) { - addHeaderView(v, null, true); - } - - public int getHeaderViewCount() { - return mHeaderViewInfos.size(); - } - - /** - * Removes a previously-added header view. - * - * @param v The view to remove - * @return true if the view was removed, false if the view was not a header - * view - */ - public boolean removeHeaderView(View v) { - if (mHeaderViewInfos.size() > 0) { - boolean result = false; - ListAdapter adapter = getAdapter(); - if (adapter != null && ((HeaderViewGridAdapter) adapter).removeHeader(v)) { - result = true; - } - removeFixedViewInfo(v, mHeaderViewInfos); - return result; - } - return false; - } - - private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) { - int len = where.size(); - for (int i = 0; i < len; ++i) { - FixedViewInfo info = where.get(i); - if (info.view == v) { - where.remove(i); - break; - } - } - } - - @Override - public void setAdapter(ListAdapter adapter) { - if (mHeaderViewInfos.size() > 0) { - HeaderViewGridAdapter hadapter = new HeaderViewGridAdapter(mHeaderViewInfos, adapter); - int numColumns = getNumColumns(); - if (numColumns > 1) { - hadapter.setNumColumns(numColumns); - } - super.setAdapter(hadapter); - } else { - super.setAdapter(adapter); - } - } - - private class FullWidthFixedViewLayout extends FrameLayout { - public FullWidthFixedViewLayout(Context context) { - super(context); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int targetWidth = HeaderGridView.this.getMeasuredWidth() - - HeaderGridView.this.getPaddingLeft() - - HeaderGridView.this.getPaddingRight(); - widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth, - MeasureSpec.getMode(widthMeasureSpec)); - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } - - /** - * ListAdapter used when a HeaderGridView has header views. This ListAdapter - * wraps another one and also keeps track of the header views and their - * associated data objects. - *<p>This is intended as a base class; you will probably not need to - * use this class directly in your own code. - */ - private static class HeaderViewGridAdapter implements WrapperListAdapter, Filterable { - - // This is used to notify the container of updates relating to number of columns - // or headers changing, which changes the number of placeholders needed - private final DataSetObservable mDataSetObservable = new DataSetObservable(); - - private final ListAdapter mAdapter; - private int mNumColumns = 1; - - // This ArrayList is assumed to NOT be null. - ArrayList<FixedViewInfo> mHeaderViewInfos; - - boolean mAreAllFixedViewsSelectable; - - private final boolean mIsFilterable; - - public HeaderViewGridAdapter(ArrayList<FixedViewInfo> headerViewInfos, ListAdapter adapter) { - mAdapter = adapter; - mIsFilterable = adapter instanceof Filterable; - - if (headerViewInfos == null) { - throw new IllegalArgumentException("headerViewInfos cannot be null"); - } - mHeaderViewInfos = headerViewInfos; - - mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos); - } - - public int getHeadersCount() { - return mHeaderViewInfos.size(); - } - - @Override - public boolean isEmpty() { - return (mAdapter == null || mAdapter.isEmpty()) && getHeadersCount() == 0; - } - - public void setNumColumns(int numColumns) { - if (numColumns < 1) { - throw new IllegalArgumentException("Number of columns must be 1 or more"); - } - if (mNumColumns != numColumns) { - mNumColumns = numColumns; - notifyDataSetChanged(); - } - } - - private boolean areAllListInfosSelectable(ArrayList<FixedViewInfo> infos) { - if (infos != null) { - for (FixedViewInfo info : infos) { - if (!info.isSelectable) { - return false; - } - } - } - return true; - } - - public boolean removeHeader(View v) { - for (int i = 0; i < mHeaderViewInfos.size(); i++) { - FixedViewInfo info = mHeaderViewInfos.get(i); - if (info.view == v) { - mHeaderViewInfos.remove(i); - - mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos); - - mDataSetObservable.notifyChanged(); - return true; - } - } - - return false; - } - - @Override - public int getCount() { - if (mAdapter != null) { - return getHeadersCount() * mNumColumns + mAdapter.getCount(); - } else { - return getHeadersCount() * mNumColumns; - } - } - - @Override - public boolean areAllItemsEnabled() { - if (mAdapter != null) { - return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled(); - } else { - return true; - } - } - - @Override - public boolean isEnabled(int position) { - // Header (negative positions will throw an ArrayIndexOutOfBoundsException) - int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; - if (position < numHeadersAndPlaceholders) { - return (position % mNumColumns == 0) - && mHeaderViewInfos.get(position / mNumColumns).isSelectable; - } - - // Adapter - final int adjPosition = position - numHeadersAndPlaceholders; - int adapterCount = 0; - if (mAdapter != null) { - adapterCount = mAdapter.getCount(); - if (adjPosition < adapterCount) { - return mAdapter.isEnabled(adjPosition); - } - } - - throw new ArrayIndexOutOfBoundsException(position); - } - - @Override - public Object getItem(int position) { - // Header (negative positions will throw an ArrayIndexOutOfBoundsException) - int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; - if (position < numHeadersAndPlaceholders) { - if (position % mNumColumns == 0) { - return mHeaderViewInfos.get(position / mNumColumns).data; - } - return null; - } - - // Adapter - final int adjPosition = position - numHeadersAndPlaceholders; - int adapterCount = 0; - if (mAdapter != null) { - adapterCount = mAdapter.getCount(); - if (adjPosition < adapterCount) { - return mAdapter.getItem(adjPosition); - } - } - - throw new ArrayIndexOutOfBoundsException(position); - } - - @Override - public long getItemId(int position) { - int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; - if (mAdapter != null && position >= numHeadersAndPlaceholders) { - int adjPosition = position - numHeadersAndPlaceholders; - int adapterCount = mAdapter.getCount(); - if (adjPosition < adapterCount) { - return mAdapter.getItemId(adjPosition); - } - } - return -1; - } - - @Override - public boolean hasStableIds() { - if (mAdapter != null) { - return mAdapter.hasStableIds(); - } - return false; - } - - @Override - public View getView(int position, View convertView, ViewGroup parent) { - // Header (negative positions will throw an ArrayIndexOutOfBoundsException) - int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns ; - if (position < numHeadersAndPlaceholders) { - View headerViewContainer = mHeaderViewInfos - .get(position / mNumColumns).viewContainer; - if (position % mNumColumns == 0) { - return headerViewContainer; - } else { - if (convertView == null) { - convertView = new View(parent.getContext()); - } - // We need to do this because GridView uses the height of the last item - // in a row to determine the height for the entire row. - convertView.setVisibility(View.INVISIBLE); - convertView.setMinimumHeight(headerViewContainer.getHeight()); - return convertView; - } - } - - // Adapter - final int adjPosition = position - numHeadersAndPlaceholders; - int adapterCount = 0; - if (mAdapter != null) { - adapterCount = mAdapter.getCount(); - if (adjPosition < adapterCount) { - return mAdapter.getView(adjPosition, convertView, parent); - } - } - - throw new ArrayIndexOutOfBoundsException(position); - } - - @Override - public int getItemViewType(int position) { - int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; - if (position < numHeadersAndPlaceholders && (position % mNumColumns != 0)) { - // Placeholders get the last view type number - return mAdapter != null ? mAdapter.getViewTypeCount() : 1; - } - if (mAdapter != null && position >= numHeadersAndPlaceholders) { - int adjPosition = position - numHeadersAndPlaceholders; - int adapterCount = mAdapter.getCount(); - if (adjPosition < adapterCount) { - return mAdapter.getItemViewType(adjPosition); - } - } - - return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER; - } - - @Override - public int getViewTypeCount() { - if (mAdapter != null) { - return mAdapter.getViewTypeCount() + 1; - } - return 2; - } - - @Override - public void registerDataSetObserver(DataSetObserver observer) { - mDataSetObservable.registerObserver(observer); - if (mAdapter != null) { - mAdapter.registerDataSetObserver(observer); - } - } - - @Override - public void unregisterDataSetObserver(DataSetObserver observer) { - mDataSetObservable.unregisterObserver(observer); - if (mAdapter != null) { - mAdapter.unregisterDataSetObserver(observer); - } - } - - @Override - public Filter getFilter() { - if (mIsFilterable) { - return ((Filterable) mAdapter).getFilter(); - } - return null; - } - - @Override - public ListAdapter getWrappedAdapter() { - return mAdapter; - } - - public void notifyDataSetChanged() { - mDataSetObservable.notifyChanged(); - } - } -} diff --git a/src/com/android/photos/views/SquareImageView.java b/src/com/android/photos/views/SquareImageView.java deleted file mode 100644 index 14eff1077..000000000 --- a/src/com/android/photos/views/SquareImageView.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.views; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.ImageView; - - -public class SquareImageView extends ImageView { - - public SquareImageView(Context context) { - super(context); - } - - public SquareImageView(Context context, AttributeSet attrs) { - super(context, attrs); - } - - public SquareImageView(Context context, AttributeSet attrs, int defStyle) { - super(context, attrs, defStyle); - } - - @Override - protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { - int widthMode = MeasureSpec.getMode(widthMeasureSpec); - int heightMode = MeasureSpec.getMode(heightMeasureSpec); - if (widthMode == MeasureSpec.EXACTLY && heightMode != MeasureSpec.EXACTLY) { - int width = MeasureSpec.getSize(widthMeasureSpec); - int height = width; - if (heightMode == MeasureSpec.AT_MOST) { - height = Math.min(height, MeasureSpec.getSize(heightMeasureSpec)); - } - setMeasuredDimension(width, height); - } else { - super.onMeasure(widthMeasureSpec, heightMeasureSpec); - } - } -} diff --git a/src/com/android/photos/views/TiledImageRenderer.java b/src/com/android/photos/views/TiledImageRenderer.java deleted file mode 100644 index c4e493b34..000000000 --- a/src/com/android/photos/views/TiledImageRenderer.java +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.views; - -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Rect; -import android.graphics.RectF; -import android.support.v4.util.LongSparseArray; -import android.util.DisplayMetrics; -import android.util.Log; -import android.util.Pools.Pool; -import android.util.Pools.SynchronizedPool; -import android.view.View; -import android.view.WindowManager; - -import com.android.gallery3d.common.Utils; -import com.android.gallery3d.glrenderer.BasicTexture; -import com.android.gallery3d.glrenderer.GLCanvas; -import com.android.gallery3d.glrenderer.UploadedTexture; - -/** - * Handles laying out, decoding, and drawing of tiles in GL - */ -public class TiledImageRenderer { - public static final int SIZE_UNKNOWN = -1; - - private static final String TAG = "TiledImageRenderer"; - private static final int UPLOAD_LIMIT = 1; - - /* - * This is the tile state in the CPU side. - * Life of a Tile: - * ACTIVATED (initial state) - * --> IN_QUEUE - by queueForDecode() - * --> RECYCLED - by recycleTile() - * IN_QUEUE --> DECODING - by decodeTile() - * --> RECYCLED - by recycleTile) - * DECODING --> RECYCLING - by recycleTile() - * --> DECODED - by decodeTile() - * --> DECODE_FAIL - by decodeTile() - * RECYCLING --> RECYCLED - by decodeTile() - * DECODED --> ACTIVATED - (after the decoded bitmap is uploaded) - * DECODED --> RECYCLED - by recycleTile() - * DECODE_FAIL -> RECYCLED - by recycleTile() - * RECYCLED --> ACTIVATED - by obtainTile() - */ - private static final int STATE_ACTIVATED = 0x01; - private static final int STATE_IN_QUEUE = 0x02; - private static final int STATE_DECODING = 0x04; - private static final int STATE_DECODED = 0x08; - private static final int STATE_DECODE_FAIL = 0x10; - private static final int STATE_RECYCLING = 0x20; - private static final int STATE_RECYCLED = 0x40; - - private static Pool<Bitmap> sTilePool = new SynchronizedPool<Bitmap>(64); - - // TILE_SIZE must be 2^N - private int mTileSize; - - private TileSource mModel; - private BasicTexture mPreview; - protected int mLevelCount; // cache the value of mScaledBitmaps.length - - // The mLevel variable indicates which level of bitmap we should use. - // Level 0 means the original full-sized bitmap, and a larger value means - // a smaller scaled bitmap (The width and height of each scaled bitmap is - // half size of the previous one). If the value is in [0, mLevelCount), we - // use the bitmap in mScaledBitmaps[mLevel] for display, otherwise the value - // is mLevelCount - private int mLevel = 0; - - private int mOffsetX; - private int mOffsetY; - - private int mUploadQuota; - private boolean mRenderComplete; - - private final RectF mSourceRect = new RectF(); - private final RectF mTargetRect = new RectF(); - - private final LongSparseArray<Tile> mActiveTiles = new LongSparseArray<Tile>(); - - // The following three queue are guarded by mQueueLock - private final Object mQueueLock = new Object(); - private final TileQueue mRecycledQueue = new TileQueue(); - private final TileQueue mUploadQueue = new TileQueue(); - private final TileQueue mDecodeQueue = new TileQueue(); - - // The width and height of the full-sized bitmap - protected int mImageWidth = SIZE_UNKNOWN; - protected int mImageHeight = SIZE_UNKNOWN; - - protected int mCenterX; - protected int mCenterY; - protected float mScale; - protected int mRotation; - - private boolean mLayoutTiles; - - // Temp variables to avoid memory allocation - private final Rect mTileRange = new Rect(); - private final Rect mActiveRange[] = {new Rect(), new Rect()}; - - private TileDecoder mTileDecoder; - private boolean mBackgroundTileUploaded; - - private int mViewWidth, mViewHeight; - private View mParent; - - /** - * Interface for providing tiles to a {@link TiledImageRenderer} - */ - public static interface TileSource { - - /** - * If the source does not care about the tile size, it should use - * {@link TiledImageRenderer#suggestedTileSize(Context)} - */ - public int getTileSize(); - public int getImageWidth(); - public int getImageHeight(); - public int getRotation(); - - /** - * Return a Preview image if available. This will be used as the base layer - * if higher res tiles are not yet available - */ - public BasicTexture getPreview(); - - /** - * The tile returned by this method can be specified this way: Assuming - * the image size is (width, height), first take the intersection of (0, - * 0) - (width, height) and (x, y) - (x + tileSize, y + tileSize). If - * in extending the region, we found some part of the region is outside - * the image, those pixels are filled with black. - * - * If level > 0, it does the same operation on a down-scaled version of - * the original image (down-scaled by a factor of 2^level), but (x, y) - * still refers to the coordinate on the original image. - * - * The method would be called by the decoder thread. - */ - public Bitmap getTile(int level, int x, int y, Bitmap reuse); - } - - public static int suggestedTileSize(Context context) { - return isHighResolution(context) ? 512 : 256; - } - - private static boolean isHighResolution(Context context) { - DisplayMetrics metrics = new DisplayMetrics(); - WindowManager wm = (WindowManager) - context.getSystemService(Context.WINDOW_SERVICE); - wm.getDefaultDisplay().getMetrics(metrics); - return metrics.heightPixels > 2048 || metrics.widthPixels > 2048; - } - - public TiledImageRenderer(View parent) { - mParent = parent; - mTileDecoder = new TileDecoder(); - mTileDecoder.start(); - } - - public int getViewWidth() { - return mViewWidth; - } - - public int getViewHeight() { - return mViewHeight; - } - - private void invalidate() { - mParent.postInvalidate(); - } - - public void setModel(TileSource model, int rotation) { - if (mModel != model) { - mModel = model; - notifyModelInvalidated(); - } - if (mRotation != rotation) { - mRotation = rotation; - mLayoutTiles = true; - } - } - - private void calculateLevelCount() { - if (mPreview != null) { - mLevelCount = Math.max(0, Utils.ceilLog2( - mImageWidth / (float) mPreview.getWidth())); - } else { - int levels = 1; - int maxDim = Math.max(mImageWidth, mImageHeight); - int t = mTileSize; - while (t < maxDim) { - t <<= 1; - levels++; - } - mLevelCount = levels; - } - } - - public void notifyModelInvalidated() { - invalidateTiles(); - if (mModel == null) { - mImageWidth = 0; - mImageHeight = 0; - mLevelCount = 0; - mPreview = null; - } else { - mImageWidth = mModel.getImageWidth(); - mImageHeight = mModel.getImageHeight(); - mPreview = mModel.getPreview(); - mTileSize = mModel.getTileSize(); - calculateLevelCount(); - } - mLayoutTiles = true; - } - - public void setViewSize(int width, int height) { - mViewWidth = width; - mViewHeight = height; - } - - public void setPosition(int centerX, int centerY, float scale) { - if (mCenterX == centerX && mCenterY == centerY - && mScale == scale) { - return; - } - mCenterX = centerX; - mCenterY = centerY; - mScale = scale; - mLayoutTiles = true; - } - - // Prepare the tiles we want to use for display. - // - // 1. Decide the tile level we want to use for display. - // 2. Decide the tile levels we want to keep as texture (in addition to - // the one we use for display). - // 3. Recycle unused tiles. - // 4. Activate the tiles we want. - private void layoutTiles() { - if (mViewWidth == 0 || mViewHeight == 0 || !mLayoutTiles) { - return; - } - mLayoutTiles = false; - - // The tile levels we want to keep as texture is in the range - // [fromLevel, endLevel). - int fromLevel; - int endLevel; - - // We want to use a texture larger than or equal to the display size. - mLevel = Utils.clamp(Utils.floorLog2(1f / mScale), 0, mLevelCount); - - // We want to keep one more tile level as texture in addition to what - // we use for display. So it can be faster when the scale moves to the - // next level. We choose the level closest to the current scale. - if (mLevel != mLevelCount) { - Rect range = mTileRange; - getRange(range, mCenterX, mCenterY, mLevel, mScale, mRotation); - mOffsetX = Math.round(mViewWidth / 2f + (range.left - mCenterX) * mScale); - mOffsetY = Math.round(mViewHeight / 2f + (range.top - mCenterY) * mScale); - fromLevel = mScale * (1 << mLevel) > 0.75f ? mLevel - 1 : mLevel; - } else { - // Activate the tiles of the smallest two levels. - fromLevel = mLevel - 2; - mOffsetX = Math.round(mViewWidth / 2f - mCenterX * mScale); - mOffsetY = Math.round(mViewHeight / 2f - mCenterY * mScale); - } - - fromLevel = Math.max(0, Math.min(fromLevel, mLevelCount - 2)); - endLevel = Math.min(fromLevel + 2, mLevelCount); - - Rect range[] = mActiveRange; - for (int i = fromLevel; i < endLevel; ++i) { - getRange(range[i - fromLevel], mCenterX, mCenterY, i, mRotation); - } - - // If rotation is transient, don't update the tile. - if (mRotation % 90 != 0) { - return; - } - - synchronized (mQueueLock) { - mDecodeQueue.clean(); - mUploadQueue.clean(); - mBackgroundTileUploaded = false; - - // Recycle unused tiles: if the level of the active tile is outside the - // range [fromLevel, endLevel) or not in the visible range. - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile tile = mActiveTiles.valueAt(i); - int level = tile.mTileLevel; - if (level < fromLevel || level >= endLevel - || !range[level - fromLevel].contains(tile.mX, tile.mY)) { - mActiveTiles.removeAt(i); - i--; - n--; - recycleTile(tile); - } - } - } - - for (int i = fromLevel; i < endLevel; ++i) { - int size = mTileSize << i; - Rect r = range[i - fromLevel]; - for (int y = r.top, bottom = r.bottom; y < bottom; y += size) { - for (int x = r.left, right = r.right; x < right; x += size) { - activateTile(x, y, i); - } - } - } - invalidate(); - } - - private void invalidateTiles() { - synchronized (mQueueLock) { - mDecodeQueue.clean(); - mUploadQueue.clean(); - - // TODO(xx): disable decoder - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile tile = mActiveTiles.valueAt(i); - recycleTile(tile); - } - mActiveTiles.clear(); - } - } - - private void getRange(Rect out, int cX, int cY, int level, int rotation) { - getRange(out, cX, cY, level, 1f / (1 << (level + 1)), rotation); - } - - // If the bitmap is scaled by the given factor "scale", return the - // rectangle containing visible range. The left-top coordinate returned is - // aligned to the tile boundary. - // - // (cX, cY) is the point on the original bitmap which will be put in the - // center of the ImageViewer. - private void getRange(Rect out, - int cX, int cY, int level, float scale, int rotation) { - - double radians = Math.toRadians(-rotation); - double w = mViewWidth; - double h = mViewHeight; - - double cos = Math.cos(radians); - double sin = Math.sin(radians); - int width = (int) Math.ceil(Math.max( - Math.abs(cos * w - sin * h), Math.abs(cos * w + sin * h))); - int height = (int) Math.ceil(Math.max( - Math.abs(sin * w + cos * h), Math.abs(sin * w - cos * h))); - - int left = (int) Math.floor(cX - width / (2f * scale)); - int top = (int) Math.floor(cY - height / (2f * scale)); - int right = (int) Math.ceil(left + width / scale); - int bottom = (int) Math.ceil(top + height / scale); - - // align the rectangle to tile boundary - int size = mTileSize << level; - left = Math.max(0, size * (left / size)); - top = Math.max(0, size * (top / size)); - right = Math.min(mImageWidth, right); - bottom = Math.min(mImageHeight, bottom); - - out.set(left, top, right, bottom); - } - - public void freeTextures() { - mLayoutTiles = true; - - mTileDecoder.finishAndWait(); - synchronized (mQueueLock) { - mUploadQueue.clean(); - mDecodeQueue.clean(); - Tile tile = mRecycledQueue.pop(); - while (tile != null) { - tile.recycle(); - tile = mRecycledQueue.pop(); - } - } - - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile texture = mActiveTiles.valueAt(i); - texture.recycle(); - } - mActiveTiles.clear(); - mTileRange.set(0, 0, 0, 0); - - while (sTilePool.acquire() != null) {} - } - - public boolean draw(GLCanvas canvas) { - layoutTiles(); - uploadTiles(canvas); - - mUploadQuota = UPLOAD_LIMIT; - mRenderComplete = true; - - int level = mLevel; - int rotation = mRotation; - int flags = 0; - if (rotation != 0) { - flags |= GLCanvas.SAVE_FLAG_MATRIX; - } - - if (flags != 0) { - canvas.save(flags); - if (rotation != 0) { - int centerX = mViewWidth / 2, centerY = mViewHeight / 2; - canvas.translate(centerX, centerY); - canvas.rotate(rotation, 0, 0, 1); - canvas.translate(-centerX, -centerY); - } - } - try { - if (level != mLevelCount) { - int size = (mTileSize << level); - float length = size * mScale; - Rect r = mTileRange; - - for (int ty = r.top, i = 0; ty < r.bottom; ty += size, i++) { - float y = mOffsetY + i * length; - for (int tx = r.left, j = 0; tx < r.right; tx += size, j++) { - float x = mOffsetX + j * length; - drawTile(canvas, tx, ty, level, x, y, length); - } - } - } else if (mPreview != null) { - mPreview.draw(canvas, mOffsetX, mOffsetY, - Math.round(mImageWidth * mScale), - Math.round(mImageHeight * mScale)); - } - } finally { - if (flags != 0) { - canvas.restore(); - } - } - - if (mRenderComplete) { - if (!mBackgroundTileUploaded) { - uploadBackgroundTiles(canvas); - } - } else { - invalidate(); - } - return mRenderComplete || mPreview != null; - } - - private void uploadBackgroundTiles(GLCanvas canvas) { - mBackgroundTileUploaded = true; - int n = mActiveTiles.size(); - for (int i = 0; i < n; i++) { - Tile tile = mActiveTiles.valueAt(i); - if (!tile.isContentValid()) { - queueForDecode(tile); - } - } - } - - private void queueForDecode(Tile tile) { - synchronized (mQueueLock) { - if (tile.mTileState == STATE_ACTIVATED) { - tile.mTileState = STATE_IN_QUEUE; - if (mDecodeQueue.push(tile)) { - mQueueLock.notifyAll(); - } - } - } - } - - private void decodeTile(Tile tile) { - synchronized (mQueueLock) { - if (tile.mTileState != STATE_IN_QUEUE) { - return; - } - tile.mTileState = STATE_DECODING; - } - boolean decodeComplete = tile.decode(); - synchronized (mQueueLock) { - if (tile.mTileState == STATE_RECYCLING) { - tile.mTileState = STATE_RECYCLED; - if (tile.mDecodedTile != null) { - sTilePool.release(tile.mDecodedTile); - tile.mDecodedTile = null; - } - mRecycledQueue.push(tile); - return; - } - tile.mTileState = decodeComplete ? STATE_DECODED : STATE_DECODE_FAIL; - if (!decodeComplete) { - return; - } - mUploadQueue.push(tile); - } - invalidate(); - } - - private Tile obtainTile(int x, int y, int level) { - synchronized (mQueueLock) { - Tile tile = mRecycledQueue.pop(); - if (tile != null) { - tile.mTileState = STATE_ACTIVATED; - tile.update(x, y, level); - return tile; - } - return new Tile(x, y, level); - } - } - - private void recycleTile(Tile tile) { - synchronized (mQueueLock) { - if (tile.mTileState == STATE_DECODING) { - tile.mTileState = STATE_RECYCLING; - return; - } - tile.mTileState = STATE_RECYCLED; - if (tile.mDecodedTile != null) { - sTilePool.release(tile.mDecodedTile); - tile.mDecodedTile = null; - } - mRecycledQueue.push(tile); - } - } - - private void activateTile(int x, int y, int level) { - long key = makeTileKey(x, y, level); - Tile tile = mActiveTiles.get(key); - if (tile != null) { - if (tile.mTileState == STATE_IN_QUEUE) { - tile.mTileState = STATE_ACTIVATED; - } - return; - } - tile = obtainTile(x, y, level); - mActiveTiles.put(key, tile); - } - - private Tile getTile(int x, int y, int level) { - return mActiveTiles.get(makeTileKey(x, y, level)); - } - - private static long makeTileKey(int x, int y, int level) { - long result = x; - result = (result << 16) | y; - result = (result << 16) | level; - return result; - } - - private void uploadTiles(GLCanvas canvas) { - int quota = UPLOAD_LIMIT; - Tile tile = null; - while (quota > 0) { - synchronized (mQueueLock) { - tile = mUploadQueue.pop(); - } - if (tile == null) { - break; - } - if (!tile.isContentValid()) { - if (tile.mTileState == STATE_DECODED) { - tile.updateContent(canvas); - --quota; - } else { - Log.w(TAG, "Tile in upload queue has invalid state: " + tile.mTileState); - } - } - } - if (tile != null) { - invalidate(); - } - } - - // Draw the tile to a square at canvas that locates at (x, y) and - // has a side length of length. - private void drawTile(GLCanvas canvas, - int tx, int ty, int level, float x, float y, float length) { - RectF source = mSourceRect; - RectF target = mTargetRect; - target.set(x, y, x + length, y + length); - source.set(0, 0, mTileSize, mTileSize); - - Tile tile = getTile(tx, ty, level); - if (tile != null) { - if (!tile.isContentValid()) { - if (tile.mTileState == STATE_DECODED) { - if (mUploadQuota > 0) { - --mUploadQuota; - tile.updateContent(canvas); - } else { - mRenderComplete = false; - } - } else if (tile.mTileState != STATE_DECODE_FAIL){ - mRenderComplete = false; - queueForDecode(tile); - } - } - if (drawTile(tile, canvas, source, target)) { - return; - } - } - if (mPreview != null) { - int size = mTileSize << level; - float scaleX = (float) mPreview.getWidth() / mImageWidth; - float scaleY = (float) mPreview.getHeight() / mImageHeight; - source.set(tx * scaleX, ty * scaleY, (tx + size) * scaleX, - (ty + size) * scaleY); - canvas.drawTexture(mPreview, source, target); - } - } - - private boolean drawTile( - Tile tile, GLCanvas canvas, RectF source, RectF target) { - while (true) { - if (tile.isContentValid()) { - canvas.drawTexture(tile, source, target); - return true; - } - - // Parent can be divided to four quads and tile is one of the four. - Tile parent = tile.getParentTile(); - if (parent == null) { - return false; - } - if (tile.mX == parent.mX) { - source.left /= 2f; - source.right /= 2f; - } else { - source.left = (mTileSize + source.left) / 2f; - source.right = (mTileSize + source.right) / 2f; - } - if (tile.mY == parent.mY) { - source.top /= 2f; - source.bottom /= 2f; - } else { - source.top = (mTileSize + source.top) / 2f; - source.bottom = (mTileSize + source.bottom) / 2f; - } - tile = parent; - } - } - - private class Tile extends UploadedTexture { - public int mX; - public int mY; - public int mTileLevel; - public Tile mNext; - public Bitmap mDecodedTile; - public volatile int mTileState = STATE_ACTIVATED; - - public Tile(int x, int y, int level) { - mX = x; - mY = y; - mTileLevel = level; - } - - @Override - protected void onFreeBitmap(Bitmap bitmap) { - sTilePool.release(bitmap); - } - - boolean decode() { - // Get a tile from the original image. The tile is down-scaled - // by (1 << mTilelevel) from a region in the original image. - try { - Bitmap reuse = sTilePool.acquire(); - if (reuse != null && reuse.getWidth() != mTileSize) { - reuse = null; - } - mDecodedTile = mModel.getTile(mTileLevel, mX, mY, reuse); - } catch (Throwable t) { - Log.w(TAG, "fail to decode tile", t); - } - return mDecodedTile != null; - } - - @Override - protected Bitmap onGetBitmap() { - Utils.assertTrue(mTileState == STATE_DECODED); - - // We need to override the width and height, so that we won't - // draw beyond the boundaries. - int rightEdge = ((mImageWidth - mX) >> mTileLevel); - int bottomEdge = ((mImageHeight - mY) >> mTileLevel); - setSize(Math.min(mTileSize, rightEdge), Math.min(mTileSize, bottomEdge)); - - Bitmap bitmap = mDecodedTile; - mDecodedTile = null; - mTileState = STATE_ACTIVATED; - return bitmap; - } - - // We override getTextureWidth() and getTextureHeight() here, so the - // texture can be re-used for different tiles regardless of the actual - // size of the tile (which may be small because it is a tile at the - // boundary). - @Override - public int getTextureWidth() { - return mTileSize; - } - - @Override - public int getTextureHeight() { - return mTileSize; - } - - public void update(int x, int y, int level) { - mX = x; - mY = y; - mTileLevel = level; - invalidateContent(); - } - - public Tile getParentTile() { - if (mTileLevel + 1 == mLevelCount) { - return null; - } - int size = mTileSize << (mTileLevel + 1); - int x = size * (mX / size); - int y = size * (mY / size); - return getTile(x, y, mTileLevel + 1); - } - - @Override - public String toString() { - return String.format("tile(%s, %s, %s / %s)", - mX / mTileSize, mY / mTileSize, mLevel, mLevelCount); - } - } - - private static class TileQueue { - private Tile mHead; - - public Tile pop() { - Tile tile = mHead; - if (tile != null) { - mHead = tile.mNext; - } - return tile; - } - - public boolean push(Tile tile) { - if (contains(tile)) { - Log.w(TAG, "Attempting to add a tile already in the queue!"); - return false; - } - boolean wasEmpty = mHead == null; - tile.mNext = mHead; - mHead = tile; - return wasEmpty; - } - - private boolean contains(Tile tile) { - Tile other = mHead; - while (other != null) { - if (other == tile) { - return true; - } - other = other.mNext; - } - return false; - } - - public void clean() { - mHead = null; - } - } - - private class TileDecoder extends Thread { - - public void finishAndWait() { - interrupt(); - try { - join(); - } catch (InterruptedException e) { - Log.w(TAG, "Interrupted while waiting for TileDecoder thread to finish!"); - } - } - - private Tile waitForTile() throws InterruptedException { - synchronized (mQueueLock) { - while (true) { - Tile tile = mDecodeQueue.pop(); - if (tile != null) { - return tile; - } - mQueueLock.wait(); - } - } - } - - @Override - public void run() { - try { - while (!isInterrupted()) { - Tile tile = waitForTile(); - decodeTile(tile); - } - } catch (InterruptedException ex) { - // We were finished - } - } - - } -} diff --git a/src/com/android/photos/views/TiledImageView.java b/src/com/android/photos/views/TiledImageView.java deleted file mode 100644 index 8bc07c051..000000000 --- a/src/com/android/photos/views/TiledImageView.java +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.photos.views; - -import android.annotation.SuppressLint; -import android.annotation.TargetApi; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.Matrix; -import android.graphics.Paint; -import android.graphics.Paint.Align; -import android.graphics.RectF; -import android.opengl.GLSurfaceView; -import android.opengl.GLSurfaceView.Renderer; -import android.os.Build; -import android.util.AttributeSet; -import android.view.Choreographer; -import android.view.Choreographer.FrameCallback; -import android.view.View; -import android.widget.FrameLayout; - -import com.android.gallery3d.glrenderer.BasicTexture; -import com.android.gallery3d.glrenderer.GLES20Canvas; -import com.android.photos.views.TiledImageRenderer.TileSource; - -import javax.microedition.khronos.egl.EGLConfig; -import javax.microedition.khronos.opengles.GL10; - -/** - * Shows an image using {@link TiledImageRenderer} using either {@link GLSurfaceView} - * or {@link BlockingGLTextureView}. - */ -public class TiledImageView extends FrameLayout { - - private static final boolean USE_TEXTURE_VIEW = false; - private static final boolean IS_SUPPORTED = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; - private static final boolean USE_CHOREOGRAPHER = - Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN; - - private BlockingGLTextureView mTextureView; - private GLSurfaceView mGLSurfaceView; - private boolean mInvalPending = false; - private FrameCallback mFrameCallback; - - private static class ImageRendererWrapper { - // Guarded by locks - float scale; - int centerX, centerY; - int rotation; - TileSource source; - Runnable isReadyCallback; - - // GL thread only - TiledImageRenderer image; - } - - private float[] mValues = new float[9]; - - // ------------------------- - // Guarded by mLock - // ------------------------- - private Object mLock = new Object(); - private ImageRendererWrapper mRenderer; - - public TiledImageView(Context context) { - this(context, null); - } - - public TiledImageView(Context context, AttributeSet attrs) { - super(context, attrs); - if (!IS_SUPPORTED) { - return; - } - - mRenderer = new ImageRendererWrapper(); - mRenderer.image = new TiledImageRenderer(this); - View view; - if (USE_TEXTURE_VIEW) { - mTextureView = new BlockingGLTextureView(context); - mTextureView.setRenderer(new TileRenderer()); - view = mTextureView; - } else { - mGLSurfaceView = new GLSurfaceView(context); - mGLSurfaceView.setEGLContextClientVersion(2); - mGLSurfaceView.setRenderer(new TileRenderer()); - mGLSurfaceView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); - view = mGLSurfaceView; - } - addView(view, new LayoutParams( - LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); - //setTileSource(new ColoredTiles()); - } - - public void destroy() { - if (!IS_SUPPORTED) { - return; - } - if (USE_TEXTURE_VIEW) { - mTextureView.destroy(); - } else { - mGLSurfaceView.queueEvent(mFreeTextures); - } - } - - private Runnable mFreeTextures = new Runnable() { - - @Override - public void run() { - mRenderer.image.freeTextures(); - } - }; - - public void onPause() { - if (!IS_SUPPORTED) { - return; - } - if (!USE_TEXTURE_VIEW) { - mGLSurfaceView.onPause(); - } - } - - public void onResume() { - if (!IS_SUPPORTED) { - return; - } - if (!USE_TEXTURE_VIEW) { - mGLSurfaceView.onResume(); - } - } - - public void setTileSource(TileSource source, Runnable isReadyCallback) { - if (!IS_SUPPORTED) { - return; - } - synchronized (mLock) { - mRenderer.source = source; - mRenderer.isReadyCallback = isReadyCallback; - mRenderer.centerX = source != null ? source.getImageWidth() / 2 : 0; - mRenderer.centerY = source != null ? source.getImageHeight() / 2 : 0; - mRenderer.rotation = source != null ? source.getRotation() : 0; - mRenderer.scale = 0; - updateScaleIfNecessaryLocked(mRenderer); - } - invalidate(); - } - - @Override - protected void onLayout(boolean changed, int left, int top, int right, - int bottom) { - super.onLayout(changed, left, top, right, bottom); - if (!IS_SUPPORTED) { - return; - } - synchronized (mLock) { - updateScaleIfNecessaryLocked(mRenderer); - } - } - - private void updateScaleIfNecessaryLocked(ImageRendererWrapper renderer) { - if (renderer == null || renderer.source == null - || renderer.scale > 0 || getWidth() == 0) { - return; - } - renderer.scale = Math.min( - (float) getWidth() / (float) renderer.source.getImageWidth(), - (float) getHeight() / (float) renderer.source.getImageHeight()); - } - - @Override - protected void dispatchDraw(Canvas canvas) { - if (!IS_SUPPORTED) { - return; - } - if (USE_TEXTURE_VIEW) { - mTextureView.render(); - } - super.dispatchDraw(canvas); - } - - @SuppressLint("NewApi") - @Override - public void setTranslationX(float translationX) { - if (!IS_SUPPORTED) { - return; - } - super.setTranslationX(translationX); - } - - @Override - public void invalidate() { - if (!IS_SUPPORTED) { - return; - } - if (USE_TEXTURE_VIEW) { - super.invalidate(); - mTextureView.invalidate(); - } else { - if (USE_CHOREOGRAPHER) { - invalOnVsync(); - } else { - mGLSurfaceView.requestRender(); - } - } - } - - @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private void invalOnVsync() { - if (!mInvalPending) { - mInvalPending = true; - if (mFrameCallback == null) { - mFrameCallback = new FrameCallback() { - @Override - public void doFrame(long frameTimeNanos) { - mInvalPending = false; - mGLSurfaceView.requestRender(); - } - }; - } - Choreographer.getInstance().postFrameCallback(mFrameCallback); - } - } - - private RectF mTempRectF = new RectF(); - public void positionFromMatrix(Matrix matrix) { - if (!IS_SUPPORTED) { - return; - } - if (mRenderer.source != null) { - final int rotation = mRenderer.source.getRotation(); - final boolean swap = !(rotation % 180 == 0); - final int width = swap ? mRenderer.source.getImageHeight() - : mRenderer.source.getImageWidth(); - final int height = swap ? mRenderer.source.getImageWidth() - : mRenderer.source.getImageHeight(); - mTempRectF.set(0, 0, width, height); - matrix.mapRect(mTempRectF); - matrix.getValues(mValues); - int cx = width / 2; - int cy = height / 2; - float scale = mValues[Matrix.MSCALE_X]; - int xoffset = Math.round((getWidth() - mTempRectF.width()) / 2 / scale); - int yoffset = Math.round((getHeight() - mTempRectF.height()) / 2 / scale); - if (rotation == 90 || rotation == 180) { - cx += (mTempRectF.left / scale) - xoffset; - } else { - cx -= (mTempRectF.left / scale) - xoffset; - } - if (rotation == 180 || rotation == 270) { - cy += (mTempRectF.top / scale) - yoffset; - } else { - cy -= (mTempRectF.top / scale) - yoffset; - } - mRenderer.scale = scale; - mRenderer.centerX = swap ? cy : cx; - mRenderer.centerY = swap ? cx : cy; - invalidate(); - } - } - - private class TileRenderer implements Renderer { - - private GLES20Canvas mCanvas; - - @Override - public void onSurfaceCreated(GL10 gl, EGLConfig config) { - mCanvas = new GLES20Canvas(); - BasicTexture.invalidateAllTextures(); - mRenderer.image.setModel(mRenderer.source, mRenderer.rotation); - } - - @Override - public void onSurfaceChanged(GL10 gl, int width, int height) { - mCanvas.setSize(width, height); - mRenderer.image.setViewSize(width, height); - } - - @Override - public void onDrawFrame(GL10 gl) { - mCanvas.clearBuffer(); - Runnable readyCallback; - synchronized (mLock) { - readyCallback = mRenderer.isReadyCallback; - mRenderer.image.setModel(mRenderer.source, mRenderer.rotation); - mRenderer.image.setPosition(mRenderer.centerX, mRenderer.centerY, - mRenderer.scale); - } - boolean complete = mRenderer.image.draw(mCanvas); - if (complete && readyCallback != null) { - synchronized (mLock) { - // Make sure we don't trample on a newly set callback/source - // if it changed while we were rendering - if (mRenderer.isReadyCallback == readyCallback) { - mRenderer.isReadyCallback = null; - } - } - if (readyCallback != null) { - post(readyCallback); - } - } - } - - } - - @SuppressWarnings("unused") - private static class ColoredTiles implements TileSource { - private static final int[] COLORS = new int[] { - Color.RED, - Color.BLUE, - Color.YELLOW, - Color.GREEN, - Color.CYAN, - Color.MAGENTA, - Color.WHITE, - }; - - private Paint mPaint = new Paint(); - private Canvas mCanvas = new Canvas(); - - @Override - public int getTileSize() { - return 256; - } - - @Override - public int getImageWidth() { - return 16384; - } - - @Override - public int getImageHeight() { - return 8192; - } - - @Override - public int getRotation() { - return 0; - } - - @Override - public Bitmap getTile(int level, int x, int y, Bitmap bitmap) { - int tileSize = getTileSize(); - if (bitmap == null) { - bitmap = Bitmap.createBitmap(tileSize, tileSize, - Bitmap.Config.ARGB_8888); - } - mCanvas.setBitmap(bitmap); - mCanvas.drawColor(COLORS[level]); - mPaint.setColor(Color.BLACK); - mPaint.setTextSize(20); - mPaint.setTextAlign(Align.CENTER); - mCanvas.drawText(x + "x" + y, 128, 128, mPaint); - tileSize <<= level; - x /= tileSize; - y /= tileSize; - mCanvas.drawText(x + "x" + y + " @ " + level, 128, 30, mPaint); - mCanvas.setBitmap(null); - return bitmap; - } - - @Override - public BasicTexture getPreview() { - return null; - } - } -} |