Merge "Generate PDF from Canvas."
This commit is contained in:
committed by
Android (Google) Code Review
commit
b06accf34f
@@ -18385,6 +18385,40 @@ package android.preference {
|
||||
|
||||
}
|
||||
|
||||
package android.print.pdf {
|
||||
|
||||
public final class PdfDocument {
|
||||
method public void close();
|
||||
method protected final void finalize() throws java.lang.Throwable;
|
||||
method public void finishPage(android.print.pdf.PdfDocument.Page);
|
||||
method public java.util.List<android.print.pdf.PdfDocument.PageInfo> getPages();
|
||||
method public static android.print.pdf.PdfDocument open();
|
||||
method public android.print.pdf.PdfDocument.Page startPage(android.print.pdf.PdfDocument.PageInfo);
|
||||
method public void writeTo(java.io.OutputStream);
|
||||
}
|
||||
|
||||
public static final class PdfDocument.Page {
|
||||
method public android.graphics.Canvas getCanvas();
|
||||
method public android.print.pdf.PdfDocument.PageInfo getInfo();
|
||||
}
|
||||
|
||||
public static final class PdfDocument.PageInfo {
|
||||
method public android.graphics.Rect getContentSize();
|
||||
method public int getDesity();
|
||||
method public android.graphics.Matrix getInitialTransform();
|
||||
method public int getPageNumber();
|
||||
method public android.graphics.Rect getPageSize();
|
||||
}
|
||||
|
||||
public static final class PdfDocument.PageInfo.Builder {
|
||||
ctor public PdfDocument.PageInfo.Builder(android.graphics.Rect, int, int);
|
||||
method public android.print.pdf.PdfDocument.PageInfo create();
|
||||
method public android.print.pdf.PdfDocument.PageInfo.Builder setContentSize(android.graphics.Rect);
|
||||
method public android.print.pdf.PdfDocument.PageInfo.Builder setInitialTransform(android.graphics.Matrix);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
package android.provider {
|
||||
|
||||
public final class AlarmClock {
|
||||
|
||||
443
core/java/android/print/pdf/PdfDocument.java
Normal file
443
core/java/android/print/pdf/PdfDocument.java
Normal file
@@ -0,0 +1,443 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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.print.pdf;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Rect;
|
||||
|
||||
import dalvik.system.CloseGuard;
|
||||
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class enables generating a PDF document from native Android content. You
|
||||
* open a new document and then for every page you want to add you start a page,
|
||||
* write content to the page, and finish the page. After you are done with all
|
||||
* pages, you write the document to an output stream and close the document.
|
||||
* After a document is closed you should not use it anymore.
|
||||
* </p>
|
||||
* <p>
|
||||
* A typical use of the APIs looks like this:
|
||||
* </p>
|
||||
* <pre>
|
||||
* // open a new document
|
||||
* PdfDocument document = PdfDocument.open();
|
||||
*
|
||||
* // crate a page description
|
||||
* PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, 100, 100), 1, 300).create();
|
||||
*
|
||||
* // start a page
|
||||
* Page page = document.startPage(pageInfo);
|
||||
*
|
||||
* // draw something on the page
|
||||
* View content = getContentView();
|
||||
* content.draw(page.getCanvas());
|
||||
*
|
||||
* // finish the page
|
||||
* document.finishPage(page);
|
||||
* . . .
|
||||
* add more pages
|
||||
* . . .
|
||||
* // write the document content
|
||||
* document.writeTo(getOutputStream());
|
||||
*
|
||||
* //close the document
|
||||
* document.close();
|
||||
* </pre>
|
||||
*/
|
||||
public final class PdfDocument {
|
||||
|
||||
private final byte[] mChunk = new byte[4096];
|
||||
|
||||
private final CloseGuard mCloseGuard = CloseGuard.get();
|
||||
|
||||
private final List<PageInfo> mPages = new ArrayList<PageInfo>();
|
||||
|
||||
private int mNativeDocument;
|
||||
|
||||
private Page mCurrentPage;
|
||||
|
||||
/**
|
||||
* Opens a new document.
|
||||
* <p>
|
||||
* <strong>Note:</strong> You must close the document after you are
|
||||
* done by calling {@link #close()}
|
||||
* </p>
|
||||
*
|
||||
* @return The document.
|
||||
*
|
||||
* @see #close()
|
||||
*/
|
||||
public static PdfDocument open() {
|
||||
return new PdfDocument();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
private PdfDocument() {
|
||||
mNativeDocument = nativeCreateDocument();
|
||||
mCloseGuard.open("close");
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a page using the provided {@link PageInfo}. After the page
|
||||
* is created you can draw arbitrary content on the page's canvas which
|
||||
* you can get by calling {@link Page#getCanvas()}. After you are done
|
||||
* drawing the content you should finish the page by calling
|
||||
* {@link #finishPage(Page). After the page is finished you should
|
||||
* no longer access the page or its canvas.
|
||||
* <p>
|
||||
* <strong>Note:</strong> Do not call this method after {@link #close()}.
|
||||
* </p>
|
||||
*
|
||||
* @param pageInfo The page info.
|
||||
* @return A blank page.
|
||||
*
|
||||
* @see #finishPage(Page)
|
||||
*/
|
||||
public Page startPage(PageInfo pageInfo) {
|
||||
throwIfClosed();
|
||||
if (pageInfo == null) {
|
||||
throw new IllegalArgumentException("page cannot be null!");
|
||||
}
|
||||
if (mCurrentPage != null) {
|
||||
throw new IllegalStateException("Previous page not finished!");
|
||||
}
|
||||
Canvas canvas = new PdfCanvas(nativeCreatePage(pageInfo.mPageSize,
|
||||
pageInfo.mContentSize, pageInfo.mInitialTransform.native_instance),
|
||||
pageInfo.mDensity);
|
||||
mCurrentPage = new Page(canvas, pageInfo);
|
||||
return mCurrentPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes a started page. You should always finish the last started page.
|
||||
* <p>
|
||||
* <strong>Note:</strong> Do not call this method after {@link #close()}.
|
||||
* </p>
|
||||
*
|
||||
* @param page The page.
|
||||
*
|
||||
* @see #startPage(PageInfo)
|
||||
*/
|
||||
public void finishPage(Page page) {
|
||||
throwIfClosed();
|
||||
if (page == null) {
|
||||
throw new IllegalArgumentException("page cannot be null");
|
||||
}
|
||||
if (page != mCurrentPage) {
|
||||
throw new IllegalStateException("invalid page");
|
||||
}
|
||||
mPages.add(page.getInfo());
|
||||
mCurrentPage = null;
|
||||
nativeAppendPage(mNativeDocument, page.mCanvas.mNativeCanvas);
|
||||
page.finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the document to an output stream.
|
||||
* <p>
|
||||
* <strong>Note:</strong> Do not call this method after {@link #close()}.
|
||||
* </p>
|
||||
*
|
||||
* @param out The output stream.
|
||||
*/
|
||||
public void writeTo(OutputStream out) {
|
||||
throwIfClosed();
|
||||
if (out == null) {
|
||||
throw new IllegalArgumentException("out cannot be null!");
|
||||
}
|
||||
nativeWriteTo(mNativeDocument, out, mChunk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pages of the document.
|
||||
*
|
||||
* @return The pages.
|
||||
*/
|
||||
public List<PageInfo> getPages() {
|
||||
return Collections.unmodifiableList(mPages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this document. This method should be called after you
|
||||
* are done working with the document. After this call the document
|
||||
* is considered closed and none of its methods should be called.
|
||||
*/
|
||||
public void close() {
|
||||
dispose();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
mCloseGuard.warnIfOpen();
|
||||
dispose();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
private void dispose() {
|
||||
if (mNativeDocument != 0) {
|
||||
nativeFinalize(mNativeDocument);
|
||||
mCloseGuard.close();
|
||||
mNativeDocument = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws an exception if the document is already closed.
|
||||
*/
|
||||
private void throwIfClosed() {
|
||||
if (mNativeDocument == 0) {
|
||||
throw new IllegalStateException("document is closed!");
|
||||
}
|
||||
}
|
||||
|
||||
private native int nativeCreateDocument();
|
||||
|
||||
private native void nativeFinalize(int document);
|
||||
|
||||
private native void nativeAppendPage(int document, int page);
|
||||
|
||||
private native void nativeWriteTo(int document, OutputStream out, byte[] chunk);
|
||||
|
||||
private static native int nativeCreatePage(Rect pageSize,
|
||||
Rect contentSize, int nativeMatrix);
|
||||
|
||||
|
||||
private final class PdfCanvas extends Canvas {
|
||||
|
||||
public PdfCanvas(int nativeCanvas, int density) {
|
||||
super(nativeCanvas);
|
||||
super.setDensity(density);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBitmap(Bitmap bitmap) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDensity(int density) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScreenDensity(int density) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents meta-data that describes a PDF {@link Page}.
|
||||
*/
|
||||
public static final class PageInfo {
|
||||
private Rect mPageSize;
|
||||
private Rect mContentSize;
|
||||
private Matrix mInitialTransform;
|
||||
private int mPageNumber;
|
||||
private int mDensity;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*/
|
||||
private PageInfo() {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the page size in pixels.
|
||||
*
|
||||
* @return The page size.
|
||||
*/
|
||||
public Rect getPageSize() {
|
||||
return mPageSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the content size in pixels.
|
||||
*
|
||||
* @return The content size.
|
||||
*/
|
||||
public Rect getContentSize() {
|
||||
return mContentSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the initial transform which is applied to the page. This may be
|
||||
* useful to move the origin to account for a margin, apply scale, or
|
||||
* apply a rotation.
|
||||
*
|
||||
* @return The initial transform.
|
||||
*/
|
||||
public Matrix getInitialTransform() {
|
||||
return mInitialTransform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the page number.
|
||||
*
|
||||
* @return The page number.
|
||||
*/
|
||||
public int getPageNumber() {
|
||||
return mPageNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the density of the page in DPI.
|
||||
*
|
||||
* @return The density.
|
||||
*/
|
||||
public int getDesity() {
|
||||
return mDensity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder for creating a {@link PageInfo}.
|
||||
*/
|
||||
public static final class Builder {
|
||||
private final PageInfo mPageInfo = new PageInfo();
|
||||
|
||||
/**
|
||||
* Creates a new builder with the mandatory page info attributes.
|
||||
*
|
||||
* @param pageSize The page size in pixels.
|
||||
* @param pageNumber The page number.
|
||||
* @param density The page density in DPI.
|
||||
*/
|
||||
public Builder(Rect pageSize, int pageNumber, int density) {
|
||||
if (pageSize.width() == 0 || pageSize.height() == 0) {
|
||||
throw new IllegalArgumentException("page width and height" +
|
||||
" must be greater than zero!");
|
||||
}
|
||||
if (pageNumber < 0) {
|
||||
throw new IllegalArgumentException("pageNumber cannot be less than zero!");
|
||||
}
|
||||
if (density <= 0) {
|
||||
throw new IllegalArgumentException("density must be greater than zero!");
|
||||
}
|
||||
mPageInfo.mPageSize = pageSize;
|
||||
mPageInfo.mPageNumber = pageNumber;
|
||||
mPageInfo.mDensity = density;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the content size in pixels.
|
||||
*
|
||||
* @param contentSize The content size.
|
||||
*/
|
||||
public Builder setContentSize(Rect contentSize) {
|
||||
Rect pageSize = mPageInfo.mPageSize;
|
||||
if (contentSize != null && (pageSize.left > contentSize.left
|
||||
|| pageSize.top > contentSize.top
|
||||
|| pageSize.right < contentSize.right
|
||||
|| pageSize.bottom < contentSize.bottom)) {
|
||||
throw new IllegalArgumentException("contentSize does not fit the pageSize!");
|
||||
}
|
||||
mPageInfo.mContentSize = contentSize;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the initial transform which is applied to the page. This may be
|
||||
* useful to move the origin to account for a margin, apply scale, or
|
||||
* apply a rotation.
|
||||
*
|
||||
* @param transform The initial transform.
|
||||
*/
|
||||
public Builder setInitialTransform(Matrix transform) {
|
||||
mPageInfo.mInitialTransform = transform;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link PageInfo}.
|
||||
*
|
||||
* @return The new instance.
|
||||
*/
|
||||
public PageInfo create() {
|
||||
if (mPageInfo.mContentSize == null) {
|
||||
mPageInfo.mContentSize = mPageInfo.mPageSize;
|
||||
}
|
||||
if (mPageInfo.mInitialTransform == null) {
|
||||
mPageInfo.mInitialTransform = new Matrix();
|
||||
}
|
||||
return mPageInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class represents a PDF document page. It has associated
|
||||
* a canvas on which you can draw content and is acquired by a
|
||||
* call to {@link #getCanvas()}. It also has associated a
|
||||
* {@link PageInfo} instance that describes its attributes.
|
||||
*/
|
||||
public static final class Page {
|
||||
private final PageInfo mPageInfo;
|
||||
private Canvas mCanvas;
|
||||
|
||||
/**
|
||||
* Creates a new instance.
|
||||
*
|
||||
* @param canvas The canvas of the page.
|
||||
* @param pageInfo The info with meta-data.
|
||||
*/
|
||||
private Page(Canvas canvas, PageInfo pageInfo) {
|
||||
mCanvas = canvas;
|
||||
mPageInfo = pageInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link Canvas} of the page.
|
||||
*
|
||||
* @return The canvas if the page is not finished, null otherwise.
|
||||
*
|
||||
* @see PdfDocument#finishPage(Page)
|
||||
*/
|
||||
public Canvas getCanvas() {
|
||||
return mCanvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link PageInfo} with meta-data for the page.
|
||||
*
|
||||
* @return The page info.
|
||||
*
|
||||
* @see PdfDocument#finishPage(Page)
|
||||
*/
|
||||
public PageInfo getInfo() {
|
||||
return mPageInfo;
|
||||
}
|
||||
|
||||
private void finish() {
|
||||
if (mCanvas != null) {
|
||||
mCanvas.release();
|
||||
mCanvas = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -140,6 +140,7 @@ LOCAL_SRC_FILES:= \
|
||||
android_util_FileObserver.cpp \
|
||||
android/opengl/poly_clip.cpp.arm \
|
||||
android/opengl/util.cpp.arm \
|
||||
android/print/android_print_pdf_PdfDocument.cpp \
|
||||
android_server_NetworkManagementSocketTagger.cpp \
|
||||
android_server_Watchdog.cpp \
|
||||
android_ddm_DdmHandleNativeHeap.cpp \
|
||||
@@ -164,6 +165,7 @@ LOCAL_C_INCLUDES += \
|
||||
$(call include-path-for, libhardware_legacy)/hardware_legacy \
|
||||
$(TOP)/frameworks/av/include \
|
||||
external/skia/src/core \
|
||||
external/skia/src/pdf \
|
||||
external/skia/src/images \
|
||||
external/skia/include/utils \
|
||||
external/sqlite/dist \
|
||||
|
||||
@@ -144,6 +144,7 @@ extern int register_android_os_FileObserver(JNIEnv *env);
|
||||
extern int register_android_os_FileUtils(JNIEnv *env);
|
||||
extern int register_android_os_UEventObserver(JNIEnv* env);
|
||||
extern int register_android_os_MemoryFile(JNIEnv* env);
|
||||
extern int register_android_print_pdf_PdfDocument(JNIEnv* env);
|
||||
extern int register_android_net_LocalSocketImpl(JNIEnv* env);
|
||||
extern int register_android_net_NetworkUtils(JNIEnv* env);
|
||||
extern int register_android_net_TrafficStats(JNIEnv* env);
|
||||
@@ -1182,6 +1183,7 @@ static const RegJNIRec gRegJNI[] = {
|
||||
REG_JNI(register_android_os_SELinux),
|
||||
REG_JNI(register_android_os_Trace),
|
||||
REG_JNI(register_android_os_UEventObserver),
|
||||
REG_JNI(register_android_print_pdf_PdfDocument),
|
||||
REG_JNI(register_android_net_LocalSocketImpl),
|
||||
REG_JNI(register_android_net_NetworkUtils),
|
||||
REG_JNI(register_android_net_TrafficStats),
|
||||
|
||||
87
core/jni/android/print/android_print_pdf_PdfDocument.cpp
Normal file
87
core/jni/android/print/android_print_pdf_PdfDocument.cpp
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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 "SkCanvas.h"
|
||||
#include "SkPDFDevice.h"
|
||||
#include "SkPDFDocument.h"
|
||||
#include "SkRect.h"
|
||||
#include "SkSize.h"
|
||||
#include "CreateJavaOutputStreamAdaptor.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
static jint nativeCreateDocument(JNIEnv* env, jobject clazz) {
|
||||
return reinterpret_cast<jint>(new SkPDFDocument());
|
||||
}
|
||||
|
||||
static void nativeFinalize(JNIEnv* env, jobject thiz, jint documentPtr) {
|
||||
delete reinterpret_cast<SkPDFDocument*>(documentPtr);
|
||||
}
|
||||
|
||||
static jint nativeCreatePage(JNIEnv* env, jobject thiz,
|
||||
jobject pageSize, jobject contentSize, jint initialTransformation) {
|
||||
SkIRect skPageSizeRect;
|
||||
GraphicsJNI::jrect_to_irect(env, pageSize, &skPageSizeRect);
|
||||
SkISize skPageSize = SkISize::Make(skPageSizeRect.width(),
|
||||
skPageSizeRect.height());
|
||||
|
||||
SkIRect skContentRect;
|
||||
GraphicsJNI::jrect_to_irect(env, contentSize, &skContentRect);
|
||||
SkISize skContentSize = SkISize::Make(skContentRect.width(),
|
||||
skContentRect.height());
|
||||
|
||||
SkMatrix* transformation = reinterpret_cast<SkMatrix*>(initialTransformation);
|
||||
SkPDFDevice* skPdfDevice = new SkPDFDevice(skPageSize, skContentSize, *transformation);
|
||||
|
||||
return reinterpret_cast<jint>(new SkCanvas(skPdfDevice));
|
||||
}
|
||||
|
||||
static void nativeAppendPage(JNIEnv* env, jobject thiz, jint documentPtr, jint pagePtr) {
|
||||
SkCanvas* page = reinterpret_cast<SkCanvas*>(pagePtr);
|
||||
SkPDFDocument* document = reinterpret_cast<SkPDFDocument*>(documentPtr);
|
||||
SkPDFDevice* device = static_cast<SkPDFDevice*>(page->getDevice());
|
||||
document->appendPage(device);
|
||||
}
|
||||
|
||||
static void nativeWriteTo(JNIEnv* env, jobject clazz, jint documentPtr,
|
||||
jobject out, jbyteArray chunk) {
|
||||
SkWStream* skWStream = CreateJavaOutputStreamAdaptor(env, out, chunk);
|
||||
SkPDFDocument* document = reinterpret_cast<SkPDFDocument*>(documentPtr);
|
||||
document->emitPDF(skWStream);
|
||||
delete skWStream;
|
||||
}
|
||||
|
||||
static JNINativeMethod gPdfDocument_Methods[] = {
|
||||
{"nativeCreateDocument", "()I", (void*) nativeCreateDocument},
|
||||
{"nativeFinalize", "(I)V", (void*) nativeFinalize},
|
||||
{"nativeCreatePage", "(Landroid/graphics/Rect;Landroid/graphics/Rect;I)I",
|
||||
(void*) nativeCreatePage},
|
||||
{"nativeAppendPage", "(II)V", (void*) nativeAppendPage},
|
||||
{"nativeWriteTo", "(ILjava/io/OutputStream;[B)V", (void*) nativeWriteTo}
|
||||
};
|
||||
|
||||
int register_android_print_pdf_PdfDocument(JNIEnv* env) {
|
||||
int result = android::AndroidRuntime::registerNativeMethods(
|
||||
env, "android/print/pdf/PdfDocument", gPdfDocument_Methods,
|
||||
NELEM(gPdfDocument_Methods));
|
||||
return result;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -37,12 +37,14 @@ import javax.microedition.khronos.opengles.GL;
|
||||
* Canvas and Drawables</a> developer guide.</p></div>
|
||||
*/
|
||||
public class Canvas {
|
||||
|
||||
// assigned in constructors or setBitmap, freed in finalizer
|
||||
int mNativeCanvas;
|
||||
|
||||
/** @hide */
|
||||
public int mNativeCanvas;
|
||||
|
||||
// may be null
|
||||
private Bitmap mBitmap;
|
||||
|
||||
|
||||
// optional field set by the caller
|
||||
private DrawFilter mDrawFilter;
|
||||
|
||||
@@ -59,7 +61,6 @@ public class Canvas {
|
||||
protected int mScreenDensity = Bitmap.DENSITY_NONE;
|
||||
|
||||
// Used by native code
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
private int mSurfaceFormat;
|
||||
|
||||
/**
|
||||
@@ -79,10 +80,9 @@ public class Canvas {
|
||||
private static final int MAXMIMUM_BITMAP_SIZE = 32766;
|
||||
|
||||
// This field is used to finalize the native Canvas properly
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
private final CanvasFinalizer mFinalizer;
|
||||
|
||||
private static class CanvasFinalizer {
|
||||
private static final class CanvasFinalizer {
|
||||
private int mNativeCanvas;
|
||||
|
||||
public CanvasFinalizer(int nativeCanvas) {
|
||||
@@ -92,13 +92,18 @@ public class Canvas {
|
||||
@Override
|
||||
protected void finalize() throws Throwable {
|
||||
try {
|
||||
if (mNativeCanvas != 0) {
|
||||
finalizer(mNativeCanvas);
|
||||
}
|
||||
dispose();
|
||||
} finally {
|
||||
super.finalize();
|
||||
}
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (mNativeCanvas != 0) {
|
||||
finalizer(mNativeCanvas);
|
||||
mNativeCanvas = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,13 +137,14 @@ public class Canvas {
|
||||
mBitmap = bitmap;
|
||||
mDensity = bitmap.mDensity;
|
||||
}
|
||||
|
||||
Canvas(int nativeCanvas) {
|
||||
|
||||
/** @hide */
|
||||
public Canvas(int nativeCanvas) {
|
||||
if (nativeCanvas == 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
mNativeCanvas = nativeCanvas;
|
||||
mFinalizer = new CanvasFinalizer(nativeCanvas);
|
||||
mFinalizer = new CanvasFinalizer(mNativeCanvas);
|
||||
mDensity = Bitmap.getDefaultDensity();
|
||||
}
|
||||
|
||||
@@ -155,7 +161,18 @@ public class Canvas {
|
||||
}
|
||||
finalizer(oldCanvas);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the native canvas pointer.
|
||||
*
|
||||
* @return The native pointer.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public int getNativeCanvas() {
|
||||
return mNativeCanvas;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null.
|
||||
*
|
||||
@@ -1659,6 +1676,15 @@ public class Canvas {
|
||||
restore();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the resources associated with this canvas.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public void release() {
|
||||
mFinalizer.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Free up as much memory as possible from private caches (e.g. fonts, images)
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user