summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java45
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Canvas_Delegate.java2
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java225
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java32
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/NinePatchDrawable.java109
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/LayoutSceneImpl.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java73
-rw-r--r--tools/layoutlib/bridge/tests/com/android/layoutlib/bridge/NinePatchTest.java1
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java1
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",