Revert "Separate Canvas JNI code from the implementation."
This reverts commit e28a5afee885cd69a5be5809f88116b601cb1a72.
Appears to cause memory corruption and random appearances of
chinese
Bug: 16343240
Bug: 16336642
Change-Id: Ife169181f40adff4b12948ed5f9d3a88dcec935b
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f65aab5..0e22174 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -90,12 +90,12 @@
android_util_Process.cpp \
android_util_StringBlock.cpp \
android_util_XmlBlock.cpp \
- android_graphics_Canvas.cpp \
android_graphics_Picture.cpp \
android/graphics/AutoDecodeCancel.cpp \
android/graphics/Bitmap.cpp \
android/graphics/BitmapFactory.cpp \
android/graphics/Camera.cpp \
+ android/graphics/Canvas.cpp \
android/graphics/CanvasProperty.cpp \
android/graphics/ColorFilter.cpp \
android/graphics/DrawFilter.cpp \
@@ -122,7 +122,6 @@
android/graphics/Rasterizer.cpp \
android/graphics/Region.cpp \
android/graphics/Shader.cpp \
- android/graphics/SkiaCanvas.cpp \
android/graphics/SurfaceTexture.cpp \
android/graphics/Typeface.cpp \
android/graphics/TypefaceImpl.cpp \
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 9f832b0..d17f46c 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -3,7 +3,6 @@
#include "SkCamera.h"
-#include "Canvas.h"
#include "GraphicsJNI.h"
static jfieldID gNativeInstanceFieldID;
@@ -96,10 +95,10 @@
}
static void Camera_applyToCanvas(JNIEnv* env, jobject obj, jlong canvasHandle) {
- SkCanvas* canvas = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
+ SkCanvas* native_canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
jlong viewHandle = env->GetLongField(obj, gNativeInstanceFieldID);
Sk3DView* v = reinterpret_cast<Sk3DView*>(viewHandle);
- v->applyToCanvas(canvas);
+ v->applyToCanvas((SkCanvas*)native_canvas);
}
static jfloat Camera_dotWithNormal(JNIEnv* env, jobject obj,
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
new file mode 100644
index 0000000..6254f3d
--- /dev/null
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -0,0 +1,1330 @@
+/*
+ * Copyright (C) 2006-2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <android_runtime/AndroidRuntime.h>
+
+#include "SkCanvas.h"
+#include "SkClipStack.h"
+#include "SkDevice.h"
+#include "SkDeque.h"
+#include "SkDrawFilter.h"
+#include "SkGraphics.h"
+#include <SkImageInfo.h>
+#include "SkPorterDuff.h"
+#include "SkShader.h"
+#include "SkTArray.h"
+#include "SkTemplates.h"
+
+#include <minikin/Layout.h>
+#include "MinikinSkia.h"
+#include "MinikinUtils.h"
+
+#include "TypefaceImpl.h"
+
+#include "unicode/ubidi.h"
+#include "unicode/ushape.h"
+
+#include <utils/Log.h>
+
+namespace android {
+
+class ClipCopier : public SkCanvas::ClipVisitor {
+public:
+ ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
+
+ virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
+ m_dstCanvas->clipRect(rect, op, antialias);
+ }
+ virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
+ m_dstCanvas->clipRRect(rrect, op, antialias);
+ }
+ virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
+ m_dstCanvas->clipPath(path, op, antialias);
+ }
+
+private:
+ SkCanvas* m_dstCanvas;
+};
+
+// Holds an SkCanvas reference plus additional native data.
+class NativeCanvasWrapper {
+private:
+ struct SaveRec {
+ int saveCount;
+ SkCanvas::SaveFlags saveFlags;
+ };
+
+public:
+ NativeCanvasWrapper(SkCanvas* canvas)
+ : mCanvas(canvas)
+ , mSaveStack(NULL) {
+ SkASSERT(canvas);
+ }
+
+ ~NativeCanvasWrapper() {
+ delete mSaveStack;
+ }
+
+ SkCanvas* getCanvas() const {
+ return mCanvas.get();
+ }
+
+ void setCanvas(SkCanvas* canvas) {
+ SkASSERT(canvas);
+ mCanvas.reset(canvas);
+
+ delete mSaveStack;
+ mSaveStack = NULL;
+ }
+
+ int save(SkCanvas::SaveFlags flags) {
+ int count = mCanvas->save();
+ recordPartialSave(flags);
+ return count;
+ }
+
+ int saveLayer(const SkRect* bounds, const SkPaint* paint,
+ SkCanvas::SaveFlags flags) {
+ int count = mCanvas->saveLayer(bounds, paint,
+ static_cast<SkCanvas::SaveFlags>(flags | SkCanvas::kMatrixClip_SaveFlag));
+ recordPartialSave(flags);
+ return count;
+ }
+
+ int saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
+ SkCanvas::SaveFlags flags) {
+ int count = mCanvas->saveLayerAlpha(bounds, alpha,
+ static_cast<SkCanvas::SaveFlags>(flags | SkCanvas::kMatrixClip_SaveFlag));
+ recordPartialSave(flags);
+ return count;
+ }
+
+ void restore() {
+ const SaveRec* rec = (NULL == mSaveStack)
+ ? NULL
+ : static_cast<SaveRec*>(mSaveStack->back());
+ int currentSaveCount = mCanvas->getSaveCount() - 1;
+ SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
+
+ if (NULL == rec || rec->saveCount != currentSaveCount) {
+ // Fast path - no record for this frame.
+ mCanvas->restore();
+ return;
+ }
+
+ bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag);
+ bool preserveClip = !(rec->saveFlags & SkCanvas::kClip_SaveFlag);
+
+ SkMatrix savedMatrix;
+ if (preserveMatrix) {
+ savedMatrix = mCanvas->getTotalMatrix();
+ }
+
+ SkTArray<SkClipStack::Element> savedClips;
+ if (preserveClip) {
+ saveClipsForFrame(savedClips, currentSaveCount);
+ }
+
+ mCanvas->restore();
+
+ if (preserveMatrix) {
+ mCanvas->setMatrix(savedMatrix);
+ }
+
+ if (preserveClip && !savedClips.empty()) {
+ applyClips(savedClips);
+ }
+
+ mSaveStack->pop_back();
+ }
+
+private:
+ void recordPartialSave(SkCanvas::SaveFlags flags) {
+ // A partial save is a save operation which doesn't capture the full canvas state.
+ // (either kMatrix_SaveFlags or kClip_SaveFlag is missing).
+
+ // Mask-out non canvas state bits.
+ flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag);
+
+ if (SkCanvas::kMatrixClip_SaveFlag == flags) {
+ // not a partial save.
+ return;
+ }
+
+ if (NULL == mSaveStack) {
+ mSaveStack = new SkDeque(sizeof(struct SaveRec), 8);
+ }
+
+ SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
+ // Store the save counter in the SkClipStack domain.
+ // (0-based, equal to the number of save ops on the stack).
+ rec->saveCount = mCanvas->getSaveCount() - 1;
+ rec->saveFlags = flags;
+ }
+
+ void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips,
+ int frameSaveCount) {
+ SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
+ SkClipStack::Iter::kTop_IterStart);
+ while (const SkClipStack::Element* elem = clipIterator.next()) {
+ if (elem->getSaveCount() < frameSaveCount) {
+ // done with the current frame.
+ break;
+ }
+ SkASSERT(elem->getSaveCount() == frameSaveCount);
+ clips.push_back(*elem);
+ }
+ }
+
+ void applyClips(const SkTArray<SkClipStack::Element>& clips) {
+ ClipCopier clipCopier(mCanvas);
+
+ // The clip stack stores clips in device space.
+ SkMatrix origMatrix = mCanvas->getTotalMatrix();
+ mCanvas->resetMatrix();
+
+ // We pushed the clips in reverse order.
+ for (int i = clips.count() - 1; i >= 0; --i) {
+ clips[i].replay(&clipCopier);
+ }
+
+ mCanvas->setMatrix(origMatrix);
+ }
+
+ SkAutoTUnref<SkCanvas> mCanvas;
+ SkDeque* mSaveStack; // lazily allocated, tracks partial saves.
+};
+
+// Returns true if the SkCanvas's clip is non-empty.
+static jboolean hasNonEmptyClip(const SkCanvas& canvas) {
+ bool emptyClip = canvas.isClipEmpty();
+ return emptyClip ? JNI_FALSE : JNI_TRUE;
+}
+
+class SkCanvasGlue {
+public:
+ // Get the native wrapper for a given handle.
+ static inline NativeCanvasWrapper* getNativeWrapper(jlong nativeHandle) {
+ SkASSERT(nativeHandle);
+ return reinterpret_cast<NativeCanvasWrapper*>(nativeHandle);
+ }
+
+ // Get the SkCanvas for a given native handle.
+ static inline SkCanvas* getNativeCanvas(jlong nativeHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(nativeHandle);
+ SkCanvas* canvas = wrapper->getCanvas();
+ SkASSERT(canvas);
+
+ return canvas;
+ }
+
+ // Construct an SkCanvas from the bitmap.
+ static SkCanvas* createCanvas(SkBitmap* bitmap) {
+ if (bitmap) {
+ return SkNEW_ARGS(SkCanvas, (*bitmap));
+ }
+
+ // Create an empty bitmap device to prevent callers from crashing
+ // if they attempt to draw into this canvas.
+ SkBitmap emptyBitmap;
+ return new SkCanvas(emptyBitmap);
+ }
+
+ // Copy the canvas matrix & clip state.
+ static void copyCanvasState(SkCanvas* srcCanvas, SkCanvas* dstCanvas) {
+ if (srcCanvas && dstCanvas) {
+ dstCanvas->setMatrix(srcCanvas->getTotalMatrix());
+ if (NULL != srcCanvas->getDevice() && NULL != dstCanvas->getDevice()) {
+ ClipCopier copier(dstCanvas);
+ srcCanvas->replayClips(&copier);
+ }
+ }
+ }
+
+ // Native JNI handlers
+ static void finalizer(JNIEnv* env, jobject clazz, jlong nativeHandle) {
+ NativeCanvasWrapper* wrapper = reinterpret_cast<NativeCanvasWrapper*>(nativeHandle);
+ delete wrapper;
+ }
+
+ // Native wrapper constructor used by Canvas(Bitmap)
+ static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
+ // No check - 0 is a valid bitmapHandle.
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkCanvas* canvas = createCanvas(bitmap);
+
+ return reinterpret_cast<jlong>(new NativeCanvasWrapper(canvas));
+ }
+
+ // Native wrapper constructor used by Canvas(native_canvas)
+ static jlong initCanvas(JNIEnv* env, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
+ return reinterpret_cast<jlong>(new NativeCanvasWrapper(canvas));
+ }
+
+ // Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
+ // optionally copying canvas matrix & clip state.
+ static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
+ jboolean copyState) {
+ NativeCanvasWrapper* wrapper = reinterpret_cast<NativeCanvasWrapper*>(canvasHandle);
+ SkCanvas* newCanvas = createCanvas(reinterpret_cast<SkBitmap*>(bitmapHandle));
+ NPE_CHECK_RETURN_VOID(env, newCanvas);
+
+ if (copyState == JNI_TRUE) {
+ copyCanvasState(wrapper->getCanvas(), newCanvas);
+ }
+
+ // setCanvas() unrefs the old canvas.
+ wrapper->setCanvas(newCanvas);
+ }
+
+ static void freeCaches(JNIEnv* env, jobject) {
+ SkGraphics::PurgeFontCache();
+ }
+
+ static void freeTextLayoutCaches(JNIEnv* env, jobject) {
+ Layout::purgeCaches();
+ }
+
+ static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ bool result = canvas->getDevice()->accessBitmap(false).isOpaque();
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ int width = canvas->getDevice()->accessBitmap(false).width();
+ return static_cast<jint>(width);
+ }
+
+ static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ int height = canvas->getDevice()->accessBitmap(false).height();
+ return static_cast<jint>(height);
+ }
+
+ static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
+ return static_cast<jint>(wrapper->save(flags));
+ }
+
+ static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat l, jfloat t, jfloat r, jfloat b,
+ jlong paintHandle, jint flagsHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
+ SkRect bounds;
+ bounds.set(l, t, r, b);
+ return static_cast<jint>(wrapper->saveLayer(&bounds, paint, flags));
+ }
+
+ static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat l, jfloat t, jfloat r, jfloat b,
+ jint alpha, jint flagsHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
+ SkRect bounds;
+ bounds.set(l, t, r, b);
+ return static_cast<jint>(wrapper->saveLayerAlpha(&bounds, alpha, flags));
+ }
+
+ static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
+ if (wrapper->getCanvas()->getSaveCount() <= 1) { // cannot restore anymore
+ doThrowISE(env, "Underflow in restore");
+ return;
+ }
+ wrapper->restore();
+ }
+
+ static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
+ return static_cast<jint>(getNativeCanvas(canvasHandle)->getSaveCount());
+ }
+
+ static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle,
+ jint restoreCount) {
+ NativeCanvasWrapper* wrapper = getNativeWrapper(canvasHandle);
+ if (restoreCount < 1) {
+ doThrowIAE(env, "Underflow in restoreToCount");
+ return;
+ }
+
+ while (wrapper->getCanvas()->getSaveCount() > restoreCount) {
+ wrapper->restore();
+ }
+ }
+
+ static void translate(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat dx, jfloat dy) {
+ getNativeCanvas(canvasHandle)->translate(dx, dy);
+ }
+
+ static void scale__FF(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat sx, jfloat sy) {
+ getNativeCanvas(canvasHandle)->scale(sx, sy);
+ }
+
+ static void rotate__F(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat degrees) {
+ getNativeCanvas(canvasHandle)->rotate(degrees);
+ }
+
+ static void skew__FF(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat sx, jfloat sy) {
+ getNativeCanvas(canvasHandle)->skew(sx, sy);
+ }
+
+ static void concat(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong matrixHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ canvas->concat(*matrix);
+ }
+
+ static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong matrixHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ if (NULL == matrix) {
+ canvas->resetMatrix();
+ } else {
+ canvas->setMatrix(*matrix);
+ }
+ }
+
+ static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat left, jfloat top, jfloat right,
+ jfloat bottom, jint op) {
+ SkRect r;
+ r.set(left, top, right, bottom);
+ SkCanvas* c = getNativeCanvas(canvasHandle);
+ c->clipRect(r, static_cast<SkRegion::Op>(op));
+ return hasNonEmptyClip(*c);
+ }
+
+ static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong pathHandle, jint op) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
+ static_cast<SkRegion::Op>(op));
+ return hasNonEmptyClip(*canvas);
+ }
+
+ static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong deviceRgnHandle, jint op) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
+ SkPath rgnPath;
+ if (deviceRgn->getBoundaryPath(&rgnPath)) {
+ // The region is specified in device space.
+ SkMatrix savedMatrix = canvas->getTotalMatrix();
+ canvas->resetMatrix();
+ canvas->clipPath(rgnPath, static_cast<SkRegion::Op>(op));
+ canvas->setMatrix(savedMatrix);
+ } else {
+ canvas->clipRect(SkRect::MakeEmpty(), static_cast<SkRegion::Op>(op));
+ }
+ return hasNonEmptyClip(*canvas);
+ }
+
+ static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong filterHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
+ }
+
+ static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong pathHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ bool result = canvas->quickReject(*reinterpret_cast<SkPath*>(pathHandle));
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static jboolean quickReject__FFFF(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat left, jfloat top, jfloat right,
+ jfloat bottom) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkRect r;
+ r.set(left, top, right, bottom);
+ bool result = canvas->quickReject(r);
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static void drawRGB(JNIEnv* env, jobject, jlong canvasHandle,
+ jint r, jint g, jint b) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ canvas->drawARGB(0xFF, r, g, b);
+ }
+
+ static void drawARGB(JNIEnv* env, jobject, jlong canvasHandle,
+ jint a, jint r, jint g, jint b) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ canvas->drawARGB(a, r, g, b);
+ }
+
+ static void drawColor__I(JNIEnv* env, jobject, jlong canvasHandle,
+ jint color) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ canvas->drawColor(color);
+ }
+
+ static void drawColor__II(JNIEnv* env, jobject, jlong canvasHandle,
+ jint color, jint modeHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
+ canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
+ }
+
+ static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawPaint(*paint);
+ }
+
+ static void doPoints(JNIEnv* env, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset, jint count,
+ jlong paintHandle, jint modeHandle) {
+ NPE_CHECK_RETURN_VOID(env, jptsArray);
+ SkCanvas::PointMode mode = static_cast<SkCanvas::PointMode>(modeHandle);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+
+ AutoJavaFloatArray autoPts(env, jptsArray);
+ float* floats = autoPts.ptr();
+ const int length = autoPts.length();
+
+ if ((offset | count) < 0 || offset + count > length) {
+ doThrowAIOOBE(env);
+ return;
+ }
+
+ // now convert the floats into SkPoints
+ count >>= 1; // now it is the number of points
+ SkAutoSTMalloc<32, SkPoint> storage(count);
+ SkPoint* pts = storage.get();
+ const float* src = floats + offset;
+ for (int i = 0; i < count; i++) {
+ pts[i].set(src[0], src[1]);
+ src += 2;
+ }
+ canvas->drawPoints(mode, count, pts, *paint);
+ }
+
+ static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset,
+ jint count, jlong paintHandle) {
+ doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
+ SkCanvas::kPoints_PointMode);
+ }
+
+ static void drawLines(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset, jint count,
+ jlong paintHandle) {
+ doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
+ SkCanvas::kLines_PointMode);
+ }
+
+ static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawPoint(x, y, *paint);
+ }
+
+ static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat startX, jfloat startY, jfloat stopX,
+ jfloat stopY, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawLine(startX, startY, stopX, stopY, *paint);
+ }
+
+ static void drawRect__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat left, jfloat top, jfloat right,
+ jfloat bottom, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawRectCoords(left, top, right, bottom, *paint);
+ }
+
+ static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
+ canvas->drawOval(oval, *paint);
+ }
+
+ static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx,
+ jfloat cy, jfloat radius, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawCircle(cx, cy, radius, *paint);
+ }
+
+ static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
+ jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, jboolean useCenter,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
+ canvas->drawArc(oval, startAngle, sweepAngle, useCenter, *paint);
+ }
+
+ static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat rx, jfloat ry,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
+ canvas->drawRoundRect(rect, rx, ry, *paint);
+ }
+
+ static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawPath(*path, *paint);
+ }
+
+ static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
+ jlong canvasHandle, jlong bitmapHandle,
+ jfloat left, jfloat top,
+ jlong paintHandle, jint canvasDensity,
+ jint screenDensity, jint bitmapDensity) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+
+ if (canvasDensity == bitmapDensity || canvasDensity == 0
+ || bitmapDensity == 0) {
+ if (screenDensity != 0 && screenDensity != bitmapDensity) {
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+ canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
+ } else {
+ canvas->drawBitmap(*bitmap, left, top, paint);
+ }
+ } else {
+ canvas->save();
+ SkScalar scale = canvasDensity / (float)bitmapDensity;
+ canvas->translate(left, top);
+ canvas->scale(scale, scale);
+
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+
+ canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
+
+ canvas->restore();
+ }
+ }
+
+ static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
+ jobject srcIRect, const SkRect& dst, SkPaint* paint,
+ jint screenDensity, jint bitmapDensity) {
+ SkIRect src, *srcPtr = NULL;
+
+ if (NULL != srcIRect) {
+ GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
+ srcPtr = &src;
+ }
+
+ if (screenDensity != 0 && screenDensity != bitmapDensity) {
+ SkPaint filteredPaint;
+ if (paint) {
+ filteredPaint = *paint;
+ }
+ filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
+ canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
+ } else {
+ canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
+ }
+ }
+
+ static void drawBitmapRF(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong bitmapHandle, jobject srcIRect,
+ jobject dstRectF, jlong paintHandle,
+ jint screenDensity, jint bitmapDensity) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkRect dst;
+ GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
+ doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
+ screenDensity, bitmapDensity);
+ }
+
+ static void drawBitmapRR(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong bitmapHandle, jobject srcIRect,
+ jobject dstRect, jlong paintHandle,
+ jint screenDensity, jint bitmapDensity) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ SkRect dst;
+ GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
+ doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
+ screenDensity, bitmapDensity);
+ }
+
+ static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
+ jintArray jcolors, jint offset, jint stride,
+ jfloat x, jfloat y, jint width, jint height,
+ jboolean hasAlpha, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
+ // correct the alphaType to kOpaque_SkAlphaType.
+ SkImageInfo info = SkImageInfo::Make(width, height,
+ hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
+ kPremul_SkAlphaType);
+ SkBitmap bitmap;
+ if (!bitmap.allocPixels(info)) {
+ return;
+ }
+
+ if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
+ 0, 0, width, height, bitmap)) {
+ return;
+ }
+
+ canvas->drawBitmap(bitmap, x, y, paint);
+ }
+
+ static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong bitmapHandle, jlong matrixHandle,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
+ }
+
+ static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong bitmapHandle, jint meshWidth, jint meshHeight,
+ jfloatArray jverts, jint vertIndex, jintArray jcolors,
+ jint colorIndex, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+
+ const int ptCount = (meshWidth + 1) * (meshHeight + 1);
+ const int indexCount = meshWidth * meshHeight * 6;
+
+ AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
+ AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
+
+ /* Our temp storage holds 2 or 3 arrays.
+ texture points [ptCount * sizeof(SkPoint)]
+ optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
+ copy to convert from float to fixed
+ indices [ptCount * sizeof(uint16_t)]
+ */
+ ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
+ storageSize += indexCount * sizeof(uint16_t); // indices[]
+
+ SkAutoMalloc storage(storageSize);
+ SkPoint* texs = (SkPoint*)storage.get();
+ SkPoint* verts;
+ uint16_t* indices;
+#ifdef SK_SCALAR_IS_FLOAT
+ verts = (SkPoint*)(vertA.ptr() + vertIndex);
+ indices = (uint16_t*)(texs + ptCount);
+#else
+ SkASSERT(false);
+#endif
+
+ // cons up texture coordinates and indices
+ {
+ const SkScalar w = SkIntToScalar(bitmap->width());
+ const SkScalar h = SkIntToScalar(bitmap->height());
+ const SkScalar dx = w / meshWidth;
+ const SkScalar dy = h / meshHeight;
+
+ SkPoint* texsPtr = texs;
+ SkScalar y = 0;
+ for (int i = 0; i <= meshHeight; i++) {
+ if (i == meshHeight) {
+ y = h; // to ensure numerically we hit h exactly
+ }
+ SkScalar x = 0;
+ for (int j = 0; j < meshWidth; j++) {
+ texsPtr->set(x, y);
+ texsPtr += 1;
+ x += dx;
+ }
+ texsPtr->set(w, y);
+ texsPtr += 1;
+ y += dy;
+ }
+ SkASSERT(texsPtr - texs == ptCount);
+ }
+
+ // cons up indices
+ {
+ uint16_t* indexPtr = indices;
+ int index = 0;
+ for (int i = 0; i < meshHeight; i++) {
+ for (int j = 0; j < meshWidth; j++) {
+ // lower-left triangle
+ *indexPtr++ = index;
+ *indexPtr++ = index + meshWidth + 1;
+ *indexPtr++ = index + meshWidth + 2;
+ // upper-right triangle
+ *indexPtr++ = index;
+ *indexPtr++ = index + meshWidth + 2;
+ *indexPtr++ = index + 1;
+ // bump to the next cell
+ index += 1;
+ }
+ // bump to the next row
+ index += 1;
+ }
+ SkASSERT(indexPtr - indices == indexCount);
+ SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
+ }
+
+ // double-check that we have legal indices
+#ifdef SK_DEBUG
+ {
+ for (int i = 0; i < indexCount; i++) {
+ SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
+ }
+ }
+#endif
+
+ // cons-up a shader for the bitmap
+ SkPaint tmpPaint;
+ if (paint) {
+ tmpPaint = *paint;
+ }
+ SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
+ SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
+ SkSafeUnref(tmpPaint.setShader(shader));
+
+ canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
+ texs, (const SkColor*)colorA.ptr(), NULL, indices,
+ indexCount, tmpPaint);
+ }
+
+ static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
+ jint modeHandle, jint vertexCount,
+ jfloatArray jverts, jint vertIndex,
+ jfloatArray jtexs, jint texIndex,
+ jintArray jcolors, jint colorIndex,
+ jshortArray jindices, jint indexIndex,
+ jint indexCount, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+
+ AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
+ AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
+ AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
+ AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
+
+ const int ptCount = vertexCount >> 1;
+
+ SkPoint* verts;
+ SkPoint* texs = NULL;
+#ifdef SK_SCALAR_IS_FLOAT
+ verts = (SkPoint*)(vertA.ptr() + vertIndex);
+ if (jtexs != NULL) {
+ texs = (SkPoint*)(texA.ptr() + texIndex);
+ }
+#else
+ SkASSERT(false);
+#endif
+
+ const SkColor* colors = NULL;
+ const uint16_t* indices = NULL;
+ if (jcolors != NULL) {
+ colors = (const SkColor*)(colorA.ptr() + colorIndex);
+ }
+ if (jindices != NULL) {
+ indices = (const uint16_t*)(indexA.ptr() + indexIndex);
+ }
+
+ canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
+ indices, indexCount, *paint);
+ }
+
+
+ static void drawText___CIIFFIPaintTypeface(JNIEnv* env, jobject, jlong canvasHandle,
+ jcharArray text, jint index, jint count,
+ jfloat x, jfloat y, jint bidiFlags,
+ jlong paintHandle, jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ jchar* textArray = env->GetCharArrayElements(text, NULL);
+ drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, bidiFlags, paint, typeface);
+ env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
+ }
+
+ static void drawText__StringIIFFIPaintTypeface(JNIEnv* env, jobject,
+ jlong canvasHandle, jstring text,
+ jint start, jint end,
+ jfloat x, jfloat y, jint bidiFlags,
+ jlong paintHandle, jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ const jchar* textArray = env->GetStringChars(text, NULL);
+ drawTextWithGlyphs(canvas, textArray, start, end, x, y, bidiFlags, paint, typeface);
+ env->ReleaseStringChars(text, textArray);
+ }
+
+ class DrawTextFunctor {
+ public:
+ DrawTextFunctor(const Layout& layout, SkCanvas* canvas, jfloat x, jfloat y, SkPaint* paint,
+ uint16_t* glyphs, SkPoint* pos)
+ : layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
+ pos(pos) { }
+
+ void operator()(size_t start, size_t end) {
+ for (size_t i = start; i < end; i++) {
+ glyphs[i] = layout.getGlyphId(i);
+ pos[i].fX = x + layout.getX(i);
+ pos[i].fY = y + layout.getY(i);
+ }
+ canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
+ }
+ private:
+ const Layout& layout;
+ SkCanvas* canvas;
+ jfloat x;
+ jfloat y;
+ SkPaint* paint;
+ uint16_t* glyphs;
+ SkPoint* pos;
+ };
+
+ static void drawGlyphsToSkia(SkCanvas* canvas, SkPaint* paint, const Layout& layout, float x, float y) {
+ size_t nGlyphs = layout.nGlyphs();
+ uint16_t* glyphs = new uint16_t[nGlyphs];
+ SkPoint* pos = new SkPoint[nGlyphs];
+
+ x += MinikinUtils::xOffsetForTextAlign(paint, layout);
+ SkPaint::Align align = paint->getTextAlign();
+ paint->setTextAlign(SkPaint::kLeft_Align);
+ paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ DrawTextFunctor f(layout, canvas, x, y, paint, glyphs, pos);
+ MinikinUtils::forFontRun(layout, paint, f);
+ doDrawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
+ paint->setTextAlign(align);
+ delete[] glyphs;
+ delete[] pos;
+ }
+
+ static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
+ int start, int end,
+ jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
+
+ jint count = end - start;
+ drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, bidiFlags, paint,
+ typeface);
+ }
+
+ static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
+ int start, int count, int contextCount,
+ jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) {
+
+ Layout layout;
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+ layout.doLayout(textArray, start, count, contextCount, css);
+ drawGlyphsToSkia(canvas, paint, layout, x, y);
+ }
+
+// Same values used by Skia
+#define kStdStrikeThru_Offset (-6.0f / 21.0f)
+#define kStdUnderline_Offset (1.0f / 9.0f)
+#define kStdUnderline_Thickness (1.0f / 18.0f)
+
+ static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length,
+ SkPaint* paint) {
+ uint32_t flags;
+ SkDrawFilter* drawFilter = canvas->getDrawFilter();
+ if (drawFilter) {
+ SkPaint paintCopy(*paint);
+ drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
+ flags = paintCopy.getFlags();
+ } else {
+ flags = paint->getFlags();
+ }
+ if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+ SkScalar left = x;
+ SkScalar right = x + length;
+ float textSize = paint->getTextSize();
+ float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
+ if (flags & SkPaint::kUnderlineText_Flag) {
+ SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
+ canvas->drawRectCoords(left, top, right, bottom, *paint);
+ }
+ if (flags & SkPaint::kStrikeThruText_Flag) {
+ SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
+ canvas->drawRectCoords(left, top, right, bottom, *paint);
+ }
+ }
+ }
+
+ static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
+ int index, int count, jfloat x, jfloat y, SkPaint* paint) {
+ SkPoint* posPtr = new SkPoint[count];
+ for (int indx = 0; indx < count; indx++) {
+ posPtr[indx].fX = x + posArray[indx * 2];
+ posPtr[indx].fY = y + posArray[indx * 2 + 1];
+ }
+ canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
+ delete[] posPtr;
+ }
+
+ static void drawTextRun___CIIIIFFZPaintTypeface(
+ JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
+ jint count, jint contextIndex, jint contextCount,
+ jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
+ jchar* chars = env->GetCharArrayElements(text, NULL);
+ drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
+ count, contextCount, x, y, bidiFlags, paint, typeface);
+ env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
+ }
+
+ static void drawTextRun__StringIIIIFFZPaintTypeface(
+ JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
+ jint end, jint contextStart, jint contextEnd,
+ jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
+ jint count = end - start;
+ jint contextCount = contextEnd - contextStart;
+ const jchar* chars = env->GetStringChars(text, NULL);
+ drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
+ count, contextCount, x, y, bidiFlags, paint, typeface);
+ env->ReleaseStringChars(text, chars);
+ }
+
+ static void drawPosText___CII_FPaint(JNIEnv* env, jobject, jlong canvasHandle,
+ jcharArray text, jint index, jint count,
+ jfloatArray pos, jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
+ jsize textCount = text ? env->GetArrayLength(text) : NULL;
+ float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
+ int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
+ SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
+ int indx;
+ for (indx = 0; indx < posCount; indx++) {
+ posPtr[indx].fX = posArray[indx << 1];
+ posPtr[indx].fY = posArray[(indx << 1) + 1];
+ }
+
+ SkPaint::TextEncoding encoding = paint->getTextEncoding();
+ paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
+ paint->setTextEncoding(encoding);
+
+ if (text) {
+ env->ReleaseCharArrayElements(text, textArray, 0);
+ }
+ if (pos) {
+ env->ReleaseFloatArrayElements(pos, posArray, 0);
+ }
+ delete[] posPtr;
+ }
+
+ static void drawPosText__String_FPaint(JNIEnv* env, jobject,
+ jlong canvasHandle, jstring text,
+ jfloatArray pos,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
+ int byteLength = text ? env->GetStringLength(text) : 0;
+ float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
+ int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
+ SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
+
+ for (int indx = 0; indx < posCount; indx++) {
+ posPtr[indx].fX = posArray[indx << 1];
+ posPtr[indx].fY = posArray[(indx << 1) + 1];
+ }
+
+ SkPaint::TextEncoding encoding = paint->getTextEncoding();
+ paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
+ canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
+ paint->setTextEncoding(encoding);
+
+ if (text) {
+ env->ReleaseStringChars(text, (const jchar*) text_);
+ }
+ if (pos) {
+ env->ReleaseFloatArrayElements(pos, posArray, 0);
+ }
+ delete[] posPtr;
+ }
+
+ class DrawTextOnPathFunctor {
+ public:
+ DrawTextOnPathFunctor(const Layout& layout, SkCanvas* canvas, float hOffset,
+ float vOffset, SkPaint* paint, SkPath* path)
+ : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
+ paint(paint), path(path) {
+ }
+ void operator()(size_t start, size_t end) {
+ uint16_t glyphs[1];
+ for (size_t i = start; i < end; i++) {
+ glyphs[0] = layout.getGlyphId(i);
+ float x = hOffset + layout.getX(i);
+ float y = vOffset + layout.getY(i);
+ canvas->drawTextOnPathHV(glyphs, sizeof(glyphs), *path, x, y, *paint);
+ }
+ }
+ private:
+ const Layout& layout;
+ SkCanvas* canvas;
+ float hOffset;
+ float vOffset;
+ SkPaint* paint;
+ SkPath* path;
+ };
+
+ static void doDrawTextOnPath(SkPaint* paint, const jchar* text, int count, int bidiFlags,
+ float hOffset, float vOffset, SkPath* path, SkCanvas* canvas, TypefaceImpl* typeface) {
+ Layout layout;
+ std::string css = MinikinUtils::setLayoutProperties(&layout, paint, bidiFlags, typeface);
+ layout.doLayout(text, 0, count, count, css);
+ hOffset += MinikinUtils::hOffsetForTextAlign(paint, layout, *path);
+ // Set align to left for drawing, as we don't want individual
+ // glyphs centered or right-aligned; the offset above takes
+ // care of all alignment.
+ SkPaint::Align align = paint->getTextAlign();
+ paint->setTextAlign(SkPaint::kLeft_Align);
+
+ DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paint, path);
+ MinikinUtils::forFontRun(layout, paint, f);
+ paint->setTextAlign(align);
+ }
+
+ static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
+ jlong canvasHandle, jcharArray text, jint index, jint count,
+ jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
+ jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ jchar* textArray = env->GetCharArrayElements(text, NULL);
+ doDrawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
+ path, canvas, typeface);
+ env->ReleaseCharArrayElements(text, textArray, 0);
+ }
+
+ static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
+ jlong canvasHandle, jstring text, jlong pathHandle,
+ jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle,
+ jlong typefaceHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
+ SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+
+ const jchar* text_ = env->GetStringChars(text, NULL);
+ int count = env->GetStringLength(text);
+ doDrawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
+ path, canvas, typeface);
+ env->ReleaseStringChars(text, text_);
+ }
+
+
+ // This function is a mirror of SkCanvas::getClipBounds except that it does
+ // not outset the edge of the clip to account for anti-aliasing. There is
+ // a skia bug to investigate pushing this logic into back into skia.
+ // (see https://code.google.com/p/skia/issues/detail?id=1303)
+ static bool getHardClipBounds(SkCanvas* canvas, SkRect* bounds) {
+ SkIRect ibounds;
+ if (!canvas->getClipDeviceBounds(&ibounds)) {
+ return false;
+ }
+
+ SkMatrix inverse;
+ // if we can't invert the CTM, we can't return local clip bounds
+ if (!canvas->getTotalMatrix().invert(&inverse)) {
+ if (bounds) {
+ bounds->setEmpty();
+ }
+ return false;
+ }
+
+ if (NULL != bounds) {
+ SkRect r = SkRect::Make(ibounds);
+ inverse.mapRect(bounds, r);
+ }
+ return true;
+ }
+
+ static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle,
+ jobject bounds) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkRect r;
+ SkIRect ir;
+ bool result = getHardClipBounds(canvas, &r);
+
+ if (!result) {
+ r.setEmpty();
+ }
+ r.round(&ir);
+
+ (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
+ return result ? JNI_TRUE : JNI_FALSE;
+ }
+
+ static void getCTM(JNIEnv* env, jobject, jlong canvasHandle,
+ jlong matrixHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
+ *matrix = canvas->getTotalMatrix();
+ }
+};
+
+static JNINativeMethod gCanvasMethods[] = {
+ {"finalizer", "(J)V", (void*) SkCanvasGlue::finalizer},
+ {"initRaster", "(J)J", (void*) SkCanvasGlue::initRaster},
+ {"initCanvas", "(J)J", (void*) SkCanvasGlue::initCanvas},
+ {"native_setBitmap", "(JJZ)V", (void*) SkCanvasGlue::setBitmap},
+ {"native_isOpaque","(J)Z", (void*) SkCanvasGlue::isOpaque},
+ {"native_getWidth","(J)I", (void*) SkCanvasGlue::getWidth},
+ {"native_getHeight","(J)I", (void*) SkCanvasGlue::getHeight},
+ {"native_save","(JI)I", (void*) SkCanvasGlue::save},
+ {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer},
+ {"native_saveLayerAlpha","(JFFFFII)I", (void*) SkCanvasGlue::saveLayerAlpha},
+ {"native_restore","(J)V", (void*) SkCanvasGlue::restore},
+ {"native_getSaveCount","(J)I", (void*) SkCanvasGlue::getSaveCount},
+ {"native_restoreToCount","(JI)V", (void*) SkCanvasGlue::restoreToCount},
+ {"native_translate","(JFF)V", (void*) SkCanvasGlue::translate},
+ {"native_scale","(JFF)V", (void*) SkCanvasGlue::scale__FF},
+ {"native_rotate","(JF)V", (void*) SkCanvasGlue::rotate__F},
+ {"native_skew","(JFF)V", (void*) SkCanvasGlue::skew__FF},
+ {"native_concat","(JJ)V", (void*) SkCanvasGlue::concat},
+ {"native_setMatrix","(JJ)V", (void*) SkCanvasGlue::setMatrix},
+ {"native_clipRect","(JFFFFI)Z", (void*) SkCanvasGlue::clipRect},
+ {"native_clipPath","(JJI)Z", (void*) SkCanvasGlue::clipPath},
+ {"native_clipRegion","(JJI)Z", (void*) SkCanvasGlue::clipRegion},
+ {"nativeSetDrawFilter", "(JJ)V", (void*) SkCanvasGlue::setDrawFilter},
+ {"native_getClipBounds","(JLandroid/graphics/Rect;)Z",
+ (void*) SkCanvasGlue::getClipBounds},
+ {"native_getCTM", "(JJ)V", (void*)SkCanvasGlue::getCTM},
+ {"native_quickReject","(JJ)Z", (void*) SkCanvasGlue::quickReject__Path},
+ {"native_quickReject","(JFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
+ {"native_drawRGB","(JIII)V", (void*) SkCanvasGlue::drawRGB},
+ {"native_drawARGB","(JIIII)V", (void*) SkCanvasGlue::drawARGB},
+ {"native_drawColor","(JI)V", (void*) SkCanvasGlue::drawColor__I},
+ {"native_drawColor","(JII)V", (void*) SkCanvasGlue::drawColor__II},
+ {"native_drawPaint","(JJ)V", (void*) SkCanvasGlue::drawPaint},
+ {"native_drawPoint", "(JFFJ)V", (void*) SkCanvasGlue::drawPoint},
+ {"native_drawPoints", "(J[FIIJ)V", (void*) SkCanvasGlue::drawPoints},
+ {"native_drawLines", "(J[FIIJ)V", (void*) SkCanvasGlue::drawLines},
+ {"native_drawLine","(JFFFFJ)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
+ {"native_drawRect","(JFFFFJ)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
+ {"native_drawOval","(JFFFFJ)V", (void*) SkCanvasGlue::drawOval},
+ {"native_drawCircle","(JFFFJ)V", (void*) SkCanvasGlue::drawCircle},
+ {"native_drawArc","(JFFFFFFZJ)V", (void*) SkCanvasGlue::drawArc},
+ {"native_drawRoundRect","(JFFFFFFJ)V",
+ (void*) SkCanvasGlue::drawRoundRect},
+ {"native_drawPath","(JJJ)V", (void*) SkCanvasGlue::drawPath},
+ {"native_drawBitmap","(JJFFJIII)V",
+ (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
+ {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/RectF;JII)V",
+ (void*) SkCanvasGlue::drawBitmapRF},
+ {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/Rect;JII)V",
+ (void*) SkCanvasGlue::drawBitmapRR},
+ {"native_drawBitmap", "(J[IIIFFIIZJ)V",
+ (void*)SkCanvasGlue::drawBitmapArray},
+ {"nativeDrawBitmapMatrix", "(JJJJ)V",
+ (void*)SkCanvasGlue::drawBitmapMatrix},
+ {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V",
+ (void*)SkCanvasGlue::drawBitmapMesh},
+ {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V",
+ (void*)SkCanvasGlue::drawVertices},
+ {"native_drawText","(J[CIIFFIJJ)V",
+ (void*) SkCanvasGlue::drawText___CIIFFIPaintTypeface},
+ {"native_drawText","(JLjava/lang/String;IIFFIJJ)V",
+ (void*) SkCanvasGlue::drawText__StringIIFFIPaintTypeface},
+ {"native_drawTextRun","(J[CIIIIFFZJJ)V",
+ (void*) SkCanvasGlue::drawTextRun___CIIIIFFZPaintTypeface},
+ {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V",
+ (void*) SkCanvasGlue::drawTextRun__StringIIIIFFZPaintTypeface},
+ {"native_drawTextOnPath","(J[CIIJFFIJJ)V",
+ (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
+ {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V",
+ (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
+
+ {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
+
+ {"freeTextLayoutCaches", "()V", (void*) SkCanvasGlue::freeTextLayoutCaches}
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include <android_runtime/AndroidRuntime.h>
+
+#define REG(env, name, array) \
+ result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
+ SK_ARRAY_COUNT(array)); \
+ if (result < 0) return result
+
+int register_android_graphics_Canvas(JNIEnv* env) {
+ int result;
+
+ REG(env, "android/graphics/Canvas", gCanvasMethods);
+
+ return result;
+}
+
+} // namespace android
+
+// GraphicsJNI helper for external clients.
+// We keep the implementation here to avoid exposing NativeCanvasWrapper
+// externally.
+SkCanvas* GraphicsJNI::getNativeCanvas(jlong nativeHandle) {
+ return android::SkCanvasGlue::getNativeCanvas(nativeHandle);
+}
diff --git a/core/jni/android/graphics/Canvas.h b/core/jni/android/graphics/Canvas.h
deleted file mode 100644
index 710845d..0000000
--- a/core/jni/android/graphics/Canvas.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_GRAPHICS_CANVAS_H
-#define ANDROID_GRAPHICS_CANVAS_H
-
-#include "SkBitmap.h"
-#include "SkCanvas.h"
-#include "SkMatrix.h"
-
-namespace android {
-
-// TODO: move this further up the stack so that all interaction with minikin
-// happens prior to calling into this interface
-class TypefaceImpl;
-
-class Canvas {
-public:
- virtual ~Canvas() {};
-
- static Canvas* create_canvas(SkBitmap* bitmap);
- static Canvas* create_canvas(SkCanvas* skiaCanvas);
-
- // TODO: enable HWUI to either create similar canvas wrapper or subclass
- // directly from Canvas
- //static Canvas* create_canvas(uirenderer::Renderer* renderer);
-
- // TODO: this is a temporary affordance until all necessary logic can be
- // moved within this interface! Further, the return value should
- // NOT be unref'd and is valid until this canvas is destroyed or a
- // new bitmap is set.
- virtual SkCanvas* getSkCanvas() = 0;
-
- virtual void setBitmap(SkBitmap* bitmap, bool copyState) = 0;
-
- virtual bool isOpaque() = 0;
- virtual int width() = 0;
- virtual int height() = 0;
-
-// ----------------------------------------------------------------------------
-// Canvas state operations
-// ----------------------------------------------------------------------------
- // Save (layer)
- virtual int getSaveCount() const = 0;
- virtual int save(SkCanvas::SaveFlags flags) = 0;
- virtual void restore() = 0;
- virtual void restoreToCount(int saveCount) = 0;
-
- virtual int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SkCanvas::SaveFlags flags) = 0;
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SkCanvas::SaveFlags flags) = 0;
-
- // Matrix
- virtual void getMatrix(SkMatrix* outMatrix) const = 0;
- virtual void setMatrix(const SkMatrix& matrix) = 0;
-
- virtual void concat(const SkMatrix& matrix) = 0;
- virtual void rotate(float degrees) = 0;
- virtual void scale(float sx, float sy) = 0;
- virtual void skew(float sx, float sy) = 0;
- virtual void translate(float dx, float dy) = 0;
-
- // clip
- virtual bool getClipBounds(SkRect* outRect) const = 0;
- virtual bool quickRejectRect(float left, float top, float right, float bottom) const = 0;
- virtual bool quickRejectPath(const SkPath& path) const = 0;
-
- virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0;
- virtual bool clipPath(const SkPath* path, SkRegion::Op op) = 0;
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op) = 0;
-
- // filters
- virtual void setDrawFilter(SkDrawFilter* drawFilter) = 0;
-
-// ----------------------------------------------------------------------------
-// Canvas draw operations
-// ----------------------------------------------------------------------------
- virtual void drawColor(int color, SkXfermode::Mode mode) = 0;
- virtual void drawPaint(const SkPaint& paint) = 0;
-
- // Geometry
- virtual void drawPoint(float x, float y, const SkPaint& paint) = 0;
- virtual void drawPoints(const float* points, int count, const SkPaint& paint) = 0;
- virtual void drawLine(float startX, float startY, float stopX, float stopY,
- const SkPaint& paint) = 0;
- virtual void drawLines(const float* points, int count, const SkPaint& paint) = 0;
- virtual void drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) = 0;
- virtual void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) = 0;
- virtual void drawCircle(float x, float y, float radius, const SkPaint& paint) = 0;
- virtual void drawOval(float left, float top, float right, float bottom,
- const SkPaint& paint) = 0;
- virtual void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) = 0;
- virtual void drawPath(const SkPath& path, const SkPaint& paint) = 0;
- virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
- const float* verts, const float* tex, const int* colors,
- const uint16_t* indices, int indexCount, const SkPaint& paint) = 0;
-
- // Bitmap-based
- virtual void drawBitmap(const SkBitmap& bitmap, float left, float top,
- const SkPaint* paint) = 0;
- virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix,
- const SkPaint* paint) = 0;
- virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) = 0;
- virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) = 0;
-
- // Text
- virtual void drawText(const char* text, int start, int count, int contextCount,
- float x, float y, int bidiFlags, const SkPaint& paint,
- TypefaceImpl* typeface) = 0;
- virtual void drawPosText(const char* text, const float* positions, int count, int posCount,
- const SkPaint& paint) = 0;
- virtual void drawTextOnPath(const char* text, int count, const SkPath& path,
- float hOffset, float vOffset, const SkPaint& paint) = 0;
-};
-
-}; // namespace android
-#endif // ANDROID_GRAPHICS_CANVAS_H
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index 74be577..5cc2b95 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -4,7 +4,6 @@
#include "JNIHelp.h"
#include "GraphicsJNI.h"
-#include "Canvas.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkMath.h"
@@ -365,7 +364,7 @@
SkASSERT(canvas);
SkASSERT(env->IsInstanceOf(canvas, gCanvas_class));
jlong canvasHandle = env->GetLongField(canvas, gCanvas_nativeInstanceID);
- SkCanvas* c = reinterpret_cast<android::Canvas*>(canvasHandle)->getSkCanvas();
+ SkCanvas* c = getNativeCanvas(canvasHandle);
SkASSERT(c);
return c;
}
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 28a6edb..8150edf 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -47,6 +47,7 @@
static SkPoint* jpointf_to_point(JNIEnv*, jobject jpointf, SkPoint* point);
static void point_to_jpointf(const SkPoint& point, JNIEnv*, jobject jpointf);
+ static SkCanvas* getNativeCanvas(jlong nativeHandle);
static SkCanvas* getNativeCanvas(JNIEnv*, jobject canvas);
static SkPaint* getNativePaint(JNIEnv*, jobject paint);
static android::TypefaceImpl* getNativeTypeface(JNIEnv*, jobject paint);
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index e82e8a6..ab5bdb0 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -23,7 +23,6 @@
#include <Caches.h>
-#include "Canvas.h"
#include "SkCanvas.h"
#include "SkRegion.h"
#include "GraphicsJNI.h"
@@ -120,7 +119,7 @@
static void drawF(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRectF,
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
- SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
+ SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
@@ -139,7 +138,7 @@
static void drawI(JNIEnv* env, jobject, jlong canvasHandle, jobject boundsRect,
jlong bitmapHandle, jlong chunkHandle, jlong paintHandle,
jint destDensity, jint srcDensity) {
- SkCanvas* canvas = reinterpret_cast<Canvas*>(canvasHandle)->getSkCanvas();
+ SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Res_png_9patch* chunk = reinterpret_cast<Res_png_9patch*>(chunkHandle);
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index d214575..bc0c25f 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-#include "Canvas.h"
#include "Picture.h"
+#include "SkCanvas.h"
#include "SkStream.h"
namespace android {
@@ -36,13 +36,12 @@
}
}
-Canvas* Picture::beginRecording(int width, int height) {
+SkCanvas* Picture::beginRecording(int width, int height) {
mPicture.reset(NULL);
mRecorder.reset(new SkPictureRecorder);
mWidth = width;
mHeight = height;
- SkCanvas* canvas = mRecorder->beginRecording(width, height, NULL, 0);
- return Canvas::create_canvas(canvas);
+ return mRecorder->beginRecording(width, height, NULL, 0);
}
void Picture::endRecording() {
@@ -94,14 +93,14 @@
}
}
-void Picture::draw(Canvas* canvas) {
+void Picture::draw(SkCanvas* canvas) {
if (NULL != mRecorder.get()) {
this->endRecording();
SkASSERT(NULL != mPicture.get());
}
if (NULL != mPicture.get()) {
// TODO: remove this const_cast once pictures are immutable
- const_cast<SkPicture*>(mPicture.get())->draw(canvas->getSkCanvas());
+ const_cast<SkPicture*>(mPicture.get())->draw(canvas);
}
}
diff --git a/core/jni/android/graphics/Picture.h b/core/jni/android/graphics/Picture.h
index a2e5d4a..abb0403 100644
--- a/core/jni/android/graphics/Picture.h
+++ b/core/jni/android/graphics/Picture.h
@@ -22,13 +22,14 @@
#include "SkRefCnt.h"
#include "SkTemplates.h"
+class SkCanvas;
+class SkPicture;
+class SkPictureRecorder;
class SkStream;
class SkWStream;
namespace android {
-class Canvas;
-
// Skia's SkPicture class has been split into an SkPictureRecorder
// and an SkPicture. AndroidPicture recreates the functionality
// of the old SkPicture interface by flip-flopping between the two
@@ -37,7 +38,7 @@
public:
explicit Picture(const Picture* src = NULL);
- Canvas* beginRecording(int width, int height);
+ SkCanvas* beginRecording(int width, int height);
void endRecording();
@@ -49,7 +50,7 @@
void serialize(SkWStream* stream) const;
- void draw(Canvas* canvas);
+ void draw(SkCanvas* canvas);
private:
int mWidth;
diff --git a/core/jni/android/graphics/SkiaCanvas.cpp b/core/jni/android/graphics/SkiaCanvas.cpp
deleted file mode 100644
index 5e93313..0000000
--- a/core/jni/android/graphics/SkiaCanvas.cpp
+++ /dev/null
@@ -1,773 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "jni.h"
-#include "Canvas.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "SkCanvas.h"
-#include "SkClipStack.h"
-#include "SkDevice.h"
-#include "SkDeque.h"
-#include "SkDrawFilter.h"
-#include "SkGraphics.h"
-#include "SkPorterDuff.h"
-#include "SkShader.h"
-#include "SkTArray.h"
-#include "SkTemplates.h"
-
-#include <minikin/Layout.h>
-#include "MinikinSkia.h"
-#include "MinikinUtils.h"
-
-#include "TypefaceImpl.h"
-
-#include "unicode/ubidi.h"
-#include "unicode/ushape.h"
-
-#include <utils/Log.h>
-
-namespace android {
-
-// Holds an SkCanvas reference plus additional native data.
-class SkiaCanvas : public Canvas {
-public:
- SkiaCanvas(SkBitmap* bitmap);
-
- SkiaCanvas(SkCanvas* canvas) : mCanvas(canvas) {
- SkASSERT(canvas);
- }
-
- virtual SkCanvas* getSkCanvas() {
- return mCanvas.get();
- }
-
- virtual void setBitmap(SkBitmap* bitmap, bool copyState);
-
- virtual bool isOpaque();
- virtual int width();
- virtual int height();
-
- virtual int getSaveCount() const;
- virtual int save(SkCanvas::SaveFlags flags);
- virtual void restore();
- virtual void restoreToCount(int saveCount);
-
- virtual int saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SkCanvas::SaveFlags flags);
- virtual int saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SkCanvas::SaveFlags flags);
-
- virtual void getMatrix(SkMatrix* outMatrix) const;
- virtual void setMatrix(const SkMatrix& matrix);
- virtual void concat(const SkMatrix& matrix);
- virtual void rotate(float degrees);
- virtual void scale(float sx, float sy);
- virtual void skew(float sx, float sy);
- virtual void translate(float dx, float dy);
-
- virtual bool getClipBounds(SkRect* outRect) const;
- virtual bool quickRejectRect(float left, float top, float right, float bottom) const;
- virtual bool quickRejectPath(const SkPath& path) const;
- virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
- virtual bool clipPath(const SkPath* path, SkRegion::Op op);
- virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
-
- virtual void setDrawFilter(SkDrawFilter* drawFilter);
-
- virtual void drawColor(int color, SkXfermode::Mode mode);
- virtual void drawPaint(const SkPaint& paint);
-
- virtual void drawPoint(float x, float y, const SkPaint& paint);
- virtual void drawPoints(const float* points, int count, const SkPaint& paint);
- virtual void drawLine(float startX, float startY, float stopX, float stopY,
- const SkPaint& paint);
- virtual void drawLines(const float* points, int count, const SkPaint& paint);
- virtual void drawRect(float left, float top, float right, float bottom, const SkPaint& paint);
- virtual void drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint);
- virtual void drawCircle(float x, float y, float radius, const SkPaint& paint);
- virtual void drawOval(float left, float top, float right, float bottom, const SkPaint& paint);
- virtual void drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint);
- virtual void drawPath(const SkPath& path, const SkPaint& paint);
- virtual void drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
- const float* verts, const float* tex, const int* colors,
- const uint16_t* indices, int indexCount, const SkPaint& paint);
-
- virtual void drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint);
- virtual void drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint);
- virtual void drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint);
- virtual void drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint);
-
- virtual void drawText(const char* text, int start, int count, int contextCount,
- float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface);
- virtual void drawPosText(const char* text, const float* positions, int count, int posCount,
- const SkPaint& paint);
- virtual void drawTextOnPath(const char* text, int count, const SkPath& path,
- float hOffset, float vOffset, const SkPaint& paint);
-
-private:
- struct SaveRec {
- int saveCount;
- SkCanvas::SaveFlags saveFlags;
- };
-
- void recordPartialSave(SkCanvas::SaveFlags flags);
- void saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount);
- void applyClips(const SkTArray<SkClipStack::Element>& clips);
-
- void drawPoints(const float* points, int count, const SkPaint& paint,
- SkCanvas::PointMode mode);
- void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
-
- SkAutoTUnref<SkCanvas> mCanvas;
- SkAutoTDelete<SkDeque> mSaveStack; // lazily allocated, tracks partial saves.
-};
-
-// Construct an SkCanvas from the bitmap.
-static SkCanvas* createCanvas(SkBitmap* bitmap) {
- if (bitmap) {
- return SkNEW_ARGS(SkCanvas, (*bitmap));
- }
-
- // Create an empty bitmap device to prevent callers from crashing
- // if they attempt to draw into this canvas.
- SkBitmap emptyBitmap;
- return new SkCanvas(emptyBitmap);
-}
-
-Canvas* Canvas::create_canvas(SkBitmap* bitmap) {
- return new SkiaCanvas(bitmap);
-}
-
-Canvas* Canvas::create_canvas(SkCanvas* skiaCanvas) {
- return new SkiaCanvas(skiaCanvas);
-}
-
-SkiaCanvas::SkiaCanvas(SkBitmap* bitmap) {
- mCanvas.reset(createCanvas(bitmap));
-}
-
-// ----------------------------------------------------------------------------
-// Canvas state operations: Replace Bitmap
-// ----------------------------------------------------------------------------
-
-class ClipCopier : public SkCanvas::ClipVisitor {
-public:
- ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
-
- virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
- m_dstCanvas->clipRect(rect, op, antialias);
- }
- virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
- m_dstCanvas->clipRRect(rrect, op, antialias);
- }
- virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
- m_dstCanvas->clipPath(path, op, antialias);
- }
-
-private:
- SkCanvas* m_dstCanvas;
-};
-
-void SkiaCanvas::setBitmap(SkBitmap* bitmap, bool copyState) {
- SkCanvas* newCanvas = createCanvas(bitmap);
- SkASSERT(newCanvas);
-
- if (copyState) {
- // Copy the canvas matrix & clip state.
- newCanvas->setMatrix(mCanvas->getTotalMatrix());
- if (NULL != mCanvas->getDevice() && NULL != newCanvas->getDevice()) {
- ClipCopier copier(newCanvas);
- mCanvas->replayClips(&copier);
- }
- }
-
- // unrefs the existing canvas
- mCanvas.reset(newCanvas);
-
- // clean up the old save stack
- mSaveStack.reset(NULL);
-}
-
-// ----------------------------------------------------------------------------
-// Canvas state operations
-// ----------------------------------------------------------------------------
-
-bool SkiaCanvas::isOpaque() {
- return mCanvas->getDevice()->accessBitmap(false).isOpaque();
-}
-
-int SkiaCanvas::width() {
- return mCanvas->getBaseLayerSize().width();
-}
-
-int SkiaCanvas::height() {
- return mCanvas->getBaseLayerSize().height();
-}
-
-// ----------------------------------------------------------------------------
-// Canvas state operations: Save (layer)
-// ----------------------------------------------------------------------------
-
-int SkiaCanvas::getSaveCount() const {
- return mCanvas->getSaveCount();
-}
-
-int SkiaCanvas::save(SkCanvas::SaveFlags flags) {
- int count = mCanvas->save();
- recordPartialSave(flags);
- return count;
-}
-
-void SkiaCanvas::restore() {
- const SaveRec* rec = (NULL == mSaveStack.get())
- ? NULL
- : static_cast<SaveRec*>(mSaveStack->back());
- int currentSaveCount = mCanvas->getSaveCount() - 1;
- SkASSERT(NULL == rec || currentSaveCount >= rec->saveCount);
-
- if (NULL == rec || rec->saveCount != currentSaveCount) {
- // Fast path - no record for this frame.
- mCanvas->restore();
- return;
- }
-
- bool preserveMatrix = !(rec->saveFlags & SkCanvas::kMatrix_SaveFlag);
- bool preserveClip = !(rec->saveFlags & SkCanvas::kClip_SaveFlag);
-
- SkMatrix savedMatrix;
- if (preserveMatrix) {
- savedMatrix = mCanvas->getTotalMatrix();
- }
-
- SkTArray<SkClipStack::Element> savedClips;
- if (preserveClip) {
- saveClipsForFrame(savedClips, currentSaveCount);
- }
-
- mCanvas->restore();
-
- if (preserveMatrix) {
- mCanvas->setMatrix(savedMatrix);
- }
-
- if (preserveClip && !savedClips.empty()) {
- applyClips(savedClips);
- }
-
- mSaveStack->pop_back();
-}
-
-void SkiaCanvas::restoreToCount(int restoreCount) {
- while (mCanvas->getSaveCount() > restoreCount) {
- this->restore();
- }
-}
-
-int SkiaCanvas::saveLayer(float left, float top, float right, float bottom,
- const SkPaint* paint, SkCanvas::SaveFlags flags) {
- SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
- int count = mCanvas->saveLayer(&bounds, paint, flags | SkCanvas::kMatrixClip_SaveFlag);
- recordPartialSave(flags);
- return count;
-}
-
-int SkiaCanvas::saveLayerAlpha(float left, float top, float right, float bottom,
- int alpha, SkCanvas::SaveFlags flags) {
- SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
- int count = mCanvas->saveLayerAlpha(&bounds, alpha, flags | SkCanvas::kMatrixClip_SaveFlag);
- recordPartialSave(flags);
- return count;
-}
-
-// ----------------------------------------------------------------------------
-// functions to emulate legacy SaveFlags (i.e. independent matrix/clip flags)
-// ----------------------------------------------------------------------------
-
-void SkiaCanvas::recordPartialSave(SkCanvas::SaveFlags flags) {
- // A partial save is a save operation which doesn't capture the full canvas state.
- // (either kMatrix_SaveFlags or kClip_SaveFlag is missing).
-
- // Mask-out non canvas state bits.
- flags = static_cast<SkCanvas::SaveFlags>(flags & SkCanvas::kMatrixClip_SaveFlag);
-
- if (SkCanvas::kMatrixClip_SaveFlag == flags) {
- // not a partial save.
- return;
- }
-
- if (NULL == mSaveStack.get()) {
- mSaveStack.reset(SkNEW_ARGS(SkDeque, (sizeof(struct SaveRec), 8)));
- }
-
- SaveRec* rec = static_cast<SaveRec*>(mSaveStack->push_back());
- // Store the save counter in the SkClipStack domain.
- // (0-based, equal to the number of save ops on the stack).
- rec->saveCount = mCanvas->getSaveCount() - 1;
- rec->saveFlags = flags;
-}
-
-void SkiaCanvas::saveClipsForFrame(SkTArray<SkClipStack::Element>& clips, int frameSaveCount) {
- SkClipStack::Iter clipIterator(*mCanvas->getClipStack(),
- SkClipStack::Iter::kTop_IterStart);
- while (const SkClipStack::Element* elem = clipIterator.next()) {
- if (elem->getSaveCount() < frameSaveCount) {
- // done with the current frame.
- break;
- }
- SkASSERT(elem->getSaveCount() == frameSaveCount);
- clips.push_back(*elem);
- }
-}
-
-void SkiaCanvas::applyClips(const SkTArray<SkClipStack::Element>& clips) {
- ClipCopier clipCopier(mCanvas);
-
- // The clip stack stores clips in device space.
- SkMatrix origMatrix = mCanvas->getTotalMatrix();
- mCanvas->resetMatrix();
-
- // We pushed the clips in reverse order.
- for (int i = clips.count() - 1; i >= 0; --i) {
- clips[i].replay(&clipCopier);
- }
-
- mCanvas->setMatrix(origMatrix);
-}
-
-// ----------------------------------------------------------------------------
-// Canvas state operations: Matrix
-// ----------------------------------------------------------------------------
-
-void SkiaCanvas::getMatrix(SkMatrix* outMatrix) const {
- *outMatrix = mCanvas->getTotalMatrix();
-}
-
-void SkiaCanvas::setMatrix(const SkMatrix& matrix) {
- mCanvas->setMatrix(matrix);
-}
-
-void SkiaCanvas::concat(const SkMatrix& matrix) {
- mCanvas->concat(matrix);
-}
-
-void SkiaCanvas::rotate(float degrees) {
- mCanvas->rotate(degrees);
-}
-
-void SkiaCanvas::scale(float sx, float sy) {
- mCanvas->scale(sx, sy);
-}
-
-void SkiaCanvas::skew(float sx, float sy) {
- mCanvas->skew(sx, sy);
-}
-
-void SkiaCanvas::translate(float dx, float dy) {
- mCanvas->translate(dx, dy);
-}
-
-// ----------------------------------------------------------------------------
-// Canvas state operations: Clips
-// ----------------------------------------------------------------------------
-
-// This function is a mirror of SkCanvas::getClipBounds except that it does
-// not outset the edge of the clip to account for anti-aliasing. There is
-// a skia bug to investigate pushing this logic into back into skia.
-// (see https://code.google.com/p/skia/issues/detail?id=1303)
-bool SkiaCanvas::getClipBounds(SkRect* outRect) const {
- SkIRect ibounds;
- if (!mCanvas->getClipDeviceBounds(&ibounds)) {
- return false;
- }
-
- SkMatrix inverse;
- // if we can't invert the CTM, we can't return local clip bounds
- if (!mCanvas->getTotalMatrix().invert(&inverse)) {
- if (outRect) {
- outRect->setEmpty();
- }
- return false;
- }
-
- if (NULL != outRect) {
- SkRect r = SkRect::Make(ibounds);
- inverse.mapRect(outRect, r);
- }
- return true;
-}
-
-bool SkiaCanvas::quickRejectRect(float left, float top, float right, float bottom) const {
- SkRect bounds = SkRect::MakeLTRB(left, top, right, bottom);
- return mCanvas->quickReject(bounds);
-}
-
-bool SkiaCanvas::quickRejectPath(const SkPath& path) const {
- return mCanvas->quickReject(path);
-}
-
-bool SkiaCanvas::clipRect(float left, float top, float right, float bottom, SkRegion::Op op) {
- SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
- mCanvas->clipRect(rect, op);
- return mCanvas->isClipEmpty();
-}
-
-bool SkiaCanvas::clipPath(const SkPath* path, SkRegion::Op op) {
- mCanvas->clipPath(*path, op);
- return mCanvas->isClipEmpty();
-}
-
-bool SkiaCanvas::clipRegion(const SkRegion* region, SkRegion::Op op) {
- SkPath rgnPath;
- if (region->getBoundaryPath(&rgnPath)) {
- // The region is specified in device space.
- SkMatrix savedMatrix = mCanvas->getTotalMatrix();
- mCanvas->resetMatrix();
- mCanvas->clipPath(rgnPath, op);
- mCanvas->setMatrix(savedMatrix);
- } else {
- mCanvas->clipRect(SkRect::MakeEmpty(), op);
- }
- return mCanvas->isClipEmpty();
-}
-
-// ----------------------------------------------------------------------------
-// Canvas state operations: Filters
-// ----------------------------------------------------------------------------
-
-void SkiaCanvas::setDrawFilter(SkDrawFilter* drawFilter) {
- mCanvas->setDrawFilter(drawFilter);
-}
-
-// ----------------------------------------------------------------------------
-// Canvas draw operations
-// ----------------------------------------------------------------------------
-
-void SkiaCanvas::drawColor(int color, SkXfermode::Mode mode) {
- mCanvas->drawColor(color, mode);
-}
-
-void SkiaCanvas::drawPaint(const SkPaint& paint) {
- mCanvas->drawPaint(paint);
-}
-
-// ----------------------------------------------------------------------------
-// Canvas draw operations: Geometry
-// ----------------------------------------------------------------------------
-
-void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint,
- SkCanvas::PointMode mode) {
- // convert the floats into SkPoints
- count >>= 1; // now it is the number of points
- SkAutoSTMalloc<32, SkPoint> storage(count);
- SkPoint* pts = storage.get();
- for (int i = 0; i < count; i++) {
- pts[i].set(points[0], points[1]);
- points += 2;
- }
- mCanvas->drawPoints(mode, count, pts, paint);
-}
-
-
-void SkiaCanvas::drawPoint(float x, float y, const SkPaint& paint) {
- mCanvas->drawPoint(x, y, paint);
-}
-
-void SkiaCanvas::drawPoints(const float* points, int count, const SkPaint& paint) {
- this->drawPoints(points, count, paint, SkCanvas::kPoints_PointMode);
-}
-
-void SkiaCanvas::drawLine(float startX, float startY, float stopX, float stopY,
- const SkPaint& paint) {
- mCanvas->drawLine(startX, startY, stopX, stopY, paint);
-}
-
-void SkiaCanvas::drawLines(const float* points, int count, const SkPaint& paint) {
- this->drawPoints(points, count, paint, SkCanvas::kLines_PointMode);
-}
-
-void SkiaCanvas::drawRect(float left, float top, float right, float bottom,
- const SkPaint& paint) {
- mCanvas->drawRectCoords(left, top, right, bottom, paint);
-
-}
-
-void SkiaCanvas::drawRoundRect(float left, float top, float right, float bottom,
- float rx, float ry, const SkPaint& paint) {
- SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
- mCanvas->drawRoundRect(rect, rx, ry, paint);
-}
-
-void SkiaCanvas::drawCircle(float x, float y, float radius, const SkPaint& paint) {
- mCanvas->drawCircle(x, y, radius, paint);
-}
-
-void SkiaCanvas::drawOval(float left, float top, float right, float bottom, const SkPaint& paint) {
- SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
- mCanvas->drawOval(oval, paint);
-}
-
-void SkiaCanvas::drawArc(float left, float top, float right, float bottom,
- float startAngle, float sweepAngle, bool useCenter, const SkPaint& paint) {
- SkRect arc = SkRect::MakeLTRB(left, top, right, bottom);
- mCanvas->drawArc(arc, startAngle, sweepAngle, useCenter, paint);
-}
-
-void SkiaCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
- mCanvas->drawPath(path, paint);
-}
-
-void SkiaCanvas::drawVertices(SkCanvas::VertexMode vertexMode, int vertexCount,
- const float* verts, const float* texs, const int* colors,
- const uint16_t* indices, int indexCount, const SkPaint& paint) {
-#ifndef SK_SCALAR_IS_FLOAT
- SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
-#endif
- const int ptCount = vertexCount >> 1;
- mCanvas->drawVertices(vertexMode, ptCount, (SkPoint*)verts, (SkPoint*)texs,
- (SkColor*)colors, NULL, indices, indexCount, paint);
-}
-
-// ----------------------------------------------------------------------------
-// Canvas draw operations: Bitmaps
-// ----------------------------------------------------------------------------
-
-void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float left, float top, const SkPaint* paint) {
- mCanvas->drawBitmap(bitmap, left, top, paint);
-}
-
-void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, const SkMatrix& matrix, const SkPaint* paint) {
- mCanvas->drawBitmapMatrix(bitmap, matrix, paint);
-}
-
-void SkiaCanvas::drawBitmap(const SkBitmap& bitmap, float srcLeft, float srcTop,
- float srcRight, float srcBottom, float dstLeft, float dstTop,
- float dstRight, float dstBottom, const SkPaint* paint) {
- SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
- SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
- mCanvas->drawBitmapRectToRect(bitmap, &srcRect, dstRect, paint);
-}
-
-void SkiaCanvas::drawBitmapMesh(const SkBitmap& bitmap, int meshWidth, int meshHeight,
- const float* vertices, const int* colors, const SkPaint* paint) {
-
- const int ptCount = (meshWidth + 1) * (meshHeight + 1);
- const int indexCount = meshWidth * meshHeight * 6;
-
- /* Our temp storage holds 2 or 3 arrays.
- texture points [ptCount * sizeof(SkPoint)]
- optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
- copy to convert from float to fixed
- indices [ptCount * sizeof(uint16_t)]
- */
- ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
- storageSize += indexCount * sizeof(uint16_t); // indices[]
-
-
-#ifndef SK_SCALAR_IS_FLOAT
- SkDEBUGFAIL("SkScalar must be a float for these conversions to be valid");
-#endif
- SkAutoMalloc storage(storageSize);
- SkPoint* texs = (SkPoint*)storage.get();
- uint16_t* indices = (uint16_t*)(texs + ptCount);
-
- // cons up texture coordinates and indices
- {
- const SkScalar w = SkIntToScalar(bitmap.width());
- const SkScalar h = SkIntToScalar(bitmap.height());
- const SkScalar dx = w / meshWidth;
- const SkScalar dy = h / meshHeight;
-
- SkPoint* texsPtr = texs;
- SkScalar y = 0;
- for (int i = 0; i <= meshHeight; i++) {
- if (i == meshHeight) {
- y = h; // to ensure numerically we hit h exactly
- }
- SkScalar x = 0;
- for (int j = 0; j < meshWidth; j++) {
- texsPtr->set(x, y);
- texsPtr += 1;
- x += dx;
- }
- texsPtr->set(w, y);
- texsPtr += 1;
- y += dy;
- }
- SkASSERT(texsPtr - texs == ptCount);
- }
-
- // cons up indices
- {
- uint16_t* indexPtr = indices;
- int index = 0;
- for (int i = 0; i < meshHeight; i++) {
- for (int j = 0; j < meshWidth; j++) {
- // lower-left triangle
- *indexPtr++ = index;
- *indexPtr++ = index + meshWidth + 1;
- *indexPtr++ = index + meshWidth + 2;
- // upper-right triangle
- *indexPtr++ = index;
- *indexPtr++ = index + meshWidth + 2;
- *indexPtr++ = index + 1;
- // bump to the next cell
- index += 1;
- }
- // bump to the next row
- index += 1;
- }
- SkASSERT(indexPtr - indices == indexCount);
- SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
- }
-
- // double-check that we have legal indices
-#ifdef SK_DEBUG
- {
- for (int i = 0; i < indexCount; i++) {
- SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
- }
- }
-#endif
-
- // cons-up a shader for the bitmap
- SkPaint tmpPaint;
- if (paint) {
- tmpPaint = *paint;
- }
- SkShader* shader = SkShader::CreateBitmapShader(bitmap,
- SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode);
- SkSafeUnref(tmpPaint.setShader(shader));
-
- mCanvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, (SkPoint*)vertices,
- texs, (const SkColor*)colors, NULL, indices,
- indexCount, tmpPaint);
-}
-
-// ----------------------------------------------------------------------------
-// Canvas draw operations: Text
-// ----------------------------------------------------------------------------
-
-class DrawTextFunctor {
-public:
- DrawTextFunctor(const Layout& layout, SkCanvas* canvas, float x, float y, SkPaint* paint,
- uint16_t* glyphs, SkPoint* pos)
- : layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
- pos(pos) { }
-
- void operator()(size_t start, size_t end) {
- for (size_t i = start; i < end; i++) {
- glyphs[i] = layout.getGlyphId(i);
- pos[i].fX = x + layout.getX(i);
- pos[i].fY = y + layout.getY(i);
- }
- canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
- }
-private:
- const Layout& layout;
- SkCanvas* canvas;
- float x;
- float y;
- SkPaint* paint;
- uint16_t* glyphs;
- SkPoint* pos;
-};
-
-void SkiaCanvas::drawText(const char* text, int start, int count, int contextCount,
- float x, float y, int bidiFlags, const SkPaint& paint, TypefaceImpl* typeface) {
- Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, &paint, bidiFlags, typeface);
- layout.doLayout((uint16_t*)text, start, count, contextCount, css);
-
- size_t nGlyphs = layout.nGlyphs();
- uint16_t* glyphs = new uint16_t[nGlyphs];
- SkPoint* pos = new SkPoint[nGlyphs];
-
- SkPaint paintCopy(paint);
- x += MinikinUtils::xOffsetForTextAlign(&paintCopy, layout);
- paintCopy.setTextAlign(SkPaint::kLeft_Align);
- paintCopy.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
-
- DrawTextFunctor f(layout, mCanvas, x, y, &paintCopy, glyphs, pos);
- MinikinUtils::forFontRun(layout, &paintCopy, f);
- drawTextDecorations(x, y, layout.getAdvance(), paintCopy);
-
- delete[] glyphs;
- delete[] pos;
-}
-
-// Same values used by Skia
-#define kStdStrikeThru_Offset (-6.0f / 21.0f)
-#define kStdUnderline_Offset (1.0f / 9.0f)
-#define kStdUnderline_Thickness (1.0f / 18.0f)
-
-void SkiaCanvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
- uint32_t flags;
- SkDrawFilter* drawFilter = mCanvas->getDrawFilter();
- if (drawFilter) {
- SkPaint paintCopy(paint);
- drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
- flags = paintCopy.getFlags();
- } else {
- flags = paint.getFlags();
- }
- if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
- SkScalar left = x;
- SkScalar right = x + length;
- float textSize = paint.getTextSize();
- float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
- if (flags & SkPaint::kUnderlineText_Flag) {
- SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
- mCanvas->drawRectCoords(left, top, right, bottom, paint);
- }
- if (flags & SkPaint::kStrikeThruText_Flag) {
- SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
- mCanvas->drawRectCoords(left, top, right, bottom, paint);
- }
- }
-}
-
-void SkiaCanvas::drawPosText(const char* text, const float* positions, int count, int posCount,
- const SkPaint& paint) {
- SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
- int indx;
- for (indx = 0; indx < posCount; indx++) {
- posPtr[indx].fX = positions[indx << 1];
- posPtr[indx].fY = positions[(indx << 1) + 1];
- }
-
- SkPaint paintCopy(paint);
- paintCopy.setTextEncoding(SkPaint::kUTF16_TextEncoding);
- mCanvas->drawPosText(text, count, posPtr, paintCopy);
-
- delete[] posPtr;
-}
-
-void SkiaCanvas::drawTextOnPath(const char* text, int count, const SkPath& path,
- float hOffset, float vOffset, const SkPaint& paint) {
- mCanvas->drawTextOnPathHV(text, count, path, hOffset, vOffset, paint);
-}
-
-} // namespace android
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index 9436a47..3812c27 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -19,9 +19,9 @@
#include <android_runtime/AndroidRuntime.h>
#include <vector>
-#include "Canvas.h"
#include "CreateJavaOutputStreamAdaptor.h"
+#include "SkCanvas.h"
#include "SkDocument.h"
#include "SkPicture.h"
#include "SkPictureRecorder.h"
@@ -132,9 +132,8 @@
jint pageWidth, jint pageHeight,
jint contentLeft, jint contentTop, jint contentRight, jint contentBottom) {
PdfDocument* document = reinterpret_cast<PdfDocument*>(documentPtr);
- SkCanvas* canvas = document->startPage(pageWidth, pageHeight,
- contentLeft, contentTop, contentRight, contentBottom);
- return reinterpret_cast<jlong>(Canvas::create_canvas(canvas));
+ return reinterpret_cast<jlong>(document->startPage(pageWidth, pageHeight,
+ contentLeft, contentTop, contentRight, contentBottom));
}
static void nativeFinishPage(JNIEnv* env, jobject thiz, jlong documentPtr) {
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
deleted file mode 100644
index fd96a90..0000000
--- a/core/jni/android_graphics_Canvas.cpp
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "jni.h"
-#include "GraphicsJNI.h"
-#include <android_runtime/AndroidRuntime.h>
-
-#include "Canvas.h"
-#include "SkGraphics.h"
-#include "SkPorterDuff.h"
-#include "TypefaceImpl.h"
-
-#include <minikin/Layout.h>
-#include "MinikinSkia.h"
-#include "MinikinUtils.h"
-
-namespace android {
-
-namespace CanvasJNI {
-
-static Canvas* get_canvas(jlong canvasHandle) {
- return reinterpret_cast<Canvas*>(canvasHandle);
-}
-
-static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
- delete get_canvas(canvasHandle);
-}
-
-// Native wrapper constructor used by Canvas(Bitmap)
-static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap));
-}
-
-// Set the given bitmap as the new draw target (wrapped in a new SkCanvas),
-// optionally copying canvas matrix & clip state.
-static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
- jboolean copyState) {
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- get_canvas(canvasHandle)->setBitmap(bitmap, copyState);
-}
-
-static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
- return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE;
-}
-
-static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
- return static_cast<jint>(get_canvas(canvasHandle)->width());
-}
-
-static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
- return static_cast<jint>(get_canvas(canvasHandle)->height());
-}
-
-static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
- return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount());
-}
-
-static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
- SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- return static_cast<jint>(get_canvas(canvasHandle)->save(flags));
-}
-
-static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
- jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags));
-}
-
-static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t,
- jfloat r, jfloat b, jint alpha, jint flagsHandle) {
- SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags));
-}
-
-static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
- Canvas* canvas = get_canvas(canvasHandle);
- if (canvas->getSaveCount() <= 1) { // cannot restore anymore
- doThrowISE(env, "Underflow in restore");
- return;
- }
- canvas->restore();
-}
-
-static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount) {
- Canvas* canvas = get_canvas(canvasHandle);
- if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) {
- doThrowIAE(env, "Underflow in restoreToCount");
- return;
- }
- canvas->restoreToCount(restoreCount);
-}
-
-static void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
- SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- get_canvas(canvasHandle)->getMatrix(matrix);
-}
-
-static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
- const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I());
-}
-
-static void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) {
- const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- get_canvas(canvasHandle)->concat(*matrix);
-}
-
-static void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) {
- get_canvas(canvasHandle)->rotate(degrees);
-}
-
-static void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
- get_canvas(canvasHandle)->scale(sx, sy);
-}
-
-static void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) {
- get_canvas(canvasHandle)->skew(sx, sy);
-}
-
-static void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) {
- get_canvas(canvasHandle)->translate(dx, dy);
-}
-
-static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) {
- SkRect r;
- SkIRect ir;
- bool result = get_canvas(canvasHandle)->getClipBounds(&r);
-
- if (!result) {
- r.setEmpty();
- }
- r.round(&ir);
-
- (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
- return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat left, jfloat top, jfloat right, jfloat bottom) {
- bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom);
- return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) {
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- bool result = get_canvas(canvasHandle)->quickRejectPath(*path);
- return result ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t,
- jfloat r, jfloat b, jint opHandle) {
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool emptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op);
- return emptyClip ? JNI_FALSE : JNI_TRUE;
-}
-
-static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
- jint opHandle) {
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool emptyClip = get_canvas(canvasHandle)->clipPath(path, op);
- return emptyClip ? JNI_FALSE : JNI_TRUE;
-}
-
-static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle,
- jint opHandle) {
- SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
- SkRegion::Op op = static_cast<SkRegion::Op>(opHandle);
- bool emptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op);
- return emptyClip ? JNI_FALSE : JNI_TRUE;
-}
-
-static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) {
- SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
- get_canvas(canvasHandle)->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
-}
-
-static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawPaint(*paint);
-}
-
-static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
- jlong paintHandle) {
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawPoint(x, y, *paint);
-}
-
-static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
- jint offset, jint count, jlong paintHandle) {
- NPE_CHECK_RETURN_VOID(env, jptsArray);
- AutoJavaFloatArray autoPts(env, jptsArray);
- float* floats = autoPts.ptr();
- const int length = autoPts.length();
-
- if ((offset | count) < 0 || offset + count > length) {
- doThrowAIOOBE(env);
- return;
- }
-
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint);
-}
-
-static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY,
- jfloat stopX, jfloat stopY, jlong paintHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint);
-}
-
-static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray,
- jint offset, jint count, jlong paintHandle) {
- NPE_CHECK_RETURN_VOID(env, jptsArray);
- AutoJavaFloatArray autoPts(env, jptsArray);
- float* floats = autoPts.ptr();
- const int length = autoPts.length();
-
- if ((offset | count) < 0 || offset + count > length) {
- doThrowAIOOBE(env);
- return;
- }
-
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint);
-}
-
-static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
- jfloat right, jfloat bottom, jlong paintHandle) {
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint);
-}
-
-static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
- jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) {
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint);
-}
-
-static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy,
- jfloat radius, jlong paintHandle) {
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint);
-}
-
-static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
- jfloat right, jfloat bottom, jlong paintHandle) {
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint);
-}
-
-static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top,
- jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle,
- jboolean useCenter, jlong paintHandle) {
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle,
- useCenter, *paint);
-}
-
-static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
- jlong paintHandle) {
- const SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawPath(*path, *paint);
-}
-
-static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
- jint modeHandle, jint vertexCount,
- jfloatArray jverts, jint vertIndex,
- jfloatArray jtexs, jint texIndex,
- jintArray jcolors, jint colorIndex,
- jshortArray jindices, jint indexIndex,
- jint indexCount, jlong paintHandle) {
- AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
- AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
- AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
- AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
-
- const float* verts = vertA.ptr() + vertIndex;
- const float* texs = texA.ptr() + vertIndex;
- const int* colors = NULL;
- const uint16_t* indices = NULL;
-
- if (jcolors != NULL) {
- colors = colorA.ptr() + colorIndex;
- }
- if (jindices != NULL) {
- indices = (const uint16_t*)(indexA.ptr() + indexIndex);
- }
-
- SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors,
- indices, indexCount, *paint);
-}
-
-static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jlong bitmapHandle,
- jfloat left, jfloat top, jlong paintHandle, jint canvasDensity,
- jint screenDensity, jint bitmapDensity) {
- Canvas* canvas = get_canvas(canvasHandle);
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-
- if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
- if (screenDensity != 0 && screenDensity != bitmapDensity) {
- SkPaint filteredPaint;
- if (paint) {
- filteredPaint = *paint;
- }
- filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
- canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
- } else {
- canvas->drawBitmap(*bitmap, left, top, paint);
- }
- } else {
- canvas->save(SkCanvas::kMatrixClip_SaveFlag);
- SkScalar scale = canvasDensity / (float)bitmapDensity;
- canvas->translate(left, top);
- canvas->scale(scale, scale);
-
- SkPaint filteredPaint;
- if (paint) {
- filteredPaint = *paint;
- }
- filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
-
- canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
- canvas->restore();
- }
-}
-
-static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
- jlong matrixHandle, jlong paintHandle) {
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawBitmap(*bitmap, *matrix, paint);
-}
-
-static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
- float srcLeft, float srcTop, float srcRight, float srcBottom,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- jlong paintHandle, jint screenDensity, jint bitmapDensity) {
- Canvas* canvas = get_canvas(canvasHandle);
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-
- if (screenDensity != 0 && screenDensity != bitmapDensity) {
- SkPaint filteredPaint;
- if (paint) {
- filteredPaint = *paint;
- }
- filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
- canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
- dstLeft, dstTop, dstRight, dstBottom, &filteredPaint);
- } else {
- canvas->drawBitmap(*bitmap, srcLeft, srcTop, srcRight, srcBottom,
- dstLeft, dstTop, dstRight, dstBottom, paint);
- }
-}
-
-static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
- jintArray jcolors, jint offset, jint stride,
- jfloat x, jfloat y, jint width, jint height,
- jboolean hasAlpha, jlong paintHandle) {
- // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will
- // correct the alphaType to kOpaque_SkAlphaType.
- SkImageInfo info = SkImageInfo::Make(width, height,
- hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType,
- kPremul_SkAlphaType);
- SkBitmap bitmap;
- if (!bitmap.allocPixels(info)) {
- return;
- }
-
- if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
- return;
- }
-
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint);
-}
-
-static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle,
- jint meshWidth, jint meshHeight, jfloatArray jverts,
- jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) {
- const int ptCount = (meshWidth + 1) * (meshHeight + 1);
- AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
- AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
-
- const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
- const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- get_canvas(canvasHandle)->drawBitmapMesh(*bitmap, meshWidth, meshHeight,
- vertA.ptr(), colorA.ptr(), paint);
-}
-
-static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
- jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
- jlong paintHandle, jlong typefaceHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
- jchar* jchars = env->GetCharArrayElements(text, NULL);
- const char* textArray = reinterpret_cast<const char*>(jchars) + index;
- get_canvas(canvasHandle)->drawText(textArray, 0, count, count, x, y, bidiFlags, *paint, typeface);
- env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
-}
-
-static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
- jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
- jlong paintHandle, jlong typefaceHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
- const int count = end - start;
- const jchar* jchars = env->GetStringChars(text, NULL);
- const char* textArray = reinterpret_cast<const char*>(jchars) + start;
- get_canvas(canvasHandle)->drawText(textArray, 0, count, count, x, y, bidiFlags, *paint, typeface);
- env->ReleaseStringChars(text, jchars);
-}
-
-static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
- jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
- jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
- jchar* jchars = env->GetCharArrayElements(text, NULL);
- const char* textArray = reinterpret_cast<const char*>(jchars) + contextIndex;
- get_canvas(canvasHandle)->drawText(textArray, index - contextIndex, count, contextCount,
- x, y, bidiFlags, *paint, typeface);
- env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
-}
-
-static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text,
- jint start, jint end, jint contextStart, jint contextEnd,
- jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
- jlong typefaceHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
- jint count = end - start;
- jint contextCount = contextEnd - contextStart;
- const jchar* jchars = env->GetStringChars(text, NULL);
- const char* textArray = reinterpret_cast<const char*>(jchars) + contextStart;
- get_canvas(canvasHandle)->drawText(textArray, start - contextStart, count, contextCount,
- x, y, bidiFlags, *paint, typeface);
- env->ReleaseStringChars(text, jchars);
-}
-
-static void drawPosTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
- jint index, jint count, jfloatArray pos, jlong paintHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- jchar* jchars = text ? env->GetCharArrayElements(text, NULL) : NULL;
- float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
- int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
-
- const char* textArray = reinterpret_cast<const char*>(jchars) + index;
- get_canvas(canvasHandle)->drawPosText(textArray, posArray, count << 1, posCount, *paint);
-
- if (text) {
- env->ReleaseCharArrayElements(text, jchars, 0);
- }
- if (pos) {
- env->ReleaseFloatArrayElements(pos, posArray, 0);
- }
-}
-
-
-static void drawPosTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
- jfloatArray pos, jlong paintHandle) {
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- const jchar* jchars = text ? env->GetStringChars(text, NULL) : NULL;
- int byteLength = text ? env->GetStringLength(text) : 0;
- float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
- int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
-
- const char* textArray = reinterpret_cast<const char*>(jchars);
- get_canvas(canvasHandle)->drawPosText(textArray , posArray, byteLength << 1, posCount, *paint);
-
- if (text) {
- env->ReleaseStringChars(text, jchars);
- }
- if (pos) {
- env->ReleaseFloatArrayElements(pos, posArray, 0);
- }
-}
-
-class DrawTextOnPathFunctor {
-public:
- DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
- float vOffset, const SkPaint& paint, const SkPath& path)
- : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
- paint(paint), path(path) {
- }
- void operator()(size_t start, size_t end) {
- uint16_t glyphs[1];
- for (size_t i = start; i < end; i++) {
- glyphs[0] = layout.getGlyphId(i);
- float x = hOffset + layout.getX(i);
- float y = vOffset + layout.getY(i);
- canvas->drawTextOnPath((const char*) glyphs, 1, path, x, y, paint);
- }
- }
-private:
- const Layout& layout;
- Canvas* canvas;
- float hOffset;
- float vOffset;
- const SkPaint& paint;
- const SkPath& path;
-};
-
-static void drawTextOnPath(Canvas* canvas, const char* text, int count, int bidiFlags,
- const SkPath& path, float hOffset, float vOffset,
- const SkPaint& paint, TypefaceImpl* typeface) {
- SkPaint paintCopy(paint);
- Layout layout;
- std::string css = MinikinUtils::setLayoutProperties(&layout, &paintCopy, bidiFlags, typeface);
- layout.doLayout((uint16_t*)text, 0, count, count, css);
- hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
-
- // Set align to left for drawing, as we don't want individual
- // glyphs centered or right-aligned; the offset above takes
- // care of all alignment.
- paintCopy.setTextAlign(SkPaint::kLeft_Align);
-
- DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
- MinikinUtils::forFontRun(layout, &paintCopy, f);
-}
-
-static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
- jint index, jint count, jlong pathHandle, jfloat hOffset,
- jfloat vOffset, jint bidiFlags, jlong paintHandle,
- jlong typefaceHandle) {
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- jchar* jchars = env->GetCharArrayElements(text, NULL);
- const char* textArray = reinterpret_cast<const char*>(jchars);
-
- drawTextOnPath(get_canvas(canvasHandle), textArray + index, count, bidiFlags, *path,
- hOffset, vOffset, *paint, typeface);
-
- env->ReleaseCharArrayElements(text, jchars, 0);
-}
-
-static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text,
- jlong pathHandle, jfloat hOffset, jfloat vOffset,
- jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
- SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
-
- const jchar* jchars = env->GetStringChars(text, NULL);
- const char* textArray = reinterpret_cast<const char*>(jchars);
- int count = env->GetStringLength(text);
-
- drawTextOnPath(get_canvas(canvasHandle), textArray, count, bidiFlags, *path,
- hOffset, vOffset, *paint, typeface);
-
- env->ReleaseStringChars(text, jchars);
-}
-
-static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) {
- get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
-}
-
-static void freeCaches(JNIEnv* env, jobject) {
- SkGraphics::PurgeFontCache();
-}
-
-static void freeTextLayoutCaches(JNIEnv* env, jobject) {
- Layout::purgeCaches();
-}
-
-}; // namespace CanvasJNI
-
-static JNINativeMethod gMethods[] = {
- {"finalizer", "(J)V", (void*) CanvasJNI::finalizer},
- {"initRaster", "(J)J", (void*) CanvasJNI::initRaster},
- {"native_setBitmap", "(JJZ)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_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","(J)V", (void*) CanvasJNI::restore},
- {"native_restoreToCount","(JI)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_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_drawBitmap","(JJFFJIII)V", (void*) CanvasJNI::drawBitmap},
- {"nativeDrawBitmapMatrix", "(JJJJ)V", (void*)CanvasJNI::drawBitmapMatrix},
- {"native_drawBitmap","(JJFFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect},
- {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray},
- {"nativeDrawBitmapMesh", "(JJII[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},
- {"freeCaches", "()V", (void*) CanvasJNI::freeCaches},
- {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}
-};
-
-int register_android_graphics_Canvas(JNIEnv* env) {
- return AndroidRuntime::registerNativeMethods(env, "android/graphics/Canvas", gMethods, NELEM(gMethods));
-}
-
-}; // namespace android
diff --git a/core/jni/android_graphics_Picture.cpp b/core/jni/android_graphics_Picture.cpp
index eb8f6dd..f827907 100644
--- a/core/jni/android_graphics_Picture.cpp
+++ b/core/jni/android_graphics_Picture.cpp
@@ -51,7 +51,7 @@
static void android_graphics_Picture_draw(JNIEnv* env, jobject, jlong canvasHandle,
jlong pictureHandle) {
- Canvas* canvas = reinterpret_cast<Canvas*>(canvasHandle);
+ SkCanvas* canvas = GraphicsJNI::getNativeCanvas(canvasHandle);
Picture* picture = reinterpret_cast<Picture*>(pictureHandle);
SkASSERT(canvas);
SkASSERT(picture);
@@ -84,7 +84,12 @@
static jlong android_graphics_Picture_beginRecording(JNIEnv* env, jobject, jlong pictHandle,
jint w, jint h) {
Picture* pict = reinterpret_cast<Picture*>(pictHandle);
- Canvas* canvas = pict->beginRecording(w, h);
+ // beginRecording does not ref its return value, it just returns it.
+ SkCanvas* canvas = pict->beginRecording(w, h);
+ // the java side will wrap this guy in a Canvas.java, which will call
+ // unref in its finalizer, so we have to ref it here, so that both that
+ // Canvas.java and our picture can both be owners
+ canvas->ref();
return reinterpret_cast<jlong>(canvas);
}
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index ef4b260..72e2056 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -158,7 +158,7 @@
if (nativeCanvas == 0) {
throw new IllegalStateException();
}
- mNativeCanvasWrapper = nativeCanvas;
+ mNativeCanvasWrapper = initCanvas(nativeCanvas);
mFinalizer = new CanvasFinalizer(mNativeCanvasWrapper);
mDensity = Bitmap.getDefaultDensity();
}
@@ -924,7 +924,7 @@
* @param b blue component (0..255) of the color to draw onto the canvas
*/
public void drawRGB(int r, int g, int b) {
- drawColor(Color.rgb(r, g, b));
+ native_drawRGB(mNativeCanvasWrapper, r, g, b);
}
/**
@@ -937,7 +937,7 @@
* @param b blue component (0..255) of the color to draw onto the canvas
*/
public void drawARGB(int a, int r, int g, int b) {
- drawColor(Color.argb(a, r, g, b));
+ native_drawARGB(mNativeCanvasWrapper, a, r, g, b);
}
/**
@@ -947,7 +947,7 @@
* @param color the color to draw onto the canvas
*/
public void drawColor(int color) {
- native_drawColor(mNativeCanvasWrapper, color, PorterDuff.Mode.SRC_OVER.nativeInt);
+ native_drawColor(mNativeCanvasWrapper, color);
}
/**
@@ -1301,28 +1301,13 @@
*/
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.mNativePaint;
-
- 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.ni(), left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
- bitmap.mDensity);
- }
+ if (dst == null) {
+ throw new NullPointerException();
+ }
+ throwIfCannotDraw(bitmap);
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), src, dst,
+ paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
+ }
/**
* Draw the specified bitmap, scaling/translating automatically to fill
@@ -1352,23 +1337,8 @@
throw new NullPointerException();
}
throwIfCannotDraw(bitmap);
- final long nativePaint = paint == null ? 0 : paint.mNativePaint;
-
- 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.ni(), left, top, right, bottom,
- dst.left, dst.top, dst.right, dst.bottom, nativePaint, mScreenDensity,
- bitmap.mDensity);
+ native_drawBitmap(mNativeCanvasWrapper, bitmap.ni(), src, dst,
+ paint != null ? paint.mNativePaint : 0, mScreenDensity, bitmap.mDensity);
}
/**
@@ -1896,6 +1866,7 @@
public static native void freeTextLayoutCaches();
private static native long initRaster(long nativeBitmapOrZero);
+ private static native long initCanvas(long canvasHandle);
private static native void native_setBitmap(long canvasHandle,
long bitmapHandle,
boolean copyState);
@@ -1948,6 +1919,11 @@
private static native boolean native_quickReject(long nativeCanvas,
float left, float top,
float right, float bottom);
+ private static native void native_drawRGB(long nativeCanvas, int r, int g,
+ int b);
+ private static native void native_drawARGB(long nativeCanvas, int a, int r,
+ int g, int b);
+ private static native void native_drawColor(long nativeCanvas, int color);
private static native void native_drawColor(long nativeCanvas, int color,
int mode);
private static native void native_drawPaint(long nativeCanvas,
@@ -1989,9 +1965,16 @@
int screenDensity,
int bitmapDensity);
private native void native_drawBitmap(long nativeCanvas, long nativeBitmap,
- float srcLeft, float srcTop, float srcRight, float srcBottom,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- long nativePaintOrZero, int screenDensity, int bitmapDensity);
+ Rect src, RectF dst,
+ long nativePaintOrZero,
+ int screenDensity,
+ int bitmapDensity);
+ private static native void native_drawBitmap(long nativeCanvas,
+ long nativeBitmap,
+ Rect src, Rect dst,
+ 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,