summaryrefslogtreecommitdiff
path: root/android
diff options
context:
space:
mode:
authorMohammad Saboorian <msab@google.com>2022-03-14 16:06:40 +0000
committerMohammad Saboorian <msab@google.com>2022-03-18 11:48:24 +0000
commit7ff9615b08822fe69ea4a86eceb1991e83e3e3db (patch)
tree17fe6122167a4c39824ebf2029998615309487a9 /android
parented21705d4777beeb6b92dfcdc7ca5a613b8aa631 (diff)
downloadidea-7ff9615b08822fe69ea4a86eceb1991e83e3e3db.tar.gz
Remove system drawn frame for round emulators
Playstore guidelines for Wear OS apps doesn't allow transparent background or device frames in the screenshot (https://support.google.com/googleplay/android-developer/answer/9866151#zippy=%2Cscreenshots). The change modifies the rectangular option to generates a play compliant screenshot. Bug: 211018814 Test: existing Change-Id: Ie4a14a39d5975b94a36111dbee9462b15efe0ea0
Diffstat (limited to 'android')
-rw-r--r--android/src/com/android/tools/idea/ddms/screenshot/DeviceArtScreenshotPostprocessor.kt12
-rw-r--r--android/src/com/android/tools/idea/ddms/screenshot/ScreenshotPostprocessor.kt4
-rw-r--r--android/src/com/android/tools/idea/ddms/screenshot/ScreenshotViewer.java27
-rw-r--r--android/testSrc/com/android/tools/idea/ddms/screenshot/ScreenshotViewerTest.kt34
4 files changed, 60 insertions, 17 deletions
diff --git a/android/src/com/android/tools/idea/ddms/screenshot/DeviceArtScreenshotPostprocessor.kt b/android/src/com/android/tools/idea/ddms/screenshot/DeviceArtScreenshotPostprocessor.kt
index 5d2197e6343..a9bfc406a34 100644
--- a/android/src/com/android/tools/idea/ddms/screenshot/DeviceArtScreenshotPostprocessor.kt
+++ b/android/src/com/android/tools/idea/ddms/screenshot/DeviceArtScreenshotPostprocessor.kt
@@ -20,6 +20,7 @@ import com.android.tools.adtui.ImageUtils
import com.android.tools.adtui.device.DeviceArtPainter
import com.intellij.util.ui.ImageUtil.applyQualityRenderingHints
import java.awt.AlphaComposite
+import java.awt.Color
import java.awt.geom.Area
import java.awt.geom.Ellipse2D
import java.awt.image.BufferedImage
@@ -30,10 +31,10 @@ import kotlin.math.max
*/
class DeviceArtScreenshotPostprocessor : ScreenshotPostprocessor {
@Slow
- override fun addFrame(screenshotImage: ScreenshotImage, framingOption: FramingOption?): BufferedImage {
+ override fun addFrame(screenshotImage: ScreenshotImage, framingOption: FramingOption?, backgroundColor: Color?): BufferedImage {
screenshotImage as DeviceScreenshotImage
if (framingOption == null) {
- return if (screenshotImage.isRoundScreen) circularClip(screenshotImage.image) else screenshotImage.image
+ return if (screenshotImage.isRoundScreen) circularClip(screenshotImage.image, backgroundColor) else screenshotImage.image
}
val frameDescriptor = (framingOption as DeviceArtFramingOption).deviceArtDescriptor
val framedImage = DeviceArtPainter.createFrame(screenshotImage.image, frameDescriptor, false, false)
@@ -41,7 +42,7 @@ class DeviceArtScreenshotPostprocessor : ScreenshotPostprocessor {
}
@Suppress("UndesirableClassUsage")
- private fun circularClip(image: BufferedImage): BufferedImage {
+ private fun circularClip(image: BufferedImage, backgroundColor: Color?): BufferedImage {
val mask = BufferedImage(image.width, image.height, BufferedImage.TYPE_INT_ARGB)
mask.createGraphics().apply {
applyQualityRenderingHints(this)
@@ -55,6 +56,11 @@ class DeviceArtScreenshotPostprocessor : ScreenshotPostprocessor {
drawImage(image, 0, 0, null)
composite = AlphaComposite.getInstance(AlphaComposite.DST_IN)
drawImage(mask, 0, 0, null)
+ if (backgroundColor != null) {
+ color = backgroundColor
+ composite = AlphaComposite.getInstance(AlphaComposite.DST_OVER)
+ fillRect(0, 0, image.width, image.height)
+ }
dispose()
}
return shapedImage
diff --git a/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotPostprocessor.kt b/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotPostprocessor.kt
index 9b3ebd45053..b84ad8b6e17 100644
--- a/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotPostprocessor.kt
+++ b/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotPostprocessor.kt
@@ -31,6 +31,7 @@
package com.android.tools.idea.ddms.screenshot
import com.android.annotations.concurrency.Slow
+import java.awt.Color
import java.awt.image.BufferedImage
/**
@@ -43,8 +44,9 @@ interface ScreenshotPostprocessor {
* @param screenshotImage the screenshot image to process
* @param framingOption determines the type of the frame to add to the image, or null to possibly
* adjust the screenshot without adding a frame
+ * @param backgroundColor the back color to use when clipping the screenshot
* @return the framed image
*/
@Slow
- fun addFrame(screenshotImage: ScreenshotImage, framingOption: FramingOption?): BufferedImage
+ fun addFrame(screenshotImage: ScreenshotImage, framingOption: FramingOption?, backgroundColor: Color?): BufferedImage
} \ No newline at end of file
diff --git a/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotViewer.java b/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotViewer.java
index 5707692ba4a..76cc9c2c7e0 100644
--- a/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotViewer.java
+++ b/android/src/com/android/tools/idea/ddms/screenshot/ScreenshotViewer.java
@@ -55,6 +55,7 @@ import com.intellij.openapi.vfs.VirtualFileWrapper;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.util.xmlb.XmlSerializerUtil;
import java.awt.BorderLayout;
+import java.awt.Color;
import java.awt.Component;
import java.awt.color.ICC_ColorSpace;
import java.awt.datatransfer.DataFlavor;
@@ -121,7 +122,7 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
private @NotNull JButton myCopyButton;
private static final class DecorationOption {
- private static final DecorationOption NO_DECORATION = new DecorationOption("Rectangular");
+ private static final DecorationOption RECTANGULAR = new DecorationOption("Rectangular");
private static final DecorationOption DISPLAY_SHAPE_CLIP = new DecorationOption("Display Shape");
private final @Nullable String myClipAction;
@@ -248,7 +249,7 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
canClipDeviceMask = ((DeviceScreenshotImage)screenshotImage).isRoundScreen();
}
DefaultComboBoxModel<DecorationOption> decorationOptions = new DefaultComboBoxModel<>();
- decorationOptions.addElement(DecorationOption.NO_DECORATION);
+ decorationOptions.addElement(DecorationOption.RECTANGULAR);
if (canClipDeviceMask) {
decorationOptions.addElement(DecorationOption.DISPLAY_SHAPE_CLIP);
}
@@ -262,8 +263,9 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
myDecorationComboBox.setSelectedIndex(defaultFramingOption + frameOptionStartIndex); // Select the default framing option.
}
else {
- // DEVICE_SHAPED or ORIGINAL (if DEVICE_SHAPED is not available).
- myDecorationComboBox.setSelectedItem(canClipDeviceMask ? DecorationOption.DISPLAY_SHAPE_CLIP : DecorationOption.NO_DECORATION);
+ // DEVICE_SHAPED or RECTANGULAR (if DEVICE_SHAPED is not available).
+ myDecorationComboBox.setSelectedItem(
+ canClipDeviceMask ? DecorationOption.DISPLAY_SHAPE_CLIP : DecorationOption.RECTANGULAR);
}
ActionListener decorationListener = event -> {
@@ -361,15 +363,17 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
private void processScreenshot(int rotateByQuadrants) {
FramingOption framingOption = null;
- boolean needsProcessing = false;
+ Color backgroundColor = null;
if (myScreenshotPostprocessor != null) {
framingOption = ((DecorationOption)myDecorationComboBox.getSelectedItem()).getFramingOption();
- needsProcessing = !myDecorationComboBox.getSelectedItem().equals(DecorationOption.NO_DECORATION);
+ if (myDecorationComboBox.getSelectedItem().equals(DecorationOption.RECTANGULAR)) {
+ backgroundColor = Color.BLACK;
+ }
}
new ImageProcessorTask(myProject, mySourceImageRef.get(), rotateByQuadrants,
- needsProcessing ? myScreenshotPostprocessor : null, framingOption,
- myBackingFile) {
+ myScreenshotPostprocessor, framingOption,
+ myBackingFile, backgroundColor) {
@Override
public void onSuccess() {
mySourceImageRef.set(getRotatedImage());
@@ -385,6 +389,7 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
private final @Nullable ScreenshotPostprocessor myScreenshotPostprocessor;
private final @Nullable FramingOption myFramingOption;
private final @Nullable VirtualFile myDestinationFile;
+ private final @Nullable Color myBackgroundColor;
private ScreenshotImage myRotatedImage;
private BufferedImage myProcessedImage;
@@ -394,7 +399,8 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
int rotateByQuadrants,
@Nullable ScreenshotPostprocessor screenshotPostprocessor,
@Nullable FramingOption framingOption,
- @Nullable VirtualFile writeToFile) {
+ @Nullable VirtualFile writeToFile,
+ @Nullable Color backgroundColor) {
super(project, AndroidBundle.message("android.ddms.screenshot.image.processor.task.title"), false);
mySrcImage = srcImage;
@@ -402,6 +408,7 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
myScreenshotPostprocessor = screenshotPostprocessor;
myFramingOption = framingOption;
myDestinationFile = writeToFile;
+ myBackgroundColor = backgroundColor;
}
@Override
@@ -412,7 +419,7 @@ public class ScreenshotViewer extends DialogWrapper implements DataProvider {
myProcessedImage = myRotatedImage.getImage();
}
else {
- myProcessedImage = myScreenshotPostprocessor.addFrame(myRotatedImage, myFramingOption);
+ myProcessedImage = myScreenshotPostprocessor.addFrame(myRotatedImage, myFramingOption, myBackgroundColor);
}
// Update the backing file, this is necessary for operations that read the backing file from the editor,
diff --git a/android/testSrc/com/android/tools/idea/ddms/screenshot/ScreenshotViewerTest.kt b/android/testSrc/com/android/tools/idea/ddms/screenshot/ScreenshotViewerTest.kt
index b5118d0f97b..3c543f0f7b8 100644
--- a/android/testSrc/com/android/tools/idea/ddms/screenshot/ScreenshotViewerTest.kt
+++ b/android/testSrc/com/android/tools/idea/ddms/screenshot/ScreenshotViewerTest.kt
@@ -31,7 +31,6 @@ import com.intellij.testFramework.RunsInEdt
import com.intellij.util.ui.EdtInvocationManager.dispatchAllInvocationEvents
import org.intellij.images.ui.ImageComponent
import org.intellij.images.ui.ImageComponentDecorator
-import org.jetbrains.kotlin.idea.gradleTooling.get
import org.junit.After
import org.junit.Before
import org.junit.Rule
@@ -39,6 +38,7 @@ import org.junit.Test
import java.awt.Color
import java.awt.image.BufferedImage
import java.util.EnumSet
+import javax.swing.JComboBox
/**
* Tests for [ScreenshotViewer].
@@ -101,19 +101,38 @@ class ScreenshotViewerTest {
val screenshotImage = DeviceScreenshotImage(createImage(200, 180), 0, true)
val viewer = createScreenshotViewer(screenshotImage, DeviceArtScreenshotPostprocessor())
val ui = FakeUi(viewer.rootPane)
+ val clipComboBox = ui.getComponent<JComboBox<*>>()
+ clipComboBox.selectFirstMatch("Display Shape")
dispatchAllInvocationEvents()
PlatformTestUtil.dispatchAllEventsInIdeEventQueue()
val processedImage: BufferedImage = ui.getComponent<ImageComponent>().document.value
- assertThat(processedImage.getRGB(screenshotImage.width / 2, screenshotImage.height / 2)).isEqualTo(Color.WHITE.rgb)
+ assertThat(processedImage.getRGB(screenshotImage.width / 2, screenshotImage.height / 2)).isEqualTo(Color.RED.rgb)
assertThat(processedImage.getRGB(5, 5)).isEqualTo(0)
assertThat(processedImage.getRGB(screenshotImage.width - 5, screenshotImage.height - 5)).isEqualTo(0)
}
+ @Test
+ fun testClipRoundScreenshotWithBackgroundColor() {
+ val screenshotImage = DeviceScreenshotImage(createImage(200, 180), 0, true)
+ val viewer = createScreenshotViewer(screenshotImage, DeviceArtScreenshotPostprocessor())
+ val ui = FakeUi(viewer.rootPane)
+
+ val clipComboBox = ui.getComponent<JComboBox<*>>()
+
+ clipComboBox.selectFirstMatch("Rectangular")
+ dispatchAllInvocationEvents()
+ PlatformTestUtil.dispatchAllEventsInIdeEventQueue()
+ val processedImage: BufferedImage = ui.getComponent<ImageComponent>().document.value
+ assertThat(processedImage.getRGB(screenshotImage.width / 2, screenshotImage.height / 2)).isEqualTo(Color.RED.rgb)
+ assertThat(processedImage.getRGB(5, 5)).isEqualTo(Color.BLACK.rgb)
+ assertThat(processedImage.getRGB(screenshotImage.width - 5, screenshotImage.height - 5)).isEqualTo(Color.BLACK.rgb)
+ }
+
private fun createImage(width: Int, height: Int): BufferedImage {
val image = ImageUtils.createDipImage(width, height, BufferedImage.TYPE_INT_ARGB)
val graphics = image.createGraphics()
- graphics.paint = Color.WHITE
+ graphics.paint = Color.RED
graphics.fillRect(0, 0, image.width, image.height)
graphics.dispose()
return image
@@ -127,4 +146,13 @@ class ScreenshotViewerTest {
viewer.show()
return viewer
}
+
+ private fun <E> JComboBox<E>.selectFirstMatch(text: String) {
+ for (i in 0 until model.size) {
+ if (model.getElementAt(i).toString() == text) {
+ this.selectedIndex = i
+ return
+ }
+ }
+ }
} \ No newline at end of file