OSDN Git Service

Refactor android.graphics.Picture JNI bindings.
authorDerek Sollenberger <djsollen@google.com>
Thu, 12 Jun 2014 16:31:10 +0000 (12:31 -0400)
committerDerek Sollenberger <djsollen@google.com>
Tue, 17 Jun 2014 19:31:43 +0000 (15:31 -0400)
This is the first CL in a series of CLs to refactor the Graphics JNI bindings.

bug: 15672762
Change-Id: I1455fa1330c7426407c06eeaad81ad37a57373b1

core/java/android/view/GLES20Canvas.java
core/jni/Android.mk
core/jni/android/graphics/AndroidPicture.cpp [deleted file]
core/jni/android/graphics/Graphics.cpp
core/jni/android/graphics/GraphicsJNI.h
core/jni/android/graphics/Picture.cpp
core/jni/android/graphics/Picture.h [moved from core/jni/android/graphics/AndroidPicture.h with 85% similarity]
core/jni/android_graphics_Picture.cpp [new file with mode: 0644]
graphics/java/android/graphics/Picture.java

index 5056097..98505c2 100644 (file)
@@ -801,20 +801,12 @@ class GLES20Canvas extends HardwareCanvas {
 
     @Override
     public void drawPicture(Picture picture) {
-        if (picture.createdFromStream) {
-            return;
-        }
-
         picture.endRecording();
         // TODO: Implement rendering
     }
 
     @Override
     public void drawPicture(Picture picture, Rect dst) {
-        if (picture.createdFromStream) {
-            return;
-        }
-
         save();
         translate(dst.left, dst.top);
         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
@@ -826,10 +818,6 @@ class GLES20Canvas extends HardwareCanvas {
 
     @Override
     public void drawPicture(Picture picture, RectF dst) {
-        if (picture.createdFromStream) {
-            return;
-        }
-
         save();
         translate(dst.left, dst.top);
         if (picture.getWidth() > 0 && picture.getHeight() > 0) {
index 15dfed1..cb00062 100644 (file)
@@ -89,7 +89,7 @@ LOCAL_SRC_FILES:= \
        android_util_Process.cpp \
        android_util_StringBlock.cpp \
        android_util_XmlBlock.cpp \
-       android/graphics/AndroidPicture.cpp \
+       android_graphics_Picture.cpp \
        android/graphics/AutoDecodeCancel.cpp \
        android/graphics/Bitmap.cpp \
        android/graphics/BitmapFactory.cpp \
diff --git a/core/jni/android/graphics/AndroidPicture.cpp b/core/jni/android/graphics/AndroidPicture.cpp
deleted file mode 100644 (file)
index 5977ab2..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2014 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.
- */
-
-#include "AndroidPicture.h"
-#include "SkCanvas.h"
-#include "SkStream.h"
-
-AndroidPicture::AndroidPicture(const AndroidPicture* src) {
-    if (NULL != src) {
-        mWidth = src->width();
-        mHeight = src->height();
-        if (NULL != src->mPicture.get()) {
-            mPicture.reset(SkRef(src->mPicture.get()));
-        } if (NULL != src->mRecorder.get()) {
-            mPicture.reset(src->makePartialCopy());
-        }
-    } else {
-        mWidth = 0;
-        mHeight = 0;
-    }
-}
-
-SkCanvas* AndroidPicture::beginRecording(int width, int height) {
-    mPicture.reset(NULL);
-    mRecorder.reset(new SkPictureRecorder);
-    mWidth = width;
-    mHeight = height;
-    return mRecorder->beginRecording(width, height, NULL, 0);
-}
-
-void AndroidPicture::endRecording() {
-    if (NULL != mRecorder.get()) {
-        mPicture.reset(mRecorder->endRecording());
-        mRecorder.reset(NULL);
-    }
-}
-
-int AndroidPicture::width() const {
-    if (NULL != mPicture.get()) {
-        SkASSERT(mPicture->width() == mWidth);
-        SkASSERT(mPicture->height() == mHeight);
-    }
-
-    return mWidth;
-}
-
-int AndroidPicture::height() const {
-    if (NULL != mPicture.get()) {
-        SkASSERT(mPicture->width() == mWidth);
-        SkASSERT(mPicture->height() == mHeight);
-    }
-
-    return mHeight;
-}
-
-AndroidPicture* AndroidPicture::CreateFromStream(SkStream* stream) {
-    AndroidPicture* newPict = new AndroidPicture;
-
-    newPict->mPicture.reset(SkPicture::CreateFromStream(stream));
-    if (NULL != newPict->mPicture.get()) {
-        newPict->mWidth = newPict->mPicture->width();
-        newPict->mHeight = newPict->mPicture->height();
-    }
-
-    return newPict;
-}
-
-void AndroidPicture::serialize(SkWStream* stream) const {
-    if (NULL != mRecorder.get()) {
-        SkAutoTDelete<SkPicture> tempPict(this->makePartialCopy());
-        tempPict->serialize(stream);
-    } else if (NULL != mPicture.get()) {
-        mPicture->serialize(stream);
-    } else {
-        SkPicture empty;
-        empty.serialize(stream);
-    }
-}
-
-void AndroidPicture::draw(SkCanvas* canvas) {
-    if (NULL != mRecorder.get()) {
-        this->endRecording();
-        SkASSERT(NULL != mPicture.get());
-    }
-    if (NULL != mPicture.get()) {
-        // TODO: remove this const_cast once pictures are immutable
-        const_cast<SkPicture*>(mPicture.get())->draw(canvas);
-    }
-}
-
-SkPicture* AndroidPicture::makePartialCopy() const {
-    SkASSERT(NULL != mRecorder.get());
-
-    SkPictureRecorder reRecorder;
-
-    SkCanvas* canvas = reRecorder.beginRecording(mWidth, mHeight, NULL, 0);
-    mRecorder->partialReplay(canvas);
-    return reRecorder.endRecording();
-}
index a4337cc..2bd7a28 100644 (file)
@@ -3,7 +3,6 @@
 #include "jni.h"
 #include "JNIHelp.h"
 #include "GraphicsJNI.h"
-#include "AndroidPicture.h"
 
 #include "SkCanvas.h"
 #include "SkDevice.h"
@@ -346,17 +345,6 @@ android::TypefaceImpl* GraphicsJNI::getNativeTypeface(JNIEnv* env, jobject paint
     return p;
 }
 
-AndroidPicture* GraphicsJNI::getNativePicture(JNIEnv* env, jobject picture)
-{
-    SkASSERT(env);
-    SkASSERT(picture);
-    SkASSERT(env->IsInstanceOf(picture, gPicture_class));
-    jlong pictureHandle = env->GetLongField(picture, gPicture_nativeInstanceID);
-    AndroidPicture* p = reinterpret_cast<AndroidPicture*>(pictureHandle);
-    SkASSERT(p);
-    return p;
-}
-
 SkRegion* GraphicsJNI::getNativeRegion(JNIEnv* env, jobject region)
 {
     SkASSERT(env);
index 2e2f920..ad174f7 100644 (file)
@@ -14,7 +14,6 @@
 class SkBitmapRegionDecoder;
 class SkCanvas;
 class SkPaint;
-class AndroidPicture;
 
 class GraphicsJNI {
 public:
@@ -50,7 +49,6 @@ public:
     static SkPaint*  getNativePaint(JNIEnv*, jobject paint);
     static android::TypefaceImpl* getNativeTypeface(JNIEnv*, jobject paint);
     static SkBitmap* getNativeBitmap(JNIEnv*, jobject bitmap);
-    static AndroidPicture* getNativePicture(JNIEnv*, jobject picture);
     static SkRegion* getNativeRegion(JNIEnv*, jobject region);
 
     // Given the 'native' long held by the Rasterizer.java object, return a
index 0683f73..4a62dc2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2014 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.
  * limitations under the License.
  */
 
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
-#include "AndroidPicture.h"
+#include "Picture.h"
 
 #include "SkCanvas.h"
 #include "SkStream.h"
-#include "SkTemplates.h"
-#include "CreateJavaOutputStreamAdaptor.h"
 
-namespace android {
+using namespace android;
 
-class SkPictureGlue {
-public:
-    static jlong newPicture(JNIEnv* env, jobject, jlong srcHandle) {
-        const AndroidPicture* src = reinterpret_cast<AndroidPicture*>(srcHandle);
-        return reinterpret_cast<jlong>(new AndroidPicture(src));
-    }
-
-    static jlong deserialize(JNIEnv* env, jobject, jobject jstream,
-                             jbyteArray jstorage) {
-        AndroidPicture* picture = NULL;
-        SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
-        if (strm) {
-            picture = AndroidPicture::CreateFromStream(strm);
-            delete strm;
+Picture::Picture(const Picture* src) {
+    if (NULL != src) {
+        mWidth = src->width();
+        mHeight = src->height();
+        if (NULL != src->mPicture.get()) {
+            mPicture.reset(SkRef(src->mPicture.get()));
+        } if (NULL != src->mRecorder.get()) {
+            mPicture.reset(src->makePartialCopy());
         }
-        return reinterpret_cast<jlong>(picture);
-    }
-
-    static void killPicture(JNIEnv* env, jobject, jlong pictureHandle) {
-        AndroidPicture* picture = reinterpret_cast<AndroidPicture*>(pictureHandle);
-        SkASSERT(picture);
-        delete picture;
-    }
-
-    static void draw(JNIEnv* env, jobject, jlong canvasHandle,
-                            jlong pictureHandle) {
-        SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
-        AndroidPicture* picture = reinterpret_cast<AndroidPicture*>(pictureHandle);
-        SkASSERT(canvas);
-        SkASSERT(picture);
-        picture->draw(canvas);
+    } else {
+        mWidth = 0;
+        mHeight = 0;
     }
+}
 
-    static jboolean serialize(JNIEnv* env, jobject, jlong pictureHandle,
-                              jobject jstream, jbyteArray jstorage) {
-        AndroidPicture* picture = reinterpret_cast<AndroidPicture*>(pictureHandle);
-        SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
-
-        if (NULL != strm) {
-            picture->serialize(strm);
-            delete strm;
-            return JNI_TRUE;
-        }
-        return JNI_FALSE;
-    }
+SkCanvas* Picture::beginRecording(int width, int height) {
+    mPicture.reset(NULL);
+    mRecorder.reset(new SkPictureRecorder);
+    mWidth = width;
+    mHeight = height;
+    return mRecorder->beginRecording(width, height, NULL, 0);
+}
 
-    static jint getWidth(JNIEnv* env, jobject jpic) {
-        NPE_CHECK_RETURN_ZERO(env, jpic);
-        AndroidPicture* pict = GraphicsJNI::getNativePicture(env, jpic);
-        int width = pict->width();
-        return static_cast<jint>(width);
+void Picture::endRecording() {
+    if (NULL != mRecorder.get()) {
+        mPicture.reset(mRecorder->endRecording());
+        mRecorder.reset(NULL);
     }
+}
 
-    static jint getHeight(JNIEnv* env, jobject jpic) {
-        NPE_CHECK_RETURN_ZERO(env, jpic);
-        AndroidPicture* pict = GraphicsJNI::getNativePicture(env, jpic);
-        int height = pict->height();
-        return static_cast<jint>(height);
+int Picture::width() const {
+    if (NULL != mPicture.get()) {
+        SkASSERT(mPicture->width() == mWidth);
+        SkASSERT(mPicture->height() == mHeight);
     }
 
-    static jlong beginRecording(JNIEnv* env, jobject, jlong pictHandle,
-                                jint w, jint h) {
-        AndroidPicture* pict = reinterpret_cast<AndroidPicture*>(pictHandle);
-        // beginRecording does not ref its return value, it just returns it.
-        SkCanvas* canvas = pict->beginRecording(w, h);
-        // the java side will wrap this guy in a Canvas.java, which will call
-        // unref in its finalizer, so we have to ref it here, so that both that
-        // Canvas.java and our picture can both be owners
-        canvas->ref();
-        return reinterpret_cast<jlong>(canvas);
-    }
+    return mWidth;
+}
 
-    static void endRecording(JNIEnv* env, jobject, jlong pictHandle) {
-        AndroidPicture* pict = reinterpret_cast<AndroidPicture*>(pictHandle);
-        pict->endRecording();
+int Picture::height() const {
+    if (NULL != mPicture.get()) {
+        SkASSERT(mPicture->width() == mWidth);
+        SkASSERT(mPicture->height() == mHeight);
     }
-};
-
-static JNINativeMethod gPictureMethods[] = {
-    {"getWidth", "()I", (void*) SkPictureGlue::getWidth},
-    {"getHeight", "()I", (void*) SkPictureGlue::getHeight},
-    {"nativeConstructor", "(J)J", (void*) SkPictureGlue::newPicture},
-    {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)SkPictureGlue::deserialize},
-    {"nativeBeginRecording", "(JII)J", (void*) SkPictureGlue::beginRecording},
-    {"nativeEndRecording", "(J)V", (void*) SkPictureGlue::endRecording},
-    {"nativeDraw", "(JJ)V", (void*) SkPictureGlue::draw},
-    {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)SkPictureGlue::serialize},
-    {"nativeDestructor","(J)V", (void*) SkPictureGlue::killPicture}
-};
 
-#include <android_runtime/AndroidRuntime.h>
+    return mHeight;
+}
 
-#define REG(env, name, array) \
-    result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
-    SK_ARRAY_COUNT(array));  \
-    if (result < 0) return result
+Picture* Picture::CreateFromStream(SkStream* stream) {
+    Picture* newPict = new Picture;
 
-int register_android_graphics_Picture(JNIEnv* env) {
-    int result;
+    newPict->mPicture.reset(SkPicture::CreateFromStream(stream));
+    if (NULL != newPict->mPicture.get()) {
+        newPict->mWidth = newPict->mPicture->width();
+        newPict->mHeight = newPict->mPicture->height();
+    }
 
-    REG(env, "android/graphics/Picture", gPictureMethods);
+    return newPict;
+}
 
-    return result;
+void Picture::serialize(SkWStream* stream) const {
+    if (NULL != mRecorder.get()) {
+        SkAutoTDelete<SkPicture> tempPict(this->makePartialCopy());
+        tempPict->serialize(stream);
+    } else if (NULL != mPicture.get()) {
+        mPicture->serialize(stream);
+    } else {
+        SkPicture empty;
+        empty.serialize(stream);
+    }
 }
 
+void Picture::draw(SkCanvas* canvas) {
+    if (NULL != mRecorder.get()) {
+        this->endRecording();
+        SkASSERT(NULL != mPicture.get());
+    }
+    if (NULL != mPicture.get()) {
+        // TODO: remove this const_cast once pictures are immutable
+        const_cast<SkPicture*>(mPicture.get())->draw(canvas);
+    }
 }
 
+SkPicture* Picture::makePartialCopy() const {
+    SkASSERT(NULL != mRecorder.get());
 
+    SkPictureRecorder reRecorder;
+
+    SkCanvas* canvas = reRecorder.beginRecording(mWidth, mHeight, NULL, 0);
+    mRecorder->partialReplay(canvas);
+    return reRecorder.endRecording();
+}
similarity index 85%
rename from core/jni/android/graphics/AndroidPicture.h
rename to core/jni/android/graphics/Picture.h
index f434941..abb0403 100644 (file)
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_PICTURE_H
-#define ANDROID_PICTURE_H
+#ifndef ANDROID_GRAPHICS_PICTURE_H
+#define ANDROID_GRAPHICS_PICTURE_H
 
 #include "SkPicture.h"
 #include "SkPictureRecorder.h"
@@ -28,13 +28,15 @@ class SkPictureRecorder;
 class SkStream;
 class SkWStream;
 
+namespace android {
+
 // Skia's SkPicture class has been split into an SkPictureRecorder
 // and an SkPicture. AndroidPicture recreates the functionality
 // of the old SkPicture interface by flip-flopping between the two
 // new classes.
-class AndroidPicture {
+class Picture {
 public:
-    explicit AndroidPicture(const AndroidPicture* src = NULL);
+    explicit Picture(const Picture* src = NULL);
 
     SkCanvas* beginRecording(int width, int height);
 
@@ -44,7 +46,7 @@ public:
 
     int height() const;
 
-    static AndroidPicture* CreateFromStream(SkStream* stream);
+    static Picture* CreateFromStream(SkStream* stream);
 
     void serialize(SkWStream* stream) const;
 
@@ -60,4 +62,6 @@ private:
     // resulting picture will have balanced saves and restores.
     SkPicture* makePartialCopy() const;
 };
-#endif // ANDROID_PICTURE_H
+
+}; // namespace android
+#endif // ANDROID_GRAPHICS_PICTURE_H
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
new file mode 100644 (file)
index 0000000..f827907
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "Picture.h"
+
+#include "SkCanvas.h"
+#include "SkStream.h"
+#include "SkTemplates.h"
+#include "CreateJavaOutputStreamAdaptor.h"
+
+namespace android {
+
+static jlong android_graphics_Picture_newPicture(JNIEnv* env, jobject, jlong srcHandle) {
+    const Picture* src = reinterpret_cast<Picture*>(srcHandle);
+    return reinterpret_cast<jlong>(new Picture(src));
+}
+
+static jlong android_graphics_Picture_deserialize(JNIEnv* env, jobject, jobject jstream,
+                                                  jbyteArray jstorage) {
+    Picture* picture = NULL;
+    SkStream* strm = CreateJavaInputStreamAdaptor(env, jstream, jstorage);
+    if (strm) {
+        picture = Picture::CreateFromStream(strm);
+        delete strm;
+    }
+    return reinterpret_cast<jlong>(picture);
+}
+
+static void android_graphics_Picture_killPicture(JNIEnv* env, jobject, jlong pictureHandle) {
+    Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+    SkASSERT(picture);
+    delete picture;
+}
+
+static void android_graphics_Picture_draw(JNIEnv* env, jobject, jlong canvasHandle,
+                                          jlong pictureHandle) {
+    SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
+    Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+    SkASSERT(canvas);
+    SkASSERT(picture);
+    picture->draw(canvas);
+}
+
+static jboolean android_graphics_Picture_serialize(JNIEnv* env, jobject, jlong pictureHandle,
+                                                   jobject jstream, jbyteArray jstorage) {
+    Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
+    SkWStream* strm = CreateJavaOutputStreamAdaptor(env, jstream, jstorage);
+
+    if (NULL != strm) {
+        picture->serialize(strm);
+        delete strm;
+        return JNI_TRUE;
+    }
+    return JNI_FALSE;
+}
+
+static jint android_graphics_Picture_getWidth(JNIEnv* env, jobject, jlong pictureHandle) {
+    Picture* pict = reinterpret_cast<Picture*>(pictureHandle);
+    return static_cast<jint>(pict->width());
+}
+
+static jint android_graphics_Picture_getHeight(JNIEnv* env, jobject, jlong pictureHandle) {
+    Picture* pict = reinterpret_cast<Picture*>(pictureHandle);
+    return static_cast<jint>(pict->height());
+}
+
+static jlong android_graphics_Picture_beginRecording(JNIEnv* env, jobject, jlong pictHandle,
+                                                     jint w, jint h) {
+    Picture* pict = reinterpret_cast<Picture*>(pictHandle);
+    // beginRecording does not ref its return value, it just returns it.
+    SkCanvas* canvas = pict->beginRecording(w, h);
+    // the java side will wrap this guy in a Canvas.java, which will call
+    // unref in its finalizer, so we have to ref it here, so that both that
+    // Canvas.java and our picture can both be owners
+    canvas->ref();
+    return reinterpret_cast<jlong>(canvas);
+}
+
+static void android_graphics_Picture_endRecording(JNIEnv* env, jobject, jlong pictHandle) {
+    Picture* pict = reinterpret_cast<Picture*>(pictHandle);
+    pict->endRecording();
+}
+
+static JNINativeMethod gMethods[] = {
+    {"nativeGetWidth", "(J)I", (void*) android_graphics_Picture_getWidth},
+    {"nativeGetHeight", "(J)I", (void*) android_graphics_Picture_getHeight},
+    {"nativeConstructor", "(J)J", (void*) android_graphics_Picture_newPicture},
+    {"nativeCreateFromStream", "(Ljava/io/InputStream;[B)J", (void*)android_graphics_Picture_deserialize},
+    {"nativeBeginRecording", "(JII)J", (void*) android_graphics_Picture_beginRecording},
+    {"nativeEndRecording", "(J)V", (void*) android_graphics_Picture_endRecording},
+    {"nativeDraw", "(JJ)V", (void*) android_graphics_Picture_draw},
+    {"nativeWriteToStream", "(JLjava/io/OutputStream;[B)Z", (void*)android_graphics_Picture_serialize},
+    {"nativeDestructor","(J)V", (void*) android_graphics_Picture_killPicture}
+};
+
+int register_android_graphics_Picture(JNIEnv* env) {
+    return AndroidRuntime::registerNativeMethods(env, "android/graphics/Picture", gMethods, NELEM(gMethods));
+}
+
+}; // namespace android
index a021165..5aa7c6a 100644 (file)
@@ -31,18 +31,13 @@ public class Picture {
     private Canvas mRecordingCanvas;
     private final long mNativePicture;
 
-    /**
-     * @hide
-     */
-    public final boolean createdFromStream;
-
     private static final int WORKING_STREAM_STORAGE = 16 * 1024;
 
     /**
      * Creates an empty picture that is ready to record.
      */
     public Picture() {
-        this(nativeConstructor(0), false);
+        this(nativeConstructor(0));
     }
 
     /**
@@ -51,7 +46,23 @@ public class Picture {
      * changes will not be reflected in this picture.
      */
     public Picture(Picture src) {
-        this(nativeConstructor(src != null ? src.mNativePicture : 0), false);
+        this(nativeConstructor(src != null ? src.mNativePicture : 0));
+    }
+
+    private Picture(long nativePicture) {
+        if (nativePicture == 0) {
+            throw new RuntimeException();
+        }
+        mNativePicture = nativePicture;
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            nativeDestructor(mNativePicture);
+        } finally {
+            super.finalize();
+        }
     }
 
     /**
@@ -85,13 +96,17 @@ public class Picture {
      * Get the width of the picture as passed to beginRecording. This
      * does not reflect (per se) the content of the picture.
      */
-    public native int getWidth();
+    public int getWidth() {
+      return nativeGetWidth(mNativePicture);
+    }
 
     /**
      * Get the height of the picture as passed to beginRecording. This
      * does not reflect (per se) the content of the picture.
      */
-    public native int getHeight();
+    public int getHeight() {
+      return nativeGetHeight(mNativePicture);
+    }
 
     /**
      * Draw this picture on the canvas.
@@ -130,7 +145,7 @@ public class Picture {
      */
     @Deprecated
     public static Picture createFromStream(InputStream stream) {
-        return new Picture(nativeCreateFromStream(stream, new byte[WORKING_STREAM_STORAGE]), true);
+        return new Picture(nativeCreateFromStream(stream, new byte[WORKING_STREAM_STORAGE]));
     }
 
     /**
@@ -159,32 +174,12 @@ public class Picture {
         }
     }
 
-    protected void finalize() throws Throwable {
-        try {
-            nativeDestructor(mNativePicture);
-        } finally {
-            super.finalize();
-        }
-    }
-
-    final long ni() {
-        return mNativePicture;
-    }
-
-    private Picture(long nativePicture, boolean fromStream) {
-        if (nativePicture == 0) {
-            throw new RuntimeException();
-        }
-        mNativePicture = nativePicture;
-        createdFromStream = fromStream;
-    }
-
     // return empty picture if src is 0, or a copy of the native src
     private static native long nativeConstructor(long nativeSrcOr0);
-    private static native long nativeCreateFromStream(InputStream stream,
-                                                byte[] storage);
-    private static native long nativeBeginRecording(long nativeCanvas,
-                                                    int w, int h);
+    private static native long nativeCreateFromStream(InputStream stream, byte[] storage);
+    private static native int nativeGetWidth(long nativePicture);
+    private static native int nativeGetHeight(long nativePicture);
+    private static native long nativeBeginRecording(long nativeCanvas, int w, int h);
     private static native void nativeEndRecording(long nativeCanvas);
     private static native void nativeDraw(long nativeCanvas, long nativePicture);
     private static native boolean nativeWriteToStream(long nativePicture,
@@ -201,18 +196,15 @@ public class Picture {
 
         @Override
         public void setBitmap(Bitmap bitmap) {
-            throw new RuntimeException(
-                                "Cannot call setBitmap on a picture canvas");
+            throw new RuntimeException("Cannot call setBitmap on a picture canvas");
         }
 
         @Override
         public void drawPicture(Picture picture) {
             if (mPicture == picture) {
-                throw new RuntimeException(
-                            "Cannot draw a picture into its recording canvas");
+                throw new RuntimeException("Cannot draw a picture into its recording canvas");
             }
             super.drawPicture(picture);
         }
     }
 }
-