From caa08ff5e9ee004634a95776fc72bb769f1286de Mon Sep 17 00:00:00 2001
From: John Reck
Date: Fri, 7 Oct 2016 13:21:36 -0700
Subject: [PATCH] The bigger update to Canvas
All draw* calls in Canvas are regular JNI
All draw* calls in DisplayListCanvas are FastNative
Unifies Canvas JNI on nMethodName naming
CanvasPerf results before:
INSTRUMENTATION_STATUS: basicViewGroupDraw_min=12492
INSTRUMENTATION_STATUS: recordSimpleBitmapView_min=13912
and after:
INSTRUMENTATION_STATUS: basicViewGroupDraw_min=11945
INSTRUMENTATION_STATUS: recordSimpleBitmapView_min=13318
Test: refactor, makes & boots
Change-Id: I06000df1d125e17d60c6498865be7a7638a4a13e
---
.../java/android/text/GraphicsOperations.java | 23 +-
.../android/text/SpannableStringBuilder.java | 8 +-
core/java/android/view/DisplayListCanvas.java | 5 +-
core/java/android/view/RecordingCanvas.java | 641 +++++++
core/java/android/widget/TextView.java | 7 +-
core/jni/android_graphics_Canvas.cpp | 124 +-
.../java/android/graphics/BaseCanvas.java | 557 ++++++
graphics/java/android/graphics/Bitmap.java | 7 +-
graphics/java/android/graphics/Canvas.java | 1659 +++++++----------
graphics/java/android/graphics/Matrix.java | 3 +-
graphics/java/android/graphics/Path.java | 3 +-
11 files changed, 1951 insertions(+), 1086 deletions(-)
create mode 100644 core/java/android/view/RecordingCanvas.java
create mode 100644 graphics/java/android/graphics/BaseCanvas.java
diff --git a/core/java/android/text/GraphicsOperations.java b/core/java/android/text/GraphicsOperations.java
index 8674c66c90d2d..6edf845978c9c 100644
--- a/core/java/android/text/GraphicsOperations.java
+++ b/core/java/android/text/GraphicsOperations.java
@@ -16,31 +16,30 @@
package android.text;
+import android.graphics.BaseCanvas;
import android.graphics.Canvas;
import android.graphics.Paint;
/**
- * Please implement this interface if your CharSequence can do quick
- * draw/measure/widths calculations from an internal array.
- * {@hide}
+ * Please implement this interface if your CharSequence can do quick draw/measure/widths
+ * calculations from an internal array.
+ *
+ * @hide
*/
-public interface GraphicsOperations
-extends CharSequence
-{
+public interface GraphicsOperations extends CharSequence {
/**
* Just like {@link Canvas#drawText}.
*/
- void drawText(Canvas c, int start, int end,
- float x, float y, Paint p);
+ void drawText(BaseCanvas c, int start, int end,
+ float x, float y, Paint p);
/**
* Just like {@link Canvas#drawTextRun}.
- * {@hide}
*/
- void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd,
+ void drawTextRun(BaseCanvas c, int start, int end, int contextStart, int contextEnd,
float x, float y, boolean isRtl, Paint p);
- /**
+ /**
* Just like {@link Paint#measureText}.
*/
float measureText(int start, int end, Paint p);
@@ -52,14 +51,12 @@ extends CharSequence
/**
* Just like {@link Paint#getTextRunAdvances}.
- * @hide
*/
float getTextRunAdvances(int start, int end, int contextStart, int contextEnd,
boolean isRtl, float[] advances, int advancesIndex, Paint paint);
/**
* Just like {@link Paint#getTextRunCursor}.
- * @hide
*/
int getTextRunCursor(int contextStart, int contextEnd, int dir, int offset,
int cursorOpt, Paint p);
diff --git a/core/java/android/text/SpannableStringBuilder.java b/core/java/android/text/SpannableStringBuilder.java
index dc8e4b93e0939..186d96bce8e1f 100644
--- a/core/java/android/text/SpannableStringBuilder.java
+++ b/core/java/android/text/SpannableStringBuilder.java
@@ -17,7 +17,7 @@
package android.text;
import android.annotation.Nullable;
-import android.graphics.Canvas;
+import android.graphics.BaseCanvas;
import android.graphics.Paint;
import android.util.Log;
@@ -1357,7 +1357,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
* Don't call this yourself -- exists for Canvas to use internally.
* {@hide}
*/
- public void drawText(Canvas c, int start, int end, float x, float y, Paint p) {
+ @Override
+ public void drawText(BaseCanvas c, int start, int end, float x, float y, Paint p) {
checkRange("drawText", start, end);
if (end <= mGapStart) {
@@ -1378,7 +1379,8 @@ public class SpannableStringBuilder implements CharSequence, GetChars, Spannable
* Don't call this yourself -- exists for Canvas to use internally.
* {@hide}
*/
- public void drawTextRun(Canvas c, int start, int end, int contextStart, int contextEnd,
+ @Override
+ public void drawTextRun(BaseCanvas c, int start, int end, int contextStart, int contextEnd,
float x, float y, boolean isRtl, Paint p) {
checkRange("drawTextRun", start, end);
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index 872303a69a506..eb41f9ebcf7fb 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -19,7 +19,6 @@ package android.view;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Bitmap;
-import android.graphics.Canvas;
import android.graphics.CanvasProperty;
import android.graphics.Paint;
import android.util.Pools.SynchronizedPool;
@@ -34,7 +33,7 @@ import dalvik.annotation.optimization.FastNative;
*
* @hide
*/
-public class DisplayListCanvas extends Canvas {
+public final class DisplayListCanvas extends RecordingCanvas {
// The recording canvas pool should be large enough to handle a deeply nested
// view hierarchy because display lists are generated recursively.
private static final int POOL_LIMIT = 25;
@@ -42,7 +41,7 @@ public class DisplayListCanvas extends Canvas {
private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
private static final SynchronizedPool sPool =
- new SynchronizedPool(POOL_LIMIT);
+ new SynchronizedPool<>(POOL_LIMIT);
RenderNode mNode;
private int mWidth;
diff --git a/core/java/android/view/RecordingCanvas.java b/core/java/android/view/RecordingCanvas.java
new file mode 100644
index 0000000000000..e4b91b75e95ae
--- /dev/null
+++ b/core/java/android/view/RecordingCanvas.java
@@ -0,0 +1,641 @@
+/*
+ * Copyright (C) 2016 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.view;
+
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.Size;
+import android.graphics.BaseCanvas;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.NinePatch;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Picture;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.TemporaryBuffer;
+import android.text.GraphicsOperations;
+import android.text.SpannableString;
+import android.text.SpannedString;
+import android.text.TextUtils;
+
+import dalvik.annotation.optimization.FastNative;
+
+/**
+ * This class is a base class for canvases that defer drawing operations, so all
+ * the draw operations can be marked @FastNative. It contains a re-implementation of
+ * all the methods in {@link BaseCanvas}.
+ *
+ * @hide
+ */
+public class RecordingCanvas extends Canvas {
+
+ public RecordingCanvas(long nativeCanvas) {
+ super(nativeCanvas);
+ }
+
+ @Override
+ public final void drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, boolean useCenter, @NonNull Paint paint) {
+ nDrawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
+ useCenter, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle,
+ boolean useCenter, @NonNull Paint paint) {
+ drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
+ paint);
+ }
+
+ @Override
+ public final void drawARGB(int a, int r, int g, int b) {
+ drawColor(Color.argb(a, r, g, b));
+ }
+
+ @Override
+ public final void drawBitmap(@NonNull Bitmap bitmap, float left, float top,
+ @Nullable Paint paint) {
+ throwIfCannotDraw(bitmap);
+ nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top,
+ paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity,
+ bitmap.mDensity);
+ }
+
+ @Override
+ public final void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix,
+ @Nullable Paint paint) {
+ nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
+ paint != null ? paint.getNativeInstance() : 0);
+ }
+
+ @Override
+ public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
+ @Nullable Paint paint) {
+ if (dst == null) {
+ throw new NullPointerException();
+ }
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+ int left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
+ }
+
+ nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+ bitmap.mDensity);
+ }
+
+ @Override
+ public final void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
+ @Nullable Paint paint) {
+ if (dst == null) {
+ throw new NullPointerException();
+ }
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+ float left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
+ }
+
+ nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+ bitmap.mDensity);
+ }
+
+ /** @deprecated checkstyle */
+ @Override
+ @Deprecated
+ public final void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
+ int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+ // check for valid input
+ if (width < 0) {
+ throw new IllegalArgumentException("width must be >= 0");
+ }
+ if (height < 0) {
+ throw new IllegalArgumentException("height must be >= 0");
+ }
+ if (Math.abs(stride) < width) {
+ throw new IllegalArgumentException("abs(stride) must be >= width");
+ }
+ int lastScanline = offset + (height - 1) * stride;
+ int length = colors.length;
+ if (offset < 0 || (offset + width > length) || lastScanline < 0
+ || (lastScanline + width > length)) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ // quick escape if there's nothing to draw
+ if (width == 0 || height == 0) {
+ return;
+ }
+ // punch down to native for the actual draw
+ nDrawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
+ paint != null ? paint.getNativeInstance() : 0);
+ }
+
+ /** @deprecated checkstyle */
+ @Override
+ @Deprecated
+ public final void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
+ int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+ // call through to the common float version
+ drawBitmap(colors, offset, stride, (float) x, (float) y, width, height,
+ hasAlpha, paint);
+ }
+
+ @Override
+ public final void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
+ @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
+ @Nullable Paint paint) {
+ if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (meshWidth == 0 || meshHeight == 0) {
+ return;
+ }
+ int count = (meshWidth + 1) * (meshHeight + 1);
+ // we mul by 2 since we need two floats per vertex
+ checkRange(verts.length, vertOffset, count * 2);
+ if (colors != null) {
+ // no mul by 2, since we need only 1 color per vertex
+ checkRange(colors.length, colorOffset, count);
+ }
+ nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
+ verts, vertOffset, colors, colorOffset,
+ paint != null ? paint.getNativeInstance() : 0);
+ }
+
+ @Override
+ public final void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
+ nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawColor(@ColorInt int color) {
+ nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
+ }
+
+ @Override
+ public final void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
+ nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt);
+ }
+
+ @Override
+ public final void drawLine(float startX, float startY, float stopX, float stopY,
+ @NonNull Paint paint) {
+ nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
+ @NonNull Paint paint) {
+ nDrawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
+ drawLines(pts, 0, pts.length, paint);
+ }
+
+ @Override
+ public final void drawOval(float left, float top, float right, float bottom,
+ @NonNull Paint paint) {
+ nDrawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
+ if (oval == null) {
+ throw new NullPointerException();
+ }
+ drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
+ }
+
+ @Override
+ public final void drawPaint(@NonNull Paint paint) {
+ nDrawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst,
+ @Nullable Paint paint) {
+ Bitmap bitmap = patch.getBitmap();
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+ nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+ mDensity, patch.getDensity());
+ }
+
+ @Override
+ public final void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst,
+ @Nullable Paint paint) {
+ Bitmap bitmap = patch.getBitmap();
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+ nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+ mDensity, patch.getDensity());
+ }
+
+ @Override
+ public final void drawPath(@NonNull Path path, @NonNull Paint paint) {
+ if (path.isSimplePath && path.rects != null) {
+ nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
+ } else {
+ nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
+ }
+ }
+
+ @Override
+ public final void drawPicture(@NonNull Picture picture) {
+ picture.endRecording();
+ int restoreCount = save();
+ picture.draw(this);
+ restoreToCount(restoreCount);
+ }
+
+ @Override
+ public final void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
+ save();
+ translate(dst.left, dst.top);
+ if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+ scale((float) dst.width() / picture.getWidth(),
+ (float) dst.height() / picture.getHeight());
+ }
+ drawPicture(picture);
+ restore();
+ }
+
+ @Override
+ public final void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
+ save();
+ translate(dst.left, dst.top);
+ if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+ scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
+ }
+ drawPicture(picture);
+ restore();
+ }
+
+ @Override
+ public final void drawPoint(float x, float y, @NonNull Paint paint) {
+ nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
+ @NonNull Paint paint) {
+ nDrawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
+ drawPoints(pts, 0, pts.length, paint);
+ }
+
+ /** @deprecated checkstyle */
+ @Override
+ @Deprecated
+ public final void drawPosText(@NonNull char[] text, int index, int count,
+ @NonNull @Size(multiple = 2) float[] pos,
+ @NonNull Paint paint) {
+ if (index < 0 || index + count > text.length || count * 2 > pos.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ for (int i = 0; i < count; i++) {
+ drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
+ }
+ }
+
+ /** @deprecated checkstyle */
+ @Override
+ @Deprecated
+ public final void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
+ @NonNull Paint paint) {
+ drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
+ }
+
+ @Override
+ public final void drawRect(float left, float top, float right, float bottom,
+ @NonNull Paint paint) {
+ nDrawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawRect(@NonNull Rect r, @NonNull Paint paint) {
+ drawRect(r.left, r.top, r.right, r.bottom, paint);
+ }
+
+ @Override
+ public final void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
+ nDrawRect(mNativeCanvasWrapper,
+ rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawRGB(int r, int g, int b) {
+ drawColor(Color.rgb(r, g, b));
+ }
+
+ @Override
+ public final void drawRoundRect(float left, float top, float right, float bottom,
+ float rx, float ry, @NonNull Paint paint) {
+ nDrawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry,
+ paint.getNativeInstance());
+ }
+
+ @Override
+ public final void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
+ drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
+ }
+
+ @Override
+ public final void drawText(@NonNull char[] text, int index, int count, float x, float y,
+ @NonNull Paint paint) {
+ if ((index | count | (index + count)
+ | (text.length - index - count)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ nDrawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
+ paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ @Override
+ public final void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
+ @NonNull Paint paint) {
+ if ((start | end | (end - start) | (text.length() - end)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (text instanceof String || text instanceof SpannedString
+ || text instanceof SpannableString) {
+ nDrawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
+ paint.mBidiFlags, 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(mNativeCanvasWrapper, buf, 0, end - start, x, y,
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
+ }
+ }
+
+ @Override
+ public final void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
+ nDrawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
+ paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ @Override
+ public final void drawText(@NonNull String text, int start, int end, float x, float y,
+ @NonNull Paint paint) {
+ if ((start | end | (end - start) | (text.length() - end)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ nDrawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
+ paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ @Override
+ public final void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
+ float hOffset, float vOffset, @NonNull Paint paint) {
+ if (index < 0 || index + count > text.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ nDrawTextOnPath(mNativeCanvasWrapper, text, index, count,
+ path.readOnlyNI(), hOffset, vOffset,
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ @Override
+ public final void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
+ float vOffset, @NonNull Paint paint) {
+ if (text.length() > 0) {
+ nDrawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+ }
+
+ @Override
+ public final void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
+ int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+ if (text == null) {
+ throw new NullPointerException("text is null");
+ }
+ if (paint == null) {
+ throw new NullPointerException("paint is null");
+ }
+ if ((index | count | contextIndex | contextCount | index - contextIndex
+ | (contextIndex + contextCount) - (index + count)
+ | text.length - (contextIndex + contextCount)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
+ x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ @Override
+ public final void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
+ int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+ if (text == null) {
+ throw new NullPointerException("text is null");
+ }
+ if (paint == null) {
+ throw new NullPointerException("paint is null");
+ }
+ if ((start | end | contextStart | contextEnd | start - contextStart | end - start
+ | contextEnd - end | text.length() - contextEnd) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (text instanceof String || text instanceof SpannedString
+ || text instanceof SpannableString) {
+ nDrawTextRun(mNativeCanvasWrapper, text.toString(), start, end, 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);
+ } else {
+ int contextLen = contextEnd - contextStart;
+ int len = end - start;
+ char[] buf = TemporaryBuffer.obtain(contextLen);
+ TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+ nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
+ 0, contextLen, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
+ }
+ }
+
+ @Override
+ public final void drawVertices(@NonNull VertexMode mode, int vertexCount,
+ @NonNull float[] verts, int vertOffset, @Nullable float[] texs, int texOffset,
+ @Nullable int[] colors, int colorOffset, @Nullable short[] indices, int indexOffset,
+ int indexCount, @NonNull Paint paint) {
+ checkRange(verts.length, vertOffset, vertexCount);
+ if (isHardwareAccelerated()) {
+ return;
+ }
+ if (texs != null) {
+ checkRange(texs.length, texOffset, vertexCount);
+ }
+ if (colors != null) {
+ checkRange(colors.length, colorOffset, vertexCount / 2);
+ }
+ if (indices != null) {
+ checkRange(indices.length, indexOffset, indexCount);
+ }
+ nDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
+ vertOffset, texs, texOffset, colors, colorOffset,
+ indices, indexOffset, indexCount, paint.getNativeInstance());
+ }
+
+ @FastNative
+ private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
+ long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity);
+
+ @FastNative
+ private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap,
+ float srcLeft, float srcTop, float srcRight, float srcBottom,
+ float dstLeft, float dstTop, float dstRight, float dstBottom,
+ long nativePaintOrZero, int screenDensity, int bitmapDensity);
+
+ @FastNative
+ private static native void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
+ float x, float y, int width, int height, boolean hasAlpha, long nativePaintOrZero);
+
+ @FastNative
+ private static native void nDrawColor(long nativeCanvas, int color, int mode);
+
+ @FastNative
+ private static native void nDrawPaint(long nativeCanvas, long nativePaint);
+
+ @FastNative
+ private static native void nDrawPoint(long canvasHandle, float x, float y, long paintHandle);
+
+ @FastNative
+ private static native void nDrawPoints(long canvasHandle, float[] pts, int offset, int count,
+ long paintHandle);
+
+ @FastNative
+ private static native void nDrawLine(long nativeCanvas, float startX, float startY, float stopX,
+ float stopY, long nativePaint);
+
+ @FastNative
+ private static native void nDrawLines(long canvasHandle, float[] pts, int offset, int count,
+ long paintHandle);
+
+ @FastNative
+ private static native void nDrawRect(long nativeCanvas, float left, float top, float right,
+ float bottom, long nativePaint);
+
+ @FastNative
+ private static native void nDrawOval(long nativeCanvas, float left, float top, float right,
+ float bottom, long nativePaint);
+
+ @FastNative
+ private static native void nDrawCircle(long nativeCanvas, float cx, float cy, float radius,
+ long nativePaint);
+
+ @FastNative
+ private static native void nDrawArc(long nativeCanvas, float left, float top, float right,
+ float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint);
+
+ @FastNative
+ private static native void nDrawRoundRect(long nativeCanvas, float left, float top, float right,
+ float bottom, float rx, float ry, long nativePaint);
+
+ @FastNative
+ private static native void nDrawPath(long nativeCanvas, long nativePath, long nativePaint);
+
+ @FastNative
+ private static native void nDrawRegion(long nativeCanvas, long nativeRegion, long nativePaint);
+
+ @FastNative
+ private static native void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
+ float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero,
+ int screenDensity, int bitmapDensity);
+
+ @FastNative
+ private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap,
+ long nativeMatrix, long nativePaint);
+
+ @FastNative
+ private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth,
+ int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset,
+ long nativePaint);
+
+ @FastNative
+ private static native void nDrawVertices(long nativeCanvas, int mode, int n, float[] verts,
+ int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
+ short[] indices, int indexOffset, int indexCount, long nativePaint);
+
+ @FastNative
+ private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
+ float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+ @FastNative
+ private static native void nDrawText(long nativeCanvas, String text, int start, int end,
+ float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+ @FastNative
+ private static native void nDrawTextRun(long nativeCanvas, String text, int start, int end,
+ int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint,
+ long nativeTypeface);
+
+ @FastNative
+ private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
+ int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
+ long nativeTypeface);
+
+ @FastNative
+ private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
+ long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint,
+ long nativeTypeface);
+
+ @FastNative
+ private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,
+ float hOffset, float vOffset, int flags, long nativePaint, long nativeTypeface);
+}
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5264d5c95dbca..f1c3079349062 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -41,6 +41,7 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
+import android.graphics.BaseCanvas;
import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.Paint;
@@ -10222,12 +10223,14 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
System.arraycopy(mChars, start + mStart, buf, off, end - start);
}
- public void drawText(Canvas c, int start, int end,
+ @Override
+ public void drawText(BaseCanvas c, int start, int end,
float x, float y, Paint p) {
c.drawText(mChars, start + mStart, end - start, x, y, p);
}
- public void drawTextRun(Canvas c, int start, int end,
+ @Override
+ public void drawTextRun(BaseCanvas c, int start, int end,
int contextStart, int contextEnd, float x, float y, boolean isRtl, Paint p) {
int count = end - start;
int contextCount = contextEnd - contextStart;
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index 43f7ca5c12371..10645e841bf89 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -368,7 +368,7 @@ static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmap
}
}
-static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap,
+static void drawBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap,
jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
jint screenDensity, jint bitmapDensity) {
Canvas* canvas = get_canvas(canvasHandle);
@@ -571,67 +571,77 @@ static void freeTextLayoutCaches(JNIEnv* env, jobject) {
}; // namespace CanvasJNI
static const JNINativeMethod gMethods[] = {
- {"getNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
- {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
- {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
- {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
- {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
- {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
- {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
+ {"nGetNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer},
+ {"nInitRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster},
+ {"nFreeCaches", "()V", (void*) CanvasJNI::freeCaches},
+ {"nFreeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches},
// ------------ @FastNative ----------------
- {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
- {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
- {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth},
- {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight},
- {"native_setHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
- {"native_save","(JI)I", (void*) CanvasJNI::save},
- {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
- {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
- {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
- {"native_restore","(JZ)V", (void*) CanvasJNI::restore},
- {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
- {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
- {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
- {"native_concat","(JJ)V", (void*) CanvasJNI::concat},
- {"native_rotate","(JF)V", (void*) CanvasJNI::rotate},
- {"native_scale","(JFF)V", (void*) CanvasJNI::scale},
- {"native_skew","(JFF)V", (void*) CanvasJNI::skew},
- {"native_translate","(JFF)V", (void*) CanvasJNI::translate},
- {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
- {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
- {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
- {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
- {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
- {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
- {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor},
- {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
- {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
- {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
- {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
- {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
- {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
- {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
- {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
- {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
- {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
- {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
- {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
- {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
- {"native_drawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
- {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
- {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
- {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
- {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
- {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
- {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
- {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
- {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
- {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
+ {"nSetBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap},
+ {"nIsOpaque","(J)Z", (void*) CanvasJNI::isOpaque},
+ {"nGetWidth","(J)I", (void*) CanvasJNI::getWidth},
+ {"nGetHeight","(J)I", (void*) CanvasJNI::getHeight},
+ {"nSetHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText},
+ {"nSave","(JI)I", (void*) CanvasJNI::save},
+ {"nSaveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer},
+ {"nSaveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha},
+ {"nGetSaveCount","(J)I", (void*) CanvasJNI::getSaveCount},
+ {"nRestore","(JZ)V", (void*) CanvasJNI::restore},
+ {"nRestoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount},
+ {"nGetCTM", "(JJ)V", (void*)CanvasJNI::getCTM},
+ {"nSetMatrix","(JJ)V", (void*) CanvasJNI::setMatrix},
+ {"nConcat","(JJ)V", (void*) CanvasJNI::concat},
+ {"nRotate","(JF)V", (void*) CanvasJNI::rotate},
+ {"nScale","(JFF)V", (void*) CanvasJNI::scale},
+ {"nSkew","(JFF)V", (void*) CanvasJNI::skew},
+ {"nTranslate","(JFF)V", (void*) CanvasJNI::translate},
+ {"nGetClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds},
+ {"nQuickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath},
+ {"nQuickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect},
+ {"nClipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect},
+ {"nClipPath","(JJI)Z", (void*) CanvasJNI::clipPath},
+ {"nClipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion},
+ {"nSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter},
+};
+
+// If called from Canvas these are regular JNI
+// If called from DisplayListCanvas they are @FastNative
+static const JNINativeMethod gDrawMethods[] = {
+ {"nDrawColor","(JII)V", (void*) CanvasJNI::drawColor},
+ {"nDrawPaint","(JJ)V", (void*) CanvasJNI::drawPaint},
+ {"nDrawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint},
+ {"nDrawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints},
+ {"nDrawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine},
+ {"nDrawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines},
+ {"nDrawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect},
+ {"nDrawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion },
+ {"nDrawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect},
+ {"nDrawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle},
+ {"nDrawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval},
+ {"nDrawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc},
+ {"nDrawPath","(JJJ)V", (void*) CanvasJNI::drawPath},
+ {"nDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices},
+ {"nDrawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch},
+ {"nDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix},
+ {"nDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh},
+ {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap},
+ {"nDrawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
+ {"nDrawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
+ {"nDrawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars},
+ {"nDrawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString},
+ {"nDrawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars},
+ {"nDrawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString},
+ {"nDrawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars},
+ {"nDrawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString},
};
int register_android_graphics_Canvas(JNIEnv* env) {
- return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
+ int ret = 0;
+ ret |= RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
+ ret |= RegisterMethodsOrDie(env, "android/graphics/BaseCanvas", gDrawMethods, NELEM(gDrawMethods));
+ ret |= RegisterMethodsOrDie(env, "android/view/RecordingCanvas", gDrawMethods, NELEM(gDrawMethods));
+ return ret;
+
}
}; // namespace android
diff --git a/graphics/java/android/graphics/BaseCanvas.java b/graphics/java/android/graphics/BaseCanvas.java
new file mode 100644
index 0000000000000..f135484adcc04
--- /dev/null
+++ b/graphics/java/android/graphics/BaseCanvas.java
@@ -0,0 +1,557 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics;
+
+import android.annotation.ColorInt;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.Size;
+import android.graphics.Canvas.VertexMode;
+import android.text.GraphicsOperations;
+import android.text.SpannableString;
+import android.text.SpannedString;
+import android.text.TextUtils;
+import android.view.RecordingCanvas;
+
+/**
+ * This class is a base class for Canvas's drawing operations. Any modifications here
+ * should be accompanied by a similar modification to {@link RecordingCanvas}.
+ *
+ * The purpose of this class is to minimize the cost of deciding between regular JNI
+ * and @FastNative JNI to just the virtual call that Canvas already has.
+ *
+ * @hide
+ */
+public abstract class BaseCanvas {
+ /**
+ * Should only be assigned in constructors (or setBitmap if software canvas),
+ * freed by NativeAllocation.
+ */
+ protected long mNativeCanvasWrapper;
+
+ /**
+ * Used to determine when compatibility scaling is in effect.
+ */
+ protected int mScreenDensity = Bitmap.DENSITY_NONE;
+ protected int mDensity = Bitmap.DENSITY_NONE;
+
+ protected void throwIfCannotDraw(Bitmap bitmap) {
+ if (bitmap.isRecycled()) {
+ throw new RuntimeException("Canvas: trying to use a recycled bitmap " + bitmap);
+ }
+ if (!bitmap.isPremultiplied() && bitmap.getConfig() == Bitmap.Config.ARGB_8888 &&
+ bitmap.hasAlpha()) {
+ throw new RuntimeException("Canvas: trying to use a non-premultiplied bitmap "
+ + bitmap);
+ }
+ }
+
+ protected final static void checkRange(int length, int offset, int count) {
+ if ((offset | count) < 0 || offset + count > length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ }
+
+ public boolean isHardwareAccelerated() {
+ return false;
+ }
+
+ // ---------------------------------------------------------------------------
+ // Drawing methods
+ // These are also implemented in DisplayListCanvas so that we can
+ // selectively apply on them
+ // Everything below here is copy/pasted from Canvas.java
+ // The JNI registration is handled by android_view_Canvas.cpp
+ // ---------------------------------------------------------------------------
+
+ public void drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, boolean useCenter, @NonNull Paint paint) {
+ nDrawArc(mNativeCanvasWrapper, left, top, right, bottom, startAngle, sweepAngle,
+ useCenter, paint.getNativeInstance());
+ }
+
+ public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
+ @NonNull Paint paint) {
+ drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
+ paint);
+ }
+
+ public void drawARGB(int a, int r, int g, int b) {
+ drawColor(Color.argb(a, r, g, b));
+ }
+
+ public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
+ throwIfCannotDraw(bitmap);
+ nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top,
+ paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity,
+ bitmap.mDensity);
+ }
+
+ public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
+ nDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
+ paint != null ? paint.getNativeInstance() : 0);
+ }
+
+ public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
+ @Nullable Paint paint) {
+ if (dst == null) {
+ throw new NullPointerException();
+ }
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+ int left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
+ }
+
+ nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+ bitmap.mDensity);
+ }
+
+ public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
+ @Nullable Paint paint) {
+ if (dst == null) {
+ throw new NullPointerException();
+ }
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+
+ float left, top, right, bottom;
+ if (src == null) {
+ left = top = 0;
+ right = bitmap.getWidth();
+ bottom = bitmap.getHeight();
+ } else {
+ left = src.left;
+ right = src.right;
+ top = src.top;
+ bottom = src.bottom;
+ }
+
+ nDrawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
+ bitmap.mDensity);
+ }
+
+ @Deprecated
+ public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
+ int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+ // check for valid input
+ if (width < 0) {
+ throw new IllegalArgumentException("width must be >= 0");
+ }
+ if (height < 0) {
+ throw new IllegalArgumentException("height must be >= 0");
+ }
+ if (Math.abs(stride) < width) {
+ throw new IllegalArgumentException("abs(stride) must be >= width");
+ }
+ int lastScanline = offset + (height - 1) * stride;
+ int length = colors.length;
+ if (offset < 0 || (offset + width > length) || lastScanline < 0
+ || (lastScanline + width > length)) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ // quick escape if there's nothing to draw
+ if (width == 0 || height == 0) {
+ return;
+ }
+ // punch down to native for the actual draw
+ nDrawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
+ paint != null ? paint.getNativeInstance() : 0);
+ }
+
+ @Deprecated
+ public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
+ int width, int height, boolean hasAlpha, @Nullable Paint paint) {
+ // call through to the common float version
+ drawBitmap(colors, offset, stride, (float) x, (float) y, width, height,
+ hasAlpha, paint);
+ }
+
+ public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
+ @NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
+ @Nullable Paint paint) {
+ if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ if (meshWidth == 0 || meshHeight == 0) {
+ return;
+ }
+ int count = (meshWidth + 1) * (meshHeight + 1);
+ // we mul by 2 since we need two floats per vertex
+ checkRange(verts.length, vertOffset, count * 2);
+ if (colors != null) {
+ // no mul by 2, since we need only 1 color per vertex
+ checkRange(colors.length, colorOffset, count);
+ }
+ nDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
+ verts, vertOffset, colors, colorOffset,
+ paint != null ? paint.getNativeInstance() : 0);
+ }
+
+ public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
+ nDrawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
+ }
+
+ public void drawColor(@ColorInt int color) {
+ nDrawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
+ }
+
+ public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
+ nDrawColor(mNativeCanvasWrapper, color, mode.nativeInt);
+ }
+
+ public void drawLine(float startX, float startY, float stopX, float stopY,
+ @NonNull Paint paint) {
+ nDrawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
+ }
+
+ public void drawLines(@Size(multiple = 4) @NonNull float[] pts, int offset, int count,
+ @NonNull Paint paint) {
+ nDrawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+ }
+
+ public void drawLines(@Size(multiple = 4) @NonNull float[] pts, @NonNull Paint paint) {
+ drawLines(pts, 0, pts.length, paint);
+ }
+
+ public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
+ nDrawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+ }
+
+ public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
+ if (oval == null) {
+ throw new NullPointerException();
+ }
+ drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
+ }
+
+ public void drawPaint(@NonNull Paint paint) {
+ nDrawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
+ }
+
+ public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
+ Bitmap bitmap = patch.getBitmap();
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+ nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+ mDensity, patch.getDensity());
+ }
+
+ public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
+ Bitmap bitmap = patch.getBitmap();
+ throwIfCannotDraw(bitmap);
+ final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
+ nDrawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
+ mDensity, patch.getDensity());
+ }
+
+ public void drawPath(@NonNull Path path, @NonNull Paint paint) {
+ if (path.isSimplePath && path.rects != null) {
+ nDrawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
+ } else {
+ nDrawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
+ }
+ }
+
+ public void drawPoint(float x, float y, @NonNull Paint paint) {
+ nDrawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
+ }
+
+ public void drawPoints(@Size(multiple = 2) float[] pts, int offset, int count,
+ @NonNull Paint paint) {
+ nDrawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
+ }
+
+ public void drawPoints(@Size(multiple = 2) @NonNull float[] pts, @NonNull Paint paint) {
+ drawPoints(pts, 0, pts.length, paint);
+ }
+
+ @Deprecated
+ public void drawPosText(@NonNull char[] text, int index, int count,
+ @NonNull @Size(multiple = 2) float[] pos,
+ @NonNull Paint paint) {
+ if (index < 0 || index + count > text.length || count * 2 > pos.length) {
+ throw new IndexOutOfBoundsException();
+ }
+ for (int i = 0; i < count; i++) {
+ drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
+ }
+ }
+
+ @Deprecated
+ public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos,
+ @NonNull Paint paint) {
+ drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
+ }
+
+ public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
+ nDrawRect(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+ }
+
+ public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
+ drawRect(r.left, r.top, r.right, r.bottom, paint);
+ }
+
+ public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
+ nDrawRect(mNativeCanvasWrapper,
+ rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
+ }
+
+ public void drawRGB(int r, int g, int b) {
+ drawColor(Color.rgb(r, g, b));
+ }
+
+ public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+ @NonNull Paint paint) {
+ nDrawRoundRect(mNativeCanvasWrapper, left, top, right, bottom, rx, ry,
+ paint.getNativeInstance());
+ }
+
+ public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
+ drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
+ }
+
+ public void drawText(@NonNull char[] text, int index, int count, float x, float y,
+ @NonNull Paint paint) {
+ if ((index | count | (index + count) |
+ (text.length - index - count)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ nDrawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
+ paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ public void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
+ @NonNull Paint paint) {
+ if ((start | end | (end - start) | (text.length() - end)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ nDrawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
+ paint.mBidiFlags, 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(mNativeCanvasWrapper, buf, 0, end - start, x, y,
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
+ }
+ }
+
+ public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
+ nDrawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
+ paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ public void drawText(@NonNull String text, int start, int end, float x, float y,
+ @NonNull Paint paint) {
+ if ((start | end | (end - start) | (text.length() - end)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ nDrawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
+ paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
+ float hOffset, float vOffset, @NonNull Paint paint) {
+ if (index < 0 || index + count > text.length) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ nDrawTextOnPath(mNativeCanvasWrapper, text, index, count,
+ path.readOnlyNI(), hOffset, vOffset,
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
+ float vOffset, @NonNull Paint paint) {
+ if (text.length() > 0) {
+ nDrawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
+ paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+ }
+
+ public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
+ int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+ if (text == null) {
+ throw new NullPointerException("text is null");
+ }
+ if (paint == null) {
+ throw new NullPointerException("paint is null");
+ }
+ if ((index | count | contextIndex | contextCount | index - contextIndex
+ | (contextIndex + contextCount) - (index + count)
+ | text.length - (contextIndex + contextCount)) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ nDrawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
+ x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+ }
+
+ public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
+ int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
+
+ if (text == null) {
+ throw new NullPointerException("text is null");
+ }
+ if (paint == null) {
+ throw new NullPointerException("paint is null");
+ }
+ if ((start | end | contextStart | contextEnd | start - contextStart | end - start
+ | contextEnd - end | text.length() - contextEnd) < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ if (text instanceof String || text instanceof SpannedString ||
+ text instanceof SpannableString) {
+ nDrawTextRun(mNativeCanvasWrapper, text.toString(), start, end, 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);
+ } else {
+ int contextLen = contextEnd - contextStart;
+ int len = end - start;
+ char[] buf = TemporaryBuffer.obtain(contextLen);
+ TextUtils.getChars(text, contextStart, contextEnd, buf, 0);
+ nDrawTextRun(mNativeCanvasWrapper, buf, start - contextStart, len,
+ 0, contextLen, x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+ TemporaryBuffer.recycle(buf);
+ }
+ }
+
+ public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
+ int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
+ int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
+ @NonNull Paint paint) {
+ checkRange(verts.length, vertOffset, vertexCount);
+ if (isHardwareAccelerated()) {
+ return;
+ }
+ if (texs != null) {
+ checkRange(texs.length, texOffset, vertexCount);
+ }
+ if (colors != null) {
+ checkRange(colors.length, colorOffset, vertexCount / 2);
+ }
+ if (indices != null) {
+ checkRange(indices.length, indexOffset, indexCount);
+ }
+ nDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
+ vertOffset, texs, texOffset, colors, colorOffset,
+ indices, indexOffset, indexCount, paint.getNativeInstance());
+ }
+
+ private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
+ long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity);
+
+ private static native void nDrawBitmap(long nativeCanvas, Bitmap bitmap, float srcLeft,
+ float srcTop,
+ float srcRight, float srcBottom, float dstLeft, float dstTop, float dstRight,
+ float dstBottom, long nativePaintOrZero, int screenDensity, int bitmapDensity);
+
+ private static native void nDrawBitmap(long nativeCanvas, int[] colors, int offset, int stride,
+ float x, float y, int width, int height, boolean hasAlpha, long nativePaintOrZero);
+
+ private static native void nDrawColor(long nativeCanvas, int color, int mode);
+
+ private static native void nDrawPaint(long nativeCanvas, long nativePaint);
+
+ private static native void nDrawPoint(long canvasHandle, float x, float y, long paintHandle);
+
+ private static native void nDrawPoints(long canvasHandle, float[] pts, int offset, int count,
+ long paintHandle);
+
+ private static native void nDrawLine(long nativeCanvas, float startX, float startY, float stopX,
+ float stopY, long nativePaint);
+
+ private static native void nDrawLines(long canvasHandle, float[] pts, int offset, int count,
+ long paintHandle);
+
+ private static native void nDrawRect(long nativeCanvas, float left, float top, float right,
+ float bottom, long nativePaint);
+
+ private static native void nDrawOval(long nativeCanvas, float left, float top, float right,
+ float bottom, long nativePaint);
+
+ private static native void nDrawCircle(long nativeCanvas, float cx, float cy, float radius,
+ long nativePaint);
+
+ private static native void nDrawArc(long nativeCanvas, float left, float top, float right,
+ float bottom, float startAngle, float sweep, boolean useCenter, long nativePaint);
+
+ private static native void nDrawRoundRect(long nativeCanvas, float left, float top, float right,
+ float bottom, float rx, float ry, long nativePaint);
+
+ private static native void nDrawPath(long nativeCanvas, long nativePath, long nativePaint);
+
+ private static native void nDrawRegion(long nativeCanvas, long nativeRegion, long nativePaint);
+
+ private static native void nDrawNinePatch(long nativeCanvas, long nativeBitmap, long ninePatch,
+ float dstLeft, float dstTop, float dstRight, float dstBottom, long nativePaintOrZero,
+ int screenDensity, int bitmapDensity);
+
+ private static native void nDrawBitmapMatrix(long nativeCanvas, Bitmap bitmap,
+ long nativeMatrix, long nativePaint);
+
+ private static native void nDrawBitmapMesh(long nativeCanvas, Bitmap bitmap, int meshWidth,
+ int meshHeight, float[] verts, int vertOffset, int[] colors, int colorOffset,
+ long nativePaint);
+
+ private static native void nDrawVertices(long nativeCanvas, int mode, int n, float[] verts,
+ int vertOffset, float[] texs, int texOffset, int[] colors, int colorOffset,
+ short[] indices, int indexOffset, int indexCount, long nativePaint);
+
+ private static native void nDrawText(long nativeCanvas, char[] text, int index, int count,
+ float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+ private static native void nDrawText(long nativeCanvas, String text, int start, int end,
+ float x, float y, int flags, long nativePaint, long nativeTypeface);
+
+ private static native void nDrawTextRun(long nativeCanvas, String text, int start, int end,
+ int contextStart, int contextEnd, float x, float y, boolean isRtl, long nativePaint,
+ long nativeTypeface);
+
+ private static native void nDrawTextRun(long nativeCanvas, char[] text, int start, int count,
+ int contextStart, int contextCount, float x, float y, boolean isRtl, long nativePaint,
+ long nativeTypeface);
+
+ private static native void nDrawTextOnPath(long nativeCanvas, char[] text, int index, int count,
+ long nativePath, float hOffset, float vOffset, int bidiFlags, long nativePaint,
+ long nativeTypeface);
+
+ private static native void nDrawTextOnPath(long nativeCanvas, String text, long nativePath,
+ float hOffset, float vOffset, int flags, long nativePaint, long nativeTypeface);
+}
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 7ce750d6e0001..fd2f705bfd452 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -73,8 +73,8 @@ public final class Bitmap implements Parcelable {
private int mHeight;
private boolean mRecycled;
- // Package-scoped for fast access.
- int mDensity = getDefaultDensity();
+ /** @hide */
+ public int mDensity = getDefaultDensity();
private static volatile Matrix sScaleMatrix;
@@ -130,8 +130,9 @@ public final class Bitmap implements Parcelable {
/**
* Return the pointer to the native object.
+ * @hide
*/
- long getNativeInstance() {
+ public long getNativeInstance() {
return mNativePtr;
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 0692a090426ec..3f0bed86e531b 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -48,17 +48,10 @@ import javax.microedition.khronos.opengles.GL;
*
* Canvas and Drawables developer guide.
*/
-public class Canvas {
+public class Canvas extends BaseCanvas {
/** @hide */
public static boolean sCompatibilityRestore = false;
- /**
- * Should only be assigned in constructors (or setBitmap if software canvas),
- * freed by NativeAllocation.
- * @hide
- */
- protected long mNativeCanvasWrapper;
-
/** @hide */
public long getNativeCanvasWrapper() {
return mNativeCanvasWrapper;
@@ -73,18 +66,6 @@ public class Canvas {
// optional field set by the caller
private DrawFilter mDrawFilter;
- /**
- * @hide
- */
- protected int mDensity = Bitmap.DENSITY_NONE;
-
- /**
- * Used to determine when compatibility scaling is in effect.
- *
- * @hide
- */
- protected int mScreenDensity = Bitmap.DENSITY_NONE;
-
// Maximum bitmap size as defined in Skia's native code
// (see SkCanvas.cpp, SkDraw.cpp)
private static final int MAXMIMUM_BITMAP_SIZE = 32766;
@@ -96,7 +77,7 @@ public class Canvas {
// Use a Holder to allow static initialization of Canvas in the boot image.
private static class NoImagePreloadHolder {
public static final NativeAllocationRegistry sRegistry = new NativeAllocationRegistry(
- Canvas.class.getClassLoader(), getNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
+ Canvas.class.getClassLoader(), nGetNativeFinalizer(), NATIVE_ALLOCATION_SIZE);
}
// This field is used to finalize the native Canvas properly
@@ -111,7 +92,7 @@ public class Canvas {
public Canvas() {
if (!isHardwareAccelerated()) {
// 0 means no native bitmap
- mNativeCanvasWrapper = initRaster(null);
+ mNativeCanvasWrapper = nInitRaster(null);
mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
this, mNativeCanvasWrapper);
} else {
@@ -133,7 +114,7 @@ public class Canvas {
throw new IllegalStateException("Immutable bitmap passed to Canvas constructor");
}
throwIfCannotDraw(bitmap);
- mNativeCanvasWrapper = initRaster(bitmap);
+ mNativeCanvasWrapper = nInitRaster(bitmap);
mFinalizer = NoImagePreloadHolder.sRegistry.registerNativeAllocation(
this, mNativeCanvasWrapper);
mBitmap = bitmap;
@@ -192,7 +173,7 @@ public class Canvas {
}
if (bitmap == null) {
- native_setBitmap(mNativeCanvasWrapper, null);
+ nSetBitmap(mNativeCanvasWrapper, null);
mDensity = Bitmap.DENSITY_NONE;
} else {
if (!bitmap.isMutable()) {
@@ -200,7 +181,7 @@ public class Canvas {
}
throwIfCannotDraw(bitmap);
- native_setBitmap(mNativeCanvasWrapper, bitmap);
+ nSetBitmap(mNativeCanvasWrapper, bitmap);
mDensity = bitmap.mDensity;
}
@@ -209,7 +190,7 @@ public class Canvas {
/** @hide */
public void setHighContrastText(boolean highContrastText) {
- native_setHighContrastText(mNativeCanvasWrapper, highContrastText);
+ nSetHighContrastText(mNativeCanvasWrapper, highContrastText);
}
/** @hide */
@@ -225,7 +206,7 @@ public class Canvas {
* @return true if the device that the current layer draws into is opaque
*/
public boolean isOpaque() {
- return native_isOpaque(mNativeCanvasWrapper);
+ return nIsOpaque(mNativeCanvasWrapper);
}
/**
@@ -234,7 +215,7 @@ public class Canvas {
* @return the width of the current drawing layer
*/
public int getWidth() {
- return native_getWidth(mNativeCanvasWrapper);
+ return nGetWidth(mNativeCanvasWrapper);
}
/**
@@ -243,7 +224,7 @@ public class Canvas {
* @return the height of the current drawing layer
*/
public int getHeight() {
- return native_getHeight(mNativeCanvasWrapper);
+ return nGetHeight(mNativeCanvasWrapper);
}
/**
@@ -371,7 +352,7 @@ public class Canvas {
* @return The value to pass to restoreToCount() to balance this save()
*/
public int save() {
- return native_save(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ return nSave(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
}
/**
@@ -391,7 +372,7 @@ public class Canvas {
* @return The value to pass to restoreToCount() to balance this save()
*/
public int save(@Saveflags int saveFlags) {
- return native_save(mNativeCanvasWrapper, saveFlags);
+ return nSave(mNativeCanvasWrapper, saveFlags);
}
/**
@@ -443,7 +424,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,
+ return nSaveLayer(mNativeCanvasWrapper, left, top, right, bottom,
paint != null ? paint.getNativeInstance() : 0,
saveFlags);
}
@@ -503,7 +484,7 @@ public class Canvas {
public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha,
@Saveflags int saveFlags) {
alpha = Math.min(255, Math.max(0, alpha));
- return native_saveLayerAlpha(mNativeCanvasWrapper, left, top, right, bottom,
+ return nSaveLayerAlpha(mNativeCanvasWrapper, left, top, right, bottom,
alpha, saveFlags);
}
@@ -521,7 +502,7 @@ public class Canvas {
*/
public void restore() {
boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
- native_restore(mNativeCanvasWrapper, throwOnUnderflow);
+ nRestore(mNativeCanvasWrapper, throwOnUnderflow);
}
/**
@@ -529,7 +510,7 @@ public class Canvas {
* This will equal # save() calls - # restore() calls.
*/
public int getSaveCount() {
- return native_getSaveCount(mNativeCanvasWrapper);
+ return nGetSaveCount(mNativeCanvasWrapper);
}
/**
@@ -547,7 +528,7 @@ public class Canvas {
*/
public void restoreToCount(int saveCount) {
boolean throwOnUnderflow = !sCompatibilityRestore || !isHardwareAccelerated();
- native_restoreToCount(mNativeCanvasWrapper, saveCount, throwOnUnderflow);
+ nRestoreToCount(mNativeCanvasWrapper, saveCount, throwOnUnderflow);
}
/**
@@ -558,7 +539,7 @@ public class Canvas {
*/
public void translate(float dx, float dy) {
if (dx == 0.0f && dy == 0.0f) return;
- native_translate(mNativeCanvasWrapper, dx, dy);
+ nTranslate(mNativeCanvasWrapper, dx, dy);
}
/**
@@ -569,7 +550,7 @@ public class Canvas {
*/
public void scale(float sx, float sy) {
if (sx == 1.0f && sy == 1.0f) return;
- native_scale(mNativeCanvasWrapper, sx, sy);
+ nScale(mNativeCanvasWrapper, sx, sy);
}
/**
@@ -594,7 +575,7 @@ public class Canvas {
*/
public void rotate(float degrees) {
if (degrees == 0.0f) return;
- native_rotate(mNativeCanvasWrapper, degrees);
+ nRotate(mNativeCanvasWrapper, degrees);
}
/**
@@ -619,7 +600,7 @@ public class Canvas {
*/
public void skew(float sx, float sy) {
if (sx == 0.0f && sy == 0.0f) return;
- native_skew(mNativeCanvasWrapper, sx, sy);
+ nSkew(mNativeCanvasWrapper, sx, sy);
}
/**
@@ -629,7 +610,7 @@ public class Canvas {
* @param matrix The matrix to preconcatenate with the current matrix
*/
public void concat(@Nullable Matrix matrix) {
- if (matrix != null) native_concat(mNativeCanvasWrapper, matrix.native_instance);
+ if (matrix != null) nConcat(mNativeCanvasWrapper, matrix.native_instance);
}
/**
@@ -646,7 +627,7 @@ public class Canvas {
* @see #concat(Matrix)
*/
public void setMatrix(@Nullable Matrix matrix) {
- native_setMatrix(mNativeCanvasWrapper,
+ nSetMatrix(mNativeCanvasWrapper,
matrix == null ? 0 : matrix.native_instance);
}
@@ -662,7 +643,7 @@ public class Canvas {
*/
@Deprecated
public void getMatrix(@NonNull Matrix ctm) {
- native_getCTM(mNativeCanvasWrapper, ctm.native_instance);
+ nGetCTM(mNativeCanvasWrapper, ctm.native_instance);
}
/**
@@ -691,7 +672,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public boolean clipRect(@NonNull RectF rect, @NonNull Region.Op op) {
- return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+ return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
op.nativeInt);
}
@@ -704,7 +685,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public boolean clipRect(@NonNull Rect rect, @NonNull Region.Op op) {
- return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+ return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
op.nativeInt);
}
@@ -716,7 +697,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public boolean clipRect(@NonNull RectF rect) {
- return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+ return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
Region.Op.INTERSECT.nativeInt);
}
@@ -728,7 +709,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public boolean clipRect(@NonNull Rect rect) {
- return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+ return nClipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
Region.Op.INTERSECT.nativeInt);
}
@@ -749,7 +730,7 @@ public class Canvas {
*/
public boolean clipRect(float left, float top, float right, float bottom,
@NonNull Region.Op op) {
- return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt);
+ return nClipRect(mNativeCanvasWrapper, left, top, right, bottom, op.nativeInt);
}
/**
@@ -766,7 +747,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public boolean clipRect(float left, float top, float right, float bottom) {
- return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom,
+ return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
Region.Op.INTERSECT.nativeInt);
}
@@ -784,7 +765,7 @@ public class Canvas {
* @return true if the resulting clip is non-empty
*/
public boolean clipRect(int left, int top, int right, int bottom) {
- return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom,
+ return nClipRect(mNativeCanvasWrapper, left, top, right, bottom,
Region.Op.INTERSECT.nativeInt);
}
@@ -796,7 +777,7 @@ public class Canvas {
* @return true if the resulting is non-empty
*/
public boolean clipPath(@NonNull Path path, @NonNull Region.Op op) {
- return native_clipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
+ return nClipPath(mNativeCanvasWrapper, path.readOnlyNI(), op.nativeInt);
}
/**
@@ -825,7 +806,7 @@ public class Canvas {
*/
@Deprecated
public boolean clipRegion(@NonNull Region region, @NonNull Region.Op op) {
- return native_clipRegion(mNativeCanvasWrapper, region.ni(), op.nativeInt);
+ return nClipRegion(mNativeCanvasWrapper, region.ni(), op.nativeInt);
}
/**
@@ -856,7 +837,7 @@ public class Canvas {
nativeFilter = filter.mNativeInt;
}
mDrawFilter = filter;
- nativeSetDrawFilter(mNativeCanvasWrapper, nativeFilter);
+ nSetDrawFilter(mNativeCanvasWrapper, nativeFilter);
}
/**
@@ -904,7 +885,7 @@ public class Canvas {
* does not intersect with the canvas' clip
*/
public boolean quickReject(@NonNull RectF rect, @NonNull EdgeType type) {
- return native_quickReject(mNativeCanvasWrapper,
+ return nQuickReject(mNativeCanvasWrapper,
rect.left, rect.top, rect.right, rect.bottom);
}
@@ -924,7 +905,7 @@ public class Canvas {
* does not intersect with the canvas' clip
*/
public boolean quickReject(@NonNull Path path, @NonNull EdgeType type) {
- return native_quickReject(mNativeCanvasWrapper, path.readOnlyNI());
+ return nQuickReject(mNativeCanvasWrapper, path.readOnlyNI());
}
/**
@@ -949,7 +930,7 @@ public class Canvas {
*/
public boolean quickReject(float left, float top, float right, float bottom,
@NonNull EdgeType type) {
- return native_quickReject(mNativeCanvasWrapper, left, top, right, bottom);
+ return nQuickReject(mNativeCanvasWrapper, left, top, right, bottom);
}
/**
@@ -963,7 +944,7 @@ public class Canvas {
* @return true if the current clip is non-empty.
*/
public boolean getClipBounds(@Nullable Rect bounds) {
- return native_getClipBounds(mNativeCanvasWrapper, bounds);
+ return nGetClipBounds(mNativeCanvasWrapper, bounds);
}
/**
@@ -978,209 +959,206 @@ public class Canvas {
}
/**
- * Fill the entire canvas' bitmap (restricted to the current clip) with the
- * specified RGB color, using srcover porterduff mode.
+ * Save the canvas state, draw the picture, and restore the canvas state.
+ * This differs from picture.draw(canvas), which does not perform any
+ * save/restore.
*
- * @param r red component (0..255) of the color to draw onto the canvas
- * @param g green component (0..255) of the color to draw onto the canvas
- * @param b blue component (0..255) of the color to draw onto the canvas
+ *
+ * Note: This forces the picture to internally call
+ * {@link Picture#endRecording} in order to prepare for playback.
+ *
+ * @param picture The picture to be drawn
*/
- public void drawRGB(int r, int g, int b) {
- drawColor(Color.rgb(r, g, b));
+ public void drawPicture(@NonNull Picture picture) {
+ picture.endRecording();
+ int restoreCount = save();
+ picture.draw(this);
+ restoreToCount(restoreCount);
}
/**
- * Fill the entire canvas' bitmap (restricted to the current clip) with the
- * specified ARGB color, using srcover porterduff mode.
- *
- * @param a alpha component (0..255) of the color to draw onto the canvas
- * @param r red component (0..255) of the color to draw onto the canvas
- * @param g green component (0..255) of the color to draw onto the canvas
- * @param b blue component (0..255) of the color to draw onto the canvas
+ * Draw the picture, stretched to fit into the dst rectangle.
*/
- public void drawARGB(int a, int r, int g, int b) {
- drawColor(Color.argb(a, r, g, b));
- }
-
- /**
- * Fill the entire canvas' bitmap (restricted to the current clip) with the
- * specified color, using srcover porterduff mode.
- *
- * @param color the color to draw onto the canvas
- */
- public void drawColor(@ColorInt int color) {
- native_drawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
- }
-
- /**
- * Fill the entire canvas' bitmap (restricted to the current clip) with the
- * specified color and porter-duff xfermode.
- *
- * @param color the color to draw with
- * @param mode the porter-duff mode to apply to the color
- */
- public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
- native_drawColor(mNativeCanvasWrapper, color, mode.nativeInt);
- }
-
- /**
- * Fill the entire canvas' bitmap (restricted to the current clip) with
- * the specified paint. This is equivalent (but faster) to drawing an
- * infinitely large rectangle with the specified paint.
- *
- * @param paint The paint used to draw onto the canvas
- */
- public void drawPaint(@NonNull Paint paint) {
- native_drawPaint(mNativeCanvasWrapper, paint.getNativeInstance());
- }
-
- /**
- * Draw a series of points. Each point is centered at the coordinate
- * specified by pts[], and its diameter is specified by the paint's stroke
- * width (as transformed by the canvas' CTM), with special treatment for
- * a stroke width of 0, which always draws exactly 1 pixel (or at most 4
- * if antialiasing is enabled). The shape of the point is controlled by
- * the paint's Cap type. The shape is a square, unless the cap type is
- * Round, in which case the shape is a circle.
- *
- * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
- * @param offset Number of values to skip before starting to draw.
- * @param count The number of values to process, after skipping offset
- * of them. Since one point uses two values, the number of
- * "points" that are drawn is really (count >> 1).
- * @param paint The paint used to draw the points
- */
- public void drawPoints(@Size(multiple=2) float[] pts, int offset, int count,
- @NonNull Paint paint) {
- native_drawPoints(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
- }
-
- /**
- * Helper for drawPoints() that assumes you want to draw the entire array
- */
- public void drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint) {
- drawPoints(pts, 0, pts.length, paint);
- }
-
- /**
- * Helper for drawPoints() for drawing a single point.
- */
- public void drawPoint(float x, float y, @NonNull Paint paint) {
- native_drawPoint(mNativeCanvasWrapper, x, y, paint.getNativeInstance());
- }
-
- /**
- * Draw a line segment with the specified start and stop x,y coordinates,
- * using the specified paint.
- *
- *
Note that since a line is always "framed", the Style is ignored in the paint.
- *
- * Degenerate lines (length is 0) will not be drawn.
- *
- * @param startX The x-coordinate of the start point of the line
- * @param startY The y-coordinate of the start point of the line
- * @param paint The paint used to draw the line
- */
- public void drawLine(float startX, float startY, float stopX, float stopY,
- @NonNull Paint paint) {
- native_drawLine(mNativeCanvasWrapper, startX, startY, stopX, stopY, paint.getNativeInstance());
- }
-
- /**
- * Draw a series of lines. Each line is taken from 4 consecutive values
- * in the pts array. Thus to draw 1 line, the array must contain at least 4
- * values. This is logically the same as drawing the array as follows:
- * drawLine(pts[0], pts[1], pts[2], pts[3]) followed by
- * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on.
- *
- * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
- * @param offset Number of values in the array to skip before drawing.
- * @param count The number of values in the array to process, after
- * skipping "offset" of them. Since each line uses 4 values,
- * the number of "lines" that are drawn is really
- * (count >> 2).
- * @param paint The paint used to draw the points
- */
- public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
- @NonNull Paint paint) {
- native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.getNativeInstance());
- }
-
- public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint) {
- drawLines(pts, 0, pts.length, paint);
- }
-
- /**
- * Draw the specified Rect using the specified paint. The rectangle will
- * be filled or framed based on the Style in the paint.
- *
- * @param rect The rect to be drawn
- * @param paint The paint used to draw the rect
- */
- public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
- native_drawRect(mNativeCanvasWrapper,
- rect.left, rect.top, rect.right, rect.bottom, paint.getNativeInstance());
- }
-
- /**
- * Draw the specified Rect using the specified Paint. The rectangle
- * will be filled or framed based on the Style in the paint.
- *
- * @param r The rectangle to be drawn.
- * @param paint The paint used to draw the rectangle
- */
- public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
- drawRect(r.left, r.top, r.right, r.bottom, paint);
- }
-
-
- /**
- * Draw the specified Rect using the specified paint. The rectangle will
- * be filled or framed based on the Style in the paint.
- *
- * @param left The left side of the rectangle to be drawn
- * @param top The top side of the rectangle to be drawn
- * @param right The right side of the rectangle to be drawn
- * @param bottom The bottom side of the rectangle to be drawn
- * @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.getNativeInstance());
- }
-
- /**
- * Draw the specified oval using the specified paint. The oval will be
- * filled or framed based on the Style in the paint.
- *
- * @param oval The rectangle bounds of the oval to be drawn
- */
- public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
- if (oval == null) {
- throw new NullPointerException();
+ public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
+ save();
+ translate(dst.left, dst.top);
+ if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+ scale((float) dst.width() / picture.getWidth(),
+ (float) dst.height() / picture.getHeight());
}
- drawOval(oval.left, oval.top, oval.right, oval.bottom, paint);
+ drawPicture(picture);
+ restore();
}
/**
- * Draw the specified oval using the specified paint. The oval will be
- * filled or framed based on the Style in the paint.
+ * Draw the picture, stretched to fit into the dst rectangle.
*/
- public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
- native_drawOval(mNativeCanvasWrapper, left, top, right, bottom, paint.getNativeInstance());
+ public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
+ save();
+ translate(dst.left, dst.top);
+ if (picture.getWidth() > 0 && picture.getHeight() > 0) {
+ scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
+ }
+ drawPicture(picture);
+ restore();
+ }
+
+ public enum VertexMode {
+ TRIANGLES(0),
+ TRIANGLE_STRIP(1),
+ TRIANGLE_FAN(2);
+
+ VertexMode(int nativeInt) {
+ this.nativeInt = nativeInt;
+ }
+
+ /**
+ * @hide
+ */
+ public final int nativeInt;
}
/**
- * Draw the specified circle using the specified paint. If radius is <= 0,
- * then nothing will be drawn. The circle will be filled or framed based
- * on the Style in the paint.
+ * Releases the resources associated with this canvas.
*
- * @param cx The x-coordinate of the center of the cirle to be drawn
- * @param cy The y-coordinate of the center of the cirle to be drawn
- * @param radius The radius of the cirle to be drawn
- * @param paint The paint used to draw the circle
+ * @hide
*/
- public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
- native_drawCircle(mNativeCanvasWrapper, cx, cy, radius, paint.getNativeInstance());
+ public void release() {
+ mNativeCanvasWrapper = 0;
+ if (mFinalizer != null) {
+ mFinalizer.run();
+ mFinalizer = null;
+ }
+ }
+
+ /**
+ * Free up as much memory as possible from private caches (e.g. fonts, images)
+ *
+ * @hide
+ */
+ public static void freeCaches() {
+ nFreeCaches();
+ }
+
+ /**
+ * Free up text layout caches
+ *
+ * @hide
+ */
+ public static void freeTextLayoutCaches() {
+ nFreeTextLayoutCaches();
+ }
+
+ private static native void nFreeCaches();
+ private static native void nFreeTextLayoutCaches();
+ private static native long nInitRaster(Bitmap bitmap);
+ private static native long nGetNativeFinalizer();
+
+ // ---------------- @FastNative -------------------
+
+ @FastNative
+ private static native void nSetBitmap(long canvasHandle,
+ Bitmap bitmap);
+ @FastNative
+ private static native boolean nIsOpaque(long canvasHandle);
+ @FastNative
+ private static native void nSetHighContrastText(long renderer, boolean highContrastText);
+ @FastNative
+ private static native int nGetWidth(long canvasHandle);
+ @FastNative
+ private static native int nGetHeight(long canvasHandle);
+
+ @FastNative
+ private static native int nSave(long canvasHandle, int saveFlags);
+ @FastNative
+ private static native int nSaveLayer(long nativeCanvas, float l,
+ float t, float r, float b,
+ long nativePaint,
+ int layerFlags);
+ @FastNative
+ private static native int nSaveLayerAlpha(long nativeCanvas, float l,
+ float t, float r, float b,
+ int alpha, int layerFlags);
+ @FastNative
+ private static native void nRestore(long canvasHandle, boolean tolerateUnderflow);
+ @FastNative
+ private static native void nRestoreToCount(long canvasHandle,
+ int saveCount,
+ boolean tolerateUnderflow);
+ @FastNative
+ private static native int nGetSaveCount(long canvasHandle);
+
+ @FastNative
+ private static native void nTranslate(long canvasHandle,
+ float dx, float dy);
+ @FastNative
+ private static native void nScale(long canvasHandle,
+ float sx, float sy);
+ @FastNative
+ private static native void nRotate(long canvasHandle, float degrees);
+ @FastNative
+ private static native void nSkew(long canvasHandle,
+ float sx, float sy);
+ @FastNative
+ private static native void nConcat(long nativeCanvas,
+ long nativeMatrix);
+ @FastNative
+ private static native void nSetMatrix(long nativeCanvas,
+ long nativeMatrix);
+ @FastNative
+ private static native boolean nClipRect(long nativeCanvas,
+ float left, float top,
+ float right, float bottom,
+ int regionOp);
+ @FastNative
+ private static native boolean nClipPath(long nativeCanvas,
+ long nativePath,
+ int regionOp);
+ @FastNative
+ private static native boolean nClipRegion(long nativeCanvas,
+ long nativeRegion,
+ int regionOp);
+ @FastNative
+ private static native void nSetDrawFilter(long nativeCanvas,
+ long nativeFilter);
+ @FastNative
+ private static native boolean nGetClipBounds(long nativeCanvas,
+ Rect bounds);
+ @FastNative
+ private static native void nGetCTM(long nativeCanvas,
+ long nativeMatrix);
+ @FastNative
+ private static native boolean nQuickReject(long nativeCanvas,
+ long nativePath);
+ @FastNative
+ private static native boolean nQuickReject(long nativeCanvas,
+ float left, float top,
+ float right, float bottom);
+
+ /**
+ * Draw the specified arc, which will be scaled to fit inside the
+ * specified oval.
+ *
+ * If the start angle is negative or >= 360, the start angle is treated
+ * as start angle modulo 360.
+ *
+ * If the sweep angle is >= 360, then the oval is drawn
+ * completely. Note that this differs slightly from SkPath::arcTo, which
+ * treats the sweep angle modulo 360. If the sweep angle is negative,
+ * the sweep angle is treated as sweep angle modulo 360
+ *
+ * The arc is drawn clockwise. An angle of 0 degrees correspond to the
+ * geometric angle of 0 degrees (3 o'clock on a watch.)
+ *
+ * @param startAngle Starting angle (in degrees) where the arc begins
+ * @param sweepAngle Sweep angle (in degrees) measured clockwise
+ * @param useCenter If true, include the center of the oval in the arc, and
+ close it if it is being stroked. This will draw a wedge
+ * @param paint The paint used to draw the arc
+ */
+ public void drawArc(float left, float top, float right, float bottom, float startAngle,
+ float sweepAngle, boolean useCenter, @NonNull Paint paint) {
+ super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
}
/**
@@ -1208,126 +1186,20 @@ public class Canvas {
*/
public void drawArc(@NonNull RectF oval, float startAngle, float sweepAngle, boolean useCenter,
@NonNull Paint paint) {
- drawArc(oval.left, oval.top, oval.right, oval.bottom, startAngle, sweepAngle, useCenter,
- paint);
+ super.drawArc(oval, startAngle, sweepAngle, useCenter, paint);
}
/**
- * Draw the specified arc, which will be scaled to fit inside the
- * specified oval.
+ * Fill the entire canvas' bitmap (restricted to the current clip) with the
+ * specified ARGB color, using srcover porterduff mode.
*
- * If the start angle is negative or >= 360, the start angle is treated
- * as start angle modulo 360.
- *
- * If the sweep angle is >= 360, then the oval is drawn
- * completely. Note that this differs slightly from SkPath::arcTo, which
- * treats the sweep angle modulo 360. If the sweep angle is negative,
- * the sweep angle is treated as sweep angle modulo 360
- *
- * The arc is drawn clockwise. An angle of 0 degrees correspond to the
- * geometric angle of 0 degrees (3 o'clock on a watch.)
- *
- * @param startAngle Starting angle (in degrees) where the arc begins
- * @param sweepAngle Sweep angle (in degrees) measured clockwise
- * @param useCenter If true, include the center of the oval in the arc, and
- close it if it is being stroked. This will draw a wedge
- * @param paint The paint used to draw the arc
+ * @param a alpha component (0..255) of the color to draw onto the canvas
+ * @param r red component (0..255) of the color to draw onto the canvas
+ * @param g green component (0..255) of the color to draw onto the canvas
+ * @param b blue component (0..255) of the color to draw onto the 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.getNativeInstance());
- }
-
- /**
- * Draw the specified round-rect using the specified paint. The roundrect
- * will be filled or framed based on the Style in the paint.
- *
- * @param rect The rectangular bounds of the roundRect to be drawn
- * @param rx The x-radius of the oval used to round the corners
- * @param ry The y-radius of the oval used to round the corners
- * @param paint The paint used to draw the roundRect
- */
- public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
- drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
- }
-
- /**
- * Draw the specified round-rect using the specified paint. The roundrect
- * will be filled or framed based on the Style in the paint.
- *
- * @param rx The x-radius of the oval used to round the corners
- * @param ry The y-radius of the oval used to round the corners
- * @param paint The paint used to draw the roundRect
- */
- 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.getNativeInstance());
- }
-
- /**
- * Draw the specified path using the specified paint. The path will be
- * filled or framed based on the Style in the paint.
- *
- * @param path The path to be drawn
- * @param paint The paint used to draw the path
- */
- public void drawPath(@NonNull Path path, @NonNull Paint paint) {
- if (path.isSimplePath && path.rects != null) {
- native_drawRegion(mNativeCanvasWrapper, path.rects.mNativeRegion, paint.getNativeInstance());
- } else {
- native_drawPath(mNativeCanvasWrapper, path.readOnlyNI(), paint.getNativeInstance());
- }
- }
-
- /**
- * @hide
- */
- protected void throwIfCannotDraw(Bitmap bitmap) {
- if (bitmap.isRecycled()) {
- throw new RuntimeException("Canvas: trying to use a recycled bitmap " + bitmap);
- }
- if (!bitmap.isPremultiplied() && bitmap.getConfig() == Bitmap.Config.ARGB_8888 &&
- bitmap.hasAlpha()) {
- throw new RuntimeException("Canvas: trying to use a non-premultiplied bitmap "
- + bitmap);
- }
- }
-
- /**
- * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
- *
- * @param patch The ninepatch object to render
- * @param dst The destination rectangle.
- * @param paint The paint to draw the bitmap with. may be null
- *
- * @hide
- */
- public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
- Bitmap bitmap = patch.getBitmap();
- throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- native_drawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint,
- mDensity, patch.getDensity());
- }
-
- /**
- * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
- *
- * @param patch The ninepatch object to render
- * @param dst The destination rectangle.
- * @param paint The paint to draw the bitmap with. may be null
- *
- * @hide
- */
- public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
- Bitmap bitmap = patch.getBitmap();
- throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
- native_drawNinePatch(mNativeCanvasWrapper, bitmap.getNativeInstance(), patch.mNativeChunk,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint,
- mDensity, patch.getDensity());
+ public void drawARGB(int a, int r, int g, int b) {
+ super.drawARGB(a, r, g, b);
}
/**
@@ -1350,57 +1222,19 @@ public class Canvas {
* @param paint The paint used to draw the bitmap (may be null)
*/
public void drawBitmap(@NonNull Bitmap bitmap, float left, float top, @Nullable Paint paint) {
- throwIfCannotDraw(bitmap);
- native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top,
- paint != null ? paint.getNativeInstance() : 0, mDensity, mScreenDensity, bitmap.mDensity);
+ super.drawBitmap(bitmap, left, top, paint);
}
/**
- * Draw the specified bitmap, scaling/translating automatically to fill
- * the destination rectangle. If the source rectangle is not null, it
- * specifies the subset of the bitmap to draw.
+ * Draw the bitmap using the specified matrix.
*
- * Note: if the paint contains a maskfilter that generates a mask which
- * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
- * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
- * Thus the color outside of the original width/height will be the edge
- * color replicated.
- *
- *
This function ignores the density associated with the bitmap.
- * This is because the source and destination rectangle coordinate
- * spaces are in their respective densities, so must already have the
- * appropriate scaling factor applied.
- *
- * @param bitmap The bitmap to be drawn
- * @param src May be null. The subset of the bitmap to be drawn
- * @param dst The rectangle that the bitmap will be scaled/translated
- * to fit into
+ * @param bitmap The bitmap to draw
+ * @param matrix The matrix used to transform the bitmap when it is drawn
* @param paint May be null. The paint used to draw the bitmap
*/
- public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
- @Nullable Paint paint) {
- if (dst == null) {
- throw new NullPointerException();
- }
- throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-
- float left, top, right, bottom;
- if (src == null) {
- left = top = 0;
- right = bitmap.getWidth();
- bottom = bitmap.getHeight();
- } else {
- left = src.left;
- right = src.right;
- top = src.top;
- bottom = src.bottom;
- }
-
- native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
- bitmap.mDensity);
- }
+ public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
+ super.drawBitmap(bitmap, matrix, paint);
+ }
/**
* Draw the specified bitmap, scaling/translating automatically to fill
@@ -1426,29 +1260,36 @@ public class Canvas {
*/
public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull Rect dst,
@Nullable Paint paint) {
- if (dst == null) {
- throw new NullPointerException();
- }
- throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.getNativeInstance();
-
- int left, top, right, bottom;
- if (src == null) {
- left = top = 0;
- right = bitmap.getWidth();
- bottom = bitmap.getHeight();
- } else {
- left = src.left;
- right = src.right;
- top = src.top;
- bottom = src.bottom;
- }
-
- native_drawBitmap(mNativeCanvasWrapper, bitmap, left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
- bitmap.mDensity);
+ super.drawBitmap(bitmap, src, dst, paint);
}
+ /**
+ * Draw the specified bitmap, scaling/translating automatically to fill
+ * the destination rectangle. If the source rectangle is not null, it
+ * specifies the subset of the bitmap to draw.
+ *
+ *
Note: if the paint contains a maskfilter that generates a mask which
+ * extends beyond the bitmap's original width/height (e.g. BlurMaskFilter),
+ * then the bitmap will be drawn as if it were in a Shader with CLAMP mode.
+ * Thus the color outside of the original width/height will be the edge
+ * color replicated.
+ *
+ *
This function ignores the density associated with the bitmap.
+ * This is because the source and destination rectangle coordinate
+ * spaces are in their respective densities, so must already have the
+ * appropriate scaling factor applied.
+ *
+ * @param bitmap The bitmap to be drawn
+ * @param src May be null. The subset of the bitmap to be drawn
+ * @param dst The rectangle that the bitmap will be scaled/translated
+ * to fit into
+ * @param paint May be null. The paint used to draw the bitmap
+ */
+ public void drawBitmap(@NonNull Bitmap bitmap, @Nullable Rect src, @NonNull RectF dst,
+ @Nullable Paint paint) {
+ super.drawBitmap(bitmap, src, dst, paint);
+ }
+
/**
* Treat the specified array of colors as a bitmap, and draw it. This gives
* the same result as first creating a bitmap from the array, and then
@@ -1476,29 +1317,7 @@ public class Canvas {
@Deprecated
public void drawBitmap(@NonNull int[] colors, int offset, int stride, float x, float y,
int width, int height, boolean hasAlpha, @Nullable Paint paint) {
- // check for valid input
- if (width < 0) {
- throw new IllegalArgumentException("width must be >= 0");
- }
- if (height < 0) {
- throw new IllegalArgumentException("height must be >= 0");
- }
- if (Math.abs(stride) < width) {
- throw new IllegalArgumentException("abs(stride) must be >= width");
- }
- int lastScanline = offset + (height - 1) * stride;
- int length = colors.length;
- if (offset < 0 || (offset + width > length) || lastScanline < 0
- || (lastScanline + width > length)) {
- throw new ArrayIndexOutOfBoundsException();
- }
- // quick escape if there's nothing to draw
- if (width == 0 || height == 0) {
- return;
- }
- // punch down to native for the actual draw
- native_drawBitmap(mNativeCanvasWrapper, colors, offset, stride, x, y, width, height, hasAlpha,
- paint != null ? paint.getNativeInstance() : 0);
+ super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
}
/**
@@ -1512,30 +1331,7 @@ public class Canvas {
@Deprecated
public void drawBitmap(@NonNull int[] colors, int offset, int stride, int x, int y,
int width, int height, boolean hasAlpha, @Nullable Paint paint) {
- // call through to the common float version
- drawBitmap(colors, offset, stride, (float)x, (float)y, width, height,
- hasAlpha, paint);
- }
-
- /**
- * Draw the bitmap using the specified matrix.
- *
- * @param bitmap The bitmap to draw
- * @param matrix The matrix used to transform the bitmap when it is drawn
- * @param paint May be null. The paint used to draw the bitmap
- */
- public void drawBitmap(@NonNull Bitmap bitmap, @NonNull Matrix matrix, @Nullable Paint paint) {
- nativeDrawBitmapMatrix(mNativeCanvasWrapper, bitmap, matrix.ni(),
- paint != null ? paint.getNativeInstance() : 0);
- }
-
- /**
- * @hide
- */
- protected static void checkRange(int length, int offset, int count) {
- if ((offset | count) < 0 || offset + count > length) {
- throw new ArrayIndexOutOfBoundsException();
- }
+ super.drawBitmap(colors, offset, stride, x, y, width, height, hasAlpha, paint);
}
/**
@@ -1567,89 +1363,299 @@ public class Canvas {
public void drawBitmapMesh(@NonNull Bitmap bitmap, int meshWidth, int meshHeight,
@NonNull float[] verts, int vertOffset, @Nullable int[] colors, int colorOffset,
@Nullable Paint paint) {
- if ((meshWidth | meshHeight | vertOffset | colorOffset) < 0) {
- throw new ArrayIndexOutOfBoundsException();
- }
- if (meshWidth == 0 || meshHeight == 0) {
- return;
- }
- int count = (meshWidth + 1) * (meshHeight + 1);
- // we mul by 2 since we need two floats per vertex
- checkRange(verts.length, vertOffset, count * 2);
- if (colors != null) {
- // no mul by 2, since we need only 1 color per vertex
- checkRange(colors.length, colorOffset, count);
- }
- nativeDrawBitmapMesh(mNativeCanvasWrapper, bitmap, meshWidth, meshHeight,
- verts, vertOffset, colors, colorOffset,
- paint != null ? paint.getNativeInstance() : 0);
- }
-
- public enum VertexMode {
- TRIANGLES(0),
- TRIANGLE_STRIP(1),
- TRIANGLE_FAN(2);
-
- VertexMode(int nativeInt) {
- this.nativeInt = nativeInt;
- }
-
- /**
- * @hide
- */
- public final int nativeInt;
+ super.drawBitmapMesh(bitmap, meshWidth, meshHeight, verts, vertOffset, colors, colorOffset,
+ paint);
}
/**
- * Draw the array of vertices, interpreted as triangles (based on mode). The
- * verts array is required, and specifies the x,y pairs for each vertex. If
- * texs is non-null, then it is used to specify the coordinate in shader
- * coordinates to use at each vertex (the paint must have a shader in this
- * case). If there is no texs array, but there is a color array, then each
- * color is interpolated across its corresponding triangle in a gradient. If
- * both texs and colors arrays are present, then they behave as before, but
- * the resulting color at each pixels is the result of multiplying the
- * colors from the shader and the color-gradient together. The indices array
- * is optional, but if it is present, then it is used to specify the index
- * of each triangle, rather than just walking through the arrays in order.
+ * Draw the specified circle using the specified paint. If radius is <= 0,
+ * then nothing will be drawn. The circle will be filled or framed based
+ * on the Style in the paint.
*
- * @param mode How to interpret the array of vertices
- * @param vertexCount The number of values in the vertices array (and
- * corresponding texs and colors arrays if non-null). Each logical
- * vertex is two values (x, y), vertexCount must be a multiple of 2.
- * @param verts Array of vertices for the mesh
- * @param vertOffset Number of values in the verts to skip before drawing.
- * @param texs May be null. If not null, specifies the coordinates to sample
- * into the current shader (e.g. bitmap tile or gradient)
- * @param texOffset Number of values in texs to skip before drawing.
- * @param colors May be null. If not null, specifies a color for each
- * vertex, to be interpolated across the triangle.
- * @param colorOffset Number of values in colors to skip before drawing.
- * @param indices If not null, array of indices to reference into the
- * vertex (texs, colors) array.
- * @param indexCount number of entries in the indices array (if not null).
- * @param paint Specifies the shader to use if the texs array is non-null.
+ * @param cx The x-coordinate of the center of the cirle to be drawn
+ * @param cy The y-coordinate of the center of the cirle to be drawn
+ * @param radius The radius of the cirle to be drawn
+ * @param paint The paint used to draw the circle
*/
- public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
- int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
- int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
+ public void drawCircle(float cx, float cy, float radius, @NonNull Paint paint) {
+ super.drawCircle(cx, cy, radius, paint);
+ }
+
+ /**
+ * Fill the entire canvas' bitmap (restricted to the current clip) with the
+ * specified color, using srcover porterduff mode.
+ *
+ * @param color the color to draw onto the canvas
+ */
+ public void drawColor(@ColorInt int color) {
+ super.drawColor(color);
+ }
+
+ /**
+ * Fill the entire canvas' bitmap (restricted to the current clip) with the
+ * specified color and porter-duff xfermode.
+ *
+ * @param color the color to draw with
+ * @param mode the porter-duff mode to apply to the color
+ */
+ public void drawColor(@ColorInt int color, @NonNull PorterDuff.Mode mode) {
+ super.drawColor(color, mode);
+ }
+
+ /**
+ * Draw a line segment with the specified start and stop x,y coordinates,
+ * using the specified paint.
+ *
+ *
Note that since a line is always "framed", the Style is ignored in the paint.
+ *
+ * Degenerate lines (length is 0) will not be drawn.
+ *
+ * @param startX The x-coordinate of the start point of the line
+ * @param startY The y-coordinate of the start point of the line
+ * @param paint The paint used to draw the line
+ */
+ public void drawLine(float startX, float startY, float stopX, float stopY,
@NonNull Paint paint) {
- checkRange(verts.length, vertOffset, vertexCount);
- if (isHardwareAccelerated()) {
- return;
- }
- if (texs != null) {
- checkRange(texs.length, texOffset, vertexCount);
- }
- if (colors != null) {
- checkRange(colors.length, colorOffset, vertexCount / 2);
- }
- if (indices != null) {
- checkRange(indices.length, indexOffset, indexCount);
- }
- nativeDrawVertices(mNativeCanvasWrapper, mode.nativeInt, vertexCount, verts,
- vertOffset, texs, texOffset, colors, colorOffset,
- indices, indexOffset, indexCount, paint.getNativeInstance());
+ super.drawLine(startX, startY, stopX, stopY, paint);
+ }
+
+ /**
+ * Draw a series of lines. Each line is taken from 4 consecutive values
+ * in the pts array. Thus to draw 1 line, the array must contain at least 4
+ * values. This is logically the same as drawing the array as follows:
+ * drawLine(pts[0], pts[1], pts[2], pts[3]) followed by
+ * drawLine(pts[4], pts[5], pts[6], pts[7]) and so on.
+ *
+ * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
+ * @param offset Number of values in the array to skip before drawing.
+ * @param count The number of values in the array to process, after
+ * skipping "offset" of them. Since each line uses 4 values,
+ * the number of "lines" that are drawn is really
+ * (count >> 2).
+ * @param paint The paint used to draw the points
+ */
+ public void drawLines(@Size(multiple=4) @NonNull float[] pts, int offset, int count,
+ @NonNull Paint paint) {
+ super.drawLines(pts, offset, count, paint);
+ }
+
+ public void drawLines(@Size(multiple=4) @NonNull float[] pts, @NonNull Paint paint) {
+ super.drawLines(pts, paint);
+ }
+
+ /**
+ * Draw the specified oval using the specified paint. The oval will be
+ * filled or framed based on the Style in the paint.
+ */
+ public void drawOval(float left, float top, float right, float bottom, @NonNull Paint paint) {
+ super.drawOval(left, top, right, bottom, paint);
+ }
+
+ /**
+ * Draw the specified oval using the specified paint. The oval will be
+ * filled or framed based on the Style in the paint.
+ *
+ * @param oval The rectangle bounds of the oval to be drawn
+ */
+ public void drawOval(@NonNull RectF oval, @NonNull Paint paint) {
+ super.drawOval(oval, paint);
+ }
+
+ /**
+ * Fill the entire canvas' bitmap (restricted to the current clip) with
+ * the specified paint. This is equivalent (but faster) to drawing an
+ * infinitely large rectangle with the specified paint.
+ *
+ * @param paint The paint used to draw onto the canvas
+ */
+ public void drawPaint(@NonNull Paint paint) {
+ super.drawPaint(paint);
+ }
+
+ /**
+ * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
+ *
+ * @param patch The ninepatch object to render
+ * @param dst The destination rectangle.
+ * @param paint The paint to draw the bitmap with. may be null
+ *
+ * @hide
+ */
+ public void drawPatch(@NonNull NinePatch patch, @NonNull Rect dst, @Nullable Paint paint) {
+ super.drawPatch(patch, dst, paint);
+ }
+
+ /**
+ * Draws the specified bitmap as an N-patch (most often, a 9-patches.)
+ *
+ * @param patch The ninepatch object to render
+ * @param dst The destination rectangle.
+ * @param paint The paint to draw the bitmap with. may be null
+ *
+ * @hide
+ */
+ public void drawPatch(@NonNull NinePatch patch, @NonNull RectF dst, @Nullable Paint paint) {
+ super.drawPatch(patch, dst, paint);
+ }
+
+ /**
+ * Draw the specified path using the specified paint. The path will be
+ * filled or framed based on the Style in the paint.
+ *
+ * @param path The path to be drawn
+ * @param paint The paint used to draw the path
+ */
+ public void drawPath(@NonNull Path path, @NonNull Paint paint) {
+ super.drawPath(path, paint);
+ }
+
+ /**
+ * Helper for drawPoints() for drawing a single point.
+ */
+ public void drawPoint(float x, float y, @NonNull Paint paint) {
+ super.drawPoint(x, y, paint);
+ }
+
+ /**
+ * Draw a series of points. Each point is centered at the coordinate
+ * specified by pts[], and its diameter is specified by the paint's stroke
+ * width (as transformed by the canvas' CTM), with special treatment for
+ * a stroke width of 0, which always draws exactly 1 pixel (or at most 4
+ * if antialiasing is enabled). The shape of the point is controlled by
+ * the paint's Cap type. The shape is a square, unless the cap type is
+ * Round, in which case the shape is a circle.
+ *
+ * @param pts Array of points to draw [x0 y0 x1 y1 x2 y2 ...]
+ * @param offset Number of values to skip before starting to draw.
+ * @param count The number of values to process, after skipping offset
+ * of them. Since one point uses two values, the number of
+ * "points" that are drawn is really (count >> 1).
+ * @param paint The paint used to draw the points
+ */
+ public void drawPoints(@Size(multiple=2) float[] pts, int offset, int count,
+ @NonNull Paint paint) {
+ super.drawPoints(pts, offset, count, paint);
+ }
+
+ /**
+ * Helper for drawPoints() that assumes you want to draw the entire array
+ */
+ public void drawPoints(@Size(multiple=2) @NonNull float[] pts, @NonNull Paint paint) {
+ super.drawPoints(pts, paint);
+ }
+
+ /**
+ * Draw the text in the array, with each character's origin specified by
+ * the pos array.
+ *
+ * @param text The text to be drawn
+ * @param index The index of the first character to draw
+ * @param count The number of characters to draw, starting from index.
+ * @param pos Array of [x,y] positions, used to position each
+ * character
+ * @param paint The paint used for the text (e.g. color, size, style)
+ *
+ * @deprecated This method does not support glyph composition and decomposition and
+ * should therefore not be used to render complex scripts. It also doesn't
+ * handle supplementary characters (eg emoji).
+ */
+ @Deprecated
+ public void drawPosText(@NonNull char[] text, int index, int count,
+ @NonNull @Size(multiple=2) float[] pos,
+ @NonNull Paint paint) {
+ super.drawPosText(text, index, count, pos, paint);
+ }
+
+ /**
+ * Draw the text in the array, with each character's origin specified by
+ * the pos array.
+ *
+ * @param text The text to be drawn
+ * @param pos Array of [x,y] positions, used to position each character
+ * @param paint The paint used for the text (e.g. color, size, style)
+ *
+ * @deprecated This method does not support glyph composition and decomposition and
+ * should therefore not be used to render complex scripts. It also doesn't
+ * handle supplementary characters (eg emoji).
+ */
+ @Deprecated
+ public void drawPosText(@NonNull String text, @NonNull @Size(multiple=2) float[] pos,
+ @NonNull Paint paint) {
+ super.drawPosText(text, pos, paint);
+ }
+
+ /**
+ * Draw the specified Rect using the specified paint. The rectangle will
+ * be filled or framed based on the Style in the paint.
+ *
+ * @param left The left side of the rectangle to be drawn
+ * @param top The top side of the rectangle to be drawn
+ * @param right The right side of the rectangle to be drawn
+ * @param bottom The bottom side of the rectangle to be drawn
+ * @param paint The paint used to draw the rect
+ */
+ public void drawRect(float left, float top, float right, float bottom, @NonNull Paint paint) {
+ super.drawRect(left, top, right, bottom, paint);
+ }
+
+ /**
+ * Draw the specified Rect using the specified Paint. The rectangle
+ * will be filled or framed based on the Style in the paint.
+ *
+ * @param r The rectangle to be drawn.
+ * @param paint The paint used to draw the rectangle
+ */
+ public void drawRect(@NonNull Rect r, @NonNull Paint paint) {
+ super.drawRect(r, paint);
+ }
+
+ /**
+ * Draw the specified Rect using the specified paint. The rectangle will
+ * be filled or framed based on the Style in the paint.
+ *
+ * @param rect The rect to be drawn
+ * @param paint The paint used to draw the rect
+ */
+ public void drawRect(@NonNull RectF rect, @NonNull Paint paint) {
+ super.drawRect(rect, paint);
+ }
+
+ /**
+ * Fill the entire canvas' bitmap (restricted to the current clip) with the
+ * specified RGB color, using srcover porterduff mode.
+ *
+ * @param r red component (0..255) of the color to draw onto the canvas
+ * @param g green component (0..255) of the color to draw onto the canvas
+ * @param b blue component (0..255) of the color to draw onto the canvas
+ */
+ public void drawRGB(int r, int g, int b) {
+ super.drawRGB(r, g, b);
+ }
+
+ /**
+ * Draw the specified round-rect using the specified paint. The roundrect
+ * will be filled or framed based on the Style in the paint.
+ *
+ * @param rx The x-radius of the oval used to round the corners
+ * @param ry The y-radius of the oval used to round the corners
+ * @param paint The paint used to draw the roundRect
+ */
+ public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+ @NonNull Paint paint) {
+ super.drawRoundRect(left, top, right, bottom, rx, ry, paint);
+ }
+
+ /**
+ * Draw the specified round-rect using the specified paint. The roundrect
+ * will be filled or framed based on the Style in the paint.
+ *
+ * @param rect The rectangular bounds of the roundRect to be drawn
+ * @param rx The x-radius of the oval used to round the corners
+ * @param ry The y-radius of the oval used to round the corners
+ * @param paint The paint used to draw the roundRect
+ */
+ public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
+ super.drawRoundRect(rect, rx, ry, paint);
}
/**
@@ -1663,46 +1669,7 @@ public class Canvas {
*/
public void drawText(@NonNull char[] text, int index, int count, float x, float y,
@NonNull Paint paint) {
- if ((index | count | (index + count) |
- (text.length - index - count)) < 0) {
- throw new IndexOutOfBoundsException();
- }
- native_drawText(mNativeCanvasWrapper, text, index, count, x, y, paint.mBidiFlags,
- paint.getNativeInstance(), paint.mNativeTypeface);
- }
-
- /**
- * Draw the text, with origin at (x,y), using the specified paint. The
- * origin is interpreted based on the Align setting in the paint.
- *
- * @param text The text to be drawn
- * @param x The x-coordinate of the origin of the text being drawn
- * @param y The y-coordinate of the baseline of the text being drawn
- * @param paint The paint used for the text (e.g. color, size, style)
- */
- 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.getNativeInstance(), paint.mNativeTypeface);
- }
-
- /**
- * Draw the text, with origin at (x,y), using the specified paint.
- * The origin is interpreted based on the Align setting in the paint.
- *
- * @param text The text to be drawn
- * @param start The index of the first character in text to draw
- * @param end (end - 1) is the index of the last character in text to draw
- * @param x The x-coordinate of the origin of the text being drawn
- * @param y The y-coordinate of the baseline of the text being drawn
- * @param paint The paint used for the text (e.g. color, size, style)
- */
- public void drawText(@NonNull String text, int start, int end, float x, float y,
- @NonNull Paint paint) {
- if ((start | end | (end - start) | (text.length() - end)) < 0) {
- throw new IndexOutOfBoundsException();
- }
- native_drawText(mNativeCanvasWrapper, text, start, end, x, y, paint.mBidiFlags,
- paint.getNativeInstance(), paint.mNativeTypeface);
+ super.drawText(text, index, count, x, y, paint);
}
/**
@@ -1720,23 +1687,72 @@ public class Canvas {
*/
public void drawText(@NonNull CharSequence text, int start, int end, float x, float y,
@NonNull Paint paint) {
- if ((start | end | (end - start) | (text.length() - end)) < 0) {
- throw new IndexOutOfBoundsException();
- }
- if (text instanceof String || text instanceof SpannedString ||
- text instanceof SpannableString) {
- native_drawText(mNativeCanvasWrapper, text.toString(), start, end, x, y,
- paint.mBidiFlags, 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);
- native_drawText(mNativeCanvasWrapper, buf, 0, end - start, x, y,
- paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
- TemporaryBuffer.recycle(buf);
- }
+ super.drawText(text, start, end, x, y, paint);
+ }
+
+ /**
+ * Draw the text, with origin at (x,y), using the specified paint. The
+ * origin is interpreted based on the Align setting in the paint.
+ *
+ * @param text The text to be drawn
+ * @param x The x-coordinate of the origin of the text being drawn
+ * @param y The y-coordinate of the baseline of the text being drawn
+ * @param paint The paint used for the text (e.g. color, size, style)
+ */
+ public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
+ super.drawText(text, x, y, paint);
+ }
+
+ /**
+ * Draw the text, with origin at (x,y), using the specified paint.
+ * The origin is interpreted based on the Align setting in the paint.
+ *
+ * @param text The text to be drawn
+ * @param start The index of the first character in text to draw
+ * @param end (end - 1) is the index of the last character in text to draw
+ * @param x The x-coordinate of the origin of the text being drawn
+ * @param y The y-coordinate of the baseline of the text being drawn
+ * @param paint The paint used for the text (e.g. color, size, style)
+ */
+ public void drawText(@NonNull String text, int start, int end, float x, float y,
+ @NonNull Paint paint) {
+ super.drawText(text, start, end, x, y, paint);
+ }
+
+ /**
+ * Draw the text, with origin at (x,y), using the specified paint, along
+ * the specified path. The paint's Align setting determins where along the
+ * path to start the text.
+ *
+ * @param text The text to be drawn
+ * @param path The path the text should follow for its baseline
+ * @param hOffset The distance along the path to add to the text's
+ * starting position
+ * @param vOffset The distance above(-) or below(+) the path to position
+ * the text
+ * @param paint The paint used for the text (e.g. color, size, style)
+ */
+ public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
+ float hOffset, float vOffset, @NonNull Paint paint) {
+ super.drawTextOnPath(text, index, count, path, hOffset, vOffset, paint);
+ }
+
+ /**
+ * Draw the text, with origin at (x,y), using the specified paint, along
+ * the specified path. The paint's Align setting determins where along the
+ * path to start the text.
+ *
+ * @param text The text to be drawn
+ * @param path The path the text should follow for its baseline
+ * @param hOffset The distance along the path to add to the text's
+ * starting position
+ * @param vOffset The distance above(-) or below(+) the path to position
+ * the text
+ * @param paint The paint used for the text (e.g. color, size, style)
+ */
+ public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
+ float vOffset, @NonNull Paint paint) {
+ super.drawTextOnPath(text, path, hOffset, vOffset, paint);
}
/**
@@ -1764,21 +1780,7 @@ public class Canvas {
*/
public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex,
int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) {
-
- if (text == null) {
- throw new NullPointerException("text is null");
- }
- if (paint == null) {
- throw new NullPointerException("paint is null");
- }
- if ((index | count | contextIndex | contextCount | index - contextIndex
- | (contextIndex + contextCount) - (index + count)
- | text.length - (contextIndex + contextCount)) < 0) {
- throw new IndexOutOfBoundsException();
- }
-
- native_drawTextRun(mNativeCanvasWrapper, text, index, count, contextIndex, contextCount,
- x, y, isRtl, paint.getNativeInstance(), paint.mNativeTypeface);
+ super.drawTextRun(text, index, count, contextIndex, contextCount, x, y, isRtl, paint);
}
/**
@@ -1818,393 +1820,44 @@ public class Canvas {
*/
public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart,
int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) {
-
- if (text == null) {
- throw new NullPointerException("text is null");
- }
- if (paint == null) {
- throw new NullPointerException("paint is null");
- }
- if ((start | end | contextStart | contextEnd | start - contextStart | end - start
- | contextEnd - end | text.length() - contextEnd) < 0) {
- throw new IndexOutOfBoundsException();
- }
-
- if (text instanceof String || text instanceof SpannedString ||
- text instanceof SpannableString) {
- native_drawTextRun(mNativeCanvasWrapper, text.toString(), start, end, 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);
- } else {
- int contextLen = contextEnd - contextStart;
- int len = end - start;
- 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.getNativeInstance(), paint.mNativeTypeface);
- TemporaryBuffer.recycle(buf);
- }
+ super.drawTextRun(text, start, end, contextStart, contextEnd, x, y, isRtl, paint);
}
/**
- * Draw the text in the array, with each character's origin specified by
- * the pos array.
+ * Draw the array of vertices, interpreted as triangles (based on mode). The
+ * verts array is required, and specifies the x,y pairs for each vertex. If
+ * texs is non-null, then it is used to specify the coordinate in shader
+ * coordinates to use at each vertex (the paint must have a shader in this
+ * case). If there is no texs array, but there is a color array, then each
+ * color is interpolated across its corresponding triangle in a gradient. If
+ * both texs and colors arrays are present, then they behave as before, but
+ * the resulting color at each pixels is the result of multiplying the
+ * colors from the shader and the color-gradient together. The indices array
+ * is optional, but if it is present, then it is used to specify the index
+ * of each triangle, rather than just walking through the arrays in order.
*
- * @param text The text to be drawn
- * @param index The index of the first character to draw
- * @param count The number of characters to draw, starting from index.
- * @param pos Array of [x,y] positions, used to position each
- * character
- * @param paint The paint used for the text (e.g. color, size, style)
- *
- * @deprecated This method does not support glyph composition and decomposition and
- * should therefore not be used to render complex scripts. It also doesn't
- * handle supplementary characters (eg emoji).
+ * @param mode How to interpret the array of vertices
+ * @param vertexCount The number of values in the vertices array (and
+ * corresponding texs and colors arrays if non-null). Each logical
+ * vertex is two values (x, y), vertexCount must be a multiple of 2.
+ * @param verts Array of vertices for the mesh
+ * @param vertOffset Number of values in the verts to skip before drawing.
+ * @param texs May be null. If not null, specifies the coordinates to sample
+ * into the current shader (e.g. bitmap tile or gradient)
+ * @param texOffset Number of values in texs to skip before drawing.
+ * @param colors May be null. If not null, specifies a color for each
+ * vertex, to be interpolated across the triangle.
+ * @param colorOffset Number of values in colors to skip before drawing.
+ * @param indices If not null, array of indices to reference into the
+ * vertex (texs, colors) array.
+ * @param indexCount number of entries in the indices array (if not null).
+ * @param paint Specifies the shader to use if the texs array is non-null.
*/
- @Deprecated
- public void drawPosText(@NonNull char[] text, int index, int count,
- @NonNull @Size(multiple=2) float[] pos,
+ public void drawVertices(@NonNull VertexMode mode, int vertexCount, @NonNull float[] verts,
+ int vertOffset, @Nullable float[] texs, int texOffset, @Nullable int[] colors,
+ int colorOffset, @Nullable short[] indices, int indexOffset, int indexCount,
@NonNull Paint paint) {
- if (index < 0 || index + count > text.length || count*2 > pos.length) {
- throw new IndexOutOfBoundsException();
- }
- for (int i = 0; i < count; i++) {
- drawText(text, index + i, 1, pos[i * 2], pos[i * 2 + 1], paint);
- }
+ super.drawVertices(mode, vertexCount, verts, vertOffset, texs, texOffset,
+ colors, colorOffset, indices, indexOffset, indexCount, paint);
}
-
- /**
- * Draw the text in the array, with each character's origin specified by
- * the pos array.
- *
- * @param text The text to be drawn
- * @param pos Array of [x,y] positions, used to position each character
- * @param paint The paint used for the text (e.g. color, size, style)
- *
- * @deprecated This method does not support glyph composition and decomposition and
- * should therefore not be used to render complex scripts. It also doesn't
- * handle supplementary characters (eg emoji).
- */
- @Deprecated
- public void drawPosText(@NonNull String text, @NonNull @Size(multiple=2) float[] pos,
- @NonNull Paint paint) {
- drawPosText(text.toCharArray(), 0, text.length(), pos, paint);
- }
-
- /**
- * Draw the text, with origin at (x,y), using the specified paint, along
- * the specified path. The paint's Align setting determins where along the
- * path to start the text.
- *
- * @param text The text to be drawn
- * @param path The path the text should follow for its baseline
- * @param hOffset The distance along the path to add to the text's
- * starting position
- * @param vOffset The distance above(-) or below(+) the path to position
- * the text
- * @param paint The paint used for the text (e.g. color, size, style)
- */
- public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path,
- float hOffset, float vOffset, @NonNull Paint paint) {
- if (index < 0 || index + count > text.length) {
- throw new ArrayIndexOutOfBoundsException();
- }
- native_drawTextOnPath(mNativeCanvasWrapper, text, index, count,
- path.readOnlyNI(), hOffset, vOffset,
- paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
- }
-
- /**
- * Draw the text, with origin at (x,y), using the specified paint, along
- * the specified path. The paint's Align setting determins where along the
- * path to start the text.
- *
- * @param text The text to be drawn
- * @param path The path the text should follow for its baseline
- * @param hOffset The distance along the path to add to the text's
- * starting position
- * @param vOffset The distance above(-) or below(+) the path to position
- * the text
- * @param paint The paint used for the text (e.g. color, size, style)
- */
- public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset,
- float vOffset, @NonNull Paint paint) {
- if (text.length() > 0) {
- native_drawTextOnPath(mNativeCanvasWrapper, text, path.readOnlyNI(), hOffset, vOffset,
- paint.mBidiFlags, paint.getNativeInstance(), paint.mNativeTypeface);
- }
- }
-
- /**
- * Save the canvas state, draw the picture, and restore the canvas state.
- * This differs from picture.draw(canvas), which does not perform any
- * save/restore.
- *
- *
- * Note: This forces the picture to internally call
- * {@link Picture#endRecording} in order to prepare for playback.
- *
- * @param picture The picture to be drawn
- */
- public void drawPicture(@NonNull Picture picture) {
- picture.endRecording();
- int restoreCount = save();
- picture.draw(this);
- restoreToCount(restoreCount);
- }
-
- /**
- * Draw the picture, stretched to fit into the dst rectangle.
- */
- public void drawPicture(@NonNull Picture picture, @NonNull RectF dst) {
- save();
- translate(dst.left, dst.top);
- if (picture.getWidth() > 0 && picture.getHeight() > 0) {
- scale(dst.width() / picture.getWidth(), dst.height() / picture.getHeight());
- }
- drawPicture(picture);
- restore();
- }
-
- /**
- * Draw the picture, stretched to fit into the dst rectangle.
- */
- public void drawPicture(@NonNull Picture picture, @NonNull Rect dst) {
- save();
- translate(dst.left, dst.top);
- if (picture.getWidth() > 0 && picture.getHeight() > 0) {
- scale((float) dst.width() / picture.getWidth(),
- (float) dst.height() / picture.getHeight());
- }
- drawPicture(picture);
- restore();
- }
-
- /**
- * Releases the resources associated with this canvas.
- *
- * @hide
- */
- public void release() {
- mNativeCanvasWrapper = 0;
- if (mFinalizer != null) {
- mFinalizer.run();
- mFinalizer = null;
- }
- }
-
- /**
- * Free up as much memory as possible from private caches (e.g. fonts, images)
- *
- * @hide
- */
- public static native void freeCaches();
-
- /**
- * Free up text layout caches
- *
- * @hide
- */
- public static native void freeTextLayoutCaches();
-
- private static native long initRaster(Bitmap bitmap);
- private static native long getNativeFinalizer();
-
- private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap, float left, float top,
- long nativePaintOrZero, int canvasDensity, int screenDensity, int bitmapDensity);
- private native void native_drawBitmap(long nativeCanvas, Bitmap bitmap,
- float srcLeft, float srcTop, float srcRight, float srcBottom,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- long nativePaintOrZero, int screenDensity, int bitmapDensity);
- private static native void native_drawBitmap(long nativeCanvas, int[] colors,
- int offset, int stride, float x, float y, int width, int height,
- boolean hasAlpha, long nativePaintOrZero);
-
- // ---------------- @FastNative -------------------
-
- @FastNative
- private static native void native_setBitmap(long canvasHandle,
- Bitmap bitmap);
- @FastNative
- private static native boolean native_isOpaque(long canvasHandle);
- @FastNative
- private static native void native_setHighContrastText(long renderer, boolean highContrastText);
- @FastNative
- private static native int native_getWidth(long canvasHandle);
- @FastNative
- private static native int native_getHeight(long canvasHandle);
-
- @FastNative
- private static native int native_save(long canvasHandle, int saveFlags);
- @FastNative
- private static native int native_saveLayer(long nativeCanvas, float l,
- float t, float r, float b,
- long nativePaint,
- int layerFlags);
- @FastNative
- private static native int native_saveLayerAlpha(long nativeCanvas, float l,
- float t, float r, float b,
- int alpha, int layerFlags);
- @FastNative
- private static native void native_restore(long canvasHandle, boolean tolerateUnderflow);
- @FastNative
- private static native void native_restoreToCount(long canvasHandle,
- int saveCount,
- boolean tolerateUnderflow);
- @FastNative
- private static native int native_getSaveCount(long canvasHandle);
-
- @FastNative
- private static native void native_translate(long canvasHandle,
- float dx, float dy);
- @FastNative
- private static native void native_scale(long canvasHandle,
- float sx, float sy);
- @FastNative
- private static native void native_rotate(long canvasHandle, float degrees);
- @FastNative
- private static native void native_skew(long canvasHandle,
- float sx, float sy);
- @FastNative
- private static native void native_concat(long nativeCanvas,
- long nativeMatrix);
- @FastNative
- private static native void native_setMatrix(long nativeCanvas,
- long nativeMatrix);
- @FastNative
- private static native boolean native_clipRect(long nativeCanvas,
- float left, float top,
- float right, float bottom,
- int regionOp);
- @FastNative
- private static native boolean native_clipPath(long nativeCanvas,
- long nativePath,
- int regionOp);
- @FastNative
- private static native boolean native_clipRegion(long nativeCanvas,
- long nativeRegion,
- int regionOp);
- @FastNative
- private static native void nativeSetDrawFilter(long nativeCanvas,
- long nativeFilter);
- @FastNative
- private static native boolean native_getClipBounds(long nativeCanvas,
- Rect bounds);
- @FastNative
- private static native void native_getCTM(long nativeCanvas,
- long nativeMatrix);
- @FastNative
- private static native boolean native_quickReject(long nativeCanvas,
- long nativePath);
- @FastNative
- private static native boolean native_quickReject(long nativeCanvas,
- float left, float top,
- float right, float bottom);
- @FastNative
- private static native void native_drawColor(long nativeCanvas, int color,
- int mode);
- @FastNative
- private static native void native_drawPaint(long nativeCanvas,
- long nativePaint);
- @FastNative
- private static native void native_drawPoint(long canvasHandle, float x, float y,
- long paintHandle);
- @FastNative
- private static native void native_drawPoints(long canvasHandle, float[] pts,
- int offset, int count,
- long paintHandle);
- @FastNative
- private static native void native_drawLine(long nativeCanvas, float startX,
- float startY, float stopX,
- float stopY, long nativePaint);
- @FastNative
- private static native void native_drawLines(long canvasHandle, float[] pts,
- int offset, int count,
- long paintHandle);
- @FastNative
- private static native void native_drawRect(long nativeCanvas, float left,
- float top, float right,
- float bottom,
- long nativePaint);
- @FastNative
- private static native void native_drawOval(long nativeCanvas, float left, float top,
- float right, float bottom, long nativePaint);
- @FastNative
- private static native void native_drawCircle(long nativeCanvas, float cx,
- float cy, float radius,
- long nativePaint);
- @FastNative
- private static native void native_drawArc(long nativeCanvas, float left, float top,
- float right, float bottom,
- float startAngle, float sweep, boolean useCenter,
- long nativePaint);
- @FastNative
- private static native void native_drawRoundRect(long nativeCanvas,
- float left, float top, float right, float bottom,
- float rx, float ry, long nativePaint);
- @FastNative
- private static native void native_drawPath(long nativeCanvas,
- long nativePath,
- long nativePaint);
- @FastNative
- private static native void native_drawRegion(long nativeCanvas,
- long nativeRegion, long nativePaint);
- @FastNative
- private static native void native_drawNinePatch(long nativeCanvas, long nativeBitmap,
- long ninePatch, float dstLeft, float dstTop, float dstRight, float dstBottom,
- long nativePaintOrZero, int screenDensity, int bitmapDensity);
- @FastNative
- private static native void nativeDrawBitmapMatrix(long nativeCanvas,
- Bitmap bitmap,
- long nativeMatrix,
- long nativePaint);
- @FastNative
- private static native void nativeDrawBitmapMesh(long nativeCanvas,
- Bitmap bitmap,
- int meshWidth, int meshHeight,
- float[] verts, int vertOffset,
- int[] colors, int colorOffset,
- long nativePaint);
- @FastNative
- private static native void nativeDrawVertices(long nativeCanvas, int mode, int n,
- float[] verts, int vertOffset, float[] texs, int texOffset,
- int[] colors, int colorOffset, short[] indices,
- int indexOffset, int indexCount, long nativePaint);
-
- @FastNative
- private static native void native_drawText(long nativeCanvas, char[] text,
- int index, int count, float x,
- float y, int flags, long nativePaint,
- long nativeTypeface);
- @FastNative
- private static native void native_drawText(long nativeCanvas, String text,
- int start, int end, float x,
- float y, int flags, long nativePaint,
- long nativeTypeface);
-
- @FastNative
- private static native void native_drawTextRun(long nativeCanvas, String text,
- int start, int end, int contextStart, int contextEnd,
- float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
-
- @FastNative
- private static native void native_drawTextRun(long nativeCanvas, char[] text,
- int start, int count, int contextStart, int contextCount,
- float x, float y, boolean isRtl, long nativePaint, long nativeTypeface);
-
- @FastNative
- private static native void native_drawTextOnPath(long nativeCanvas,
- char[] text, int index,
- int count, long nativePath,
- float hOffset,
- float vOffset, int bidiFlags,
- long nativePaint, long nativeTypeface);
- @FastNative
- private static native void native_drawTextOnPath(long nativeCanvas,
- String text, long nativePath,
- float hOffset,
- float vOffset,
- int flags, long nativePaint, long nativeTypeface);
}
diff --git a/graphics/java/android/graphics/Matrix.java b/graphics/java/android/graphics/Matrix.java
index 35cedae1e49a1..486070c99e3fd 100644
--- a/graphics/java/android/graphics/Matrix.java
+++ b/graphics/java/android/graphics/Matrix.java
@@ -838,7 +838,8 @@ public class Matrix {
}
- /* package */ final long ni() {
+ /** @hide */
+ public final long ni() {
return native_instance;
}
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index 2294b862192da..4ed2581f2b329 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -775,7 +775,8 @@ public class Path {
}
}
- final long readOnlyNI() {
+ /** @hide */
+ public final long readOnlyNI() {
return mNativePath;
}