diff options
Diffstat (limited to 'graphics/java/android')
| -rw-r--r-- | graphics/java/android/graphics/Atlas.java | 39 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Bitmap.java | 105 | ||||
| -rw-r--r-- | graphics/java/android/graphics/BitmapShader.java | 5 | ||||
| -rw-r--r-- | graphics/java/android/graphics/Canvas.java | 22 | ||||
| -rw-r--r-- | graphics/java/android/graphics/NinePatch.java | 16 | ||||
| -rw-r--r-- | graphics/java/android/graphics/drawable/DrawableContainer.java | 4 | ||||
| -rw-r--r-- | graphics/java/android/graphics/drawable/Icon.java | 482 | ||||
| -rw-r--r-- | graphics/java/android/graphics/drawable/RippleDrawable.java | 7 | ||||
| -rw-r--r-- | graphics/java/android/graphics/pdf/PdfRenderer.java | 4 |
9 files changed, 578 insertions, 106 deletions
diff --git a/graphics/java/android/graphics/Atlas.java b/graphics/java/android/graphics/Atlas.java index 39a5a53..e0a5345 100644 --- a/graphics/java/android/graphics/Atlas.java +++ b/graphics/java/android/graphics/Atlas.java @@ -21,10 +21,12 @@ package android.graphics; */ public class Atlas { /** - * This flag indicates whether the packing algorithm will attempt - * to rotate entries to make them fit better in the atlas. + * WARNING: These flag values are part of the on-disk configuration information, + * do not change their values. */ - public static final int FLAG_ALLOW_ROTATIONS = 0x1; + + /** DELETED: FLAG_ROTATION = 0x01 */ + /** * This flag indicates whether the packing algorithm should leave * an empty 1 pixel wide border around each bitmap. This border can @@ -52,9 +54,7 @@ public class Atlas { /** * Represents a bitmap packed in the atlas. Each entry has a location in - * pixels in the atlas and a rotation flag. If the entry was rotated, the - * bitmap must be rotated by 90 degrees (in either direction as long as - * the origin remains the same) before being rendered into the atlas. + * pixels in the atlas and a rotation flag. */ public static class Entry { /** @@ -65,11 +65,6 @@ public class Atlas { * Location, in pixels, of the bitmap on the Y axis in the atlas. */ public int y; - - /** - * If true, the bitmap must be rotated 90 degrees in the atlas. - */ - public boolean rotated; } private final Policy mPolicy; @@ -239,7 +234,6 @@ public class Atlas { private final SplitDecision mSplitDecision; - private final boolean mAllowRotation; private final int mPadding; /** @@ -263,7 +257,6 @@ public class Atlas { } SlicePolicy(int width, int height, int flags, SplitDecision splitDecision) { - mAllowRotation = (flags & FLAG_ALLOW_ROTATIONS) != 0; mPadding = (flags & FLAG_ADD_PADDING) != 0 ? 1 : 0; // The entire atlas is empty at first, minus padding @@ -360,26 +353,9 @@ public class Atlas { * * @return True if the rectangle was packed in the atlas, false otherwise */ - @SuppressWarnings("SuspiciousNameCombination") private boolean insert(Cell cell, Cell prev, int width, int height, Entry entry) { - boolean rotated = false; - - // If the rectangle doesn't fit we'll try to rotate it - // if possible before giving up if (cell.width < width || cell.height < height) { - if (mAllowRotation) { - if (cell.width < height || cell.height < width) { - return false; - } - - // Rotate the rectangle - int temp = width; - width = height; - height = temp; - rotated = true; - } else { - return false; - } + return false; } // Remaining free space after packing the rectangle @@ -433,7 +409,6 @@ public class Atlas { // Return the location and rotation of the packed rectangle entry.x = cell.x; entry.y = cell.y; - entry.rotated = rotated; return true; } diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java index e2f7799..bd52848 100644 --- a/graphics/java/android/graphics/Bitmap.java +++ b/graphics/java/android/graphics/Bitmap.java @@ -41,13 +41,13 @@ public final class Bitmap implements Parcelable { */ public static final int DENSITY_NONE = 0; - private final long mSkBitmapPtr; - /** * Backing buffer for the Bitmap. */ private byte[] mBuffer; + // Convenience for JNI access + private final long mNativePtr; private final BitmapFinalizer mFinalizer; private final boolean mIsMutable; @@ -115,17 +115,16 @@ public final class Bitmap implements Parcelable { mRequestPremultiplied = requestPremultiplied; mBuffer = buffer; - // we delete this in our finalizer - mSkBitmapPtr = nativeBitmap; - mNinePatchChunk = ninePatchChunk; mNinePatchInsets = ninePatchInsets; if (density >= 0) { mDensity = density; } - int nativeAllocationByteCount = buffer == null ? getByteCount() : 0; - mFinalizer = new BitmapFinalizer(nativeBitmap, nativeAllocationByteCount); + mNativePtr = nativeBitmap; + mFinalizer = new BitmapFinalizer(nativeBitmap); + int nativeAllocationByteCount = (buffer == null ? getByteCount() : 0); + mFinalizer.setNativeAllocationByteCount(nativeAllocationByteCount); } /** @@ -223,8 +222,8 @@ public final class Bitmap implements Parcelable { throw new IllegalStateException("native-backed bitmaps may not be reconfigured"); } - nativeReconfigure(mSkBitmapPtr, width, height, config.nativeInt, mBuffer.length, - mRequestPremultiplied); + nativeReconfigure(mFinalizer.mNativeBitmap, width, height, config.nativeInt, + mBuffer.length, mRequestPremultiplied); mWidth = width; mHeight = height; } @@ -301,7 +300,7 @@ public final class Bitmap implements Parcelable { */ public void recycle() { if (!mRecycled && mFinalizer.mNativeBitmap != 0) { - if (nativeRecycle(mSkBitmapPtr)) { + if (nativeRecycle(mFinalizer.mNativeBitmap)) { // return value indicates whether native pixel object was actually recycled. // false indicates that it is still in use at the native level and these // objects should not be collected now. They will be collected later when the @@ -331,7 +330,8 @@ public final class Bitmap implements Parcelable { * @return The current generation ID for this bitmap. */ public int getGenerationId() { - return nativeGenerationId(mSkBitmapPtr); + if (mRecycled) return 0; + return nativeGenerationId(mFinalizer.mNativeBitmap); } /** @@ -487,7 +487,7 @@ public final class Bitmap implements Parcelable { throw new RuntimeException("Buffer not large enough for pixels"); } - nativeCopyPixelsToBuffer(mSkBitmapPtr, dst); + nativeCopyPixelsToBuffer(mFinalizer.mNativeBitmap, dst); // now update the buffer's position int position = dst.position(); @@ -527,7 +527,7 @@ public final class Bitmap implements Parcelable { throw new RuntimeException("Buffer not large enough for pixels"); } - nativeCopyPixelsFromBuffer(mSkBitmapPtr, src); + nativeCopyPixelsFromBuffer(mFinalizer.mNativeBitmap, src); // now update the buffer's position int position = src.position(); @@ -549,7 +549,7 @@ public final class Bitmap implements Parcelable { */ public Bitmap copy(Config config, boolean isMutable) { checkRecycled("Can't copy a recycled bitmap"); - Bitmap b = nativeCopy(mSkBitmapPtr, config.nativeInt, isMutable); + Bitmap b = nativeCopy(mFinalizer.mNativeBitmap, config.nativeInt, isMutable); if (b != null) { b.setPremultiplied(mRequestPremultiplied); b.mDensity = mDensity; @@ -810,7 +810,7 @@ public final class Bitmap implements Parcelable { } bm.setHasAlpha(hasAlpha); if (config == Config.ARGB_8888 && !hasAlpha) { - nativeErase(bm.mSkBitmapPtr, 0xff000000); + nativeErase(bm.mFinalizer.mNativeBitmap, 0xff000000); } // No need to initialize the bitmap to zeroes with other configs; // it is backed by a VM byte array which is by definition preinitialized @@ -1000,8 +1000,8 @@ public final class Bitmap implements Parcelable { throw new IllegalArgumentException("quality must be 0..100"); } Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "Bitmap.compress"); - boolean result = nativeCompress(mSkBitmapPtr, format.nativeInt, quality, - stream, new byte[WORKING_COMPRESS_STORAGE]); + boolean result = nativeCompress(mFinalizer.mNativeBitmap, format.nativeInt, + quality, stream, new byte[WORKING_COMPRESS_STORAGE]); Trace.traceEnd(Trace.TRACE_TAG_RESOURCES); return result; } @@ -1041,7 +1041,8 @@ public final class Bitmap implements Parcelable { * @see BitmapFactory.Options#inPremultiplied */ public final boolean isPremultiplied() { - return nativeIsPremultiplied(mSkBitmapPtr); + if (mRecycled) return false; + return nativeIsPremultiplied(mFinalizer.mNativeBitmap); } /** @@ -1065,8 +1066,9 @@ public final class Bitmap implements Parcelable { * @see BitmapFactory.Options#inPremultiplied */ public final void setPremultiplied(boolean premultiplied) { + checkRecycled("setPremultiplied called on a recycled bitmap"); mRequestPremultiplied = premultiplied; - nativeSetPremultiplied(mSkBitmapPtr, premultiplied); + nativeSetPremultiplied(mFinalizer.mNativeBitmap, premultiplied); } /** Returns the bitmap's width */ @@ -1158,7 +1160,7 @@ public final class Bitmap implements Parcelable { * @return number of bytes between rows of the native bitmap pixels. */ public final int getRowBytes() { - return nativeRowBytes(mSkBitmapPtr); + return nativeRowBytes(mFinalizer.mNativeBitmap); } /** @@ -1201,7 +1203,8 @@ public final class Bitmap implements Parcelable { * that config, otherwise return null. */ public final Config getConfig() { - return Config.nativeToConfig(nativeConfig(mSkBitmapPtr)); + if (mRecycled) return Config.ARGB_8888; + return Config.nativeToConfig(nativeConfig(mFinalizer.mNativeBitmap)); } /** Returns true if the bitmap's config supports per-pixel alpha, and @@ -1213,7 +1216,8 @@ public final class Bitmap implements Parcelable { * it will return true by default. */ public final boolean hasAlpha() { - return nativeHasAlpha(mSkBitmapPtr); + if (mRecycled) return false; + return nativeHasAlpha(mFinalizer.mNativeBitmap); } /** @@ -1227,7 +1231,8 @@ public final class Bitmap implements Parcelable { * non-opaque per-pixel alpha values. */ public void setHasAlpha(boolean hasAlpha) { - nativeSetHasAlpha(mSkBitmapPtr, hasAlpha, mRequestPremultiplied); + checkRecycled("setHasAlpha called on a recycled bitmap"); + nativeSetHasAlpha(mFinalizer.mNativeBitmap, hasAlpha, mRequestPremultiplied); } /** @@ -1248,7 +1253,8 @@ public final class Bitmap implements Parcelable { * @see #setHasMipMap(boolean) */ public final boolean hasMipMap() { - return nativeHasMipMap(mSkBitmapPtr); + if (mRecycled) return false; + return nativeHasMipMap(mFinalizer.mNativeBitmap); } /** @@ -1272,7 +1278,8 @@ public final class Bitmap implements Parcelable { * @see #hasMipMap() */ public final void setHasMipMap(boolean hasMipMap) { - nativeSetHasMipMap(mSkBitmapPtr, hasMipMap); + checkRecycled("setHasMipMap called on a recycled bitmap"); + nativeSetHasMipMap(mFinalizer.mNativeBitmap, hasMipMap); } /** @@ -1285,7 +1292,7 @@ public final class Bitmap implements Parcelable { if (!isMutable()) { throw new IllegalStateException("cannot erase immutable bitmaps"); } - nativeErase(mSkBitmapPtr, c); + nativeErase(mFinalizer.mNativeBitmap, c); } /** @@ -1302,7 +1309,7 @@ public final class Bitmap implements Parcelable { public int getPixel(int x, int y) { checkRecycled("Can't call getPixel() on a recycled bitmap"); checkPixelAccess(x, y); - return nativeGetPixel(mSkBitmapPtr, x, y); + return nativeGetPixel(mFinalizer.mNativeBitmap, x, y); } /** @@ -1335,7 +1342,7 @@ public final class Bitmap implements Parcelable { return; // nothing to do } checkPixelsAccess(x, y, width, height, offset, stride, pixels); - nativeGetPixels(mSkBitmapPtr, pixels, offset, stride, + nativeGetPixels(mFinalizer.mNativeBitmap, pixels, offset, stride, x, y, width, height); } @@ -1416,7 +1423,7 @@ public final class Bitmap implements Parcelable { throw new IllegalStateException(); } checkPixelAccess(x, y); - nativeSetPixel(mSkBitmapPtr, x, y, color); + nativeSetPixel(mFinalizer.mNativeBitmap, x, y, color); } /** @@ -1452,7 +1459,7 @@ public final class Bitmap implements Parcelable { return; // nothing to do } checkPixelsAccess(x, y, width, height, offset, stride, pixels); - nativeSetPixels(mSkBitmapPtr, pixels, offset, stride, + nativeSetPixels(mFinalizer.mNativeBitmap, pixels, offset, stride, x, y, width, height); } @@ -1490,7 +1497,7 @@ public final class Bitmap implements Parcelable { */ public void writeToParcel(Parcel p, int flags) { checkRecycled("Can't parcel a recycled bitmap"); - if (!nativeWriteToParcel(mSkBitmapPtr, mIsMutable, mDensity, p)) { + if (!nativeWriteToParcel(mFinalizer.mNativeBitmap, mIsMutable, mDensity, p)) { throw new RuntimeException("native writeToParcel failed"); } } @@ -1536,7 +1543,7 @@ public final class Bitmap implements Parcelable { public Bitmap extractAlpha(Paint paint, int[] offsetXY) { checkRecycled("Can't extractAlpha on a recycled bitmap"); long nativePaint = paint != null ? paint.getNativeInstance() : 0; - Bitmap bm = nativeExtractAlpha(mSkBitmapPtr, nativePaint, offsetXY); + Bitmap bm = nativeExtractAlpha(mFinalizer.mNativeBitmap, nativePaint, offsetXY); if (bm == null) { throw new RuntimeException("Failed to extractAlpha on Bitmap"); } @@ -1550,7 +1557,8 @@ public final class Bitmap implements Parcelable { * If other is null, return false. */ public boolean sameAs(Bitmap other) { - return this == other || (other != null && nativeSameAs(mSkBitmapPtr, other.mSkBitmapPtr)); + return this == other || (other != null + && nativeSameAs(mFinalizer.mNativeBitmap, other.mFinalizer.mNativeBitmap)); } /** @@ -1565,12 +1573,18 @@ public final class Bitmap implements Parcelable { * and therefore is harmless. */ public void prepareToDraw() { - nativePrepareToDraw(mSkBitmapPtr); + // TODO: Consider having this start an async upload? + // With inPurgeable no-op'd there's currently no use for this + // method, but it could have interesting future uses. } - /** @hide */ - public final long getSkBitmap() { - return mSkBitmapPtr; + /** + * Refs the underlying SkPixelRef and returns a pointer to it. + * + * @hide + * */ + public final long refSkPixelRef() { + return nativeRefPixelRef(mNativePtr); } private static class BitmapFinalizer { @@ -1578,12 +1592,17 @@ public final class Bitmap implements Parcelable { // Native memory allocated for the duration of the Bitmap, // if pixel data allocated into native memory, instead of java byte[] - private final int mNativeAllocationByteCount; + private int mNativeAllocationByteCount; - BitmapFinalizer(long nativeBitmap, int nativeAllocationByteCount) { + BitmapFinalizer(long nativeBitmap) { mNativeBitmap = nativeBitmap; - mNativeAllocationByteCount = nativeAllocationByteCount; + } + public void setNativeAllocationByteCount(int nativeByteCount) { + if (mNativeAllocationByteCount != 0) { + VMRuntime.getRuntime().registerNativeFree(mNativeAllocationByteCount); + } + mNativeAllocationByteCount = nativeByteCount; if (mNativeAllocationByteCount != 0) { VMRuntime.getRuntime().registerNativeAllocation(mNativeAllocationByteCount); } @@ -1596,9 +1615,7 @@ public final class Bitmap implements Parcelable { } catch (Throwable t) { // Ignore } finally { - if (mNativeAllocationByteCount != 0) { - VMRuntime.getRuntime().registerNativeFree(mNativeAllocationByteCount); - } + setNativeAllocationByteCount(0); nativeDestructor(mNativeBitmap); mNativeBitmap = 0; } @@ -1650,7 +1667,6 @@ public final class Bitmap implements Parcelable { long nativePaint, int[] offsetXY); - private static native void nativePrepareToDraw(long nativeBitmap); private static native boolean nativeHasAlpha(long nativeBitmap); private static native boolean nativeIsPremultiplied(long nativeBitmap); private static native void nativeSetPremultiplied(long nativeBitmap, @@ -1661,4 +1677,5 @@ public final class Bitmap implements Parcelable { private static native boolean nativeHasMipMap(long nativeBitmap); private static native void nativeSetHasMipMap(long nativeBitmap, boolean hasMipMap); private static native boolean nativeSameAs(long nativeBitmap0, long nativeBitmap1); + private static native long nativeRefPixelRef(long nativeBitmap); } diff --git a/graphics/java/android/graphics/BitmapShader.java b/graphics/java/android/graphics/BitmapShader.java index f2f890e..bd74bc8 100644 --- a/graphics/java/android/graphics/BitmapShader.java +++ b/graphics/java/android/graphics/BitmapShader.java @@ -42,8 +42,7 @@ public class BitmapShader extends Shader { mBitmap = bitmap; mTileX = tileX; mTileY = tileY; - final long b = bitmap.getSkBitmap(); - init(nativeCreate(b, tileX.nativeInt, tileY.nativeInt)); + init(nativeCreate(bitmap, tileX.nativeInt, tileY.nativeInt)); } /** @@ -56,6 +55,6 @@ public class BitmapShader extends Shader { return copy; } - private static native long nativeCreate(long native_bitmap, int shaderTileModeX, + private static native long nativeCreate(Bitmap bitmap, int shaderTileModeX, int shaderTileModeY); } diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java index 9fe8e0c..392a5b6 100644 --- a/graphics/java/android/graphics/Canvas.java +++ b/graphics/java/android/graphics/Canvas.java @@ -81,10 +81,6 @@ public class Canvas { */ protected int mScreenDensity = Bitmap.DENSITY_NONE; - // Used by native code - @SuppressWarnings("UnusedDeclaration") - private int mSurfaceFormat; - // Maximum bitmap size as defined in Skia's native code // (see SkCanvas.cpp, SkDraw.cpp) private static final int MAXMIMUM_BITMAP_SIZE = 32766; @@ -1327,7 +1323,7 @@ public class Canvas { */ public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) { throwIfCannotDraw(bitmap); - native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, + native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity); } @@ -1373,7 +1369,7 @@ public class Canvas { bottom = src.bottom; } - native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom, + native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -1420,7 +1416,7 @@ public class Canvas { bottom = src.bottom; } - native_drawBitmap(mNativeCanvasWrapper, bitmap.getSkBitmap(), left, top, right, bottom, + native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom, dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity, bitmap.mDensity); } @@ -1501,7 +1497,7 @@ public class Canvas { * @param paint May be null. The paint used to draw the bitmap */ public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) { - nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.getSkBitmap(), matrix.ni(), + nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(), paint != null ? paint.getNativeInstance() : 0); } @@ -1556,7 +1552,7 @@ public class Canvas { // no mul by 2, since we need only 1 color per vertex checkRange(colors.length, colorOffset, count); } - nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap.getSkBitmap(), meshWidth, meshHeight, + nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset, paint != null ? paint.getNativeInstance() : 0); } @@ -2066,13 +2062,13 @@ public class Canvas { private static native void native_drawPath(long nativeCanvas, long nativePath, long nativePaint); - private native void native_drawBitmap(long nativeCanvas, long nativeBitmap, + private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top, long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity); - private native void native_drawBitmap(long nativeCanvas, long nativeBitmap, + private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity); @@ -2082,11 +2078,11 @@ public class Canvas { boolean hasAlpha, long nativePaintOrZero); private static native void nativeDrawBitmapMatrix(long nativeCanvas, - long nativeBitmap, + Bitmap bitmap, long nativeMatrix, long nativePaint); private static native void nativeDrawBitmapMesh(long nativeCanvas, - long nativeBitmap, + Bitmap bitmap, int meshWidth, int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset, diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java index 9c4299a..21a212a 100644 --- a/graphics/java/android/graphics/NinePatch.java +++ b/graphics/java/android/graphics/NinePatch.java @@ -98,7 +98,7 @@ public class NinePatch { public NinePatch(Bitmap bitmap, byte[] chunk, String srcName) { mBitmap = bitmap; mSrcName = srcName; - mNativeChunk = validateNinePatchChunk(mBitmap.getSkBitmap(), chunk); + mNativeChunk = validateNinePatchChunk(chunk); } /** @@ -199,12 +199,12 @@ public class NinePatch { } void drawSoftware(Canvas canvas, RectF location, Paint paint) { - nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk, + nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk, paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity); } void drawSoftware(Canvas canvas, Rect location, Paint paint) { - nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.getSkBitmap(), mNativeChunk, + nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap, mNativeChunk, paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity); } @@ -252,7 +252,7 @@ public class NinePatch { * that are transparent. */ public final Region getTransparentRegion(Rect bounds) { - long r = nativeGetTransparentRegion(mBitmap.getSkBitmap(), mNativeChunk, bounds); + long r = nativeGetTransparentRegion(mBitmap, mNativeChunk, bounds); return r != 0 ? new Region(r) : null; } @@ -271,11 +271,11 @@ public class NinePatch { * If validation is successful, this method returns a native Res_png_9patch* * object used by the renderers. */ - private static native long validateNinePatchChunk(long bitmap, byte[] chunk); + private static native long validateNinePatchChunk(byte[] chunk); private static native void nativeFinalize(long chunk); - private static native void nativeDraw(long canvas_instance, RectF loc, long bitmap_instance, + private static native void nativeDraw(long canvas_instance, RectF loc, Bitmap bitmap_instance, long c, long paint_instance_or_null, int destDensity, int srcDensity); - private static native void nativeDraw(long canvas_instance, Rect loc, long bitmap_instance, + private static native void nativeDraw(long canvas_instance, Rect loc, Bitmap bitmap_instance, long c, long paint_instance_or_null, int destDensity, int srcDensity); - private static native long nativeGetTransparentRegion(long bitmap, long chunk, Rect location); + private static native long nativeGetTransparentRegion(Bitmap bitmap, long chunk, Rect location); } diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java index b03fe3a..4a06805 100644 --- a/graphics/java/android/graphics/drawable/DrawableContainer.java +++ b/graphics/java/android/graphics/drawable/DrawableContainer.java @@ -295,9 +295,9 @@ public class DrawableContainer extends Drawable implements Drawable.Callback { @Override public void setHotspotBounds(int left, int top, int right, int bottom) { if (mHotspotBounds == null) { - mHotspotBounds = new Rect(left, top, bottom, right); + mHotspotBounds = new Rect(left, top, right, bottom); } else { - mHotspotBounds.set(left, top, bottom, right); + mHotspotBounds.set(left, top, right, bottom); } if (mCurrDrawable != null) { diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java new file mode 100644 index 0000000..47a1f77 --- /dev/null +++ b/graphics/java/android/graphics/drawable/Icon.java @@ -0,0 +1,482 @@ +/* + * Copyright (C) 2015 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.drawable; + +import android.annotation.DrawableRes; +import android.content.ContentResolver; +import android.content.pm.PackageManager; +import android.content.res.Resources; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Handler; +import android.os.Message; +import android.os.Parcel; +import android.os.Parcelable; +import android.util.Log; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.lang.IllegalArgumentException; +import java.lang.Override; + +/** + * An umbrella container for several serializable graphics representations, including Bitmaps, + * compressed bitmap images (e.g. JPG or PNG), and drawable resources (including vectors). + * + * <a href="https://developer.android.com/training/displaying-bitmaps/index.html">Much ink</a> + * has been spilled on the best way to load images, and many clients may have different needs when + * it comes to threading and fetching. This class is therefore focused on encapsulation rather than + * behavior. + */ + +public final class Icon implements Parcelable { + private static final String TAG = "Icon"; + + private static final int TYPE_BITMAP = 1; + private static final int TYPE_RESOURCE = 2; + private static final int TYPE_DATA = 3; + private static final int TYPE_URI = 4; + + private final int mType; + + // To avoid adding unnecessary overhead, we have a few basic objects that get repurposed + // based on the value of mType. + + // TYPE_BITMAP: Bitmap + // TYPE_RESOURCE: Resources + // TYPE_DATA: DataBytes + private Object mObj1; + + // TYPE_RESOURCE: package name + // TYPE_URI: uri string + private String mString1; + + // TYPE_RESOURCE: resId + // TYPE_DATA: data length + private int mInt1; + + // TYPE_DATA: data offset + private int mInt2; + + // Internal accessors for different mType variants + private Bitmap getBitmap() { + if (mType != TYPE_BITMAP) { + throw new IllegalStateException("called getBitmap() on " + this); + } + return (Bitmap) mObj1; + } + + private int getDataLength() { + if (mType != TYPE_DATA) { + throw new IllegalStateException("called getDataLength() on " + this); + } + synchronized (this) { + return mInt1; + } + } + + private int getDataOffset() { + if (mType != TYPE_DATA) { + throw new IllegalStateException("called getDataOffset() on " + this); + } + synchronized (this) { + return mInt2; + } + } + + private byte[] getDataBytes() { + if (mType != TYPE_DATA) { + throw new IllegalStateException("called getDataBytes() on " + this); + } + synchronized (this) { + return (byte[]) mObj1; + } + } + + private Resources getResources() { + if (mType != TYPE_RESOURCE) { + throw new IllegalStateException("called getResources() on " + this); + } + return (Resources) mObj1; + } + + private String getResPackage() { + if (mType != TYPE_RESOURCE) { + throw new IllegalStateException("called getResPackage() on " + this); + } + return mString1; + } + + private int getResId() { + if (mType != TYPE_RESOURCE) { + throw new IllegalStateException("called getResId() on " + this); + } + return mInt1; + } + + private String getUriString() { + if (mType != TYPE_URI) { + throw new IllegalStateException("called getUriString() on " + this); + } + return mString1; + } + + private Uri getUri() { + return Uri.parse(getUriString()); + } + + // Convert a int32 into a four-char string + private static final String typeToString(int x) { + switch (x) { + case TYPE_BITMAP: return "BITMAP"; + case TYPE_DATA: return "DATA"; + case TYPE_RESOURCE: return "RESOURCE"; + case TYPE_URI: return "URI"; + default: return "UNKNOWN"; + } + } + + /** + * Invokes {@link #loadDrawable(Context)} on the given {@link android.os.Handler Handler} + * and then sends <code>andThen</code> to the same Handler when finished. + * + * @param context {@link android.content.Context Context} in which to load the drawable; see + * {@link #loadDrawable(Context)} + * @param andThen {@link android.os.Message} to send to its target once the drawable + * is available. The {@link android.os.Message#obj obj} + * property is populated with the Drawable. + */ + public void loadDrawableAsync(Context context, Message andThen) { + if (andThen.getTarget() == null) { + throw new IllegalArgumentException("callback message must have a target handler"); + } + new LoadDrawableTask(context, andThen).runAsync(); + } + + /** + * Invokes {@link #loadDrawable(Context)} on a background thread + * and then runs <code>andThen</code> on the UI thread when finished. + * + * @param context {@link android.content.Context Context} in which to load the drawable; see + * {@link #loadDrawable(Context)} + * @param handler {@link android.os.Handler} on which to run <code>andThen</code>. + * @param listener a callback to run on the provided + * Handler once the drawable is available. + */ + public void loadDrawableAsync(Context context, Handler handler, + final OnDrawableLoadedListener listener) { + new LoadDrawableTask(context, handler, listener).runAsync(); + } + + /** + * Returns a Drawable that can be used to draw the image inside this Icon, constructing it + * if necessary. Depending on the type of image, this may not be something you want to do on + * the UI thread, so consider using + * {@link #loadDrawableAsync(Context, Message) loadDrawableAsync} instead. + * + * @param context {@link android.content.Context Context} in which to load the drawable; used + * to access {@link android.content.res.Resources Resources}, for example. + * @return A fresh instance of a drawable for this image, yours to keep. + */ + public Drawable loadDrawable(Context context) { + switch (mType) { + case TYPE_BITMAP: + return new BitmapDrawable(context.getResources(), getBitmap()); + case TYPE_RESOURCE: + if (getResources() == null) { + if (getResPackage() == null || "android".equals(getResPackage())) { + mObj1 = Resources.getSystem(); + } else { + final PackageManager pm = context.getPackageManager(); + try { + mObj1 = pm.getResourcesForApplication(getResPackage()); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, + String.format("Unable to find package '%s'", getResPackage()), + e); + break; + } + } + } + return getResources().getDrawable(getResId(), context.getTheme()); + case TYPE_DATA: + return new BitmapDrawable(context.getResources(), + BitmapFactory.decodeByteArray(getDataBytes(), getDataOffset(), getDataLength()) + ); + case TYPE_URI: + final Uri uri = getUri(); + final String scheme = uri.getScheme(); + InputStream is = null; + if (ContentResolver.SCHEME_CONTENT.equals(scheme) + || ContentResolver.SCHEME_FILE.equals(scheme)) { + try { + is = context.getContentResolver().openInputStream(uri); + } catch (Exception e) { + Log.w(TAG, "Unable to load image from URI: " + uri, e); + } + } else { + try { + is = new FileInputStream(new File(mString1)); + } catch (FileNotFoundException e) { + Log.w(TAG, "Unable to load image from path: " + uri, e); + } + } + if (is != null) { + return new BitmapDrawable(context.getResources(), + BitmapFactory.decodeStream(is)); + } + break; + } + return null; + } + + private Icon(int mType) { + this.mType = mType; + } + + /** + * Create a Icon pointing to a drawable resource. + * @param res Resources for a package containing the resource in question + * @param resid ID of the drawable resource + */ + public static Icon createWithResource(Resources res, @DrawableRes int resid) { + final Icon rep = new Icon(TYPE_RESOURCE); + rep.mObj1 = res; + rep.mInt1 = resid; + rep.mString1 = res.getResourcePackageName(resid); + return rep; + } + + /** + * Create a Icon pointing to a bitmap in memory. + * @param bits A valid {@link android.graphics.Bitmap} object + */ + public static Icon createWithBitmap(Bitmap bits) { + final Icon rep = new Icon(TYPE_BITMAP); + rep.mObj1 = bits; + return rep; + } + + /** + * Create a Icon pointing to a compressed bitmap stored in a byte array. + * @param data Byte array storing compressed bitmap data of a type that + * {@link android.graphics.BitmapFactory} + * can decode (see {@link android.graphics.Bitmap.CompressFormat}). + * @param offset Offset into <code>data</code> at which the bitmap data starts + * @param length Length of the bitmap data + */ + public static Icon createWithData(byte[] data, int offset, int length) { + final Icon rep = new Icon(TYPE_DATA); + rep.mObj1 = data; + rep.mInt1 = length; + rep.mInt2 = offset; + return rep; + } + + /** + * Create a Icon pointing to a content specified by URI. + * + * @param uri A uri referring to local content:// or file:// image data. + */ + public static Icon createWithContentUri(String uri) { + final Icon rep = new Icon(TYPE_URI); + rep.mString1 = uri; + return rep; + } + + /** + * Create a Icon pointing to a content specified by URI. + * + * @param uri A uri referring to local content:// or file:// image data. + */ + public static Icon createWithContentUri(Uri uri) { + final Icon rep = new Icon(TYPE_URI); + rep.mString1 = uri.toString(); + return rep; + } + + /** + * Create a Icon pointing to + * + * @param path A path to a file that contains compressed bitmap data of + * a type that {@link android.graphics.BitmapFactory} can decode. + */ + public static Icon createWithFilePath(String path) { + final Icon rep = new Icon(TYPE_URI); + rep.mString1 = path; + return rep; + } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder("Icon(typ=").append(typeToString(mType)); + switch (mType) { + case TYPE_BITMAP: + sb.append(" size=") + .append(getBitmap().getWidth()) + .append("x") + .append(getBitmap().getHeight()); + break; + case TYPE_RESOURCE: + sb.append(" pkg=") + .append(getResPackage()) + .append(" id=") + .append(String.format("%08x", getResId())); + break; + case TYPE_DATA: + sb.append(" len=").append(getDataLength()); + if (getDataOffset() != 0) { + sb.append(" off=").append(getDataOffset()); + } + break; + case TYPE_URI: + sb.append(" uri=").append(getUriString()); + break; + } + sb.append(")"); + return sb.toString(); + } + + /** + * Parcelable interface + */ + public int describeContents() { + return (mType == TYPE_BITMAP || mType == TYPE_DATA) + ? Parcelable.CONTENTS_FILE_DESCRIPTOR : 0; + } + + // ===== Parcelable interface ====== + + private Icon(Parcel in) { + this(in.readInt()); + switch (mType) { + case TYPE_BITMAP: + final Bitmap bits = Bitmap.CREATOR.createFromParcel(in); + mObj1 = bits; + break; + case TYPE_RESOURCE: + final String pkg = in.readString(); + final int resId = in.readInt(); + mString1 = pkg; + mInt1 = resId; + break; + case TYPE_DATA: + final int len = in.readInt(); + final byte[] a = in.readBlob(); + if (len != a.length) { + throw new RuntimeException("internal unparceling error: blob length (" + + a.length + ") != expected length (" + len + ")"); + } + mInt1 = len; + mObj1 = a; + break; + case TYPE_URI: + final String uri = in.readString(); + mString1 = uri; + break; + default: + throw new RuntimeException("invalid " + + this.getClass().getSimpleName() + " type in parcel: " + mType); + } + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + switch (mType) { + case TYPE_BITMAP: + final Bitmap bits = getBitmap(); + dest.writeInt(TYPE_BITMAP); + getBitmap().writeToParcel(dest, flags); + break; + case TYPE_RESOURCE: + dest.writeInt(TYPE_RESOURCE); + dest.writeString(getResPackage()); + dest.writeInt(getResId()); + break; + case TYPE_DATA: + dest.writeInt(TYPE_DATA); + dest.writeInt(getDataLength()); + dest.writeBlob(getDataBytes(), getDataOffset(), getDataLength()); + break; + case TYPE_URI: + dest.writeInt(TYPE_URI); + dest.writeString(getUriString()); + break; + } + } + + public static final Parcelable.Creator<Icon> CREATOR + = new Parcelable.Creator<Icon>() { + public Icon createFromParcel(Parcel in) { + return new Icon(in); + } + + public Icon[] newArray(int size) { + return new Icon[size]; + } + }; + + /** + * Implement this interface to receive notification when + * {@link #loadDrawableAsync(Context, Handler, OnDrawableLoadedListener) loadDrawableAsync} + * is finished and your Drawable is ready. + */ + public interface OnDrawableLoadedListener { + void onDrawableLoaded(Drawable d); + } + + /** + * Wrapper around loadDrawable that does its work on a pooled thread and then + * fires back the given (targeted) Message. + */ + private class LoadDrawableTask implements Runnable { + final Context mContext; + final Message mMessage; + + public LoadDrawableTask(Context context, final Handler handler, + final OnDrawableLoadedListener listener) { + mContext = context; + mMessage = Message.obtain(handler, new Runnable() { + @Override + public void run() { + listener.onDrawableLoaded((Drawable) mMessage.obj); + } + }); + } + + public LoadDrawableTask(Context context, Message message) { + mContext = context; + mMessage = message; + } + + @Override + public void run() { + mMessage.obj = loadDrawable(mContext); + mMessage.sendToTarget(); + } + + public void runAsync() { + AsyncTask.THREAD_POOL_EXECUTOR.execute(this); + } + } +} diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java index f67dcb3..efc171c 100644 --- a/graphics/java/android/graphics/drawable/RippleDrawable.java +++ b/graphics/java/android/graphics/drawable/RippleDrawable.java @@ -53,8 +53,11 @@ import java.util.Arrays; * attribute identifier. * <p> * A touch feedback drawable may contain multiple child layers, including a - * special mask layer that is not drawn to the screen. A single layer may be set - * as the mask by specifying its android:id value as {@link android.R.id#mask}. + * special mask layer that is not drawn to the screen. A single layer may be + * set as the mask from XML by specifying its {@code android:id} value as + * {@link android.R.id#mask}. At run time, a single layer may be set as the + * mask using {@code setId(..., android.R.id.mask)} or an existing mask layer + * may be replaced using {@code setDrawableByLayerId(android.R.id.mask, ...)}. * <pre> * <code><!-- A red ripple masked against an opaque rectangle. --/> * <ripple android:color="#ffff0000"> diff --git a/graphics/java/android/graphics/pdf/PdfRenderer.java b/graphics/java/android/graphics/pdf/PdfRenderer.java index b32dcc6..feb8052 100644 --- a/graphics/java/android/graphics/pdf/PdfRenderer.java +++ b/graphics/java/android/graphics/pdf/PdfRenderer.java @@ -380,7 +380,7 @@ public final class PdfRenderer implements AutoCloseable { final long transformPtr = (transform != null) ? transform.native_instance : 0; - nativeRenderPage(mNativeDocument, mNativePage, destination.getSkBitmap(), contentLeft, + nativeRenderPage(mNativeDocument, mNativePage, destination, contentLeft, contentTop, contentRight, contentBottom, transformPtr, renderMode); } @@ -425,7 +425,7 @@ public final class PdfRenderer implements AutoCloseable { private static native void nativeClose(long documentPtr); private static native int nativeGetPageCount(long documentPtr); private static native boolean nativeScaleForPrinting(long documentPtr); - private static native void nativeRenderPage(long documentPtr, long pagePtr, long destPtr, + private static native void nativeRenderPage(long documentPtr, long pagePtr, Bitmap dest, int destLeft, int destTop, int destRight, int destBottom, long matrixPtr, int renderMode); private static native long nativeOpenPageAndGetSize(long documentPtr, int pageIndex, Point outSize); |
