From 13bdc3355c781dc2614f2810a42d3a9e73f5bed9 Mon Sep 17 00:00:00 2001 From: Xavier Ducrohet Date: Sun, 6 Feb 2011 10:58:16 -0800 Subject: [PATCH] LayoutLib: improved rendering for system/title/action bars. Change-Id: I926531e9ad4a7b98e04e23cac3837794f7c89449 --- .../bridge/resources/bars/action_bar.xml | 6 +- .../hdpi/stat_sys_wifi_signal_4_fully.png | Bin 0 -> 1195 bytes .../bars/hdpi/status_bar_background.9.png | Bin 0 -> 3233 bytes .../bars/mdpi/status_bar_background.9.png | Bin 0 -> 204 bytes .../resources/bars/phone_system_bar.xml | 9 +- .../resources/bars/tablet_system_bar.xml | 6 +- .../bridge/resources/bars/title_bar.xml | 3 +- .../graphics/BitmapFactory_Delegate.java | 43 ++++++- .../android/graphics/NinePatch_Delegate.java | 86 ++++++------- .../layoutlib/bridge/bars/CustomBar.java | 96 ++++++++++---- .../layoutlib/bridge/bars/PhoneSystemBar.java | 10 ++ .../bridge/bars/TabletSystemBar.java | 7 ++ .../layoutlib/bridge/impl/ResourceHelper.java | 119 ++++++++++-------- .../tools/layoutlib/create/CreateInfo.java | 1 + 14 files changed, 253 insertions(+), 133 deletions(-) create mode 100644 tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png create mode 100644 tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png create mode 100644 tools/layoutlib/bridge/resources/bars/mdpi/status_bar_background.9.png diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml index cd99a096d07cb..51983f2d3ecec 100644 --- a/tools/layoutlib/bridge/resources/bars/action_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/action_bar.xml @@ -2,10 +2,8 @@ + android:layout_width="wrap_content"/> + android:layout_height="wrap_content"/> diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png b/tools/layoutlib/bridge/resources/bars/hdpi/stat_sys_wifi_signal_4_fully.png new file mode 100644 index 0000000000000000000000000000000000000000..bd44b529ee74a5915f7bc57d9c11adfcacf39c32 GIT binary patch literal 1195 zcmeAS@N?(olHy`uVBq!ia0vp^DnM+&!3HEN-EW8jDYhhUcNd2LAh=-f^2tCE&H|6f zVg?3oArNM~bhqvgNU*HHF&#*Q^)rO6JadbIfw|k$#W5t}@Y@-&c~=ZXTKBhzXe9A} zV9;T>7IH;Zv{X2U`6Cm*$DgigpVlj}Y$-{b)LFS9|Jjj3qr*P8mPc)xbm)lPzjI%| z`aakcyX|Zg+lI~I%qfx6QXk%5qkR2yhM$$g+_!J8YN)-C{I1)24 zuYUCk!)V#BmInGthS3g!>$G&_BYT2YHqDr1u#?kBF?=adUUTIPt{FFfsGU%|$Fz>| z`r%N|-qg7l4YgFc*|UUG7Iis1Gb?y4b7YB&Z=?FdeOib3A1zqdz^=?Ck+q(=L)&2< z*EN|Ryfyn29M?~f2z4x+R8`EF)YmxQs@$)dJL^BooEV0=*Y;T6eG=kn@9$OL*l!d* zS;DhpcK(7|t~XeIcv){V6HHD%^HDL-wKmS;dCaub zRWY2AVtcJO#mXGrSQ>>J#`SFoWmc0QA0Y(lc=gKy=Z%ht*? z?bhF*ZFbs|z4K#K$%6eA@d&XRrW zCr`ezj!!l=VPaL)$;N0V{SO;MF4P{r${HzH?_<8+wB^h?m4z%ze^{*iu=PwzXX&<2 zixmw&I=jBlm=`2-$LfVxL3(GX>W4Xvi=7@XpFUxYz^~U!w(Ib}JM6GYf5F^arWzha zla5Y$w@vZ`d%Q2-*6StN^Wv;db3}4^+%)5^eWCim`h)VK#bs9w=PqsX5x-mhQL^s4 z%p?92c2>cH`BNqx+%svxk-XI@O`LYj`+aPzj_%*+<2og3+7@oMvYEHULK#wL9QkxU z_<>}1(UBJaOm3}-E;BY|tDY8OUl&={R)5oaY4qbcZT~MvE$^IfXQeGDymV6s@#{g#xzzck8;Daeva6$@9aww=txL z@m_5FU*qpzbKXyOjn*o`=W~+l&EuoCt@-*eA$`4?aER?=i^E)JpY6zz-d-QdKDS0O zYZ((TkBXMKMwB=gr6!hS=I1GdWag$a80s4u>l+&WyST0#s6Z8@ASJOR)hZdJDwV;= zz|c_Fz);u7JjBq<%D~vl#7Nh`!pgwFb#hYISzQ2XkOA2coS#-w ro>-L1;Fyx1l&avCS(I9yUzA;};2dmPxb?9aP#uG(tDnm{r-UW|SsnPU literal 0 HcmV?d00001 diff --git a/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png b/tools/layoutlib/bridge/resources/bars/hdpi/status_bar_background.9.png new file mode 100644 index 0000000000000000000000000000000000000000..a4be298796632accec380d660b1ff1589d920515 GIT binary patch literal 3233 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 BM!En1 literal 0 HcmV?d00001 diff --git a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml index 29df90906fcf5..5211b0a9b6e04 100644 --- a/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/phone_system_bar.xml @@ -3,10 +3,11 @@ + android:layout_weight="1"/> + android:layout_width="wrap_content"/> + diff --git a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml index 8a3b87ae48c04..c5acddb6196ae 100644 --- a/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/tablet_system_bar.xml @@ -13,8 +13,12 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1"/> + + android:layout_marginLeft="3dip" + android:layout_marginRight="15dip"/> diff --git a/tools/layoutlib/bridge/resources/bars/title_bar.xml b/tools/layoutlib/bridge/resources/bars/title_bar.xml index 29fcc4b40b7f9..76d78d9169d46 100644 --- a/tools/layoutlib/bridge/resources/bars/title_bar.xml +++ b/tools/layoutlib/bridge/resources/bars/title_bar.xml @@ -2,6 +2,5 @@ + android:layout_height="wrap_content"/> diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java index 44b14dc46fb80..c4fffc86ae360 100644 --- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java @@ -40,6 +40,46 @@ import java.io.InputStream; */ /*package*/ class BitmapFactory_Delegate { + // ------ Java delegates ------ + + /*package*/ static Bitmap finishDecode(Bitmap bm, Rect outPadding, Options opts) { + if (bm == null || opts == null) { + return bm; + } + + final int density = opts.inDensity; + if (density == 0) { + return bm; + } + + bm.setDensity(density); + final int targetDensity = opts.inTargetDensity; + if (targetDensity == 0 || density == targetDensity || density == opts.inScreenDensity) { + return bm; + } + + byte[] np = bm.getNinePatchChunk(); + final boolean isNinePatch = np != null && NinePatch.isNinePatchChunk(np); + // DELEGATE CHANGE: never scale 9-patch + if (opts.inScaled && isNinePatch == false) { + float scale = targetDensity / (float)density; + // TODO: This is very inefficient and should be done in native by Skia + final Bitmap oldBitmap = bm; + bm = Bitmap.createScaledBitmap(oldBitmap, (int) (bm.getWidth() * scale + 0.5f), + (int) (bm.getHeight() * scale + 0.5f), true); + oldBitmap.recycle(); + + if (isNinePatch) { + np = nativeScaleNinePatch(np, scale, outPadding); + bm.setNinePatchChunk(np); + } + bm.setDensity(targetDensity); + } + + return bm; + } + + // ------ Native Delegates ------ /*package*/ static void nativeSetDefaultConfig(int nativeConfig) { @@ -107,7 +147,8 @@ import java.io.InputStream; } /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) { - // don't scale for now. + // don't scale for now. This should not be called anyway since we re-implement + // BitmapFactory.finishDecode(); return chunk; } diff --git a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java index 7a6da95dbb898..61ed71ee36a6e 100644 --- a/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java +++ b/tools/layoutlib/bridge/src/android/graphics/NinePatch_Delegate.java @@ -91,6 +91,50 @@ public final class NinePatch_Delegate { return array; } + /** + * 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. + */ + public static NinePatchChunk getChunk(byte[] array) { + SoftReference 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(chunk)); + } + } catch (IOException e) { + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Failed to deserialize NinePatchChunk content.", e, null /*data*/); + return null; + } catch (ClassNotFoundException e) { + Bridge.getLog().error(LayoutLog.TAG_BROKEN, + "Failed to deserialize NinePatchChunk class.", e, null /*data*/); + return null; + } finally { + if (ois != null) { + try { + ois.close(); + } catch (IOException e) { + } + } + } + } + + return chunk; + } + // ---- native methods ---- /*package*/ static boolean isNinePatchChunk(byte[] chunk) { @@ -173,47 +217,5 @@ public final class NinePatch_Delegate { // ---- 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 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(chunk)); - } - } catch (IOException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk content.", e, null /*data*/); - return null; - } catch (ClassNotFoundException e) { - Bridge.getLog().error(LayoutLog.TAG_BROKEN, - "Failed to deserialize NinePatchChunk class.", e, null /*data*/); - 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/bars/CustomBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java index f03999405592d..70c507c48b08b 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/CustomBar.java @@ -24,6 +24,7 @@ import com.android.layoutlib.bridge.android.BridgeContext; import com.android.layoutlib.bridge.android.BridgeXmlBlockParser; import com.android.layoutlib.bridge.impl.ResourceHelper; import com.android.resources.Density; +import com.android.resources.ResourceType; import org.kxml2.io.KXmlParser; import org.xmlpull.v1.XmlPullParser; @@ -36,6 +37,7 @@ import android.graphics.Bitmap_Delegate; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.TypedValue; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; @@ -62,6 +64,7 @@ abstract class CustomBar extends LinearLayout { throws XmlPullParserException { super(context); setOrientation(LinearLayout.HORIZONTAL); + setGravity(Gravity.CENTER_VERTICAL); setBackgroundColor(0xFF000000); LayoutInflater inflater = (LayoutInflater) getContext().getSystemService( @@ -79,33 +82,58 @@ abstract class CustomBar extends LinearLayout { inflater.inflate(bridgeParser, this, true); } + private InputStream getIcon(String iconName, Density[] densityInOut, String[] pathOut, + boolean tryOtherDensities) { + // current density + Density density = densityInOut[0]; + + // bitmap url relative to this class + pathOut[0] = "/bars/" + density.getResourceValue() + "/" + iconName; + + InputStream stream = getClass().getResourceAsStream(pathOut[0]); + if (stream == null && tryOtherDensities) { + for (Density d : Density.values()) { + if (d != density) { + densityInOut[0] = d; + stream = getIcon(iconName, densityInOut, pathOut, false /*tryOtherDensities*/); + if (stream != null) { + return stream; + } + } + } + } + + return stream; + } + protected void loadIcon(int index, String iconName, Density density) { View child = getChildAt(index); if (child instanceof ImageView) { ImageView imageView = (ImageView) child; - // bitmap url relative to this class - String path = "/bars/" + density.getResourceValue() + "/" + iconName; + String[] pathOut = new String[1]; + Density[] densityInOut = new Density[] { density }; + InputStream stream = getIcon(iconName, densityInOut, pathOut, + true /*tryOtherDensities*/); + density = densityInOut[0]; - // create a bitmap - Bitmap bitmap = Bridge.getCachedBitmap(path, true /*isFramework*/); - - if (bitmap == null) { - InputStream stream = getClass().getResourceAsStream(path); - - if (stream != null) { + if (stream != null) { + // look for a cached bitmap + Bitmap bitmap = Bridge.getCachedBitmap(pathOut[0], true /*isFramework*/); + if (bitmap == null) { try { bitmap = Bitmap_Delegate.createBitmap(stream, false /*isMutable*/, density); - Bridge.setCachedBitmap(path, bitmap, true /*isFramework*/); + Bridge.setCachedBitmap(pathOut[0], bitmap, true /*isFramework*/); } catch (IOException e) { return; } } - } - if (bitmap != null) { - BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), bitmap); - imageView.setBackgroundDrawable(drawable); + if (bitmap != null) { + BitmapDrawable drawable = new BitmapDrawable(getContext().getResources(), + bitmap); + imageView.setBackgroundDrawable(drawable); + } } } } @@ -113,19 +141,39 @@ abstract class CustomBar extends LinearLayout { protected void loadIcon(int index, String iconReference) { ResourceValue value = getResourceValue(iconReference); if (value != null) { - View child = getChildAt(index); - if (child instanceof ImageView) { - ImageView imageView = (ImageView) child; - - Drawable drawable = ResourceHelper.getDrawable( - value, (BridgeContext) mContext); - if (drawable != null) { - imageView.setBackgroundDrawable(drawable); - } - } + loadIcon(index, value); } } + protected Drawable loadIcon(int index, ResourceType type, String name) { + BridgeContext bridgeContext = (BridgeContext) mContext; + RenderResources res = bridgeContext.getRenderResources(); + + // find the resource + ResourceValue value = res.getFrameworkResource(type, name); + + // resolve it if needed + value = res.resolveResValue(value); + return loadIcon(index, value); + } + + private Drawable loadIcon(int index, ResourceValue value) { + View child = getChildAt(index); + if (child instanceof ImageView) { + ImageView imageView = (ImageView) child; + + Drawable drawable = ResourceHelper.getDrawable( + value, (BridgeContext) mContext); + if (drawable != null) { + imageView.setBackgroundDrawable(drawable); + } + + return drawable; + } + + return null; + } + protected TextView setText(int index, String stringReference) { View child = getChildAt(index); if (child instanceof TextView) { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java index 92615dc260d55..e3022b4198d4c 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/PhoneSystemBar.java @@ -17,10 +17,14 @@ package com.android.layoutlib.bridge.bars; import com.android.resources.Density; +import com.android.resources.ResourceType; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LevelListDrawable; +import android.view.Gravity; import android.widget.TextView; public class PhoneSystemBar extends CustomBar { @@ -28,11 +32,17 @@ public class PhoneSystemBar extends CustomBar { public PhoneSystemBar(Context context, Density density) throws XmlPullParserException { super(context, density, "/bars/tablet_system_bar.xml"); + setGravity(mGravity | Gravity.RIGHT); + // Cannot access the inside items through id because no R.id values have been // created for them. // We do know the order though. // 0 is the spacer loadIcon(1, "stat_sys_wifi_signal_4_fully.png", density); + Drawable drawable = loadIcon(2, ResourceType.DRAWABLE, "stat_sys_battery_charge"); + if (drawable instanceof LevelListDrawable) { + ((LevelListDrawable) drawable).setLevel(100); + } } @Override diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java index bc61799b3bd27..db1efdb145976 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/TabletSystemBar.java @@ -17,10 +17,13 @@ package com.android.layoutlib.bridge.bars; import com.android.resources.Density; +import com.android.resources.ResourceType; import org.xmlpull.v1.XmlPullParserException; import android.content.Context; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LevelListDrawable; import android.widget.TextView; public class TabletSystemBar extends CustomBar { @@ -36,6 +39,10 @@ public class TabletSystemBar extends CustomBar { loadIcon(2, "ic_sysbar_recent_default.png", density); // 3 is the spacer loadIcon(4, "stat_sys_wifi_signal_4_fully.png", density); + Drawable drawable = loadIcon(5, ResourceType.DRAWABLE, "stat_sys_battery_charge"); + if (drawable instanceof LevelListDrawable) { + ((LevelListDrawable) drawable).setLevel(100); + } } @Override 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 cea7cf360ce2a..19392a7d36344 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 @@ -43,8 +43,10 @@ import android.graphics.drawable.NinePatchDrawable; import android.util.TypedValue; import java.io.File; +import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -171,59 +173,24 @@ public final class ResourceHelper { String lowerCaseValue = stringValue.toLowerCase(); + Density density = Density.MEDIUM; + if (value instanceof DensityBasedResourceValue) { + density = + ((DensityBasedResourceValue)value).getResourceDensity(); + } + + if (lowerCaseValue.endsWith(NinePatch.EXTENSION_9PATCH)) { File file = new File(stringValue); if (file.isFile()) { - // see if we still have both the chunk and the bitmap in the caches - NinePatchChunk chunk = Bridge.getCached9Patch(stringValue, - value.isFramework() ? null : context.getProjectKey()); - Bitmap bitmap = Bridge.getCachedBitmap(stringValue, - value.isFramework() ? null : context.getProjectKey()); - - // if either chunk or bitmap is null, then we reload the 9-patch file. - if (chunk == null || bitmap == null) { - try { - NinePatch ninePatch = NinePatch.load(file.toURI().toURL(), - false /* convert */); - if (ninePatch != null) { - if (chunk == null) { - chunk = ninePatch.getChunk(); - - Bridge.setCached9Patch(stringValue, chunk, - value.isFramework() ? null : context.getProjectKey()); - } - - if (bitmap == null) { - Density density = Density.MEDIUM; - if (value instanceof DensityBasedResourceValue) { - density = - ((DensityBasedResourceValue)value).getResourceDensity(); - } - - bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), - false /*isMutable*/, - density); - - Bridge.setCachedBitmap(stringValue, bitmap, - value.isFramework() ? null : context.getProjectKey()); - } - } - } catch (MalformedURLException e) { - // URL is wrong, we'll return null below - } catch (IOException e) { - // failed to read the file, we'll return null below. - Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, - "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); - } - } - - 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); + try { + return getNinePatchDrawable( + new FileInputStream(file), density, value.isFramework(), + stringValue, context); + } catch (IOException e) { + // failed to read the file, we'll return null below. + Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ, + "Failed lot load " + file.getAbsolutePath(), e, null /*data*/); } } @@ -262,11 +229,6 @@ public final class ResourceHelper { value.isFramework() ? null : context.getProjectKey()); if (bitmap == null) { - Density density = Density.MEDIUM; - if (value instanceof DensityBasedResourceValue) { - density = ((DensityBasedResourceValue)value).getResourceDensity(); - } - bitmap = Bitmap_Delegate.createBitmap(bmpFile, false /*isMutable*/, density); Bridge.setCachedBitmap(stringValue, bitmap, @@ -296,6 +258,52 @@ public final class ResourceHelper { return null; } + private static Drawable getNinePatchDrawable(InputStream inputStream, Density density, + boolean isFramework, String cacheKey, BridgeContext context) throws IOException { + // see if we still have both the chunk and the bitmap in the caches + NinePatchChunk chunk = Bridge.getCached9Patch(cacheKey, + isFramework ? null : context.getProjectKey()); + Bitmap bitmap = Bridge.getCachedBitmap(cacheKey, + isFramework ? null : context.getProjectKey()); + + // if either chunk or bitmap is null, then we reload the 9-patch file. + if (chunk == null || bitmap == null) { + try { + NinePatch ninePatch = NinePatch.load(inputStream, true /*is9Patch*/, + false /* convert */); + if (ninePatch != null) { + if (chunk == null) { + chunk = ninePatch.getChunk(); + + Bridge.setCached9Patch(cacheKey, chunk, + isFramework ? null : context.getProjectKey()); + } + + if (bitmap == null) { + bitmap = Bitmap_Delegate.createBitmap(ninePatch.getImage(), + false /*isMutable*/, + density); + + Bridge.setCachedBitmap(cacheKey, bitmap, + isFramework ? null : context.getProjectKey()); + } + } + } catch (MalformedURLException e) { + // URL is wrong, we'll return null below + } + } + + 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); + } + + return null; + } // ------- TypedValue stuff // This is taken from //device/libs/utils/ResourceTypes.cpp @@ -458,3 +466,4 @@ public final class ResourceHelper { return false; } } + 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 fb215ab69015c..eff6bbc893b14 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 @@ -97,6 +97,7 @@ public final class CreateInfo implements ICreateInfo { "android.app.Fragment#instantiate", //(Landroid/content/Context;Ljava/lang/String;Landroid/os/Bundle;)Landroid/app/Fragment;", "android.content.res.Resources$Theme#obtainStyledAttributes", "android.content.res.Resources$Theme#resolveAttribute", + "android.graphics.BitmapFactory#finishDecode", "android.os.Handler#sendMessageAtTime", "android.os.Build#getString", "android.view.LayoutInflater#rInflate",