From 63483e17de4d2441acaabcee4185b0bb25e1d94c Mon Sep 17 00:00:00 2001 From: Andrew Shulaev Date: Wed, 4 Mar 2015 16:20:19 +0000 Subject: Added function to render a drawable in all available states Change-Id: I230cc5775a09120efe9c82a4017b001aa510ddff --- .../src/com/android/layoutlib/bridge/Bridge.java | 2 +- .../bridge/android/RenderParamsFlags.java | 39 ++++++++++++++ .../bridge/android/SessionParamsFlags.java | 37 ------------- .../layoutlib/bridge/impl/RenderDrawable.java | 62 +++++++++++++++++++--- .../layoutlib/bridge/impl/RenderSessionImpl.java | 6 +-- 5 files changed, 97 insertions(+), 49 deletions(-) create mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java delete mode 100644 tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java index 4d2c2fc20588..c6d60f8a76f6 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -181,7 +181,7 @@ public final class Bridge extends com.android.ide.common.rendering.api.Bridge { */ private static LayoutLog sCurrentLog = sDefaultLog; - private static final int LAST_SUPPORTED_FEATURE = Features.PREFERENCES_RENDERING; + private static final int LAST_SUPPORTED_FEATURE = Features.RENDER_ALL_DRAWABLE_STATES; @Override public int getApiLevel() { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java new file mode 100644 index 000000000000..cfc8f40be093 --- /dev/null +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.layoutlib.bridge.android; + +import com.android.ide.common.rendering.api.SessionParams.Key; + +/** + * This contains all known keys for the {@link RenderParams#getFlag(Key)}. + *

+ * The IDE has its own copy of this class which may be newer or older than this one. + *

+ * Constants should never be modified or removed from this class. + */ +public final class RenderParamsFlags { + + public static final Key FLAG_KEY_ROOT_TAG = + new Key("rootTag", String.class); + public static final Key FLAG_KEY_DISABLE_BITMAP_CACHING = + new Key("disableBitmapCaching", Boolean.class); + public static final Key FLAG_KEY_RENDER_ALL_DRAWABLE_STATES = + new Key("renderAllDrawableStates", Boolean.class); + + // Disallow instances. + private RenderParamsFlags() {} +} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java deleted file mode 100644 index 51a010411c6c..000000000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/SessionParamsFlags.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2014 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.layoutlib.bridge.android; - -import com.android.ide.common.rendering.api.SessionParams; - -/** - * This contains all known keys for the {@link SessionParams#getFlag(SessionParams.Key)}. - *

- * The IDE has its own copy of this class which may be newer or older than this one. - *

- * Constants should never be modified or removed from this class. - */ -public final class SessionParamsFlags { - - public static final SessionParams.Key FLAG_KEY_ROOT_TAG = - new SessionParams.Key("rootTag", String.class); - public static final SessionParams.Key FLAG_KEY_DISABLE_BITMAP_CACHING = - new SessionParams.Key("disableBitmapCaching", Boolean.class); - - // Disallow instances. - private SessionParamsFlags() {} -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java index 669e6b5d9865..3dee1e23dfe2 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderDrawable.java @@ -16,20 +16,20 @@ package com.android.layoutlib.bridge.impl; -import static com.android.ide.common.rendering.api.Result.Status.ERROR_UNKNOWN; - import com.android.ide.common.rendering.api.DrawableParams; import com.android.ide.common.rendering.api.HardwareConfig; import com.android.ide.common.rendering.api.ResourceValue; import com.android.ide.common.rendering.api.Result; import com.android.ide.common.rendering.api.Result.Status; import com.android.layoutlib.bridge.android.BridgeContext; +import com.android.layoutlib.bridge.android.RenderParamsFlags; import com.android.resources.ResourceType; import android.graphics.Bitmap; import android.graphics.Bitmap_Delegate; import android.graphics.Canvas; import android.graphics.drawable.Drawable; +import android.graphics.drawable.StateListDrawable; import android.view.AttachInfo_Accessor; import android.view.View.MeasureSpec; import android.widget.FrameLayout; @@ -38,7 +38,9 @@ import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Graphics2D; import java.awt.image.BufferedImage; -import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; /** * Action to render a given Drawable provided through {@link DrawableParams#getDrawable()}. @@ -71,11 +73,37 @@ public class RenderDrawable extends RenderAction { return Status.ERROR_NOT_A_DRAWABLE.createResult(); } + Drawable d = ResourceHelper.getDrawable(drawableResource, context); + + final Boolean allStates = + params.getFlag(RenderParamsFlags.FLAG_KEY_RENDER_ALL_DRAWABLE_STATES); + if (allStates == Boolean.TRUE) { + final List result; + + if (d instanceof StateListDrawable) { + result = new ArrayList(); + final StateListDrawable stateList = (StateListDrawable) d; + for (int i = 0; i < stateList.getStateCount(); i++) { + final Drawable stateDrawable = stateList.getStateDrawable(i); + result.add(renderImage(hardwareConfig, stateDrawable, context)); + } + } else { + result = Collections.singletonList(renderImage(hardwareConfig, d, context)); + } + + return Status.SUCCESS.createResult(result); + } else { + BufferedImage image = renderImage(hardwareConfig, d, context); + return Status.SUCCESS.createResult(image); + } + } + + private BufferedImage renderImage(HardwareConfig hardwareConfig, Drawable d, + BridgeContext context) { // create a simple FrameLayout FrameLayout content = new FrameLayout(context); // get the actual Drawable object to draw - Drawable d = ResourceHelper.getDrawable(drawableResource, context); content.setBackground(d); // set the AttachInfo on the root view. @@ -83,8 +111,27 @@ public class RenderDrawable extends RenderAction { // measure - int w = hardwareConfig.getScreenWidth(); - int h = hardwareConfig.getScreenHeight(); + int w = d.getIntrinsicWidth(); + int h = d.getIntrinsicHeight(); + + final int screenWidth = hardwareConfig.getScreenWidth(); + final int screenHeight = hardwareConfig.getScreenHeight(); + + if (w == -1 || h == -1) { + // Use screen size when either intrinsic width or height isn't available + w = screenWidth; + h = screenHeight; + } else if (w > screenWidth || h > screenHeight) { + // If image wouldn't fit to the screen, resize it to avoid cropping. + + // We need to find scale such that scale * w <= screenWidth, scale * h <= screenHeight + double scale = Math.min((double) screenWidth / w, (double) screenHeight / h); + + // scale * w / scale * h = w / h, so, proportions are preserved. + w = (int) Math.floor(scale * w); + h = (int) Math.floor(scale * h); + } + int w_spec = MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY); int h_spec = MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY); content.measure(w_spec, h_spec); @@ -108,8 +155,7 @@ public class RenderDrawable extends RenderAction { // and draw content.draw(canvas); - - return Status.SUCCESS.createResult(image); + return image; } protected BufferedImage getImage(int w, int h) { 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 875cc8759701..607563ab5d1e 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 @@ -50,7 +50,7 @@ import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.SessionParamsFlags; +import com.android.layoutlib.bridge.android.RenderParamsFlags; import com.android.layoutlib.bridge.bars.BridgeActionBar; import com.android.layoutlib.bridge.bars.AppCompatActionBar; import com.android.layoutlib.bridge.bars.Config; @@ -400,7 +400,7 @@ public class RenderSessionImpl extends RenderAction { // it can instantiate the custom Fragment. Fragment_Delegate.setProjectCallback(params.getProjectCallback()); - String rootTag = params.getFlag(SessionParamsFlags.FLAG_KEY_ROOT_TAG); + String rootTag = params.getFlag(RenderParamsFlags.FLAG_KEY_ROOT_TAG); boolean isPreference = "PreferenceScreen".equals(rootTag); View view; if (isPreference) { @@ -557,7 +557,7 @@ public class RenderSessionImpl extends RenderAction { // This is useful when mImage is just a wrapper of Graphics2D so // it doesn't get cached. boolean disableBitmapCaching = Boolean.TRUE.equals(params.getFlag( - SessionParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); + RenderParamsFlags.FLAG_KEY_DISABLE_BITMAP_CACHING)); if (newRenderSize || mCanvas == null || disableBitmapCaching) { if (params.getImageFactory() != null) { mImage = params.getImageFactory().getImage( -- cgit v1.2.3-59-g8ed1b