OSDN Git Service

Mutable Java Shaders with Immutable Native Shaders
authorDerek Sollenberger <djsollen@google.com>
Tue, 2 Sep 2014 19:42:54 +0000 (15:42 -0400)
committerDerek Sollenberger <djsollen@google.com>
Mon, 6 Oct 2014 17:04:45 +0000 (13:04 -0400)
bug: 17641888
Change-Id: I0f05387423cde185dab1a1453f89d5251ca1a4f9

12 files changed:
core/java/android/view/GLES20Canvas.java
core/java/android/view/HardwareLayer.java
core/java/android/view/RenderNode.java
core/jni/android/graphics/Shader.cpp
graphics/java/android/graphics/Bitmap.java
graphics/java/android/graphics/Canvas.java
graphics/java/android/graphics/CanvasProperty.java
graphics/java/android/graphics/LayerRasterizer.java
graphics/java/android/graphics/Movie.java
graphics/java/android/graphics/NinePatch.java
graphics/java/android/graphics/Paint.java
graphics/java/android/graphics/Shader.java

index 1b57c24..08aa472 100644 (file)
@@ -447,7 +447,7 @@ class GLES20Canvas extends HardwareCanvas {
             return saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, paint, saveFlags);
         }
 
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
         return nSaveLayer(mRenderer, nativePaint, saveFlags);
     }
 
@@ -457,7 +457,7 @@ class GLES20Canvas extends HardwareCanvas {
     public int saveLayer(float left, float top, float right, float bottom, Paint paint,
             int saveFlags) {
         if (left < right && top < bottom) {
-            final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+            final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
             return nSaveLayer(mRenderer, left, top, right, bottom, nativePaint, saveFlags);
         }
         return save(saveFlags);
@@ -541,7 +541,7 @@ class GLES20Canvas extends HardwareCanvas {
     public void drawArc(float left, float top, float right, float bottom,
             float startAngle, float sweepAngle, boolean useCenter, Paint paint) {
         nDrawArc(mRenderer, left, top, right, bottom,
-                startAngle, sweepAngle, useCenter, paint.mNativePaint);
+                startAngle, sweepAngle, useCenter, paint.getNativeInstance());
     }
 
     private static native void nDrawArc(long renderer, float left, float top,
@@ -557,7 +557,7 @@ class GLES20Canvas extends HardwareCanvas {
     public void drawPatch(NinePatch patch, Rect dst, Paint paint) {
         Bitmap bitmap = patch.getBitmap();
         throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
         nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
                 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
     }
@@ -566,7 +566,7 @@ class GLES20Canvas extends HardwareCanvas {
     public void drawPatch(NinePatch patch, RectF dst, Paint paint) {
         Bitmap bitmap = patch.getBitmap();
         throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
         nDrawPatch(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, patch.mNativeChunk,
                 dst.left, dst.top, dst.right, dst.bottom, nativePaint);
     }
@@ -577,7 +577,7 @@ class GLES20Canvas extends HardwareCanvas {
     @Override
     public void drawBitmap(Bitmap bitmap, float left, float top, Paint paint) {
         throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
         nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, left, top, nativePaint);
     }
 
@@ -587,7 +587,7 @@ class GLES20Canvas extends HardwareCanvas {
     @Override
     public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
         throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
         nDrawBitmap(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer,
                 matrix.native_instance, nativePaint);
     }
@@ -598,7 +598,7 @@ class GLES20Canvas extends HardwareCanvas {
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
         throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
 
         int left, top, right, bottom;
         if (src == null) {
@@ -619,7 +619,7 @@ class GLES20Canvas extends HardwareCanvas {
     @Override
     public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
         throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
 
         float left, top, right, bottom;
         if (src == null) {
@@ -664,7 +664,7 @@ class GLES20Canvas extends HardwareCanvas {
             throw new ArrayIndexOutOfBoundsException();
         }
 
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
         nDrawBitmap(mRenderer, colors, offset, stride, x, y,
                 width, height, hasAlpha, nativePaint);
     }
@@ -697,7 +697,7 @@ class GLES20Canvas extends HardwareCanvas {
             checkRange(colors.length, colorOffset, count);
         }
 
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
         nDrawBitmapMesh(mRenderer, bitmap.mNativeBitmap, bitmap.mBuffer, meshWidth, meshHeight,
                 verts, vertOffset, colors, colorOffset, nativePaint);
     }
@@ -708,7 +708,7 @@ class GLES20Canvas extends HardwareCanvas {
 
     @Override
     public void drawCircle(float cx, float cy, float radius, Paint paint) {
-        nDrawCircle(mRenderer, cx, cy, radius, paint.mNativePaint);
+        nDrawCircle(mRenderer, cx, cy, radius, paint.getNativeInstance());
     }
 
     private static native void nDrawCircle(long renderer, float cx, float cy,
@@ -766,7 +766,7 @@ class GLES20Canvas extends HardwareCanvas {
         if ((offset | count) < 0 || offset + count > pts.length) {
             throw new IllegalArgumentException("The lines array must contain 4 elements per line.");
         }
-        nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint);
+        nDrawLines(mRenderer, pts, offset, count, paint.getNativeInstance());
     }
 
     private static native void nDrawLines(long renderer, float[] points,
@@ -779,7 +779,7 @@ class GLES20Canvas extends HardwareCanvas {
 
     @Override
     public void drawOval(float left, float top, float right, float bottom, Paint paint) {
-        nDrawOval(mRenderer, left, top, right, bottom, paint.mNativePaint);
+        nDrawOval(mRenderer, left, top, right, bottom, paint.getNativeInstance());
     }
 
     private static native void nDrawOval(long renderer, float left, float top,
@@ -796,10 +796,10 @@ class GLES20Canvas extends HardwareCanvas {
     public void drawPath(Path path, Paint paint) {
         if (path.isSimplePath) {
             if (path.rects != null) {
-                nDrawRects(mRenderer, path.rects.mNativeRegion, paint.mNativePaint);
+                nDrawRects(mRenderer, path.rects.mNativeRegion, paint.getNativeInstance());
             }
         } else {
-            nDrawPath(mRenderer, path.mNativePath, paint.mNativePaint);
+            nDrawPath(mRenderer, path.mNativePath, paint.getNativeInstance());
         }
     }
 
@@ -829,7 +829,7 @@ class GLES20Canvas extends HardwareCanvas {
     public void drawPoints(float[] pts, int offset, int count, Paint paint) {
         if (count < 2) return;
 
-        nDrawPoints(mRenderer, pts, offset, count, paint.mNativePaint);
+        nDrawPoints(mRenderer, pts, offset, count, paint.getNativeInstance());
     }
 
     private static native void nDrawPoints(long renderer, float[] points,
@@ -840,7 +840,7 @@ class GLES20Canvas extends HardwareCanvas {
     @Override
     public void drawRect(float left, float top, float right, float bottom, Paint paint) {
         if (left == right || top == bottom) return;
-        nDrawRect(mRenderer, left, top, right, bottom, paint.mNativePaint);
+        nDrawRect(mRenderer, left, top, right, bottom, paint.getNativeInstance());
     }
 
     private static native void nDrawRect(long renderer, float left, float top,
@@ -864,7 +864,7 @@ class GLES20Canvas extends HardwareCanvas {
     @Override
     public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
             Paint paint) {
-        nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
+        nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.getNativeInstance());
     }
 
     private static native void nDrawRoundRect(long renderer, float left, float top,
@@ -877,7 +877,7 @@ class GLES20Canvas extends HardwareCanvas {
         }
 
         nDrawText(mRenderer, text, index, count, x, y,
-                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     private static native void nDrawText(long renderer, char[] text, int index, int count,
@@ -888,14 +888,14 @@ class GLES20Canvas extends HardwareCanvas {
         if (text instanceof String || text instanceof SpannedString ||
                 text instanceof SpannableString) {
             nDrawText(mRenderer, text.toString(), start, end, x, y, paint.mBidiFlags,
-                    paint.mNativePaint, paint.mNativeTypeface);
+                    paint.getNativeInstance(), paint.mNativeTypeface);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawText(this, start, end, x, y, paint);
         } else {
             char[] buf = TemporaryBuffer.obtain(end - start);
             TextUtils.getChars(text, start, end, buf, 0);
             nDrawText(mRenderer, buf, 0, end - start, x, y,
-                    paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
             TemporaryBuffer.recycle(buf);
         }
     }
@@ -907,7 +907,7 @@ class GLES20Canvas extends HardwareCanvas {
         }
 
         nDrawText(mRenderer, text, start, end, x, y,
-                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     private static native void nDrawText(long renderer, String text, int start, int end,
@@ -916,7 +916,7 @@ class GLES20Canvas extends HardwareCanvas {
     @Override
     public void drawText(String text, float x, float y, Paint paint) {
         nDrawText(mRenderer, text, 0, text.length(), x, y,
-                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     @Override
@@ -927,7 +927,7 @@ class GLES20Canvas extends HardwareCanvas {
         }
 
         nDrawTextOnPath(mRenderer, text, index, count, path.mNativePath, hOffset, vOffset,
-                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     private static native void nDrawTextOnPath(long renderer, char[] text, int index, int count,
@@ -939,7 +939,7 @@ class GLES20Canvas extends HardwareCanvas {
         if (text.length() == 0) return;
 
         nDrawTextOnPath(mRenderer, text, 0, text.length(), path.mNativePath, hOffset, vOffset,
-                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     private static native void nDrawTextOnPath(long renderer, String text, int start, int end,
@@ -954,7 +954,7 @@ class GLES20Canvas extends HardwareCanvas {
         }
 
         nDrawTextRun(mRenderer, text, index, count, contextIndex, contextCount, x, y, isRtl,
-                paint.mNativePaint, paint.mNativeTypeface);
+                paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     private static native void nDrawTextRun(long renderer, char[] text, int index, int count,
@@ -970,7 +970,7 @@ class GLES20Canvas extends HardwareCanvas {
         if (text instanceof String || text instanceof SpannedString ||
                 text instanceof SpannableString) {
             nDrawTextRun(mRenderer, text.toString(), start, end, contextStart,
-                    contextEnd, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+                    contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawTextRun(this, start, end,
                     contextStart, contextEnd, x, y, isRtl, paint);
@@ -980,7 +980,7 @@ class GLES20Canvas extends HardwareCanvas {
             char[] buf = TemporaryBuffer.obtain(contextLen);
             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
             nDrawTextRun(mRenderer, buf, start - contextStart, len, 0, contextLen,
-                    x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+                    x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
             TemporaryBuffer.recycle(buf);
         }
     }
index 0c2e944..be2a990 100644 (file)
@@ -52,7 +52,7 @@ final class HardwareLayer {
      * @see View#setLayerPaint(android.graphics.Paint)
      */
     public void setLayerPaint(Paint paint) {
-        nSetLayerPaint(mFinalizer.get(), paint.mNativePaint);
+        nSetLayerPaint(mFinalizer.get(), paint.getNativeInstance());
         mRenderer.pushLayerUpdate(this);
     }
 
index 47f72a8..09eb486 100644 (file)
@@ -305,7 +305,7 @@ public class RenderNode {
     }
 
     public boolean setLayerPaint(Paint paint) {
-        return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.mNativePaint : 0);
+        return nSetLayerPaint(mNativeRenderNode, paint != null ? paint.getNativeInstance() : 0);
     }
 
     public boolean setClipBounds(@Nullable Rect rect) {
index e02aa5e..8f7f3fc 100644 (file)
@@ -56,17 +56,31 @@ static void Shader_destructor(JNIEnv* env, jobject o, jlong shaderHandle, jlong
     SkSafeUnref(shader);
 }
 
-static void Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle)
+static jlong Shader_setLocalMatrix(JNIEnv* env, jobject o, jlong shaderHandle, jlong matrixHandle)
 {
-    SkShader* shader       = reinterpret_cast<SkShader*>(shaderHandle);
+    // ensure we have a valid matrix to use
     const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
-    if (shader) {
-        if (matrix) {
-            shader->setLocalMatrix(*matrix);
-        } else {
-            shader->resetLocalMatrix();
+    if (NULL == matrix) {
+        matrix = &SkMatrix::I();
+    }
+
+    // The current shader will no longer need a direct reference owned by Shader.java
+    // as all the data needed is contained within the newly created LocalMatrixShader.
+    SkASSERT(shaderHandle);
+    SkAutoTUnref<SkShader> currentShader(reinterpret_cast<SkShader*>(shaderHandle));
+
+    SkMatrix currentMatrix;
+    SkAutoTUnref<SkShader> baseShader(currentShader->refAsALocalMatrixShader(&currentMatrix));
+    if (baseShader.get()) {
+        // if the matrices are same then there is no need to allocate a new
+        // shader that is identical to the existing one.
+        if (currentMatrix == *matrix) {
+            return reinterpret_cast<jlong>(currentShader.detach());
         }
+        return reinterpret_cast<jlong>(SkShader::CreateLocalMatrixShader(baseShader, *matrix));
     }
+
+    return reinterpret_cast<jlong>(SkShader::CreateLocalMatrixShader(currentShader, *matrix));
 }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////
@@ -237,7 +251,7 @@ static JNINativeMethod gColorMethods[] = {
 
 static JNINativeMethod gShaderMethods[] = {
     { "nativeDestructor",        "(J)V",    (void*)Shader_destructor        },
-    { "nativeSetLocalMatrix",    "(JJ)V",   (void*)Shader_setLocalMatrix    }
+    { "nativeSetLocalMatrix",    "(JJ)J",   (void*)Shader_setLocalMatrix    }
 };
 
 static JNINativeMethod gBitmapShaderMethods[] = {
index 3090ffd..004d0ae 100644 (file)
@@ -1542,7 +1542,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.mNativePaint : 0;
+        long nativePaint = paint != null ? paint.getNativeInstance() : 0;
         Bitmap bm = nativeExtractAlpha(mNativeBitmap, nativePaint, offsetXY);
         if (bm == null) {
             throw new RuntimeException("Failed to extractAlpha on Bitmap");
index f45c0cb..edf0fb9 100644 (file)
@@ -430,7 +430,7 @@ public class Canvas {
     public int saveLayer(float left, float top, float right, float bottom, @Nullable Paint paint,
             @Saveflags int saveFlags) {
         return native_saveLayer(mNativeCanvasWrapper, left, top, right, bottom,
-                paint != null ? paint.mNativePaint : 0,
+                paint != null ? paint.getNativeInstance() : 0,
                 saveFlags);
     }
 
@@ -974,7 +974,7 @@ public class Canvas {
      * @param paint The paint used to draw onto the canvas
      */
     public void drawPaint(@NonNull Paint paint) {
-        native_drawPaint(mNativeCanvasWrapper, paint.mNativePaint);
+        native_drawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
     }
 
     /**
@@ -994,7 +994,7 @@ public class Canvas {
      * @param paint    The paint used to draw the points
      */
     public void drawPoints(float[] pts, int offset, int count, @NonNull Paint paint) {
-        native_drawPoints(mNativeCanvasWrapper, pts, offset, count, paint.mNativePaint);
+        native_drawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
     }
 
     /**
@@ -1008,7 +1008,7 @@ public class Canvas {
      * Helper for drawPoints() for drawing a single point.
      */
     public void drawPoint(float x, float y, @NonNull Paint paint) {
-        native_drawPoint(mNativeCanvasWrapper, x, y, paint.mNativePaint);
+        native_drawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
     }
 
     /**
@@ -1025,7 +1025,7 @@ public class Canvas {
      */
     public void drawLine(float startX, float startY, float stopX, float stopY,
             @NonNull Paint paint) {
-        native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.mNativePaint);
+        native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
     }
 
     /**
@@ -1044,7 +1044,7 @@ public class Canvas {
      * @param paint    The paint used to draw the points
      */
     public void drawLines(float[] pts, int offset, int count, Paint paint) {
-        native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.mNativePaint);
+        native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
     }
 
     public void drawLines(@NonNull float[] pts, @NonNull Paint paint) {
@@ -1060,7 +1060,7 @@ public class Canvas {
      */
     public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
         native_drawRect(mNativeCanvasWrapper,
-                rect.left, rect.top, rect.right, rect.bottom, paint.mNativePaint);
+                rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
     }
 
     /**
@@ -1086,7 +1086,7 @@ public class Canvas {
      * @param paint  The paint used to draw the rect
      */
     public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
-        native_drawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.mNativePaint);
+        native_drawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
     }
 
     /**
@@ -1107,7 +1107,7 @@ public class Canvas {
      * filled or framed based on the Style in the paint.
      */
     public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
-        native_drawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.mNativePaint);
+        native_drawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
     }
 
     /**
@@ -1121,7 +1121,7 @@ public class Canvas {
      * @param paint  The paint used to draw the circle
      */
     public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
-        native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.mNativePaint);
+        native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
     }
 
     /**
@@ -1177,7 +1177,7 @@ public class Canvas {
     public void drawArc(float left, float top, float right, float bottom, float startAngle,
             float sweepAngle, boolean useCenter, @NonNull Paint paint) {
         native_drawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
-                useCenter, paint.mNativePaint);
+                useCenter, paint.getNativeInstance());
     }
 
     /**
@@ -1203,7 +1203,7 @@ public class Canvas {
      */
     public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
             @NonNull Paint paint) {
-        native_drawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, paint.mNativePaint);
+        native_drawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry, paint.getNativeInstance());
     }
 
     /**
@@ -1214,7 +1214,7 @@ public class Canvas {
      * @param paint The paint used to draw the path
      */
     public void drawPath(@NonNull Path path, @NonNull Paint paint) {
-        native_drawPath(mNativeCanvasWrapper, path.ni(), paint.mNativePaint);
+        native_drawPath(mNativeCanvasWrapper, path.ni(), paint.getNativeInstance());
     }
 
     /**
@@ -1279,7 +1279,7 @@ public class Canvas {
     public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
         throwIfCannotDraw(bitmap);
         native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), left, top,
-                paint != null ? paint.mNativePaint : 0, mDensity, mScreenDensity, bitmap.mDensity);
+                paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
     }
 
     /**
@@ -1310,7 +1310,7 @@ public class Canvas {
           throw new NullPointerException();
       }
       throwIfCannotDraw(bitmap);
-      final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+      final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
 
       float left, top, right, bottom;
       if (src == null) {
@@ -1357,7 +1357,7 @@ public class Canvas {
             throw new NullPointerException();
         }
         throwIfCannotDraw(bitmap);
-        final long nativePaint = paint == null ? 0 : paint.mNativePaint;
+        final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
 
         int left, top, right, bottom;
         if (src == null) {
@@ -1425,7 +1425,7 @@ public class Canvas {
         }
         // punch down to native for the actual draw
         native_drawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
-                paint != null ? paint.mNativePaint : 0);
+                paint != null ? paint.getNativeInstance() : 0);
     }
 
     /**
@@ -1453,7 +1453,7 @@ public class Canvas {
      */
     public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
         nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap.ni(), matrix.ni(),
-                paint != null ? paint.mNativePaint : 0);
+                paint != null ? paint.getNativeInstance() : 0);
     }
 
     /**
@@ -1509,7 +1509,7 @@ public class Canvas {
         }
         nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap.ni(), meshWidth, meshHeight,
                 verts, vertOffset, colors, colorOffset,
-                paint != null ? paint.mNativePaint : 0);
+                paint != null ? paint.getNativeInstance() : 0);
     }
 
     public enum VertexMode {
@@ -1573,7 +1573,7 @@ public class Canvas {
         }
         nativeDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
                 vertOffset, texs, texOffset, colors, colorOffset,
-                indices, indexOffset, indexCount, paint.mNativePaint);
+                indices, indexOffset, indexCount, paint.getNativeInstance());
     }
 
     /**
@@ -1592,7 +1592,7 @@ public class Canvas {
             throw new IndexOutOfBoundsException();
         }
         native_drawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
-                paint.mNativePaint, paint.mNativeTypeface);
+                paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     /**
@@ -1606,7 +1606,7 @@ public class Canvas {
      */
     public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
         native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
-                paint.mNativePaint, paint.mNativeTypeface);
+                paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     /**
@@ -1626,7 +1626,7 @@ public class Canvas {
             throw new IndexOutOfBoundsException();
         }
         native_drawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
-                paint.mNativePaint, paint.mNativeTypeface);
+                paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     /**
@@ -1647,7 +1647,7 @@ public class Canvas {
         if (text instanceof String || text instanceof SpannedString ||
             text instanceof SpannableString) {
             native_drawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
-                    paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawText(this, start, end, x, y,
                     paint);
@@ -1655,7 +1655,7 @@ public class Canvas {
             char[] buf = TemporaryBuffer.obtain(end - start);
             TextUtils.getChars(text, start, end, buf, 0);
             native_drawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
-                    paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
             TemporaryBuffer.recycle(buf);
         }
     }
@@ -1694,7 +1694,7 @@ public class Canvas {
         }
 
         native_drawTextRun(mNativeCanvasWrapper, text, index, count,
-                contextIndex, contextCount, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+                contextIndex, contextCount, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     /**
@@ -1730,7 +1730,7 @@ public class Canvas {
         if (text instanceof String || text instanceof SpannedString ||
                 text instanceof SpannableString) {
             native_drawTextRun(mNativeCanvasWrapper, text.toString(), start, end,
-                    contextStart, contextEnd, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+                    contextStart, contextEnd, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
         } else if (text instanceof GraphicsOperations) {
             ((GraphicsOperations) text).drawTextRun(this, start, end,
                     contextStart, contextEnd, x, y, isRtl, paint);
@@ -1740,7 +1740,7 @@ public class Canvas {
             char[] buf = TemporaryBuffer.obtain(contextLen);
             TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
             native_drawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
-                    0, contextLen, x, y, isRtl, paint.mNativePaint, paint.mNativeTypeface);
+                    0, contextLen, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
             TemporaryBuffer.recycle(buf);
         }
     }
@@ -1808,7 +1808,7 @@ public class Canvas {
         }
         native_drawTextOnPath(mNativeCanvasWrapper, text, index, count,
                 path.ni(), hOffset, vOffset,
-                paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
     }
 
     /**
@@ -1828,7 +1828,7 @@ public class Canvas {
             float vOffset, @NonNull Paint paint) {
         if (text.length() > 0) {
             native_drawTextOnPath(mNativeCanvasWrapper, text, path.ni(), hOffset, vOffset,
-                    paint.mBidiFlags, paint.mNativePaint, paint.mNativeTypeface);
+                    paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
         }
     }
 
index be86060..ea3886c 100644 (file)
@@ -31,7 +31,7 @@ public final class CanvasProperty<T> {
     }
 
     public static CanvasProperty<Paint> createPaint(Paint initialValue) {
-        return new CanvasProperty<Paint>(nCreatePaint(initialValue.mNativePaint));
+        return new CanvasProperty<Paint>(nCreatePaint(initialValue.getNativeInstance()));
     }
 
     private CanvasProperty(long nativeContainer) {
index e7a24a4..b692ecf 100644 (file)
@@ -28,11 +28,11 @@ public class LayerRasterizer extends Rasterizer {
         object itself, so it may be reused without danger of side-effects.
     */
     public void addLayer(Paint paint, float dx, float dy) {
-        nativeAddLayer(native_instance, paint.mNativePaint, dx, dy);
+        nativeAddLayer(native_instance, paint.getNativeInstance(), dx, dy);
     }
 
     public void addLayer(Paint paint) {
-        nativeAddLayer(native_instance, paint.mNativePaint, 0, 0);
+        nativeAddLayer(native_instance, paint.getNativeInstance(), 0, 0);
     }
 
     private static native long nativeConstructor();
index ba37340..dd5b62d 100644 (file)
@@ -40,7 +40,7 @@ public class Movie {
     private native void nDraw(Canvas canvas, float x, float y, long paintHandle);
 
     public void draw(Canvas canvas, float x, float y, Paint paint) {
-        nDraw(canvas, x, y, paint != null ? paint.mNativePaint : 0);
+        nDraw(canvas, x, y, paint != null ? paint.getNativeInstance() : 0);
     }
 
     public void draw(Canvas canvas, float x, float y) {
index 6f42046..ebc86aa 100644 (file)
@@ -200,12 +200,12 @@ public class NinePatch {
 
     void drawSoftware(Canvas canvas, RectF location, Paint paint) {
         nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.ni(), mNativeChunk,
-                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
+                paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
     }
 
     void drawSoftware(Canvas canvas, Rect location, Paint paint) {
         nativeDraw(canvas.getNativeCanvasWrapper(), location, mBitmap.ni(), mNativeChunk,
-                paint != null ? paint.mNativePaint : 0, canvas.mDensity, mBitmap.mDensity);
+                paint != null ? paint.getNativeInstance() : 0, canvas.mDensity, mBitmap.mDensity);
     }
 
     /**
index 652fe64..ac61518 100644 (file)
@@ -29,10 +29,9 @@ import java.util.Locale;
  */
 public class Paint {
 
-    /**
-     * @hide
-     */
-    public long mNativePaint;
+    private long mNativePaint;
+    private long mNativeShader = 0;
+
     /**
      * @hide
      */
@@ -445,7 +444,7 @@ public class Paint {
      *              new paint.
      */
     public Paint(Paint paint) {
-        mNativePaint = native_initWithPaint(paint.mNativePaint);
+        mNativePaint = native_initWithPaint(paint.getNativeInstance());
         setClassVariablesFrom(paint);
     }
 
@@ -464,6 +463,7 @@ public class Paint {
         mPathEffect = null;
         mRasterizer = null;
         mShader = null;
+        mNativeShader = 0;
         mTypeface = null;
         mNativeTypeface = 0;
         mXfermode = null;
@@ -500,11 +500,8 @@ public class Paint {
         mMaskFilter = paint.mMaskFilter;
         mPathEffect = paint.mPathEffect;
         mRasterizer = paint.mRasterizer;
-        if (paint.mShader != null) {
-            mShader = paint.mShader.copy();
-        } else {
-            mShader = null;
-        }
+        mShader = paint.mShader;
+        mNativeShader = paint.mNativeShader;
         mTypeface = paint.mTypeface;
         mNativeTypeface = paint.mNativeTypeface;
         mXfermode = paint.mXfermode;
@@ -531,6 +528,19 @@ public class Paint {
     }
 
     /**
+     * Return the pointer to the native object while ensuring that any
+     * mutable objects that are attached to the paint are also up-to-date.
+     *
+     * @hide
+     */
+    public long getNativeInstance() {
+        if (mShader != null && mShader.getNativeInstance() != mNativeShader) {
+            native_setShader(mNativePaint, mShader.getNativeInstance());
+        }
+        return mNativePaint;
+    }
+
+    /**
      * Return the bidi flags on the paint.
      *
      * @return the bidi flags on the paint
@@ -920,10 +930,12 @@ public class Paint {
      * @return       shader
      */
     public Shader setShader(Shader shader) {
-        long shaderNative = 0;
-        if (shader != null)
-            shaderNative = shader.getNativeInstance();
-        native_setShader(mNativePaint, shaderNative);
+        if (shader != null) {
+            mNativeShader = shader.getNativeInstance();
+        } else {
+            mNativeShader = 0;
+        }
+        native_setShader(mNativePaint, mNativeShader);
         mShader = shader;
         return shader;
     }
index 6934955..a96d2cb 100644 (file)
@@ -82,7 +82,8 @@ public class Shader {
      */
     public void setLocalMatrix(Matrix localM) {
         mLocalMatrix = localM;
-        nativeSetLocalMatrix(native_instance, localM == null ? 0 : localM.native_instance);
+        native_instance = nativeSetLocalMatrix(native_instance,
+                localM == null ? 0 : localM.native_instance);
     }
 
     protected void finalize() throws Throwable {
@@ -120,5 +121,5 @@ public class Shader {
     }
 
     private static native void nativeDestructor(long native_shader);
-    private static native void nativeSetLocalMatrix(long native_shader, long matrix_instance);
+    private static native long nativeSetLocalMatrix(long native_shader, long matrix_instance);
 }