[DO NOT MERGE] Unify the cropping mechanism in Preview and in Rotation
Move most of the scaling and cropping logic from ImagePreviewFragment
into WallpaperCropUtils and reuse it in DefaultWallpaperPersister when
setting a wallpaper in rotation.
Fixes: 155943055
Change-Id: Id010ee18da7ee055a3595fdeff7122f7ef0d7630
diff --git a/src/com/android/wallpaper/module/DefaultWallpaperPersister.java b/src/com/android/wallpaper/module/DefaultWallpaperPersister.java
index 27e4491..f19e116 100755
--- a/src/com/android/wallpaper/module/DefaultWallpaperPersister.java
+++ b/src/com/android/wallpaper/module/DefaultWallpaperPersister.java
@@ -19,16 +19,19 @@
import android.app.Activity;
import android.app.WallpaperManager;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.Point;
+import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.os.AsyncTask;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.view.Display;
+import android.view.View;
import android.view.WindowManager;
import androidx.annotation.Nullable;
@@ -45,6 +48,7 @@
import com.android.wallpaper.module.BitmapCropper.Callback;
import com.android.wallpaper.util.BitmapTransformer;
import com.android.wallpaper.util.ScreenSizeCalculator;
+import com.android.wallpaper.util.WallpaperCropUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@@ -342,7 +346,7 @@
@Override
public int setWallpaperBitmapInNextRotation(Bitmap wallpaperBitmap) {
- return setWallpaperBitmapInRotationStatic(wallpaperBitmap);
+ return cropAndSetWallpaperBitmapInRotationStatic(wallpaperBitmap);
}
@Override
@@ -359,7 +363,7 @@
*/
private boolean setWallpaperInRotationStatic(Bitmap wallpaperBitmap, List<String> attributions,
String actionUrl, int actionLabelRes, int actionIconRes, String collectionId) {
- final int wallpaperId = setWallpaperBitmapInRotationStatic(wallpaperBitmap);
+ final int wallpaperId = cropAndSetWallpaperBitmapInRotationStatic(wallpaperBitmap);
if (wallpaperId == 0) {
return false;
@@ -423,7 +427,50 @@
*
* @return wallpaper ID for the wallpaper bitmap.
*/
- private int setWallpaperBitmapInRotationStatic(Bitmap wallpaperBitmap) {
+ private int cropAndSetWallpaperBitmapInRotationStatic(Bitmap wallpaperBitmap) {
+ // Calculate crop and scale of the wallpaper to match the default one used in preview
+ Point wallpaperSize = new Point(wallpaperBitmap.getWidth(), wallpaperBitmap.getHeight());
+ WindowManager windowManager =
+ (WindowManager) mAppContext.getSystemService(Context.WINDOW_SERVICE);
+ Resources resources = mAppContext.getResources();
+ Point defaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
+ resources, windowManager.getDefaultDisplay());
+ Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(
+ windowManager.getDefaultDisplay());
+
+ boolean isRtl = resources.getConfiguration().getLayoutDirection()
+ == View.LAYOUT_DIRECTION_RTL;
+ // Determine minimum zoom to fit maximum visible area of wallpaper on crop surface.
+ float defaultWallpaperZoom =
+ WallpaperCropUtils.calculateMinZoom(wallpaperSize, defaultCropSurfaceSize);
+ float minWallpaperZoom =
+ WallpaperCropUtils.calculateMinZoom(wallpaperSize, screenSize);
+
+ PointF centerPosition = WallpaperCropUtils.calculateDefaultCenter(wallpaperSize,
+ defaultCropSurfaceSize, screenSize, defaultWallpaperZoom, isRtl);
+
+ Point scaledCenter = new Point((int) (minWallpaperZoom * centerPosition.x),
+ (int) (minWallpaperZoom * centerPosition.y));
+
+ int offsetX = Math.max(0, -(screenSize.x / 2 - scaledCenter.x));
+ int offsetY = Math.max(0, -(screenSize.y / 2 - scaledCenter.y));
+
+ Rect cropRect = WallpaperCropUtils.calculateCropRect(minWallpaperZoom, wallpaperSize,
+ defaultCropSurfaceSize, screenSize, offsetX, offsetY, isRtl);
+
+ Rect scaledCropRect = new Rect(
+ Math.round((float) cropRect.left / minWallpaperZoom),
+ Math.round((float) cropRect.top / minWallpaperZoom),
+ Math.round((float) cropRect.right / minWallpaperZoom),
+ Math.round((float) cropRect.bottom / minWallpaperZoom));
+
+ // Scale and crop the bitmap
+ wallpaperBitmap = Bitmap.createBitmap(wallpaperBitmap,
+ scaledCropRect.left,
+ scaledCropRect.top,
+ scaledCropRect.width(),
+ scaledCropRect.height());
+
// Set wallpaper to home-only instead of both home and lock if there's a distinct lock-only
// static wallpaper set so we don't override the lock wallpaper.
boolean isLockWallpaperSet = isSeparateLockScreenWallpaperSet();
diff --git a/src/com/android/wallpaper/picker/ImagePreviewFragment.java b/src/com/android/wallpaper/picker/ImagePreviewFragment.java
index a6babe3..30a95ab 100755
--- a/src/com/android/wallpaper/picker/ImagePreviewFragment.java
+++ b/src/com/android/wallpaper/picker/ImagePreviewFragment.java
@@ -26,7 +26,6 @@
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Bundle;
-import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -282,73 +281,23 @@
float minWallpaperZoom =
WallpaperCropUtils.calculateMinZoom(mRawWallpaperSize, mScreenSize);
- Point screenToCropSurfacePosition = WallpaperCropUtils.calculateCenterPosition(
- mDefaultCropSurfaceSize, mScreenSize, true /* alignStart */, isRtl());
- Point zoomedWallpaperSize = new Point(
- Math.round(mRawWallpaperSize.x * defaultWallpaperZoom),
- Math.round(mRawWallpaperSize.y * defaultWallpaperZoom));
- Point cropSurfaceToWallpaperPosition = WallpaperCropUtils.calculateCenterPosition(
- zoomedWallpaperSize, mDefaultCropSurfaceSize, false /* alignStart */, isRtl());
-
+ PointF centerPosition = WallpaperCropUtils.calculateDefaultCenter(mRawWallpaperSize,
+ mDefaultCropSurfaceSize, mScreenSize, defaultWallpaperZoom, isRtl());
// Set min wallpaper zoom and max zoom on MosaicView widget.
mFullResImageView.setMaxScale(Math.max(DEFAULT_WALLPAPER_MAX_ZOOM, defaultWallpaperZoom));
mFullResImageView.setMinScale(minWallpaperZoom);
- // Set center to composite positioning between scaled wallpaper and screen.
- PointF centerPosition = new PointF(
- mRawWallpaperSize.x / 2f,
- mRawWallpaperSize.y / 2f);
- centerPosition.offset(-(screenToCropSurfacePosition.x + cropSurfaceToWallpaperPosition.x),
- -(screenToCropSurfacePosition.y + cropSurfaceToWallpaperPosition.y));
-
mFullResImageView.setScaleAndCenter(minWallpaperZoom, centerPosition);
}
private Rect calculateCropRect() {
- // Calculate Rect of wallpaper in physical pixel terms (i.e., scaled to current zoom).
float wallpaperZoom = mFullResImageView.getScale();
- int scaledWallpaperWidth = (int) (mRawWallpaperSize.x * wallpaperZoom);
- int scaledWallpaperHeight = (int) (mRawWallpaperSize.y * wallpaperZoom);
Rect rect = new Rect();
mFullResImageView.visibleFileRect(rect);
int scrollX = (int) (rect.left * wallpaperZoom);
int scrollY = (int) (rect.top * wallpaperZoom);
-
- rect.set(0, 0, scaledWallpaperWidth, scaledWallpaperHeight);
-
- Display defaultDisplay = requireActivity().getWindowManager().getDefaultDisplay();
- Point screenSize = ScreenSizeCalculator.getInstance().getScreenSize(defaultDisplay);
- // Crop rect should start off as the visible screen and then include extra width and height
- // if available within wallpaper at the current zoom.
- Rect cropRect = new Rect(scrollX, scrollY, scrollX + screenSize.x, scrollY + screenSize.y);
-
- Point defaultCropSurfaceSize = WallpaperCropUtils.getDefaultCropSurfaceSize(
- getResources(), defaultDisplay);
- int extraWidth = defaultCropSurfaceSize.x - screenSize.x;
- int extraHeightTopAndBottom = (int) ((defaultCropSurfaceSize.y - screenSize.y) / 2f);
-
- // Try to increase size of screenRect to include extra width depending on the layout
- // direction.
- if (isRtl()) {
- cropRect.left = Math.max(cropRect.left - extraWidth, rect.left);
- } else {
- cropRect.right = Math.min(cropRect.right + extraWidth, rect.right);
- }
-
- // Try to increase the size of the cropRect to to include extra height.
- int availableExtraHeightTop = cropRect.top - Math.max(
- rect.top,
- cropRect.top - extraHeightTopAndBottom);
- int availableExtraHeightBottom = Math.min(
- rect.bottom,
- cropRect.bottom + extraHeightTopAndBottom) - cropRect.bottom;
-
- int availableExtraHeightTopAndBottom =
- Math.min(availableExtraHeightTop, availableExtraHeightBottom);
- cropRect.top -= availableExtraHeightTopAndBottom;
- cropRect.bottom += availableExtraHeightTopAndBottom;
-
- return cropRect;
+ return WallpaperCropUtils.calculateCropRect(wallpaperZoom, mRawWallpaperSize,
+ mDefaultCropSurfaceSize, mScreenSize, scrollX, scrollY, isRtl());
}
@Override
diff --git a/src/com/android/wallpaper/util/WallpaperCropUtils.java b/src/com/android/wallpaper/util/WallpaperCropUtils.java
index 4940eb1..67bd00b 100755
--- a/src/com/android/wallpaper/util/WallpaperCropUtils.java
+++ b/src/com/android/wallpaper/util/WallpaperCropUtils.java
@@ -17,6 +17,8 @@
import android.content.res.Resources;
import android.graphics.Point;
+import android.graphics.PointF;
+import android.graphics.Rect;
import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.view.Display;
@@ -138,4 +140,91 @@
}
return minZoom;
}
+
+ /**
+ * Calculates the center position of a wallpaper of the given size, based on a "crop surface"
+ * (with extra width to account for parallax) superimposed on the screen. Trying to show as
+ * much of the wallpaper as possible on the crop surface and align screen to crop surface such
+ * that the centered wallpaper matches what would be seen by the user in the left-most home
+ * screen.
+ *
+ * @param wallpaperSize full size of the wallpaper
+ * @param cropSurfaceSize ideal crop size
+ * @see #getDefaultCropSurfaceSize(Resources, Display)
+ * @param screenSize size of the display
+ * @param defaultWallpaperScale default scale the wallpaper is set to
+ * @param isRtl whether we're in RTL mode
+ * @return a point corresponding to the position of wallpaper that should be in the center
+ * of the screen.
+ */
+ public static PointF calculateDefaultCenter(Point wallpaperSize, Point cropSurfaceSize,
+ Point screenSize, float defaultWallpaperScale, boolean isRtl) {
+ Point screenToCropSurfacePosition = calculateCenterPosition(
+ cropSurfaceSize, screenSize, true /* alignStart */, isRtl);
+ Point zoomedWallpaperSize = new Point(
+ Math.round(wallpaperSize.x * defaultWallpaperScale),
+ Math.round(wallpaperSize.y * defaultWallpaperScale));
+ Point cropSurfaceToWallpaperPosition = calculateCenterPosition(
+ zoomedWallpaperSize, cropSurfaceSize, false /* alignStart */, isRtl);
+
+ // Set center to composite positioning between scaled wallpaper and screen.
+ PointF centerPosition = new PointF(
+ wallpaperSize.x / 2f,
+ wallpaperSize.y / 2f);
+ centerPosition.offset(-(screenToCropSurfacePosition.x + cropSurfaceToWallpaperPosition.x),
+ -(screenToCropSurfacePosition.y + cropSurfaceToWallpaperPosition.y));
+ return centerPosition;
+ }
+
+ /**
+ * Calculates the rectangle to crop a wallpaper of the given size, and considering the given
+ * scrollX and scrollY offsets
+ * @param wallpaperZoom zoom applied to the raw wallpaper image
+ * @param wallpaperSize full ("raw") wallpaper size
+ * @param defaultCropSurfaceSize @see #getDefaultCropSurfaceSize(Resources, Display)
+ * @param screenSize size of the display
+ * @param scrollX x-axis offset the cropping area from the wallpaper's 0,0 position
+ * @param scrollY y-axis offset the cropping area from the wallpaper's 0,0 position
+ * @param isRtl whether we're in RTL mode
+ * @return a Rect representing the area of the wallpaper to crop.
+ */
+ public static Rect calculateCropRect(float wallpaperZoom, Point wallpaperSize,
+ Point defaultCropSurfaceSize, Point screenSize, int scrollX, int scrollY,
+ boolean isRtl) {
+ // Calculate Rect of wallpaper in physical pixel terms (i.e., scaled to current zoom).
+ int scaledWallpaperWidth = (int) (wallpaperSize.x * wallpaperZoom);
+ int scaledWallpaperHeight = (int) (wallpaperSize.y * wallpaperZoom);
+ Rect rect = new Rect();
+ rect.set(0, 0, scaledWallpaperWidth, scaledWallpaperHeight);
+
+ // Crop rect should start off as the visible screen and then include extra width and height
+ // if available within wallpaper at the current zoom.
+ Rect cropRect = new Rect(scrollX, scrollY, scrollX + screenSize.x, scrollY + screenSize.y);
+
+ int extraWidth = defaultCropSurfaceSize.x - screenSize.x;
+ int extraHeightTopAndBottom = (int) ((defaultCropSurfaceSize.y - screenSize.y) / 2f);
+
+ // Try to increase size of screenRect to include extra width depending on the layout
+ // direction.
+ if (isRtl) {
+ cropRect.left = Math.max(cropRect.left - extraWidth, rect.left);
+ } else {
+ cropRect.right = Math.min(cropRect.right + extraWidth, rect.right);
+ }
+
+ // Try to increase the size of the cropRect to to include extra height.
+ int availableExtraHeightTop = cropRect.top - Math.max(
+ rect.top,
+ cropRect.top - extraHeightTopAndBottom);
+ int availableExtraHeightBottom = Math.min(
+ rect.bottom,
+ cropRect.bottom + extraHeightTopAndBottom) - cropRect.bottom;
+
+ int availableExtraHeightTopAndBottom =
+ Math.min(availableExtraHeightTop, availableExtraHeightBottom);
+ cropRect.top -= availableExtraHeightTopAndBottom;
+ cropRect.bottom += availableExtraHeightTopAndBottom;
+
+ return cropRect;
+ }
}