summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java8
-rw-r--r--gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java11
-rw-r--r--src/com/android/camera/CameraActivity.java16
-rw-r--r--src/com/android/camera/CameraManager.java23
-rw-r--r--src/com/android/camera/PhotoMenu.java25
-rw-r--r--src/com/android/camera/PhotoModule.java2
-rw-r--r--src/com/android/camera/PhotoUI.java2
-rw-r--r--src/com/android/camera/PieController.java21
-rw-r--r--src/com/android/camera/VideoMenu.java17
-rw-r--r--src/com/android/camera/VideoModule.java8
-rw-r--r--src/com/android/camera/ui/CameraControls.java (renamed from src/com/android/camera/ui/SwitcherBackgroundView.java)55
-rw-r--r--src/com/android/camera/ui/CameraRootView.java85
-rw-r--r--src/com/android/camera/ui/PieItem.java73
-rw-r--r--src/com/android/camera/ui/PieRenderer.java167
-rw-r--r--src/com/android/camera/ui/RotatableLayout.java35
-rw-r--r--src/com/android/gallery3d/filtershow/cache/CachingPipeline.java11
-rw-r--r--src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java13
-rw-r--r--src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java4
-rw-r--r--src_pd/com/android/gallery3d/util/UsageStatistics.java4
-rw-r--r--tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java55
-rw-r--r--tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java13
21 files changed, 428 insertions, 220 deletions
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java b/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java
index 2fef9ede0..a1cf0fc85 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifInterface.java
@@ -20,6 +20,7 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.util.SparseIntArray;
+import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
@@ -758,7 +759,7 @@ public class ExifInterface {
}
InputStream is = null;
try {
- is = (InputStream) new FileInputStream(inFileName);
+ is = (InputStream) new BufferedInputStream(new FileInputStream(inFileName));
readExif(is);
} catch (IOException e) {
closeSilently(is);
@@ -800,6 +801,7 @@ public class ExifInterface {
}
OutputStream s = getExifWriterStream(exifOutStream);
s.write(jpeg, 0, jpeg.length);
+ s.flush();
}
/**
@@ -817,6 +819,7 @@ public class ExifInterface {
}
OutputStream s = getExifWriterStream(exifOutStream);
bmap.compress(Bitmap.CompressFormat.JPEG, 90, s);
+ s.flush();
}
/**
@@ -834,6 +837,7 @@ public class ExifInterface {
}
OutputStream s = getExifWriterStream(exifOutStream);
doExifStreamIO(jpegStream, s);
+ s.flush();
}
/**
@@ -1010,7 +1014,7 @@ public class ExifInterface {
boolean ret;
try {
File temp = new File(filename);
- is = new FileInputStream(temp);
+ is = new BufferedInputStream(new FileInputStream(temp));
// Parse beginning of APP1 in exif to find size of exif header.
ExifParser parser = null;
diff --git a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
index e5a5bf009..ae501a50f 100644
--- a/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
+++ b/gallerycommon/src/com/android/gallery3d/exif/ExifOutputStream.java
@@ -18,6 +18,7 @@ package com.android.gallery3d.exif;
import android.util.Log;
+import java.io.BufferedOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
@@ -58,6 +59,7 @@ import java.nio.ByteOrder;
class ExifOutputStream extends FilterOutputStream {
private static final String TAG = "ExifOutputStream";
private static final boolean DEBUG = false;
+ private static final int STREAMBUFFER_SIZE = 0x00010000; // 64Kb
private static final int STATE_SOI = 0;
private static final int STATE_FRAME_HEADER = 1;
@@ -75,11 +77,12 @@ class ExifOutputStream extends FilterOutputStream {
private int mState = STATE_SOI;
private int mByteToSkip;
private int mByteToCopy;
+ private byte[] mSingleByteArray = new byte[1];
private ByteBuffer mBuffer = ByteBuffer.allocate(4);
private final ExifInterface mInterface;
protected ExifOutputStream(OutputStream ou, ExifInterface iRef) {
- super(ou);
+ super(new BufferedOutputStream(ou, STREAMBUFFER_SIZE));
mInterface = iRef;
}
@@ -190,10 +193,8 @@ class ExifOutputStream extends FilterOutputStream {
*/
@Override
public void write(int oneByte) throws IOException {
- byte[] buf = new byte[] {
- (byte) (0xff & oneByte)
- };
- write(buf);
+ mSingleByteArray[0] = (byte) (0xff & oneByte);
+ write(mSingleByteArray);
}
/**
diff --git a/src/com/android/camera/CameraActivity.java b/src/com/android/camera/CameraActivity.java
index 3813cce34..1215cecf0 100644
--- a/src/com/android/camera/CameraActivity.java
+++ b/src/com/android/camera/CameraActivity.java
@@ -118,7 +118,6 @@ public class CameraActivity extends ActivityBase
public void init() {
boolean landscape = Util.getDisplayRotation(this) % 180 == 90;
- setMargins(landscape);
mControlsBackground = findViewById(R.id.blocker);
mCameraControls = findViewById(R.id.camera_controls);
mShutter = (ShutterButton) findViewById(R.id.shutter_button);
@@ -318,24 +317,9 @@ public class CameraActivity extends ActivityBase
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
- boolean landscape = (config.orientation == Configuration.ORIENTATION_LANDSCAPE);
- setMargins(landscape);
mCurrentModule.onConfigurationChanged(config);
}
- private void setMargins(boolean landscape) {
- ViewGroup appRoot = (ViewGroup) findViewById(R.id.content);
- FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) appRoot.getLayoutParams();
- int navBarWidth = getResources().getDimensionPixelSize(R.dimen.navigation_bar_width);
- int navBarHeight = getResources().getDimensionPixelSize(R.dimen.navigation_bar_height);
- if (landscape) {
- lp.setMargins(navBarHeight, 0, navBarHeight - navBarWidth, 0);
- } else {
- lp.setMargins(0, navBarHeight, 0, 0);
- }
- appRoot.setLayoutParams(lp);
- }
-
@Override
public void onPause() {
mPaused = true;
diff --git a/src/com/android/camera/CameraManager.java b/src/com/android/camera/CameraManager.java
index be82ea613..b354654b6 100644
--- a/src/com/android/camera/CameraManager.java
+++ b/src/com/android/camera/CameraManager.java
@@ -74,7 +74,6 @@ public class CameraManager {
private static final int ENABLE_SHUTTER_SOUND = 24;
private Handler mCameraHandler;
- private CameraProxy mCameraProxy;
private android.hardware.Camera mCamera;
// This holder is used when we need to pass the exception
@@ -139,7 +138,6 @@ public class CameraManager {
case RELEASE:
mCamera.release();
mCamera = null;
- mCameraProxy = null;
return;
case RECONNECT:
@@ -226,11 +224,15 @@ public class CameraManager {
return;
case SET_PARAMETERS:
+ mParametersIsDirty = true;
mCamera.setParameters((Parameters) msg.obj);
return;
case GET_PARAMETERS:
- mParameters = mCamera.getParameters();
+ if (mParametersIsDirty) {
+ mParameters = mCamera.getParameters();
+ mParametersIsDirty = false;
+ }
return;
case SET_PARAMETERS_ASYNC:
@@ -256,7 +258,6 @@ public class CameraManager {
Log.e(TAG, "Fail to release the camera.");
}
mCamera = null;
- mCameraProxy = null;
}
throw e;
}
@@ -280,9 +281,8 @@ public class CameraManager {
// a view hierarchy can touch its views.
mCamera = android.hardware.Camera.open(cameraId);
if (mCamera != null) {
- mCameraProxy = new CameraProxy();
mParametersIsDirty = true;
- return mCameraProxy;
+ return new CameraProxy();
} else {
return null;
}
@@ -334,8 +334,11 @@ public class CameraManager {
mCameraHandler.sendEmptyMessage(START_PREVIEW_ASYNC);
}
+ // stopPreview() is synchronous because many resources should be released after
+ // the preview is stopped.
public void stopPreview() {
mCameraHandler.sendEmptyMessage(STOP_PREVIEW);
+ waitDone();
}
public void setPreviewCallback(final PreviewCallback cb) {
@@ -424,7 +427,6 @@ public class CameraManager {
Log.v(TAG, "null parameters in setParameters()");
return;
}
- mParametersIsDirty = true;
mCameraHandler.obtainMessage(SET_PARAMETERS, params).sendToTarget();
}
@@ -434,16 +436,13 @@ public class CameraManager {
Log.v(TAG, "null parameters in setParameters()");
return;
}
- mParametersIsDirty = true;
mCameraHandler.removeMessages(SET_PARAMETERS_ASYNC);
mCameraHandler.obtainMessage(SET_PARAMETERS_ASYNC, params).sendToTarget();
}
public Parameters getParameters() {
- if (mParametersIsDirty || mParameters == null) {
- mCameraHandler.sendEmptyMessage(GET_PARAMETERS);
- if (waitDone()) mParametersIsDirty = false;
- }
+ mCameraHandler.sendEmptyMessage(GET_PARAMETERS);
+ waitDone();
return mParameters;
}
diff --git a/src/com/android/camera/PhotoMenu.java b/src/com/android/camera/PhotoMenu.java
index 280ad44a9..92396c71b 100644
--- a/src/com/android/camera/PhotoMenu.java
+++ b/src/com/android/camera/PhotoMenu.java
@@ -34,6 +34,15 @@ public class PhotoMenu extends PieController
TimerSettingPopup.Listener,
ListPrefSettingPopup.Listener {
private static String TAG = "CAM_photomenu";
+
+ private static final int POS_HDR = 0;
+ private static final int POS_EXP = 1;
+ private static final int POS_MORE = 2;
+ private static final int POS_FLASH = 3;
+ private static final int POS_SWITCH = 4;
+ private static final int POS_WB = 1;
+ private static final int POS_SET = 2;
+
private final String mSettingOff;
private PhotoUI mUI;
@@ -53,20 +62,19 @@ public class PhotoMenu extends PieController
super.initialize(group);
mPopup = null;
mSecondPopup = null;
- float sweep = (float) (SWEEP * Math.PI);
PieItem item = null;
// flash
if (group.findPreference(CameraSettings.KEY_FLASH_MODE) != null) {
- item = makeItem(CameraSettings.KEY_FLASH_MODE, CENTER - sweep, sweep);
+ item = makeItem(CameraSettings.KEY_FLASH_MODE, POS_FLASH, 5);
mRenderer.addItem(item);
}
// exposure compensation
- item = makeItem(CameraSettings.KEY_EXPOSURE, CENTER + sweep, sweep);
+ item = makeItem(CameraSettings.KEY_EXPOSURE, POS_EXP, 5);
mRenderer.addItem(item);
// camera switcher
if (group.findPreference(CameraSettings.KEY_CAMERA_ID) != null) {
item = makeItem(R.drawable.ic_switch_photo_facing_holo_light);
- item.setFixedSlice(CENTER - 2 * sweep, sweep);
+ item.setPosition(POS_SWITCH, 5);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(PieItem item) {
@@ -88,7 +96,7 @@ public class PhotoMenu extends PieController
// hdr
if (group.findPreference(CameraSettings.KEY_CAMERA_HDR) != null) {
item = makeItem(R.drawable.ic_hdr);
- item.setFixedSlice(CENTER + 2 * sweep, sweep);
+ item.setPosition(POS_HDR, 5);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(PieItem item) {
@@ -108,11 +116,10 @@ public class PhotoMenu extends PieController
// more settings
PieItem more = makeItem(R.drawable.ic_settings_holo_light);
- more.setFixedSlice(CENTER, sweep);
+ more.setPosition(POS_MORE, 5);
mRenderer.addItem(more);
// white balance
- item = makeItem(CameraSettings.KEY_WHITE_BALANCE,
- CENTER + sweep, sweep);
+ item = makeItem(CameraSettings.KEY_WHITE_BALANCE, POS_WB, 5);
more.addItem(item);
// settings popup
mOtherKeys = new String[] {
@@ -124,7 +131,7 @@ public class PhotoMenu extends PieController
CameraSettings.KEY_TIMER_SOUND_EFFECTS,
};
item = makeItem(R.drawable.ic_settings_holo_light);
- item.setFixedSlice(CENTER, sweep);
+ item.setPosition(POS_SET, 5);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(PieItem item) {
diff --git a/src/com/android/camera/PhotoModule.java b/src/com/android/camera/PhotoModule.java
index f4bd4ce1d..22bd6503f 100644
--- a/src/com/android/camera/PhotoModule.java
+++ b/src/com/android/camera/PhotoModule.java
@@ -1013,6 +1013,8 @@ public class PhotoModule
mFaceDetectionStarted = false;
setCameraState(SNAPSHOT_IN_PROGRESS);
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ UsageStatistics.ACTION_CAPTURE_DONE, "Photo");
return true;
}
diff --git a/src/com/android/camera/PhotoUI.java b/src/com/android/camera/PhotoUI.java
index 1af870abc..29ebd6a70 100644
--- a/src/com/android/camera/PhotoUI.java
+++ b/src/com/android/camera/PhotoUI.java
@@ -115,6 +115,8 @@ public class PhotoUI implements PieListener,
h = width;
}
if (mPreviewWidth != w || mPreviewHeight != h) {
+ mPreviewWidth = w;
+ mPreviewHeight = h;
mController.onScreenSizeChanged(width, height, w, h);
}
}
diff --git a/src/com/android/camera/PieController.java b/src/com/android/camera/PieController.java
index 2145fd894..c5d1b8b41 100644
--- a/src/com/android/camera/PieController.java
+++ b/src/com/android/camera/PieController.java
@@ -37,10 +37,6 @@ public class PieController {
protected static final int MODE_PHOTO = 0;
protected static final int MODE_VIDEO = 1;
- protected static float CENTER = (float) Math.PI / 2;
- protected static final float SWEEP = 0.06f;
-
-
protected CameraActivity mActivity;
protected PreferenceGroup mPreferenceGroup;
protected OnPreferenceChangedListener mListener;
@@ -88,7 +84,7 @@ public class PieController {
return new PieItem(drawable, 0);
}
- public PieItem makeItem(String prefKey, float center, float sweep) {
+ public PieItem makeItem(String prefKey, int position, int count) {
final IconListPreference pref =
(IconListPreference) mPreferenceGroup.findPreference(prefKey);
if (pref == null) return null;
@@ -103,8 +99,7 @@ public class PieController {
resid = pref.getSingleIcon();
}
PieItem item = makeItem(resid);
- // use center and sweep to determine layout
- item.setFixedSlice(center, sweep);
+ item.setPosition(position, count);
mPreferences.add(pref);
mPreferenceMap.put(pref, item);
int nOfEntries = pref.getEntries().length;
@@ -116,7 +111,7 @@ public class PieController {
} else {
inner = makeItem(pref.getEntries()[i]);
}
- layoutInner(inner, i, nOfEntries);
+ inner.setPosition(i, nOfEntries);
item.addItem(inner);
final int index = i;
inner.setOnClickListener(new OnClickListener() {
@@ -137,14 +132,8 @@ public class PieController {
return item;
}
- protected void layoutInner(PieItem item, int ix, int n) {
- float sweep = (float) (SWEEP * Math.PI);//FLOAT_PI_DIVIDED_BY_TWO / Math.max(n, 5);
- float start = CENTER + (n - 1) * (sweep / 2f);
- item.setFixedSlice(start - ix * sweep, sweep);
- }
-
- public void addItem(String prefKey, float center, float sweep) {
- PieItem item = makeItem(prefKey, center, sweep);
+ public void addItem(String prefKey, int position, int count) {
+ PieItem item = makeItem(prefKey, position, count);
mRenderer.addItem(item);
}
diff --git a/src/com/android/camera/VideoMenu.java b/src/com/android/camera/VideoMenu.java
index 0f987aa87..d9629d3ac 100644
--- a/src/com/android/camera/VideoMenu.java
+++ b/src/com/android/camera/VideoMenu.java
@@ -34,6 +34,10 @@ public class VideoMenu extends PieController
TimeIntervalPopup.Listener {
private static String TAG = "CAM_VideoMenu";
+ private static final int POS_WB = 1;
+ private static final int POS_SET = 2;
+ private static final int POS_FLASH = 3;
+ private static final int POS_SWITCH = 4;
private VideoUI mUI;
private String[] mOtherKeys;
@@ -53,13 +57,14 @@ public class VideoMenu extends PieController
super.initialize(group);
mPopup = null;
mPopupStatus = POPUP_NONE;
- float sweep = (float)(SWEEP * Math.PI);
- addItem(CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE, CENTER - sweep, sweep);
- addItem(CameraSettings.KEY_WHITE_BALANCE, CENTER + sweep, sweep);
+ PieItem item = makeItem(CameraSettings.KEY_VIDEOCAMERA_FLASH_MODE, POS_FLASH, 5);
+ mRenderer.addItem(item);
+ item = makeItem(CameraSettings.KEY_WHITE_BALANCE, POS_WB, 5);
+ mRenderer.addItem(item);
// camera switcher
- PieItem item = makeItem(R.drawable.ic_switch_video_facing_holo_light);
- item.setFixedSlice(CENTER - 2 * sweep, sweep);
+ item = makeItem(R.drawable.ic_switch_video_facing_holo_light);
+ item.setPosition(POS_SWITCH, 5);
item.setOnClickListener(new OnClickListener() {
@Override
@@ -84,7 +89,7 @@ public class VideoMenu extends PieController
CameraSettings.KEY_RECORD_LOCATION
};
item = makeItem(R.drawable.ic_settings_holo_light);
- item.setFixedSlice(CENTER, sweep);
+ item.setPosition(POS_SET, 5);
item.setOnClickListener(new OnClickListener() {
@Override
public void onClick(PieItem item) {
diff --git a/src/com/android/camera/VideoModule.java b/src/com/android/camera/VideoModule.java
index 1f31778df..09a406ce5 100644
--- a/src/com/android/camera/VideoModule.java
+++ b/src/com/android/camera/VideoModule.java
@@ -450,6 +450,8 @@ public class VideoModule implements CameraModule,
mActivity.mCameraDevice.takePicture(null, null, null, new JpegPictureCallback(loc));
showVideoSnapshotUI(true);
mSnapshotInProgress = true;
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ UsageStatistics.ACTION_CAPTURE_DONE, "VideoSnapshot");
}
@Override
@@ -1547,6 +1549,8 @@ public class VideoModule implements CameraModule,
updateRecordingTime();
keepScreenOn();
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ UsageStatistics.ACTION_CAPTURE_START, "Video");
}
private void showCaptureResult() {
@@ -1662,6 +1666,10 @@ public class VideoModule implements CameraModule,
// Update the parameters here because the parameters might have been altered
// by MediaRecorder.
if (!mPaused) mParameters = mActivity.mCameraDevice.getParameters();
+ UsageStatistics.onEvent(UsageStatistics.COMPONENT_CAMERA,
+ fail ? UsageStatistics.ACTION_CAPTURE_FAIL :
+ UsageStatistics.ACTION_CAPTURE_DONE, "Video",
+ SystemClock.uptimeMillis() - mRecordingStartTime);
return fail;
}
diff --git a/src/com/android/camera/ui/SwitcherBackgroundView.java b/src/com/android/camera/ui/CameraControls.java
index 710412cce..a7d1f215e 100644
--- a/src/com/android/camera/ui/SwitcherBackgroundView.java
+++ b/src/com/android/camera/ui/CameraControls.java
@@ -27,38 +27,57 @@ import android.widget.FrameLayout.LayoutParams;
import com.android.camera.Util;
import com.android.gallery3d.R;
-/*
- * This is a simple view that has a gradient background. The background
- * needs to rotate when orientation changes, so that the side of the drawable
- * that is dark is always aligned to the side of the screen, and the side that is
- * closer to the center of the screen is transparent.
- * */
-public class SwitcherBackgroundView extends View
+public class CameraControls extends RotatableLayout
{
- public SwitcherBackgroundView(Context context, AttributeSet attrs) {
+ private View mBackgroundView;
+ public CameraControls(Context context, AttributeSet attrs) {
super(context, attrs);
- setBackgroundResource(R.drawable.switcher_bg);
}
- public SwitcherBackgroundView(Context context) {
+ public CameraControls(Context context) {
super(context);
- setBackgroundResource(R.drawable.switcher_bg);
}
+
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
+ adjustBackground();
+ }
+
+ @Override
+ public void onFinishInflate() {
+ super.onFinishInflate();
+ mBackgroundView = findViewById(R.id.blocker);
+ }
+
+ // In reverse landscape and reverse portrait, camera controls will be laid out
+ // on the wrong side of the screen. We need to make adjustment to move the controls
+ // to the USB side
+ public void adjustControlsToRightPosition() {
+ Configuration config = getResources().getConfiguration();
+ int orientation = Util.getDisplayRotation((Activity) getContext());
+ if (orientation == 270 && config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ flipChildren();
+ }
+ if (orientation == 180 && config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+ flipChildren();
+ }
+ adjustBackground();
+ }
+
+ private void adjustBackground() {
// remove current drawable and reset rotation
- setBackgroundDrawable(null);
- setRotationX(0);
- setRotationY(0);
+ mBackgroundView.setBackgroundDrawable(null);
+ mBackgroundView.setRotationX(0);
+ mBackgroundView.setRotationY(0);
// if the switcher background is top aligned we need to flip the background
// drawable vertically; if left aligned, flip horizontally
- int gravity = ((LayoutParams) getLayoutParams()).gravity;
+ int gravity = ((LayoutParams) mBackgroundView.getLayoutParams()).gravity;
if ((gravity & Gravity.TOP) == Gravity.TOP) {
- setRotationX(180);
+ mBackgroundView.setRotationX(180);
} else if ((gravity & Gravity.LEFT) == Gravity.LEFT) {
- setRotationY(180);
+ mBackgroundView.setRotationY(180);
}
- setBackgroundResource(R.drawable.switcher_bg);
+ mBackgroundView.setBackgroundResource(R.drawable.switcher_bg);
}
}
diff --git a/src/com/android/camera/ui/CameraRootView.java b/src/com/android/camera/ui/CameraRootView.java
new file mode 100644
index 000000000..cce649530
--- /dev/null
+++ b/src/com/android/camera/ui/CameraRootView.java
@@ -0,0 +1,85 @@
+/*
+ * 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.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.Gravity;
+import android.view.View;
+import android.widget.FrameLayout;
+import android.widget.RelativeLayout;
+
+import com.android.camera.Util;
+import com.android.gallery3d.R;
+
+public class CameraRootView extends RelativeLayout
+ implements RotatableLayout.RotationListener {
+
+ private int mOffset = 0;
+ public CameraRootView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ // Layout the window as if we did not need navigation bar
+ setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+ | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+ }
+
+ @Override
+ protected boolean fitSystemWindows(Rect insets) {
+ super.fitSystemWindows(insets);
+ // insets include status bar, navigation bar, etc
+ // In this case, we are only concerned with the size of nav bar
+ if (mOffset > 0) return true;
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+ if (insets.bottom > 0) {
+ mOffset = insets.bottom;
+ } else if (insets.right > 0) {
+ mOffset = insets.right;
+ }
+ Configuration config = getResources().getConfiguration();
+ if (config.orientation == Configuration.ORIENTATION_PORTRAIT) {
+ lp.setMargins(0, 0, 0, mOffset);
+ } else if (config.orientation == Configuration.ORIENTATION_LANDSCAPE) {
+ lp.setMargins(0, 0, mOffset, 0);
+ }
+ CameraControls controls = (CameraControls) findViewById(R.id.camera_controls);
+ if (controls != null) {
+ controls.setRotationListener(this);
+ controls.adjustControlsToRightPosition();
+ }
+ return true;
+ }
+
+ @Override
+ public void onRotation(int rotation) {
+ FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) getLayoutParams();
+ int b = lp.bottomMargin;
+ int t = lp.topMargin;
+ int l = lp.leftMargin;
+ int r = lp.rightMargin;
+ rotation = (rotation + 360) % 360;
+ if (rotation == 90) {
+ lp.setMargins(b, l, t, r);
+ } else if (rotation == 270) {
+ lp.setMargins(t, r, b, l);
+ } else if (rotation == 180) {
+ lp.setMargins(r, b, l, t);
+ }
+ }
+}
diff --git a/src/com/android/camera/ui/PieItem.java b/src/com/android/camera/ui/PieItem.java
index bbfa1dc82..6128e0422 100644
--- a/src/com/android/camera/ui/PieItem.java
+++ b/src/com/android/camera/ui/PieItem.java
@@ -19,7 +19,6 @@ package com.android.camera.ui;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
-import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import java.util.ArrayList;
@@ -36,12 +35,9 @@ public class PieItem {
private Drawable mDrawable;
private int level;
- private float mCenter;
- private float start;
- private float sweep;
- private float animate;
- private int inner;
- private int outer;
+ private int mPosition;
+ private int mCount;
+
private boolean mSelected;
private boolean mEnabled;
private List<PieItem> mItems;
@@ -61,9 +57,19 @@ public class PieItem {
setAlpha(1f);
}
mEnabled = true;
- setAnimationAngle(getAnimationAngle());
- start = -1;
- mCenter = -1;
+ }
+
+ public void setPosition(int pos, int count) {
+ mPosition = pos;
+ mCount = count;
+ }
+
+ public int getPosition() {
+ return mPosition;
+ }
+
+ public int getCount() {
+ return mCount;
}
public boolean hasItems() {
@@ -85,6 +91,10 @@ public class PieItem {
mItems = null;
}
+ public void setLevel(int level) {
+ this.level = level;
+ }
+
public void setPath(Path p) {
mPath = p;
}
@@ -102,14 +112,6 @@ public class PieItem {
mDrawable.setAlpha((int) (255 * alpha));
}
- public void setAnimationAngle(float a) {
- animate = a;
- }
-
- public float getAnimationAngle() {
- return animate;
- }
-
public void setEnabled(boolean enabled) {
mEnabled = enabled;
if (mChangeAlphaWhenDisabled) {
@@ -137,41 +139,6 @@ public class PieItem {
return level;
}
- public void setGeometry(float st, float sw, int inside, int outside) {
- start = st;
- sweep = sw;
- inner = inside;
- outer = outside;
- }
-
- public void setFixedSlice(float center, float sweep) {
- mCenter = center;
- this.sweep = sweep;
- }
-
- public float getCenter() {
- return mCenter;
- }
-
- public float getStart() {
- return start;
- }
-
- public float getStartAngle() {
- return start + animate;
- }
-
- public float getSweep() {
- return sweep;
- }
-
- public int getInnerRadius() {
- return inner;
- }
-
- public int getOuterRadius() {
- return outer;
- }
public void setOnClickListener(OnClickListener listener) {
mOnClickListener = listener;
diff --git a/src/com/android/camera/ui/PieRenderer.java b/src/com/android/camera/ui/PieRenderer.java
index dffa47e1e..0d8312ca4 100644
--- a/src/com/android/camera/ui/PieRenderer.java
+++ b/src/com/android/camera/ui/PieRenderer.java
@@ -74,10 +74,14 @@ public class PieRenderer extends OverlayRenderer
private static final int MSG_OPEN = 0;
private static final int MSG_CLOSE = 1;
private static final int MSG_OPENSUBMENU = 2;
- private static final float PIE_SWEEP = (float)(Math.PI / 2);
+
+ protected static float CENTER = (float) Math.PI / 2;
+ protected static final float SWEEP_SLICE = 0.14f;
+ protected static final float SWEEP_ARC = 0.23f;
+
// geometry
- private Point mSliceCenter;
private int mRadius;
+ private int mRadiusInc;
// the detection if touch is inside a slice is offset
// inbounds by this amount to allow the selection to show before the
@@ -101,9 +105,11 @@ public class PieRenderer extends OverlayRenderer
private int mFocusY;
private int mCenterX;
private int mCenterY;
+ private int mArcCenterY;
+ private int mSliceCenterY;
private int mPieCenterX;
private int mPieCenterY;
- private int mIconRadius;
+ private int mSliceRadius;
private int mArcRadius;
private int mArcOffset;
@@ -126,6 +132,9 @@ public class PieRenderer extends OverlayRenderer
private LinearAnimation mFadeIn;
private FadeOutAnimation mFadeOut;
private volatile boolean mFocusCancelled;
+ private PointF mPolar = new PointF();
+
+
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
@@ -169,9 +178,9 @@ public class PieRenderer extends OverlayRenderer
mOpen.add(new PieItem(null, 0));
Resources res = ctx.getResources();
mRadius = (int) res.getDimensionPixelSize(R.dimen.pie_radius_start);
+ mRadiusInc = (int) res.getDimensionPixelSize(R.dimen.pie_radius_increment);
mCircleSize = mRadius - res.getDimensionPixelSize(R.dimen.focus_radius_offset);
mTouchOffset = (int) res.getDimensionPixelSize(R.dimen.pie_touch_offset);
- mSliceCenter = new Point(0,0);
mSelectedPaint = new Paint();
mSelectedPaint.setColor(Color.argb(255, 51, 181, 229));
mSelectedPaint.setAntiAlias(true);
@@ -201,7 +210,7 @@ public class PieRenderer extends OverlayRenderer
mMenuArcPaint.setColor(Color.argb(140, 255, 255, 255));
mMenuArcPaint.setStrokeWidth(10);
mMenuArcPaint.setStyle(Paint.Style.STROKE);
- mIconRadius = res.getDimensionPixelSize(R.dimen.pie_item_radius);
+ mSliceRadius = res.getDimensionPixelSize(R.dimen.pie_item_radius);
mArcRadius = res.getDimensionPixelSize(R.dimen.pie_arc_radius);
mArcOffset = res.getDimensionPixelSize(R.dimen.pie_arc_offset);
}
@@ -299,8 +308,8 @@ public class PieRenderer extends OverlayRenderer
public void setCenter(int x, int y) {
mPieCenterX = x;
mPieCenterY = y;
- mSliceCenter.x = x;
- mSliceCenter.y = y - mArcOffset + mIconRadius;
+ mSliceCenterY = y - mArcOffset + mSliceRadius;
+ mArcCenterY = y - mArcOffset + mArcRadius;
}
@Override
@@ -325,60 +334,40 @@ public class PieRenderer extends OverlayRenderer
}
private void layoutPie() {
- int inner = mIconRadius;
- int outer = inner + mTouchOffset;
- int gap = 1;
- layoutItems(0, getRoot().getItems(), (float) (Math.PI / 2), inner, outer, gap);
- }
-
- private void layoutItems(int level, List<PieItem> items, float centerAngle, int inner, int outer, int gap) {
- float emptyangle = PIE_SWEEP / 16;
- float sweep = (float) (PIE_SWEEP - 2 * emptyangle) / items.size();
- float angle = centerAngle - PIE_SWEEP / 2 + emptyangle + sweep / 2;
- // check if we have custom geometry
- // first item we find triggers custom sweep for all
- // this allows us to re-use the path
- for (PieItem item : items) {
- if (item.getCenter() >= 0) {
- sweep = item.getSweep();
- break;
- }
- }
- Point p = new Point(mSliceCenter);
- p.y -= level * mTouchOffset;
- Path path = makeSlice(getDegrees(0) - gap, getDegrees(sweep) + gap,
- outer, inner, p);
+ layoutItems(0, getRoot().getItems());
+ }
+
+ private void layoutItems(int level, List<PieItem> items) {
+ int extend = 1;
+ Path path = makeSlice(getDegrees(0) + extend, getDegrees(SWEEP_ARC) - extend,
+ mArcRadius, mArcRadius + mRadiusInc + mRadiusInc / 4,
+ mPieCenterX, mArcCenterY - level * mRadiusInc);
for (PieItem item : items) {
// shared between items
item.setPath(path);
- if (item.getCenter() >= 0) {
- angle = item.getCenter();
- }
+ float angle = getArcCenter(item);
int w = item.getIntrinsicWidth();
int h = item.getIntrinsicHeight();
// move views to outer border
- int r = inner + (outer - inner) * 2 / 3;
+ int r = mArcRadius + mRadiusInc * 2 / 3;
int x = (int) (r * Math.cos(angle));
- int y = mSliceCenter.y - (level * mTouchOffset) - (int) (r * Math.sin(angle)) - h / 2;
- x = mSliceCenter.x + x - w / 2;
+ int y = mArcCenterY - (level * mRadiusInc) - (int) (r * Math.sin(angle)) - h / 2;
+ x = mPieCenterX + x - w / 2;
item.setBounds(x, y, x + w, y + h);
- float itemstart = angle - sweep / 2;
- item.setGeometry(itemstart, sweep, inner, outer);
+ item.setLevel(level);
if (item.hasItems()) {
- layoutItems(level + 1, item.getItems(), MATH_PI_2, inner,
- outer, gap);
+ layoutItems(level + 1, item.getItems());
}
- angle += sweep;
}
}
- private Path makeSlice(float start, float end, int outer, int inner, Point center) {
+ private Path makeSlice(float start, float end, int inner, int outer, int cx, int cy) {
RectF bb =
- new RectF(center.x - outer, center.y - outer, center.x + outer,
- center.y + outer);
+ new RectF(cx - outer, cy - outer, cx + outer,
+ cy + outer);
RectF bbi =
- new RectF(center.x - inner, center.y - inner, center.x + inner,
- center.y + inner);
+ new RectF(cx - inner, cy - inner, cx + inner,
+ cy + inner);
Path path = new Path();
path.arcTo(bb, start, end - start, true);
path.arcTo(bbi, end, start - end);
@@ -386,6 +375,18 @@ public class PieRenderer extends OverlayRenderer
return path;
}
+ private float getArcCenter(PieItem item) {
+ return getCenter(item.getPosition(), item.getCount(), SWEEP_ARC);
+ }
+
+ private float getSliceCenter(PieItem item) {
+ return getCenter(item.getPosition(), item.getCount(), SWEEP_SLICE);
+ }
+
+ private float getCenter(int pos, int count, float sweep) {
+ return CENTER + (count - 1) * sweep / 2f - pos * sweep;
+ }
+
/**
* converts a
* @param angle from 0..PI to Android degrees (clockwise starting at 3 o'clock)
@@ -475,14 +476,14 @@ public class PieRenderer extends OverlayRenderer
}
if (!hasOpenItem() || (mXFade != null)) {
// draw base menu
- drawArc(canvas, getLevel());
+ drawArc(canvas, getLevel(), getParent());
for (PieItem item : getParent().getItems()) {
drawItem(Math.max(0, mOpen.size() - 2), canvas, item, alpha);
}
}
if (hasOpenItem()) {
int level = getLevel();
- drawArc(canvas, level);
+ drawArc(canvas, level, getOpenItem());
for (PieItem inner : getOpenItem().getItems()) {
if (mFadeOut != null) {
drawItem(level, canvas, inner, alpha);
@@ -494,25 +495,37 @@ public class PieRenderer extends OverlayRenderer
canvas.restoreToCount(state);
}
- private void drawArc(Canvas canvas, int level) {
+ private void drawArc(Canvas canvas, int level, PieItem item) {
// arc
if (mState == STATE_PIE) {
- int nr = mArcRadius;
- int cy = mPieCenterY - mArcOffset + mArcRadius - level * mTouchOffset;
- canvas.drawArc(new RectF(mPieCenterX - nr, cy - mArcRadius,
- mPieCenterX + nr, cy + mArcRadius),
- 252, 36, false, mMenuArcPaint);
+ int min = Integer.MAX_VALUE;
+ int max = Integer.MIN_VALUE;
+ int count = 0;
+ for (PieItem child : item.getItems()) {
+ final int p = child.getPosition();
+ count = child.getCount();
+ if (p < min) min = p;
+ if (p > max) max = p;
+ }
+ float start = CENTER + (count - 1) * SWEEP_ARC / 2f - min * SWEEP_ARC + SWEEP_ARC / 2f;
+ float end = CENTER + (count - 1) * SWEEP_ARC / 2f - max * SWEEP_ARC - SWEEP_ARC / 2f;
+ int cy = mArcCenterY - level * mRadiusInc;
+ canvas.drawArc(new RectF(mPieCenterX - mArcRadius, cy - mArcRadius,
+ mPieCenterX + mArcRadius, cy + mArcRadius),
+ getDegrees(end), getDegrees(start) - getDegrees(end), false, mMenuArcPaint);
}
}
+
private void drawItem(int level, Canvas canvas, PieItem item, float alpha) {
if (mState == STATE_PIE) {
if (item.getPath() != null) {
- int y = mSliceCenter.y - level * mTouchOffset;
+ int y = mArcCenterY - level * mRadiusInc;
if (item.isSelected()) {
Paint p = mSelectedPaint;
int state = canvas.save();
- float r = getDegrees(item.getStartAngle());
- canvas.rotate(r, mSliceCenter.x, y);
+ float angle = getArcCenter(item) - SWEEP_ARC / 2f;
+ angle = getDegrees(angle);
+ canvas.rotate(angle, mPieCenterX, y);
if (mFadeOut != null) {
p.setAlpha((int)(255 * alpha));
}
@@ -537,13 +550,13 @@ public class PieRenderer extends OverlayRenderer
float x = evt.getX();
float y = evt.getY();
int action = evt.getActionMasked();
- PointF polar = getPolar(x, y, !mTapMode);
+ getPolar(x, y, !mTapMode, mPolar);
if (MotionEvent.ACTION_DOWN == action) {
mDown.x = (int) evt.getX();
mDown.y = (int) evt.getY();
mOpening = false;
if (mTapMode) {
- PieItem item = findItem(polar);
+ PieItem item = findItem(mPolar);
if ((item != null) && (mCurrentItem != item)) {
mState = STATE_PIE;
onEnter(item);
@@ -557,7 +570,7 @@ public class PieRenderer extends OverlayRenderer
if (isVisible()) {
PieItem item = mCurrentItem;
if (mTapMode) {
- item = findItem(polar);
+ item = findItem(mPolar);
if (mOpening) {
mOpening = false;
return true;
@@ -582,7 +595,7 @@ public class PieRenderer extends OverlayRenderer
mHandler.removeMessages(MSG_OPENSUBMENU);
return false;
} else if (MotionEvent.ACTION_MOVE == action) {
- if (pulledToCenter(polar)) {
+ if (pulledToCenter(mPolar)) {
mHandler.removeMessages(MSG_OPENSUBMENU);
if (hasOpenItem()) {
if (mCurrentItem != null) {
@@ -595,7 +608,7 @@ public class PieRenderer extends OverlayRenderer
}
return false;
}
- PieItem item = findItem(polar);
+ PieItem item = findItem(mPolar);
boolean moved = hasMoved(evt);
if ((item != null) && (mCurrentItem != item) && (!mOpening || moved)) {
mHandler.removeMessages(MSG_OPENSUBMENU);
@@ -612,24 +625,32 @@ public class PieRenderer extends OverlayRenderer
}
private boolean pulledToCenter(PointF polarCoords) {
- return polarCoords.y < mIconRadius - mArcOffset;
+ return polarCoords.y < mArcRadius - mRadiusInc;
}
- private PointF getPolar(float x, float y, boolean useOffset) {
- PointF res = new PointF();
+ private boolean inside(PointF polar, PieItem item) {
+ float start = getSliceCenter(item) - SWEEP_SLICE / 2f;
+ boolean res = (mArcRadius < polar.y)
+ && (start < polar.x)
+ && (start + SWEEP_SLICE > polar.x)
+ && (!mTapMode || (mArcRadius + mRadiusInc > polar.y));
+ return res;
+ }
+
+ private void getPolar(float x, float y, boolean useOffset, PointF res) {
// get angle and radius from x/y
res.x = (float) Math.PI / 2;
- x = x - mSliceCenter.x;
- y = mSliceCenter.y - getLevel() * mTouchOffset - y;
- res.y = (float) Math.sqrt(x * x + y * y);
+ x = x - mPieCenterX;
+ float y1 = mSliceCenterY - getLevel() * mRadiusInc - y;
+ float y2 = mArcCenterY - getLevel() * mRadiusInc - y;
+ res.y = (float) Math.sqrt(x * x + y2 * y2);
if (x != 0) {
- res.x = (float) Math.atan2(y, x);
+ res.x = (float) Math.atan2(y1, x);
if (res.x < 0) {
res.x = (float) (2 * Math.PI + res.x);
}
}
res.y = res.y + (useOffset ? mTouchOffset : 0);
- return res;
}
private boolean hasMoved(MotionEvent e) {
@@ -733,12 +754,6 @@ public class PieRenderer extends OverlayRenderer
return null;
}
- private boolean inside(PointF polar, PieItem item) {
- return (item.getInnerRadius() < polar.y)
- && (item.getStartAngle() < polar.x)
- && (item.getStartAngle() + item.getSweep() > polar.x)
- && (!mTapMode || (item.getOuterRadius() > polar.y));
- }
@Override
public boolean handlesTouch() {
diff --git a/src/com/android/camera/ui/RotatableLayout.java b/src/com/android/camera/ui/RotatableLayout.java
index 4edec5dd7..6836b39b2 100644
--- a/src/com/android/camera/ui/RotatableLayout.java
+++ b/src/com/android/camera/ui/RotatableLayout.java
@@ -39,6 +39,10 @@ public class RotatableLayout extends FrameLayout {
private static final String TAG = "RotatableLayout";
private int mPrevRotation;
+ private RotationListener mListener = null;
+ public interface RotationListener {
+ public void onRotation(int rotation);
+ }
public RotatableLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@@ -53,12 +57,15 @@ public class RotatableLayout extends FrameLayout {
@Override
public void onFinishInflate() { // get initial orientation
+ super.onFinishInflate();
mPrevRotation = Util.getDisplayRotation((Activity) getContext());
}
@Override
public void onConfigurationChanged(Configuration config) {
super.onConfigurationChanged(config);
+ int rotation = Util.getDisplayRotation((Activity) getContext());
+ boolean clockwise = isClockWiseRotation(mPrevRotation, rotation);
// Change the size of the layout
ViewGroup.LayoutParams lp = getLayoutParams();
int width = lp.width;
@@ -66,15 +73,33 @@ public class RotatableLayout extends FrameLayout {
lp.height = width;
lp.width = height;
setLayoutParams(lp);
+
// rotate all the children
- int rotation = Util.getDisplayRotation((Activity) getContext());
- boolean clockwise = isClockWiseRotation(mPrevRotation, rotation);
mPrevRotation = rotation;
+ rotateChildren(clockwise);
+ }
+
+ protected void rotateChildren(boolean clockwise) {
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
rotate(child, clockwise);
}
+ if (mListener != null) mListener.onRotation(clockwise ? 90 : 270);
+ }
+
+ protected void flipChildren() {
+ mPrevRotation = Util.getDisplayRotation((Activity) getContext());
+ int childCount = getChildCount();
+ for (int i = 0; i < childCount; i++) {
+ View child = getChildAt(i);
+ flip(child);
+ }
+ if (mListener != null) mListener.onRotation(180);
+ }
+
+ public void setRotationListener(RotationListener listener) {
+ mListener = listener;
}
public static boolean isClockWiseRotation(int prevRotation, int currentRotation) {
@@ -181,4 +206,10 @@ public class RotatableLayout extends FrameLayout {
lp.height = width;
view.setLayoutParams(lp);
}
+
+ // Rotate a given view 180 degrees
+ public static void flip(View view) {
+ rotateClockwise(view);
+ rotateClockwise(view);
+ }
} \ No newline at end of file
diff --git a/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java b/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java
index 8c312a92b..055309f22 100644
--- a/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java
+++ b/src/com/android/gallery3d/filtershow/cache/CachingPipeline.java
@@ -283,6 +283,13 @@ public class CachingPipeline {
|| request.getType() == RenderingRequest.ICON_RENDERING
|| request.getType() == RenderingRequest.PARTIAL_RENDERING
|| request.getType() == RenderingRequest.HIGHRES_RENDERING) {
+
+ if (request.getType() == RenderingRequest.ICON_RENDERING) {
+ mEnvironment.setQuality(ImagePreset.QUALITY_ICON);
+ } else {
+ mEnvironment.setQuality(ImagePreset.QUALITY_PREVIEW);
+ }
+
Bitmap bmp = preset.apply(bitmap, mEnvironment);
request.setBitmap(bmp);
mFiltersManager.freeFilterResources(preset);
@@ -393,7 +400,9 @@ public class CachingPipeline {
mOutPixelsAllocation.getType());
needsUpdate = true;
}
- mInPixelsAllocation.copyFrom(bitmap);
+ if (RS != null) {
+ mInPixelsAllocation.copyFrom(bitmap);
+ }
if (bitmap.getWidth() != mWidth
|| bitmap.getHeight() != mHeight) {
mWidth = bitmap.getWidth();
diff --git a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
index 2aeaed877..a0523c14e 100644
--- a/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
+++ b/src/com/android/gallery3d/filtershow/filters/ImageFilterRS.java
@@ -16,7 +16,6 @@
package com.android.gallery3d.filtershow.filters;
-import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.support.v8.renderscript.*;
@@ -28,6 +27,8 @@ import com.android.gallery3d.filtershow.cache.CachingPipeline;
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 volatile boolean mResourcesLoaded = false;
@@ -65,11 +66,19 @@ public abstract class ImageFilterRS extends ImageFilter {
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()) {
+ || !isResourcesLoaded() || sizeChanged) {
freeResources();
createFilter(rsc, scaleFactor, quality);
setResourcesLoaded(true);
+ mLastInputWidth = getInPixelsAllocation().getType().getX();
+ mLastInputHeight = getInPixelsAllocation().getType().getY();
}
bindScriptValues();
runFilter();
diff --git a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
index 6c3417ad3..8fcc028af 100644
--- a/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
+++ b/src/com/android/gallery3d/filtershow/imageshow/ImageDraw.java
@@ -83,8 +83,8 @@ public class ImageDraw extends ImageShow {
float[] mTmpPoint = new float[2]; // so we do not malloc
@Override
public boolean onTouchEvent(MotionEvent event) {
- boolean ret = super.onTouchEvent(event);
if (event.getPointerCount() > 1) {
+ boolean ret = super.onTouchEvent(event);
if (mFRep.getCurrentDrawing() != null) {
mFRep.clearCurrentSection();
mEditorDraw.commitLocalRepresentation();
@@ -93,7 +93,7 @@ public class ImageDraw extends ImageShow {
}
if (event.getAction() != MotionEvent.ACTION_DOWN) {
if (mFRep.getCurrentDrawing() == null) {
- return ret;
+ return super.onTouchEvent(event);
}
}
diff --git a/src_pd/com/android/gallery3d/util/UsageStatistics.java b/src_pd/com/android/gallery3d/util/UsageStatistics.java
index cf27ac58f..9246ab10a 100644
--- a/src_pd/com/android/gallery3d/util/UsageStatistics.java
+++ b/src_pd/com/android/gallery3d/util/UsageStatistics.java
@@ -36,6 +36,10 @@ public class UsageStatistics {
public static final String TRANSITION_BUTTON_TAP = "ButtonTap";
public static final String TRANSITION_SWIPE = "Swipe";
+ public static final String ACTION_CAPTURE_START = "CaptureStart";
+ public static final String ACTION_CAPTURE_FAIL = "CaptureFail";
+ public static final String ACTION_CAPTURE_DONE = "CaptureDone";
+
public static void initialize(Context context) {}
public static void showOptInDialogIfNeeded(Activity activity) {}
public static void setPendingTransitionCause(String cause) {}
diff --git a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java
index 8c4fc3dea..1286c5801 100644
--- a/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java
+++ b/tests/src/com/android/gallery3d/exif/ExifOutputStreamTest.java
@@ -18,6 +18,7 @@ package com.android.gallery3d.exif;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
+import android.util.Log;
import java.io.ByteArrayInputStream;
import java.io.File;
@@ -131,6 +132,60 @@ public class ExifOutputStreamTest extends ExifXmlDataTestCase {
}
}
+ public void testOutputSpeed() throws Exception {
+ final String LOGTAG = "testOutputSpeed";
+ InputStream imageInputStream = null;
+ OutputStream imageOutputStream = null;
+ try {
+ try {
+ imageInputStream = getImageInputStream();
+ // Read the image data
+ Bitmap bmp = BitmapFactory.decodeStream(imageInputStream);
+ // The image is invalid
+ if (bmp == null) {
+ return;
+ }
+ imageInputStream.close();
+ int nLoops = 20;
+ long totalReadDuration = 0;
+ long totalWriteDuration = 0;
+ for (int i = 0; i < nLoops; i++) {
+ imageInputStream = reopenFileStream();
+ // Read exif data
+ long startTime = System.nanoTime();
+ ExifData exifData = new ExifReader(mInterface).read(imageInputStream);
+ long endTime = System.nanoTime();
+ long duration = endTime - startTime;
+ totalReadDuration += duration;
+ Log.v(LOGTAG, " read time: " + duration);
+ imageInputStream.close();
+
+ // Encode the image with the exif data
+ imageOutputStream = (OutputStream) new FileOutputStream(mTmpFile);
+ ExifOutputStream exifOutputStream = new ExifOutputStream(imageOutputStream,
+ mInterface);
+ exifOutputStream.setExifData(exifData);
+ startTime = System.nanoTime();
+ bmp.compress(Bitmap.CompressFormat.JPEG, 90, exifOutputStream);
+ endTime = System.nanoTime();
+ duration = endTime - startTime;
+ totalWriteDuration += duration;
+ Log.v(LOGTAG, " write time: " + duration);
+ exifOutputStream.close();
+ }
+ Log.v(LOGTAG, "======================= normal");
+ Log.v(LOGTAG, "avg read time: " + totalReadDuration / nLoops);
+ Log.v(LOGTAG, "avg write time: " + totalWriteDuration / nLoops);
+ Log.v(LOGTAG, "=======================");
+ } finally {
+ Util.closeSilently(imageInputStream);
+ Util.closeSilently(imageOutputStream);
+ }
+ } catch (Exception e) {
+ throw new Exception(getImageTitle(), e);
+ }
+ }
+
@Override
public void tearDown() throws Exception {
super.tearDown();
diff --git a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java
index 5f200ea92..da860208b 100644
--- a/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java
+++ b/tests/src/com/android/gallery3d/exif/ExifXmlDataTestCase.java
@@ -92,4 +92,17 @@ public class ExifXmlDataTestCase extends InstrumentationTestCase {
return String.format(RES_ID_TITLE, mImageResourceId);
}
}
+
+ protected InputStream reopenFileStream() throws Exception {
+ try {
+ if (mImagePath != null) {
+ return new FileInputStream(mImagePath);
+ } else {
+ Resources res = getInstrumentation().getContext().getResources();
+ return res.openRawResource(mImageResourceId);
+ }
+ } catch (Exception e) {
+ throw new Exception(getImageTitle(), e);
+ }
+ }
}