From f3cb4ba213a0fa4d1c184c430a2eaac7e27ccf6f Mon Sep 17 00:00:00 2001 From: Diego Perez Date: Mon, 16 Feb 2015 17:14:16 +0000 Subject: [PATCH 1/2] Avoid caching mImage on the main render loop and use clipping. + Added a session flag that avoids caching mImage. This is useful when mImage is just a Graphics2D wrapper that might change at any time. + Make GcSnapshot aware of the clipping so it doesn't need to render the whole area if not needed. Change-Id: Ie0134c2bc2741b5fa6648313864c851bbac066cf (cherry picked from commit 2c5e85b303077d2120b428bd4c7e6ecb6970935b) --- .../layoutlib/bridge/impl/GcSnapshot.java | 19 +++++++++++++++++-- .../bridge/impl/RenderSessionImpl.java | 17 ++++++++++++++--- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java index 3a0321a167ca3..c34f9b51a3492 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/GcSnapshot.java @@ -35,6 +35,7 @@ import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Composite; import java.awt.Graphics2D; +import java.awt.Rectangle; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.AffineTransform; @@ -615,8 +616,22 @@ public class GcSnapshot { return; } - int width = layer.getImage().getWidth(); - int height = layer.getImage().getHeight(); + int width; + int height; + Rectangle clipBounds = originalGraphics.getClipBounds(); + if (clipBounds != null) { + if (clipBounds.width == 0 || clipBounds.height == 0) { + // Clip is 0 so no need to paint anything. + return; + } + // If we have clipBounds available, use them as they will always be + // smaller than the full layer size. + width = clipBounds.width; + height = clipBounds.height; + } else { + width = layer.getImage().getWidth(); + height = layer.getImage().getHeight(); + } // Create a temporary image to which the color filter will be applied. BufferedImage image = new BufferedImage(width, height, diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index 95576ef9120b0..c8497d4279e4a 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -554,7 +554,14 @@ public class RenderSessionImpl extends RenderAction { // draw the views // create the BufferedImage into which the layout will be rendered. boolean newImage = false; - if (newRenderSize || mCanvas == null) { + + // When disableBitmapCaching is true, we do not reuse mImage and + // we create a new one in every render. + // This is useful when mImage is just a wrapper of Graphics2D so + // it doesn't get cached. + boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( + RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); + if (newRenderSize || mCanvas == null || disableBitmapCaching) { if (params.getImageFactory() != null) { mImage = params.getImageFactory().getImage( mMeasuredScreenWidth, @@ -581,8 +588,12 @@ public class RenderSessionImpl extends RenderAction { Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, true /*isMutable*/, hardwareConfig.getDensity()); - // create a Canvas around the Android bitmap - mCanvas = new Canvas(bitmap); + if (mCanvas == null) { + // create a Canvas around the Android bitmap + mCanvas = new Canvas(bitmap); + } else { + mCanvas.setBitmap(bitmap); + } mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue()); } From 8ff8de2cf2ebc136d3dd8d8a8b5e4912e483bb2b Mon Sep 17 00:00:00 2001 From: Diego Perez Date: Wed, 5 Nov 2014 11:30:48 +0000 Subject: [PATCH 2/2] Add new parameter to the render method to allow forcing a measure pass. Change-Id: I60c09f3375fc85c257a449f4372220741e01db54 (cherry picked from commit c13aa0c035cd226d27323bc0e533632ba32f6a84) --- .../com/android/layoutlib/bridge/BridgeRenderSession.java | 5 ++++- .../com/android/layoutlib/bridge/impl/RenderSessionImpl.java | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java index e0f87fd63b111..feb25905390cf 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java @@ -86,11 +86,14 @@ public class BridgeRenderSession extends RenderSession { } @Override - public Result render(long timeout) { + public Result render(long timeout, boolean forceMeasure) { try { Bridge.prepareThread(); mLastResult = mSession.acquire(timeout); if (mLastResult.isSuccess()) { + if (forceMeasure) { + mSession.invalidateRenderingSize(); + } mLastResult = mSession.render(false /*freshRender*/); } } finally { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java index c8497d4279e4a..2439dde263b7d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java @@ -1642,7 +1642,7 @@ public class RenderSessionImpl extends RenderAction { return null; } - private void invalidateRenderingSize() { + public void invalidateRenderingSize() { mMeasuredScreenWidth = mMeasuredScreenHeight = -1; }