diff options
10 files changed, 330 insertions, 166 deletions
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java index 6fd59c4..212223c 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java +++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java @@ -456,7 +456,11 @@ public class BitmapFactory { // into is.read(...) This number is not related to the value passed // to mark(...) above. try { - bm = Bitmap_Delegate.createBitmap(is, Density.MEDIUM); + Density density = Density.MEDIUM; + if (opts != null) { + density = Density.getEnum(opts.inDensity); + } + bm = Bitmap_Delegate.createBitmap(is, true, density); } catch (IOException e) { return null; } diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java index 0920497..b4c51b2 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java @@ -75,32 +75,56 @@ public class Bitmap_Delegate { /** * Creates and returns a {@link Bitmap} initialized with the given file content. + * + * @param input the file from which to read the bitmap content + * @param isMutable whether the bitmap is mutable + * @param density the density associated with the bitmap + * + * @see Bitmap#isMutable() + * @see Bitmap#getDensity() */ - public static Bitmap createBitmap(File input, Density density) throws IOException { + public static Bitmap createBitmap(File input, boolean isMutable, Density density) + throws IOException { // create a delegate with the content of the file. Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input)); - return createBitmap(delegate, density.getValue()); + return createBitmap(delegate, isMutable, density.getValue()); } /** * Creates and returns a {@link Bitmap} initialized with the given stream content. + * + * @param input the stream from which to read the bitmap content + * @param isMutable whether the bitmap is mutable + * @param density the density associated with the bitmap + * + * @see Bitmap#isMutable() + * @see Bitmap#getDensity() */ - public static Bitmap createBitmap(InputStream input, Density density) throws IOException { + public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density) + throws IOException { // create a delegate with the content of the stream. Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input)); - return createBitmap(delegate, density.getValue()); + return createBitmap(delegate, isMutable, density.getValue()); } /** * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage} + * + * @param image the bitmap content + * @param isMutable whether the bitmap is mutable + * @param density the density associated with the bitmap + * + * @see Bitmap#isMutable() + * @see Bitmap#getDensity() */ - public static Bitmap createBitmap(BufferedImage image, Density density) throws IOException { + public static Bitmap createBitmap(BufferedImage image, boolean isMutable, Density density) + throws IOException { // create a delegate with the given image. Bitmap_Delegate delegate = new Bitmap_Delegate(image); - return createBitmap(delegate, density.getValue()); + return createBitmap(delegate, isMutable, density.getValue()); } /** @@ -153,7 +177,7 @@ public class Bitmap_Delegate { // create a delegate with the content of the stream. Bitmap_Delegate delegate = new Bitmap_Delegate(image); - return createBitmap(delegate, Bitmap.getDefaultDensity()); + return createBitmap(delegate, mutable, Bitmap.getDefaultDensity()); } /*package*/ static Bitmap nativeCopy(int srcBitmap, int nativeConfig, boolean isMutable) { @@ -166,8 +190,7 @@ public class Bitmap_Delegate { } /*package*/ static void nativeRecycle(int nativeBitmap) { - // FIXME implement native delegate - throw new UnsupportedOperationException("Native delegate needed for Bitmap"); + sManager.removeDelegate(nativeBitmap); } /*package*/ static boolean nativeCompress(int nativeBitmap, int format, int quality, @@ -336,11 +359,11 @@ public class Bitmap_Delegate { mImage = image; } - private static Bitmap createBitmap(Bitmap_Delegate delegate, int density) { + private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) { // get its native_int int nativeInt = sManager.addDelegate(delegate); // and create/return a new Bitmap with it - return new Bitmap(nativeInt, true /*isMutable*/, null /*ninePatchChunk*/, density); + return new Bitmap(nativeInt, isMutable, null /*ninePatchChunk*/, density); } } diff --git a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java index cea07af..08f3c7a 100644 --- a/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java @@ -960,7 +960,7 @@ public class Canvas_Delegate { * Creates a new {@link Graphics2D} based on the {@link Paint} parameters. * <p/>The object must be disposed ({@link Graphics2D#dispose()}) after being used. */ - private Graphics2D getCustomGraphics(Paint_Delegate paint) { + /*package*/ Graphics2D getCustomGraphics(Paint_Delegate paint) { // make new one Graphics2D g = getGraphics2d(); g = (Graphics2D)g.create(); diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java new file mode 100644 index 0000000..3d26e47 --- /dev/null +++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2010 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 android.graphics; + +import com.android.layoutlib.bridge.impl.DelegateManager; +import com.android.ninepatch.NinePatchChunk; + +import android.graphics.drawable.NinePatchDrawable; + +import java.awt.Graphics2D; +import java.awt.image.BufferedImage; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.lang.ref.SoftReference; +import java.util.HashMap; +import java.util.Map; + +/** + * Delegate implementing the native methods of android.graphics.NinePatch + * + * Through the layoutlib_create tool, the original native methods of NinePatch have been replaced + * by calls to methods of the same name in this delegate class. + * + * Because it's a stateless class to start with, there's no need to keep a {@link DelegateManager} + * around to map int to instance of the delegate. + * + */ +public class NinePatch_Delegate { + + /** + * Cache map for {@link NinePatchChunk}. + * When the chunks are created they are serialized into a byte[], and both are put + * in the cache, using a {@link SoftReference} for the chunk. The default Java classes + * for {@link NinePatch} and {@link NinePatchDrawable} only reference to the byte[] data, and + * provide this for drawing. + * Using the cache map allows us to not have to deserialize the byte[] back into a + * {@link NinePatchChunk} every time a rendering is done. + */ + private final static Map<byte[], SoftReference<NinePatchChunk>> sChunkCache = + new HashMap<byte[], SoftReference<NinePatchChunk>>(); + + // ---- Public Helper methods ---- + + /** + * Serializes the given chunk. + * + * @return the serialized data for the chunk. + */ + public static byte[] serialize(NinePatchChunk chunk) { + // serialize the chunk to get a byte[] + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = null; + try { + oos = new ObjectOutputStream(baos); + oos.writeObject(chunk); + } catch (IOException e) { + //FIXME log this. + return null; + } finally { + if (oos != null) { + try { + oos.close(); + } catch (IOException e) { + } + } + } + + // get the array and add it to the cache + byte[] array = baos.toByteArray(); + sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); + return array; + } + + // ---- native methods ---- + + /*package*/ static boolean isNinePatchChunk(byte[] chunk) { + NinePatchChunk chunkObject = getChunk(chunk); + if (chunkObject != null) { + return true; + } + + return false; + } + + /*package*/ static void validateNinePatchChunk(int bitmap, byte[] chunk) { + // the default JNI implementation only checks that the byte[] has the same + // size as the C struct it represent. Since we cannot do the same check (serialization + // will return different size depending on content), we do nothing. + } + + /*package*/ static void nativeDraw(int canvas_instance, RectF loc, int bitmap_instance, + byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) { + draw(canvas_instance, + (int) loc.left, (int) loc.top, (int) loc.width(), (int) loc.height(), + bitmap_instance, c, paint_instance_or_null, + destDensity, srcDensity); + } + + /*package*/ static void nativeDraw(int canvas_instance, Rect loc, int bitmap_instance, + byte[] c, int paint_instance_or_null, int destDensity, int srcDensity) { + draw(canvas_instance, + loc.left, loc.top, loc.width(), loc.height(), + bitmap_instance, c, paint_instance_or_null, + destDensity, srcDensity); + } + + private static void draw(int canvas_instance, + int left, int top, int right, int bottom, + int bitmap_instance, byte[] c, int paint_instance_or_null, + int destDensity, int srcDensity) { + // get the delegate from the native int. + Bitmap_Delegate bitmap_delegate = Bitmap_Delegate.getDelegate(bitmap_instance); + if (bitmap_delegate == null) { + assert false; + return; + } + + if (c == null) { + // not a 9-patch? + BufferedImage image = bitmap_delegate.getImage(); + Canvas_Delegate.native_drawBitmap(canvas_instance, bitmap_instance, + new Rect(0, 0, image.getWidth(), image.getHeight()), + new Rect(left, top, right, bottom), + paint_instance_or_null, destDensity, srcDensity); + return; + } + + NinePatchChunk chunkObject = getChunk(c); + assert chunkObject != null; + if (chunkObject == null) { + return; + } + + Canvas_Delegate canvas_delegate = Canvas_Delegate.getDelegate(canvas_instance); + if (canvas_delegate == null) { + assert false; + return; + } + + // this one can be null + Paint_Delegate paint_delegate = Paint_Delegate.getDelegate(paint_instance_or_null); + + Graphics2D graphics; + if (paint_delegate != null) { + graphics = canvas_delegate.getCustomGraphics(paint_delegate); + } else { + graphics = canvas_delegate.getGraphics2d(); + } + + try { + chunkObject.draw(bitmap_delegate.getImage(), graphics, + left, top, right - left, bottom - top); + } finally { + if (paint_delegate != null) { + graphics.dispose(); + } + } + + } + + /*package*/ static int nativeGetTransparentRegion(int bitmap, byte[] chunk, Rect location) { + return 0; + } + + // ---- Private Helper methods ---- + + /** + * Returns a {@link NinePatchChunk} object for the given serialized representation. + * + * If the chunk is present in the cache then the object from the cache is returned, otherwise + * the array is deserialized into a {@link NinePatchChunk} object. + * + * @param array the serialized representation of the chunk. + * @return the NinePatchChunk or null if deserialization failed. + */ + private static NinePatchChunk getChunk(byte[] array) { + SoftReference<NinePatchChunk> chunkRef = sChunkCache.get(array); + NinePatchChunk chunk = chunkRef.get(); + if (chunk == null) { + ByteArrayInputStream bais = new ByteArrayInputStream(array); + ObjectInputStream ois = null; + try { + ois = new ObjectInputStream(bais); + chunk = (NinePatchChunk) ois.readObject(); + + // put back the chunk in the cache + if (chunk != null) { + sChunkCache.put(array, new SoftReference<NinePatchChunk>(chunk)); + } + } catch (IOException e) { + // FIXME: log this + return null; + } catch (ClassNotFoundException e) { + // FIXME: log this + return null; + } finally { + if (ois != null) { + try { + ois.close(); + } catch (IOException e) { + } + } + } + } + + return chunk; + } +} 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 e691fdf..35ba73d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java @@ -26,7 +26,7 @@ import com.android.layoutlib.api.SceneResult; import com.android.layoutlib.bridge.android.BridgeAssetManager; import com.android.layoutlib.bridge.impl.FontLoader; import com.android.layoutlib.bridge.impl.LayoutSceneImpl; -import com.android.ninepatch.NinePatch; +import com.android.ninepatch.NinePatchChunk; import com.android.tools.layoutlib.create.MethodAdapter; import com.android.tools.layoutlib.create.OverrideMethod; @@ -73,13 +73,13 @@ public final class Bridge extends LayoutBridge { private final static Map<Object, Map<String, SoftReference<Bitmap>>> sProjectBitmapCache = new HashMap<Object, Map<String, SoftReference<Bitmap>>>(); - private final static Map<Object, Map<String, SoftReference<NinePatch>>> sProject9PatchCache = - new HashMap<Object, Map<String, SoftReference<NinePatch>>>(); + private final static Map<Object, Map<String, SoftReference<NinePatchChunk>>> sProject9PatchCache = + new HashMap<Object, Map<String, SoftReference<NinePatchChunk>>>(); private final static Map<String, SoftReference<Bitmap>> sFrameworkBitmapCache = new HashMap<String, SoftReference<Bitmap>>(); - private final static Map<String, SoftReference<NinePatch>> sFramework9PatchCache = - new HashMap<String, SoftReference<NinePatch>>(); + private final static Map<String, SoftReference<NinePatchChunk>> sFramework9PatchCache = + new HashMap<String, SoftReference<NinePatchChunk>>(); private static Map<String, Map<String, Integer>> sEnumValueMap; @@ -252,23 +252,23 @@ public final class Bridge extends LayoutBridge { } /** - * Sets a 9 patch in a project cache or in the framework cache. + * Sets a 9 patch chunk in a project cache or in the framework cache. * @param value the path of the 9 patch * @param ninePatch the 9 patch object * @param projectKey the key of the project, or null to put the bitmap in the framework cache. */ - public static void setCached9Patch(String value, NinePatch ninePatch, Object projectKey) { + public static void setCached9Patch(String value, NinePatchChunk ninePatch, Object projectKey) { if (projectKey != null) { - Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey); + Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey); if (map == null) { - map = new HashMap<String, SoftReference<NinePatch>>(); + map = new HashMap<String, SoftReference<NinePatchChunk>>(); sProject9PatchCache.put(projectKey, map); } - map.put(value, new SoftReference<NinePatch>(ninePatch)); + map.put(value, new SoftReference<NinePatchChunk>(ninePatch)); } else { - sFramework9PatchCache.put(value, new SoftReference<NinePatch>(ninePatch)); + sFramework9PatchCache.put(value, new SoftReference<NinePatchChunk>(ninePatch)); } } @@ -436,24 +436,24 @@ public final class Bridge extends LayoutBridge { } /** - * Returns the 9 patch for a specific path, from a specific project cache, or from the + * Returns the 9 patch chunk for a specific path, from a specific project cache, or from the * framework cache. * @param value the path of the 9 patch * @param projectKey the key of the project, or null to query the framework cache. * @return the cached 9 patch or null if not found. */ - public static NinePatch getCached9Patch(String value, Object projectKey) { + public static NinePatchChunk getCached9Patch(String value, Object projectKey) { if (projectKey != null) { - Map<String, SoftReference<NinePatch>> map = sProject9PatchCache.get(projectKey); + Map<String, SoftReference<NinePatchChunk>> map = sProject9PatchCache.get(projectKey); if (map != null) { - SoftReference<NinePatch> ref = map.get(value); + SoftReference<NinePatchChunk> ref = map.get(value); if (ref != null) { return ref.get(); } } } else { - SoftReference<NinePatch> ref = sFramework9PatchCache.get(value); + SoftReference<NinePatchChunk> ref = sFramework9PatchCache.get(value); if (ref != null) { return ref.get(); } diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java deleted file mode 100644 index 4efa631..0000000 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2008 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.ninepatch.NinePatch; - -import android.graphics.Canvas; -import android.graphics.Canvas_Delegate; -import android.graphics.ColorFilter; -import android.graphics.Rect; -import android.graphics.drawable.Drawable; - -public class NinePatchDrawable extends Drawable { - - private NinePatch m9Patch; - - public NinePatchDrawable(NinePatch ninePatch) { - m9Patch = ninePatch; - } - - @Override - public int getMinimumWidth() { - return m9Patch.getWidth(); - } - - @Override - public int getMinimumHeight() { - return m9Patch.getHeight(); - } - - /** - * Return the intrinsic width of the underlying drawable object. Returns - * -1 if it has no intrinsic width, such as with a solid color. - */ - @Override - public int getIntrinsicWidth() { - return m9Patch.getWidth(); - } - - /** - * Return the intrinsic height of the underlying drawable object. Returns - * -1 if it has no intrinsic height, such as with a solid color. - */ - @Override - public int getIntrinsicHeight() { - return m9Patch.getHeight(); - } - - /** - * Return in padding the insets suggested by this Drawable for placing - * content inside the drawable's bounds. Positive values move toward the - * center of the Drawable (set Rect.inset). Returns true if this drawable - * actually has a padding, else false. When false is returned, the padding - * is always set to 0. - */ - @Override - public boolean getPadding(Rect padding) { - int[] padd = new int[4]; - m9Patch.getPadding(padd); - padding.left = padd[0]; - padding.top = padd[1]; - padding.right = padd[2]; - padding.bottom = padd[3]; - return true; - } - - @Override - public void draw(Canvas canvas) { - Rect r = getBounds(); - Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas); - m9Patch.draw(canvasDelegate.getGraphics2d(), r.left, r.top, r.width(), r.height()); - - return; - } - - - // ----------- Not implemented methods --------------- - - - @Override - public int getOpacity() { - // FIXME - return 0xFF; - } - - @Override - public void setAlpha(int arg0) { - // FIXME ! - } - - @Override - public void setColorFilter(ColorFilter arg0) { - // FIXME - } -} diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java index 2e3f9a8..f7d249e 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java @@ -313,10 +313,12 @@ public class LayoutSceneImpl { // create an Android bitmap around the BufferedImage Bitmap bitmap = Bitmap_Delegate.createBitmap(mImage, + true /*isMutable*/, Density.getEnum(mParams.getDensity())); // create a Canvas around the Android bitmap Canvas canvas = new Canvas(bitmap); + canvas.setDensity(mParams.getDensity()); // to set the logger, get the native delegate Canvas_Delegate canvasDelegate = Canvas_Delegate.getDelegate(canvas); diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java index 3e506b8..ceb8a0d 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java @@ -22,8 +22,8 @@ import com.android.layoutlib.api.IResourceValue; import com.android.layoutlib.bridge.Bridge; import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; -import com.android.layoutlib.bridge.android.NinePatchDrawable; import com.android.ninepatch.NinePatch; +import com.android.ninepatch.NinePatchChunk; import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; @@ -31,9 +31,12 @@ import org.xmlpull.v1.XmlPullParserException; import android.graphics.Bitmap; import android.graphics.Bitmap_Delegate; +import android.graphics.NinePatch_Delegate; +import android.graphics.Rect; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; +import android.graphics.drawable.NinePatchDrawable; import android.util.TypedValue; import java.io.File; @@ -121,15 +124,38 @@ public final class ResourceHelper { if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) { File file = new File(stringValue); if (file.isFile()) { - NinePatch ninePatch = Bridge.getCached9Patch(stringValue, + // see if we still have both the chunk and the bitmap in the caches + NinePatchChunk chunk = Bridge.getCached9Patch(stringValue, + isFramework ? null : context.getProjectKey()); + Bitmap bitmap = Bridge.getCachedBitmap(stringValue, isFramework ? null : context.getProjectKey()); - if (ninePatch == null) { + // if either chunk or bitmap is null, then we reload the 9-patch file. + if (chunk == null || bitmap == null) { try { - ninePatch = NinePatch.load(file.toURL(), false /* convert */); + NinePatch ninePatch = NinePatch.load(file.toURL(), false /* convert */); + if (ninePatch != null) { + if (chunk == null) { + chunk = ninePatch.getChunk(); - Bridge.setCached9Patch(stringValue, ninePatch, - isFramework ? null : context.getProjectKey()); + Bridge.setCached9Patch(stringValue, chunk, + isFramework ? null : context.getProjectKey()); + } + + if (bitmap == null) { + Density density = Density.MEDIUM; + if (value instanceof IDensityBasedResourceValue) { + density = ((IDensityBasedResourceValue)value).getDensity(); + } + + bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), + false /*isMutable*/, + density); + + Bridge.setCachedBitmap(stringValue, bitmap, + isFramework ? null : context.getProjectKey()); + } + } } catch (MalformedURLException e) { // URL is wrong, we'll return null below } catch (IOException e) { @@ -137,8 +163,13 @@ public final class ResourceHelper { } } - if (ninePatch != null) { - return new NinePatchDrawable(ninePatch); + if (chunk != null && bitmap != null) { + int[] padding = chunk.getPadding(); + Rect paddingRect = new Rect(padding[0], padding[1], padding[2], padding[3]); + + return new NinePatchDrawable(context.getResources(), bitmap, + NinePatch_Delegate.serialize(chunk), + paddingRect, null); } } @@ -174,27 +205,15 @@ public final class ResourceHelper { isFramework ? null : context.getProjectKey()); if (bitmap == null) { - // always create the cache copy in the original density. - bitmap = Bitmap_Delegate.createBitmap(bmpFile, Density.MEDIUM); - Bridge.setCachedBitmap(stringValue, bitmap, - isFramework ? null : context.getProjectKey()); - } - - try { + Density density = Density.MEDIUM; if (value instanceof IDensityBasedResourceValue) { - Density density = ((IDensityBasedResourceValue)value).getDensity(); - if (density != Density.MEDIUM) { - // create a copy of the bitmap - bitmap = Bitmap.createBitmap(bitmap); - - // apply the density - bitmap.setDensity(density.getValue()); - } + density = ((IDensityBasedResourceValue)value).getDensity(); } - } catch (NoClassDefFoundError error) { - // look like we're running in an older version of ADT that doesn't include - // the new layoutlib_api. Let's just ignore this, the drawing will just be - // wrong. + + bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, + density); + Bridge.setCachedBitmap(stringValue, bitmap, + isFramework ? null : context.getProjectKey()); } return new BitmapDrawable(context.getResources(), bitmap); diff --git a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java index 23351ab..a3219e7 100644 --- a/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java +++ b/tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java @@ -48,5 +48,4 @@ public class NinePatchTest extends TestCase { assertEquals(36, mPatch.getWidth()); assertEquals(25, mPatch.getHeight()); } - } diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java index b9c7113..bb2e6b3 100644 --- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java +++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java @@ -109,6 +109,7 @@ public final class CreateInfo implements ICreateInfo { "android.graphics.DashPathEffect", "android.graphics.LinearGradient", "android.graphics.Matrix", + "android.graphics.NinePatch", "android.graphics.Paint", "android.graphics.PathEffect", "android.graphics.PorterDuffXfermode", |