Encapsulate Canvas.mNativeCanvas

Currently, the native canvas is accessed/manipulated from several
unrelated classes.

In order to facilitate SaveFlags emulation, this CL encapsulates
the field and refactors its external users.

Two main changes:

* new getNativeCanvas() getter for use in Java-level clients.
* JNI canvas swappers (GraphicsBuffers, Surface, TextureView &
  AssetAtlasService) are refactored based on the exising/equivalent
  safeCanvasSwap() Canvas method.

Change-Id: I966bd4898f0838fb3699e226d3d3d51e0224ea97
This commit is contained in:
Florin Malita
2014-05-06 21:07:19 -04:00
parent ae949571f0
commit c677675e9c
9 changed files with 44 additions and 118 deletions

View File

@@ -74,15 +74,10 @@ static struct {
} gRectClassInfo;
static struct {
jfieldID mFinalizer;
jfieldID mNativeCanvas;
jfieldID mSurfaceFormat;
jmethodID safeCanvasSwap;
} gCanvasClassInfo;
static struct {
jfieldID mNativeCanvas;
} gCanvasFinalizerClassInfo;
#define GET_INT(object, field) \
env->GetIntField(object, field)
@@ -146,15 +141,6 @@ static void android_view_GraphiceBuffer_destroy(JNIEnv* env, jobject clazz,
// Canvas management
// ----------------------------------------------------------------------------
static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
GET_LONG(canvasObj, gCanvasClassInfo.mNativeCanvas));
SET_LONG(canvasObj, gCanvasClassInfo.mNativeCanvas, (long) newCanvas);
SET_LONG(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (long) newCanvas);
SkSafeUnref(previousCanvas);
}
static inline SkBitmap::Config convertPixelFormat(int32_t format) {
switch (format) {
case PIXEL_FORMAT_RGBA_8888:
@@ -213,7 +199,7 @@ static jboolean android_view_GraphicBuffer_lockCanvas(JNIEnv* env, jobject,
SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer->getPixelFormat());
SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
swapCanvasPtr(env, canvas, nativeCanvas);
INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
SkRect clipRect;
clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
@@ -233,7 +219,7 @@ static jboolean android_view_GraphicBuffer_unlockCanvasAndPost(JNIEnv* env, jobj
GraphicBufferWrapper* wrapper =
reinterpret_cast<GraphicBufferWrapper*>(wrapperHandle);
SkCanvas* nativeCanvas = SkNEW(SkCanvas);
swapCanvasPtr(env, canvas, nativeCanvas);
INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
if (wrapper) {
status_t status = wrapper->buffer->unlock();
@@ -332,13 +318,8 @@ int register_android_view_GraphicBuffer(JNIEnv* env) {
GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I");
FIND_CLASS(clazz, "android/graphics/Canvas");
GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer",
"Landroid/graphics/Canvas$CanvasFinalizer;");
GET_FIELD_ID(gCanvasClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "J");
GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");
FIND_CLASS(clazz, "android/graphics/Canvas$CanvasFinalizer");
GET_FIELD_ID(gCanvasFinalizerClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "J");
GET_METHOD_ID(gCanvasClassInfo.safeCanvasSwap, clazz, "safeCanvasSwap", "(JZ)V");
return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}

View File

@@ -69,15 +69,10 @@ static struct {
} gRectClassInfo;
static struct {
jfieldID mFinalizer;
jfieldID mNativeCanvas;
jfieldID mSurfaceFormat;
jmethodID safeCanvasSwap;
} gCanvasClassInfo;
static struct {
jfieldID mNativeCanvas;
} gCanvasFinalizerClassInfo;
// ----------------------------------------------------------------------------
// this is just a pointer we use to pass to inc/decStrong
@@ -191,15 +186,6 @@ static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
}
}
static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
env->GetLongField(canvasObj, gCanvasClassInfo.mNativeCanvas));
env->SetLongField(canvasObj, gCanvasClassInfo.mNativeCanvas, (jlong)newCanvas);
env->SetLongField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (jlong)newCanvas);
SkSafeUnref(previousCanvas);
}
static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
jlong nativeObject, jobject canvasObj, jobject dirtyRectObj) {
sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
@@ -247,7 +233,7 @@ static jlong nativeLockCanvas(JNIEnv* env, jclass clazz,
}
SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
swapCanvasPtr(env, canvasObj, nativeCanvas);
env->CallVoidMethod(canvasObj, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
if (dirtyRectPtr) {
nativeCanvas->clipRect( SkRect::Make(reinterpret_cast<const SkIRect&>(dirtyRect)) );
@@ -277,7 +263,7 @@ static void nativeUnlockCanvasAndPost(JNIEnv* env, jclass clazz,
// detach the canvas from the surface
SkCanvas* nativeCanvas = SkNEW(SkCanvas);
swapCanvasPtr(env, canvasObj, nativeCanvas);
env->CallVoidMethod(canvasObj, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
// unlock surface
status_t err = surface->unlockAndPost();
@@ -388,12 +374,8 @@ int register_android_view_Surface(JNIEnv* env)
gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "(J)V");
clazz = env->FindClass("android/graphics/Canvas");
gCanvasClassInfo.mFinalizer = env->GetFieldID(clazz, "mFinalizer", "Landroid/graphics/Canvas$CanvasFinalizer;");
gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "J");
gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
clazz = env->FindClass("android/graphics/Canvas$CanvasFinalizer");
gCanvasFinalizerClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "J");
gCanvasClassInfo.safeCanvasSwap = env->GetMethodID(clazz, "safeCanvasSwap", "(JZ)V");
clazz = env->FindClass("android/graphics/Rect");
gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");

View File

@@ -44,15 +44,10 @@ static struct {
} gRectClassInfo;
static struct {
jfieldID mFinalizer;
jfieldID mNativeCanvas;
jfieldID mSurfaceFormat;
jmethodID safeCanvasSwap;
} gCanvasClassInfo;
static struct {
jfieldID mNativeCanvas;
} gCanvasFinalizerClassInfo;
static struct {
jfieldID nativeWindow;
} gTextureViewClassInfo;
@@ -125,15 +120,6 @@ static void android_view_TextureView_destroyNativeWindow(JNIEnv* env, jobject te
}
}
static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
env->GetLongField(canvasObj, gCanvasClassInfo.mNativeCanvas));
env->SetLongField(canvasObj, gCanvasClassInfo.mNativeCanvas, (jlong)newCanvas);
env->SetLongField(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (jlong)newCanvas);
SkSafeUnref(previousCanvas);
}
static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
jlong nativeWindow, jobject canvas, jobject dirtyRect) {
@@ -175,7 +161,7 @@ static jboolean android_view_TextureView_lockCanvas(JNIEnv* env, jobject,
SET_INT(canvas, gCanvasClassInfo.mSurfaceFormat, buffer.format);
SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (bitmap));
swapCanvasPtr(env, canvas, nativeCanvas);
INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
SkRect clipRect;
clipRect.set(rect.left, rect.top, rect.right, rect.bottom);
@@ -193,7 +179,7 @@ static void android_view_TextureView_unlockCanvasAndPost(JNIEnv* env, jobject,
jlong nativeWindow, jobject canvas) {
SkCanvas* nativeCanvas = SkNEW(SkCanvas);
swapCanvasPtr(env, canvas, nativeCanvas);
INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
if (nativeWindow) {
sp<ANativeWindow> window((ANativeWindow*) nativeWindow);
@@ -241,13 +227,8 @@ int register_android_view_TextureView(JNIEnv* env) {
GET_FIELD_ID(gRectClassInfo.bottom, clazz, "bottom", "I");
FIND_CLASS(clazz, "android/graphics/Canvas");
GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer",
"Landroid/graphics/Canvas$CanvasFinalizer;");
GET_FIELD_ID(gCanvasClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "J");
GET_FIELD_ID(gCanvasClassInfo.mSurfaceFormat, clazz, "mSurfaceFormat", "I");
FIND_CLASS(clazz, "android/graphics/Canvas$CanvasFinalizer");
GET_FIELD_ID(gCanvasFinalizerClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "J");
GET_METHOD_ID(gCanvasClassInfo.safeCanvasSwap, clazz, "safeCanvasSwap", "(JZ)V");
FIND_CLASS(clazz, "android/view/TextureView");
GET_FIELD_ID(gTextureViewClassInfo.nativeWindow, clazz, "mNativeWindow", "J");

View File

@@ -154,7 +154,7 @@ public class Camera {
getMatrix(mMatrix);
canvas.concat(mMatrix);
} else {
nativeApplyToCanvas(canvas.mNativeCanvas);
nativeApplyToCanvas(canvas.getNativeCanvas());
}
}

View File

@@ -39,8 +39,12 @@ import javax.microedition.khronos.opengles.GL;
public class Canvas {
// assigned in constructors or setBitmap, freed in finalizer
private long mNativeCanvas;
/** @hide */
public long mNativeCanvas;
public long getNativeCanvas() {
return mNativeCanvas;
}
// may be null
private Bitmap mBitmap;

View File

@@ -164,12 +164,12 @@ public class NinePatch {
}
void drawSoftware(Canvas canvas, RectF location, Paint paint) {
nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk,
nativeDraw(canvas.getNativeCanvas(), location, mBitmap.ni(), mNativeChunk,
paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
}
void drawSoftware(Canvas canvas, Rect location, Paint paint) {
nativeDraw(canvas.mNativeCanvas, location, mBitmap.ni(), mNativeChunk,
nativeDraw(canvas.getNativeCanvas(), location, mBitmap.ni(), mNativeChunk,
paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
}

View File

@@ -107,7 +107,7 @@ public class Picture {
if (mRecordingCanvas != null) {
endRecording();
}
nativeDraw(canvas.mNativeCanvas, mNativePicture);
nativeDraw(canvas.getNativeCanvas(), mNativePicture);
}
/**

View File

@@ -46,33 +46,16 @@ namespace android {
// ----------------------------------------------------------------------------
static struct {
jfieldID mFinalizer;
jfieldID mNativeCanvas;
jmethodID safeCanvasSwap;
} gCanvasClassInfo;
static struct {
jfieldID mNativeCanvas;
} gCanvasFinalizerClassInfo;
#define GET_LONG(object, field) \
env->GetLongField(object, field)
#define SET_LONG(object, field, value) \
env->SetLongField(object, field, value)
#define INVOKEV(object, method, ...) \
env->CallVoidMethod(object, method, __VA_ARGS__)
// ----------------------------------------------------------------------------
// Canvas management
// ----------------------------------------------------------------------------
static inline void swapCanvasPtr(JNIEnv* env, jobject canvasObj, SkCanvas* newCanvas) {
jobject canvasFinalizerObj = env->GetObjectField(canvasObj, gCanvasClassInfo.mFinalizer);
SkCanvas* previousCanvas = reinterpret_cast<SkCanvas*>(
GET_LONG(canvasObj, gCanvasClassInfo.mNativeCanvas));
SET_LONG(canvasObj, gCanvasClassInfo.mNativeCanvas, (long) newCanvas);
SET_LONG(canvasFinalizerObj, gCanvasFinalizerClassInfo.mNativeCanvas, (long) newCanvas);
SkSafeUnref(previousCanvas);
}
static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, jobject,
jobject canvas, jint width, jint height) {
@@ -82,7 +65,7 @@ static jlong com_android_server_AssetAtlasService_acquireCanvas(JNIEnv* env, job
bitmap->eraseColor(0);
SkCanvas* nativeCanvas = SkNEW_ARGS(SkCanvas, (*bitmap));
swapCanvasPtr(env, canvas, nativeCanvas);
INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
return reinterpret_cast<jlong>(bitmap);
}
@@ -92,7 +75,7 @@ static void com_android_server_AssetAtlasService_releaseCanvas(JNIEnv* env, jobj
SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
SkCanvas* nativeCanvas = SkNEW(SkCanvas);
swapCanvasPtr(env, canvas, nativeCanvas);
INVOKEV(canvas, gCanvasClassInfo.safeCanvasSwap, (jlong)nativeCanvas, false);
delete bitmap;
}
@@ -242,9 +225,9 @@ static jboolean com_android_server_AssetAtlasService_upload(JNIEnv* env, jobject
var = env->FindClass(className); \
LOG_FATAL_IF(! var, "Unable to find class " className);
#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
LOG_FATAL_IF(! var, "Unable to find field " fieldName);
#define GET_METHOD_ID(var, clazz, methodName, methodDescriptor) \
var = env->GetMethodID(clazz, methodName, methodDescriptor); \
LOG_FATAL_IF(!var, "Unable to find method " methodName);
const char* const kClassPathName = "com/android/server/AssetAtlasService";
@@ -261,12 +244,7 @@ int register_android_server_AssetAtlasService(JNIEnv* env) {
jclass clazz;
FIND_CLASS(clazz, "android/graphics/Canvas");
GET_FIELD_ID(gCanvasClassInfo.mFinalizer, clazz, "mFinalizer",
"Landroid/graphics/Canvas$CanvasFinalizer;");
GET_FIELD_ID(gCanvasClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "J");
FIND_CLASS(clazz, "android/graphics/Canvas$CanvasFinalizer");
GET_FIELD_ID(gCanvasFinalizerClassInfo.mNativeCanvas, clazz, "mNativeCanvas", "J");
GET_METHOD_ID(gCanvasClassInfo.safeCanvasSwap, clazz, "safeCanvasSwap", "(JZ)V");
return jniRegisterNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
}

View File

@@ -71,7 +71,7 @@ public final class Canvas_Delegate {
* Returns the native delegate associated to a given {@link Canvas} object.
*/
public static Canvas_Delegate getDelegate(Canvas canvas) {
return sManager.getDelegate(canvas.mNativeCanvas);
return sManager.getDelegate(canvas.getNativeCanvas());
}
/**
@@ -102,7 +102,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static boolean isOpaque(Canvas thisCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return false;
}
@@ -113,7 +113,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static int getWidth(Canvas thisCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return 0;
}
@@ -124,7 +124,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static int getHeight(Canvas thisCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return 0;
}
@@ -135,7 +135,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void translate(Canvas thisCanvas, float dx, float dy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return;
}
@@ -146,7 +146,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void rotate(Canvas thisCanvas, float degrees) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return;
}
@@ -157,7 +157,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void scale(Canvas thisCanvas, float sx, float sy) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return;
}
@@ -168,7 +168,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void skew(Canvas thisCanvas, float kx, float ky) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return;
}
@@ -204,7 +204,7 @@ public final class Canvas_Delegate {
/*package*/ static boolean clipRect(Canvas thisCanvas, float left, float top, float right,
float bottom) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return false;
}
@@ -227,7 +227,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static int save(Canvas thisCanvas, int saveFlags) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return 0;
}
@@ -238,7 +238,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void restore(Canvas thisCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return;
}
@@ -249,7 +249,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static int getSaveCount(Canvas thisCanvas) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return 0;
}
@@ -260,7 +260,7 @@ public final class Canvas_Delegate {
@LayoutlibDelegate
/*package*/ static void restoreToCount(Canvas thisCanvas, int saveCount) {
// get the delegate from the native int.
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.mNativeCanvas);
Canvas_Delegate canvasDelegate = sManager.getDelegate(thisCanvas.getNativeCanvas());
if (canvasDelegate == null) {
return;
}
@@ -287,7 +287,7 @@ public final class Canvas_Delegate {
/*package*/ static void drawLines(Canvas thisCanvas,
final float[] pts, final int offset, final int count,
Paint paint) {
draw(thisCanvas.mNativeCanvas, paint.mNativePaint, false /*compositeOnly*/,
draw(thisCanvas.getNativeCanvas(), paint.mNativePaint, false /*compositeOnly*/,
false /*forceSrcMode*/, new GcSnapshot.Drawable() {
@Override
public void draw(Graphics2D graphics, Paint_Delegate paintDelegate) {