OSDN Git Service

LayoutLib: Replace custom BitmapFactory by a simpler delegate
authorXavier Ducrohet <xav@android.com>
Sat, 5 Feb 2011 00:40:49 +0000 (16:40 -0800)
committerXavier Ducrohet <xav@android.com>
Sat, 5 Feb 2011 00:40:49 +0000 (16:40 -0800)
Change-Id: Ie61a0a5b4426e64bb71a22d76d05efa4c0865e5e

tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java [deleted file]
tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java [new file with mode: 0644]
tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeResources.java
tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java

diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory.java
deleted file mode 100644 (file)
index ee60eb4..0000000
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * 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.ide.common.rendering.api.LayoutLog;
-import com.android.layoutlib.bridge.Bridge;
-import com.android.layoutlib.bridge.android.BridgeResources.NinePatchInputStream;
-import com.android.ninepatch.NinePatch;
-import com.android.ninepatch.NinePatchChunk;
-import com.android.resources.Density;
-
-import android.content.res.AssetManager;
-import android.content.res.Resources;
-import android.util.DisplayMetrics;
-import android.util.TypedValue;
-
-import java.io.BufferedInputStream;
-import java.io.FileDescriptor;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-
-/**
- * Creates Bitmap objects from various sources, including files, streams,
- * and byte-arrays.
- */
-public class BitmapFactory {
-    public static class Options {
-        /**
-         * Create a default Options object, which if left unchanged will give
-         * the same result from the decoder as if null were passed.
-         */
-        public Options() {
-            inDither = true;
-            inScaled = true;
-        }
-
-        /**
-         * If set to true, the decoder will return null (no bitmap), but
-         * the out... fields will still be set, allowing the caller to query
-         * the bitmap without having to allocate the memory for its pixels.
-         */
-        public boolean inJustDecodeBounds;
-
-        /**
-         * If set to a value > 1, requests the decoder to subsample the original
-         * image, returning a smaller image to save memory. The sample size is
-         * the number of pixels in either dimension that correspond to a single
-         * pixel in the decoded bitmap. For example, inSampleSize == 4 returns
-         * an image that is 1/4 the width/height of the original, and 1/16 the
-         * number of pixels. Any value <= 1 is treated the same as 1. Note: the
-         * decoder will try to fulfill this request, but the resulting bitmap
-         * may have different dimensions that precisely what has been requested.
-         * Also, powers of 2 are often faster/easier for the decoder to honor.
-         */
-        public int inSampleSize;
-
-        /**
-         * If this is non-null, the decoder will try to decode into this
-         * internal configuration. If it is null, or the request cannot be met,
-         * the decoder will try to pick the best matching config based on the
-         * system's screen depth, and characteristics of the original image such
-         * as if it has per-pixel alpha (requiring a config that also does).
-         */
-        public Bitmap.Config inPreferredConfig;
-
-        /**
-         * If dither is true, the decoder will attempt to dither the decoded
-         * image.
-         */
-        public boolean inDither;
-
-        /**
-         * The pixel density to use for the bitmap.  This will always result
-         * in the returned bitmap having a density set for it (see
-         * {@link Bitmap#setDensity(int) Bitmap.setDensity(int)).  In addition,
-         * if {@link #inScaled} is set (which it is by default} and this
-         * density does not match {@link #inTargetDensity}, then the bitmap
-         * will be scaled to the target density before being returned.
-         *
-         * <p>If this is 0,
-         * {@link BitmapFactory#decodeResource(Resources, int)},
-         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
-         * and {@link BitmapFactory#decodeResourceStream}
-         * will fill in the density associated with the resource.  The other
-         * functions will leave it as-is and no density will be applied.
-         *
-         * @see #inTargetDensity
-         * @see #inScreenDensity
-         * @see #inScaled
-         * @see Bitmap#setDensity(int)
-         * @see android.util.DisplayMetrics#densityDpi
-         */
-        public int inDensity;
-
-        /**
-         * The pixel density of the destination this bitmap will be drawn to.
-         * This is used in conjunction with {@link #inDensity} and
-         * {@link #inScaled} to determine if and how to scale the bitmap before
-         * returning it.
-         *
-         * <p>If this is 0,
-         * {@link BitmapFactory#decodeResource(Resources, int)},
-         * {@link BitmapFactory#decodeResource(Resources, int, android.graphics.BitmapFactory.Options)},
-         * and {@link BitmapFactory#decodeResourceStream}
-         * will fill in the density associated the Resources object's
-         * DisplayMetrics.  The other
-         * functions will leave it as-is and no scaling for density will be
-         * performed.
-         *
-         * @see #inDensity
-         * @see #inScreenDensity
-         * @see #inScaled
-         * @see android.util.DisplayMetrics#densityDpi
-         */
-        public int inTargetDensity;
-
-        /**
-         * The pixel density of the actual screen that is being used.  This is
-         * purely for applications running in density compatibility code, where
-         * {@link #inTargetDensity} is actually the density the application
-         * sees rather than the real screen density.
-         *
-         * <p>By setting this, you
-         * allow the loading code to avoid scaling a bitmap that is currently
-         * in the screen density up/down to the compatibility density.  Instead,
-         * if {@link #inDensity} is the same as {@link #inScreenDensity}, the
-         * bitmap will be left as-is.  Anything using the resulting bitmap
-         * must also used {@link Bitmap#getScaledWidth(int)
-         * Bitmap.getScaledWidth} and {@link Bitmap#getScaledHeight
-         * Bitmap.getScaledHeight} to account for any different between the
-         * bitmap's density and the target's density.
-         *
-         * <p>This is never set automatically for the caller by
-         * {@link BitmapFactory} itself.  It must be explicitly set, since the
-         * caller must deal with the resulting bitmap in a density-aware way.
-         *
-         * @see #inDensity
-         * @see #inTargetDensity
-         * @see #inScaled
-         * @see android.util.DisplayMetrics#densityDpi
-         */
-        public int inScreenDensity;
-
-        /**
-         * When this flag is set, if {@link #inDensity} and
-         * {@link #inTargetDensity} are not 0, the
-         * bitmap will be scaled to match {@link #inTargetDensity} when loaded,
-         * rather than relying on the graphics system scaling it each time it
-         * is drawn to a Canvas.
-         *
-         * <p>This flag is turned on by default and should be turned off if you need
-         * a non-scaled version of the bitmap.  Nine-patch bitmaps ignore this
-         * flag and are always scaled.
-         */
-        public boolean inScaled;
-
-        /**
-         * If this is set to true, then the resulting bitmap will allocate its
-         * pixels such that they can be purged if the system needs to reclaim
-         * memory. In that instance, when the pixels need to be accessed again
-         * (e.g. the bitmap is drawn, getPixels() is called), they will be
-         * automatically re-decoded.
-         *
-         * For the re-decode to happen, the bitmap must have access to the
-         * encoded data, either by sharing a reference to the input
-         * or by making a copy of it. This distinction is controlled by
-         * inInputShareable. If this is true, then the bitmap may keep a shallow
-         * reference to the input. If this is false, then the bitmap will
-         * explicitly make a copy of the input data, and keep that. Even if
-         * sharing is allowed, the implementation may still decide to make a
-         * deep copy of the input data.
-         */
-        public boolean inPurgeable;
-
-        /**
-         * This field works in conjuction with inPurgeable. If inPurgeable is
-         * false, then this field is ignored. If inPurgeable is true, then this
-         * field determines whether the bitmap can share a reference to the
-         * input data (inputstream, array, etc.) or if it must make a deep copy.
-         */
-        public boolean inInputShareable;
-
-        /**
-         * Normally bitmap allocations count against the dalvik heap, which
-         * means they help trigger GCs when a lot have been allocated. However,
-         * in rare cases, the caller may want to allocate the bitmap outside of
-         * that heap. To request that, set inNativeAlloc to true. In these
-         * rare instances, it is solely up to the caller to ensure that OOM is
-         * managed explicitly by calling bitmap.recycle() as soon as such a
-         * bitmap is no longer needed.
-         *
-         * @hide pending API council approval
-         */
-        public boolean inNativeAlloc;
-
-        /**
-         * The resulting width of the bitmap, set independent of the state of
-         * inJustDecodeBounds. However, if there is an error trying to decode,
-         * outWidth will be set to -1.
-         */
-        public int outWidth;
-
-        /**
-         * The resulting height of the bitmap, set independent of the state of
-         * inJustDecodeBounds. However, if there is an error trying to decode,
-         * outHeight will be set to -1.
-         */
-        public int outHeight;
-
-        /**
-         * If known, this string is set to the mimetype of the decoded image.
-         * If not know, or there is an error, it is set to null.
-         */
-        public String outMimeType;
-
-        /**
-         * Temp storage to use for decoding.  Suggest 16K or so.
-         */
-        public byte[] inTempStorage;
-
-        private native void requestCancel();
-
-        /**
-         * Flag to indicate that cancel has been called on this object.  This
-         * is useful if there's an intermediary that wants to first decode the
-         * bounds and then decode the image.  In that case the intermediary
-         * can check, inbetween the bounds decode and the image decode, to see
-         * if the operation is canceled.
-         */
-        public boolean mCancel;
-
-        /**
-         *  This can be called from another thread while this options object is
-         *  inside a decode... call. Calling this will notify the decoder that
-         *  it should cancel its operation. This is not guaranteed to cancel
-         *  the decode, but if it does, the decoder... operation will return
-         *  null, or if inJustDecodeBounds is true, will set outWidth/outHeight
-         *  to -1
-         */
-        public void requestCancelDecode() {
-            mCancel = true;
-            requestCancel();
-        }
-    }
-
-    /**
-     * Decode a file path into a bitmap. If the specified file name is null,
-     * or cannot be decoded into a bitmap, the function returns null.
-     *
-     * @param pathName complete path name for the file to be decoded.
-     * @param opts null-ok; Options that control downsampling and whether the
-     *             image should be completely decoded, or just is size returned.
-     * @return The decoded bitmap, or null if the image data could not be
-     *         decoded, or, if opts is non-null, if opts requested only the
-     *         size be returned (in opts.outWidth and opts.outHeight)
-     */
-    public static Bitmap decodeFile(String pathName, Options opts) {
-        Bitmap bm = null;
-        InputStream stream = null;
-        try {
-            stream = new FileInputStream(pathName);
-            bm = decodeStream(stream, null, opts);
-        } catch (Exception e) {
-            /*  do nothing.
-                If the exception happened on open, bm will be null.
-            */
-        } finally {
-            if (stream != null) {
-                try {
-                    stream.close();
-                } catch (IOException e) {
-                    // do nothing here
-                }
-            }
-        }
-        return bm;
-    }
-
-    /**
-     * Decode a file path into a bitmap. If the specified file name is null,
-     * or cannot be decoded into a bitmap, the function returns null.
-     *
-     * @param pathName complete path name for the file to be decoded.
-     * @return the resulting decoded bitmap, or null if it could not be decoded.
-     */
-    public static Bitmap decodeFile(String pathName) {
-        return decodeFile(pathName, null);
-    }
-
-    /**
-     * Decode a new Bitmap from an InputStream. This InputStream was obtained from
-     * resources, which we pass to be able to scale the bitmap accordingly.
-     */
-    public static Bitmap decodeResourceStream(Resources res, TypedValue value,
-            InputStream is, Rect pad, Options opts) {
-
-        if (opts == null) {
-            opts = new Options();
-        }
-
-        if (opts.inDensity == 0 && value != null) {
-            final int density = value.density;
-            if (density == TypedValue.DENSITY_DEFAULT) {
-                opts.inDensity = DisplayMetrics.DENSITY_DEFAULT;
-            } else if (density != TypedValue.DENSITY_NONE) {
-                opts.inDensity = density;
-            }
-        }
-
-        if (opts.inTargetDensity == 0 && res != null) {
-            opts.inTargetDensity = res.getDisplayMetrics().densityDpi;
-        }
-
-        return decodeStream(is, pad, opts);
-    }
-
-    /**
-     * Synonym for opening the given resource and calling
-     * {@link #decodeResourceStream}.
-     *
-     * @param res   The resources object containing the image data
-     * @param id The resource id of the image data
-     * @param opts null-ok; Options that control downsampling and whether the
-     *             image should be completely decoded, or just is size returned.
-     * @return The decoded bitmap, or null if the image data could not be
-     *         decoded, or, if opts is non-null, if opts requested only the
-     *         size be returned (in opts.outWidth and opts.outHeight)
-     */
-    public static Bitmap decodeResource(Resources res, int id, Options opts) {
-        Bitmap bm = null;
-        InputStream is = null;
-
-        try {
-            final TypedValue value = new TypedValue();
-            is = res.openRawResource(id, value);
-
-            bm = decodeResourceStream(res, value, is, null, opts);
-        } catch (Exception e) {
-            /*  do nothing.
-                If the exception happened on open, bm will be null.
-                If it happened on close, bm is still valid.
-            */
-            Bridge.getLog().error(LayoutLog.TAG_RESOURCES_READ,
-                    String.format("Error decoding bitmap of id 0x%x", id), e, null /*data*/);
-        } finally {
-            try {
-                if (is != null) is.close();
-            } catch (IOException e) {
-                // Ignore
-            }
-        }
-
-        return bm;
-    }
-
-    /**
-     * Synonym for {@link #decodeResource(Resources, int, android.graphics.BitmapFactory.Options)}
-     * will null Options.
-     *
-     * @param res The resources object containing the image data
-     * @param id The resource id of the image data
-     * @return The decoded bitmap, or null if the image could not be decode.
-     */
-    public static Bitmap decodeResource(Resources res, int id) {
-        return decodeResource(res, id, null);
-    }
-
-    /**
-     * Decode an immutable bitmap from the specified byte array.
-     *
-     * @param data byte array of compressed image data
-     * @param offset offset into imageData for where the decoder should begin
-     *               parsing.
-     * @param length the number of bytes, beginning at offset, to parse
-     * @param opts null-ok; Options that control downsampling and whether the
-     *             image should be completely decoded, or just is size returned.
-     * @return The decoded bitmap, or null if the image data could not be
-     *         decoded, or, if opts is non-null, if opts requested only the
-     *         size be returned (in opts.outWidth and opts.outHeight)
-     */
-    public static Bitmap decodeByteArray(byte[] data, int offset, int length, Options opts) {
-        if ((offset | length) < 0 || data.length < offset + length) {
-            throw new ArrayIndexOutOfBoundsException();
-        }
-
-        // FIXME: implement as needed, but it's unlikely that this is needed in the context of the bridge.
-        return null;
-        //return nativeDecodeByteArray(data, offset, length, opts);
-    }
-
-    /**
-     * Decode an immutable bitmap from the specified byte array.
-     *
-     * @param data byte array of compressed image data
-     * @param offset offset into imageData for where the decoder should begin
-     *               parsing.
-     * @param length the number of bytes, beginning at offset, to parse
-     * @return The decoded bitmap, or null if the image could not be decode.
-     */
-    public static Bitmap decodeByteArray(byte[] data, int offset, int length) {
-        return decodeByteArray(data, offset, length, null);
-    }
-
-    /**
-     * Decode an input stream into a bitmap. If the input stream is null, or
-     * cannot be used to decode a bitmap, the function returns null.
-     * The stream's position will be where ever it was after the encoded data
-     * was read.
-     *
-     * @param is The input stream that holds the raw data to be decoded into a
-     *           bitmap.
-     * @param outPadding If not null, return the padding rect for the bitmap if
-     *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If
-     *                   no bitmap is returned (null) then padding is
-     *                   unchanged.
-     * @param opts null-ok; Options that control downsampling and whether the
-     *             image should be completely decoded, or just is size returned.
-     * @return The decoded bitmap, or null if the image data could not be
-     *         decoded, or, if opts is non-null, if opts requested only the
-     *         size be returned (in opts.outWidth and opts.outHeight)
-     */
-    public static Bitmap decodeStream(InputStream is, Rect outPadding, Options opts) {
-        // we don't throw in this case, thus allowing the caller to only check
-        // the cache, and not force the image to be decoded.
-        if (is == null) {
-            return null;
-        }
-
-        boolean isNinePatch = is instanceof NinePatchInputStream;
-
-        // we need mark/reset to work properly
-
-        if (!is.markSupported()) {
-            is = new BufferedInputStream(is, 16 * 1024);
-        }
-
-        // so we can call reset() if a given codec gives up after reading up to
-        // this many bytes. FIXME: need to find out from the codecs what this
-        // value should be.
-        is.mark(1024);
-
-        Bitmap  bm;
-
-        if (is instanceof AssetManager.AssetInputStream) {
-            Bridge.getLog().error(LayoutLog.TAG_UNSUPPORTED,
-                    "Bitmap.decodeStream: " +
-                    "InputStream is unsupported (AssetManager.AssetInputStream)", null /*data*/);
-            return null;
-        } else {
-            // pass some temp storage down to the native code. 1024 is made up,
-            // but should be large enough to avoid too many small calls back
-            // into is.read(...) This number is not related to the value passed
-            // to mark(...) above.
-            try {
-                Density density = Density.MEDIUM;
-                if (opts != null) {
-                    density = Density.getEnum(opts.inDensity);
-                }
-
-                if (isNinePatch) {
-                    // load the bitmap as a nine patch
-                    NinePatch ninePatch = NinePatch.load(is, true /*is9Patch*/, false /*convert*/);
-
-                    // get the bitmap and chunk objects.
-                    bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
-                            density);
-                    NinePatchChunk chunk = ninePatch.getChunk();
-
-                    // put the chunk in the bitmap
-                    bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
-
-                    // read the padding
-                    int[] padding = chunk.getPadding();
-                    outPadding.left = padding[0];
-                    outPadding.top = padding[1];
-                    outPadding.right = padding[2];
-                    outPadding.bottom = padding[3];
-                } else {
-                    // load the bitmap directly.
-                    bm = Bitmap_Delegate.createBitmap(is, true, density);
-                }
-            } catch (IOException e) {
-                return null;
-            }
-        }
-
-        return finishDecode(bm, outPadding, opts);
-    }
-
-    private 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 = false; //np != null && NinePatch.isNinePatchChunk(np);
-        if (opts.inScaled || isNinePatch) {
-            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;
-    }
-
-    /**
-     * Decode an input stream into a bitmap. If the input stream is null, or
-     * cannot be used to decode a bitmap, the function returns null.
-     * The stream's position will be where ever it was after the encoded data
-     * was read.
-     *
-     * @param is The input stream that holds the raw data to be decoded into a
-     *           bitmap.
-     * @return The decoded bitmap, or null if the image data could not be
-     *         decoded, or, if opts is non-null, if opts requested only the
-     *         size be returned (in opts.outWidth and opts.outHeight)
-     */
-    public static Bitmap decodeStream(InputStream is) {
-        return decodeStream(is, null, null);
-    }
-
-    /**
-     * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
-     * return null. The position within the descriptor will not be changed when
-     * this returns, so the descriptor can be used again as-is.
-     *
-     * @param fd The file descriptor containing the bitmap data to decode
-     * @param outPadding If not null, return the padding rect for the bitmap if
-     *                   it exists, otherwise set padding to [-1,-1,-1,-1]. If
-     *                   no bitmap is returned (null) then padding is
-     *                   unchanged.
-     * @param opts null-ok; Options that control downsampling and whether the
-     *             image should be completely decoded, or just is size returned.
-     * @return the decoded bitmap, or null
-     */
-    public static Bitmap decodeFileDescriptor(FileDescriptor fd, Rect outPadding, Options opts) {
-        return null;
-
-        /* FIXME: implement as needed
-        try {
-            if (MemoryFile.isMemoryFile(fd)) {
-                int mappedlength = MemoryFile.getMappedSize(fd);
-                MemoryFile file = new MemoryFile(fd, mappedlength, "r");
-                InputStream is = file.getInputStream();
-                Bitmap bm = decodeStream(is, outPadding, opts);
-                return finishDecode(bm, outPadding, opts);
-            }
-        } catch (IOException ex) {
-            // invalid filedescriptor, no need to call nativeDecodeFileDescriptor()
-            return null;
-        }
-        //Bitmap bm = nativeDecodeFileDescriptor(fd, outPadding, opts);
-        //return finishDecode(bm, outPadding, opts);
-        */
-    }
-
-    /**
-     * Decode a bitmap from the file descriptor. If the bitmap cannot be decoded
-     * return null. The position within the descriptor will not be changed when
-     * this returns, so the descriptor can be used again as is.
-     *
-     * @param fd The file descriptor containing the bitmap data to decode
-     * @return the decoded bitmap, or null
-     */
-    public static Bitmap decodeFileDescriptor(FileDescriptor fd) {
-        return decodeFileDescriptor(fd, null, null);
-    }
-}
-
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
new file mode 100644 (file)
index 0000000..44b14dc
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2011 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.Bridge;
+import com.android.layoutlib.bridge.android.BridgeResources.NinePatchInputStream;
+import com.android.layoutlib.bridge.impl.DelegateManager;
+import com.android.ninepatch.NinePatchChunk;
+import com.android.resources.Density;
+
+import android.graphics.BitmapFactory.Options;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * Delegate implementing the native methods of android.graphics.BitmapFactory
+ *
+ * Through the layoutlib_create tool, the original native methods of BitmapFactory 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.
+ *
+ */
+/*package*/ class BitmapFactory_Delegate {
+
+    // ------ Native Delegates ------
+
+    /*package*/ static void nativeSetDefaultConfig(int nativeConfig) {
+        // pass
+    }
+
+    /*package*/ static Bitmap nativeDecodeStream(InputStream is, byte[] storage,
+            Rect padding, Options opts) {
+        Bitmap bm = null;
+
+        Density density = Density.MEDIUM;
+        if (opts != null) {
+            density = Density.getEnum(opts.inDensity);
+        }
+
+        try {
+            if (is instanceof NinePatchInputStream) {
+                NinePatchInputStream npis = (NinePatchInputStream) is;
+                npis.disableFakeMarkSupport();
+
+                // load the bitmap as a nine patch
+                com.android.ninepatch.NinePatch ninePatch = com.android.ninepatch.NinePatch.load(
+                        npis, true /*is9Patch*/, false /*convert*/);
+
+                // get the bitmap and chunk objects.
+                bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
+                        density);
+                NinePatchChunk chunk = ninePatch.getChunk();
+
+                // put the chunk in the bitmap
+                bm.setNinePatchChunk(NinePatch_Delegate.serialize(chunk));
+
+                // read the padding
+                int[] paddingarray = chunk.getPadding();
+                padding.left = paddingarray[0];
+                padding.top = paddingarray[1];
+                padding.right = paddingarray[2];
+                padding.bottom = paddingarray[3];
+            } else {
+                // load the bitmap directly.
+                bm = Bitmap_Delegate.createBitmap(is, true, density);
+            }
+        } catch (IOException e) {
+            Bridge.getLog().error(null,"Failed to load image" , e, null);
+        }
+
+        return bm;
+    }
+
+    /*package*/ static Bitmap nativeDecodeFileDescriptor(FileDescriptor fd,
+            Rect padding, Options opts) {
+        opts.inBitmap = null;
+        return null;
+    }
+
+    /*package*/ static Bitmap nativeDecodeAsset(int asset, Rect padding, Options opts) {
+        opts.inBitmap = null;
+        return null;
+    }
+
+    /*package*/ static Bitmap nativeDecodeByteArray(byte[] data, int offset,
+            int length, Options opts) {
+        opts.inBitmap = null;
+        return null;
+    }
+
+    /*package*/ static byte[] nativeScaleNinePatch(byte[] chunk, float scale, Rect pad) {
+        // don't scale for now.
+        return chunk;
+    }
+
+    /*package*/ static boolean nativeIsSeekable(FileDescriptor fd) {
+        return true;
+    }
+}
index efe6955..3e80614 100644 (file)
@@ -21,6 +21,7 @@ import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.impl.DelegateManager;
 import com.android.resources.Density;
 
+import android.graphics.Bitmap;
 import android.graphics.Bitmap.Config;
 import android.os.Parcel;
 
index d31fcc8..5e5aeb1 100644 (file)
@@ -65,9 +65,26 @@ public final class BridgeResources extends Resources {
      * to know whether this is 9-patch or not, such as BitmapFactory.
      */
     public class NinePatchInputStream extends FileInputStream {
+        private boolean mFakeMarkSupport = true;
         public NinePatchInputStream(File file) throws FileNotFoundException {
             super(file);
         }
+
+        @Override
+        public boolean markSupported() {
+            if (mFakeMarkSupport) {
+                // this is needed so that BitmapFactory doesn't wrap this in a BufferedInputStream.
+                return true;
+            }
+
+            return super.markSupported();
+        }
+
+        public void disableFakeMarkSupport() {
+            // disable fake mark support so that in case codec actually try to use them
+            // we don't lie to them.
+            mFakeMarkSupport = false;
+        }
     }
 
     /**
index 291f076..fb215ab 100644 (file)
@@ -112,6 +112,7 @@ public final class CreateInfo implements ICreateInfo {
         "android.animation.PropertyValuesHolder",
         "android.graphics.AvoidXfermode",
         "android.graphics.Bitmap",
+        "android.graphics.BitmapFactory",
         "android.graphics.BitmapShader",
         "android.graphics.BlurMaskFilter",
         "android.graphics.Canvas",
@@ -164,7 +165,6 @@ public final class CreateInfo implements ICreateInfo {
      */
     private final static String[] RENAMED_CLASSES =
         new String[] {
-            "android.graphics.BitmapFactory",       "android.graphics._Original_BitmapFactory",
             "android.os.ServiceManager",            "android.os._Original_ServiceManager",
             "android.view.SurfaceView",             "android.view._Original_SurfaceView",
             "android.view.accessibility.AccessibilityManager", "android.view.accessibility._Original_AccessibilityManager",