blob: 9e0996a64b6b4758e1b438ce68f6f725cd5ca0de [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006-2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "jni.h"
18#include "GraphicsJNI.h"
19#include <android_runtime/AndroidRuntime.h>
20
21#include "SkCanvas.h"
22#include "SkDevice.h"
Raph Leviene174ae22012-10-03 15:26:47 -070023#include "SkDrawFilter.h"
Mike Reedcaf0df12009-04-27 14:32:05 -040024#include "SkGraphics.h"
25#include "SkImageRef_GlobalPool.h"
Mike Reed47c0d4e2009-06-22 22:53:52 -040026#include "SkPorterDuff.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027#include "SkShader.h"
28#include "SkTemplates.h"
29
Raph Leviena0336302013-05-22 16:16:59 -070030#ifdef USE_MINIKIN
31#include <minikin/Layout.h>
32#include "MinikinSkia.h"
Raph Levien1a73f7322014-01-30 16:06:28 -080033#include "MinikinUtils.h"
Raph Leviena0336302013-05-22 16:16:59 -070034#endif
35
Doug Feltf7cb1f72010-07-01 16:20:43 -070036#include "TextLayout.h"
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -070037#include "TextLayoutCache.h"
Raph Leviena0336302013-05-22 16:16:59 -070038#include "TypefaceImpl.h"
Doug Feltf7cb1f72010-07-01 16:20:43 -070039
Doug Feltf47d7402010-04-21 16:01:52 -070040#include "unicode/ubidi.h"
Doug Felt0c702b82010-05-14 10:55:42 -070041#include "unicode/ushape.h"
42
Doug Felt0c702b82010-05-14 10:55:42 -070043#include <utils/Log.h>
Doug Feltf47d7402010-04-21 16:01:52 -070044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045static uint32_t get_thread_msec() {
46#if defined(HAVE_POSIX_CLOCKS)
47 struct timespec tm;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000048
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080049 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
Ashok Bhat36bef0b2014-01-20 20:08:01 +000050
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080051 return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
52#else
53 struct timeval tv;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000054
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055 gettimeofday(&tv, NULL);
56 return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
57#endif
58}
59
60namespace android {
61
Derek Sollenberger5b6591c2013-02-28 11:18:50 -050062class ClipCopier : public SkCanvas::ClipVisitor {
63public:
64 ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
65
66 virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
67 m_dstCanvas->clipRect(rect, op, antialias);
68 }
Leon Scrogginscc11f152014-03-31 16:52:13 -040069 virtual void clipRRect(const SkRRect& rrect, SkRegion::Op op, bool antialias) {
70 m_dstCanvas->clipRRect(rrect, op, antialias);
71 }
Derek Sollenberger5b6591c2013-02-28 11:18:50 -050072 virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
73 m_dstCanvas->clipPath(path, op, antialias);
74 }
75
76private:
77 SkCanvas* m_dstCanvas;
78};
79
Leon Scrogginscc11f152014-03-31 16:52:13 -040080// Returns true if the SkCanvas's clip is non-empty.
81static jboolean hasNonEmptyClip(const SkCanvas& canvas) {
82 bool emptyClip = canvas.isClipEmpty();
83 return emptyClip ? JNI_FALSE : JNI_TRUE;
84}
85
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086class SkCanvasGlue {
87public:
88
Ashok Bhat36bef0b2014-01-20 20:08:01 +000089 static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
90 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 canvas->unref();
92 }
93
Ashok Bhat36bef0b2014-01-20 20:08:01 +000094 static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
95 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040096 if (bitmap) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +000097 return reinterpret_cast<jlong>(new SkCanvas(*bitmap));
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040098 } else {
99 // Create an empty bitmap device to prevent callers from crashing
100 // if they attempt to draw into this canvas.
101 SkBitmap emptyBitmap;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000102 return reinterpret_cast<jlong>(new SkCanvas(emptyBitmap));
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -0400103 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800104 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000105
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500106 static void copyCanvasState(JNIEnv* env, jobject clazz,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000107 jlong srcCanvasHandle, jlong dstCanvasHandle) {
108 SkCanvas* srcCanvas = reinterpret_cast<SkCanvas*>(srcCanvasHandle);
109 SkCanvas* dstCanvas = reinterpret_cast<SkCanvas*>(dstCanvasHandle);
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500110 if (srcCanvas && dstCanvas) {
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500111 dstCanvas->setMatrix(srcCanvas->getTotalMatrix());
Derek Sollenberger5b6591c2013-02-28 11:18:50 -0500112 if (NULL != srcCanvas->getDevice() && NULL != dstCanvas->getDevice()) {
113 ClipCopier copier(dstCanvas);
114 srcCanvas->replayClips(&copier);
115 }
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500116 }
117 }
118
Derek Sollenberger5b6591c2013-02-28 11:18:50 -0500119
Mike Reedcaf0df12009-04-27 14:32:05 -0400120 static void freeCaches(JNIEnv* env, jobject) {
121 // these are called in no particular order
Mike Reedcaf0df12009-04-27 14:32:05 -0400122 SkImageRef_GlobalPool::SetRAMUsed(0);
Derek Sollenberger889a3fa2012-01-31 14:08:22 -0500123 SkGraphics::PurgeFontCache();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800124 }
Fabrice Di Meglio30ca5cd2012-05-07 17:45:44 -0700125
126 static void freeTextLayoutCaches(JNIEnv* env, jobject) {
127 TextLayoutEngine::getInstance().purgeCaches();
128 }
129
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
131 NPE_CHECK_RETURN_ZERO(env, jcanvas);
132 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000133 bool result = canvas->getDevice()->accessBitmap(false).isOpaque();
134 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 }
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000136
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000137 static jint getWidth(JNIEnv* env, jobject jcanvas) {
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000138 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000139 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
140 int width = canvas->getDevice()->accessBitmap(false).width();
141 return static_cast<jint>(width);
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000142 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000143
144 static jint getHeight(JNIEnv* env, jobject jcanvas) {
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000145 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000146 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
147 int height = canvas->getDevice()->accessBitmap(false).height();
148 return static_cast<jint>(height);
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000149 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000150
151 static jint saveAll(JNIEnv* env, jobject jcanvas) {
152 NPE_CHECK_RETURN_ZERO(env, jcanvas);
153 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
154 return static_cast<jint>(result);
155 }
156
157 static jint save(JNIEnv* env, jobject jcanvas, jint flagsHandle) {
158 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
159 NPE_CHECK_RETURN_ZERO(env, jcanvas);
160 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
161 return static_cast<jint>(result);
162 }
163
164 static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds,
165 jlong paintHandle, jint flags) {
166 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
167 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 SkRect* bounds_ = NULL;
169 SkRect storage;
170 if (bounds != NULL) {
171 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
172 bounds_ = &storage;
173 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000174 return canvas->saveLayer(bounds_, paint, static_cast<SkCanvas::SaveFlags>(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000176
177 static jint saveLayer4F(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 jfloat l, jfloat t, jfloat r, jfloat b,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000179 jlong paintHandle, jint flags) {
180 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
181 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800182 SkRect bounds;
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400183 bounds.set(l, t, r, b);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000184 int result = canvas->saveLayer(&bounds, paint,
185 static_cast<SkCanvas::SaveFlags>(flags));
186 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800187 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000188
189 static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle,
190 jobject bounds, jint alpha, jint flags) {
191 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 SkRect* bounds_ = NULL;
193 SkRect storage;
194 if (bounds != NULL) {
195 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
196 bounds_ = &storage;
197 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000198 int result = canvas->saveLayerAlpha(bounds_, alpha,
199 static_cast<SkCanvas::SaveFlags>(flags));
200 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800201 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000202
203 static jint saveLayerAlpha4F(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 jfloat l, jfloat t, jfloat r, jfloat b,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000205 jint alpha, jint flags) {
206 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800207 SkRect bounds;
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400208 bounds.set(l, t, r, b);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000209 int result = canvas->saveLayerAlpha(&bounds, alpha,
210 static_cast<SkCanvas::SaveFlags>(flags));
211 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800212 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000213
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 static void restore(JNIEnv* env, jobject jcanvas) {
215 NPE_CHECK_RETURN_VOID(env, jcanvas);
216 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
217 if (canvas->getSaveCount() <= 1) { // cannot restore anymore
218 doThrowISE(env, "Underflow in restore");
219 return;
220 }
221 canvas->restore();
222 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000223
224 static jint getSaveCount(JNIEnv* env, jobject jcanvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000226 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
227 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000229
230 static void restoreToCount(JNIEnv* env, jobject jcanvas, jint restoreCount) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 NPE_CHECK_RETURN_VOID(env, jcanvas);
232 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
233 if (restoreCount < 1) {
234 doThrowIAE(env, "Underflow in restoreToCount");
235 return;
236 }
237 canvas->restoreToCount(restoreCount);
238 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
241 NPE_CHECK_RETURN_VOID(env, jcanvas);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400242 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx, dy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800243 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000244
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800245 static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
246 NPE_CHECK_RETURN_VOID(env, jcanvas);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400247 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx, sy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800248 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000249
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800250 static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
251 NPE_CHECK_RETURN_VOID(env, jcanvas);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400252 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800253 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000254
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800255 static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
256 NPE_CHECK_RETURN_VOID(env, jcanvas);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400257 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx, sy);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800258 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000259
260 static void concat(JNIEnv* env, jobject, jlong canvasHandle,
261 jlong matrixHandle) {
262 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
263 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800264 canvas->concat(*matrix);
265 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000266
267 static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle,
268 jlong matrixHandle) {
269 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
270 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 if (NULL == matrix) {
272 canvas->resetMatrix();
273 } else {
274 canvas->setMatrix(*matrix);
275 }
276 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800278 static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
279 jfloat top, jfloat right, jfloat bottom) {
280 NPE_CHECK_RETURN_ZERO(env, jcanvas);
281 SkRect r;
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400282 r.set(left, top, right, bottom);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800283 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
Leon Scrogginscc11f152014-03-31 16:52:13 -0400284 c->clipRect(r);
285 return hasNonEmptyClip(*c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800286 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000287
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800288 static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
289 jint top, jint right, jint bottom) {
290 NPE_CHECK_RETURN_ZERO(env, jcanvas);
291 SkRect r;
292 r.set(SkIntToScalar(left), SkIntToScalar(top),
293 SkIntToScalar(right), SkIntToScalar(bottom));
Leon Scrogginscc11f152014-03-31 16:52:13 -0400294 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
295 c->clipRect(r);
296 return hasNonEmptyClip(*c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800297 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000298
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
300 NPE_CHECK_RETURN_ZERO(env, jcanvas);
301 NPE_CHECK_RETURN_ZERO(env, rectf);
302 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
303 SkRect tmp;
Leon Scrogginscc11f152014-03-31 16:52:13 -0400304 c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
305 return hasNonEmptyClip(*c);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800306 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800308 static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
309 NPE_CHECK_RETURN_ZERO(env, jcanvas);
310 NPE_CHECK_RETURN_ZERO(env, rect);
311 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
312 SkRect tmp;
Leon Scrogginscc11f152014-03-31 16:52:13 -0400313 c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
314 return hasNonEmptyClip(*c);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000315
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000317
318 static jboolean clipRect(JNIEnv* env, jobject, jlong canvasHandle,
319 jfloat left, jfloat top, jfloat right, jfloat bottom,
320 jint op) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 SkRect rect;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000322 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400323 rect.set(left, top, right, bottom);
Leon Scrogginscc11f152014-03-31 16:52:13 -0400324 canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
325 return hasNonEmptyClip(*canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000327
328 static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
Narayan Kamath017546e2014-02-06 11:50:31 +0000329 jlong pathHandle, jint op) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000330 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
Leon Scrogginscc11f152014-03-31 16:52:13 -0400331 canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
332 static_cast<SkRegion::Op>(op));
333 return hasNonEmptyClip(*canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800334 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000335
336 static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
337 jlong deviceRgnHandle, jint op) {
338 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
339 SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
Leon Scrogginscc11f152014-03-31 16:52:13 -0400340 canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
341 return hasNonEmptyClip(*canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800342 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000343
344 static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
Narayan Kamath017546e2014-02-06 11:50:31 +0000345 jlong filterHandle) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000346 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
Narayan Kamath017546e2014-02-06 11:50:31 +0000347 canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800348 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000349
350 static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400351 jobject rect) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000352 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 SkRect rect_;
354 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
Leon Scrogginscc11f152014-03-31 16:52:13 -0400355 bool result = canvas->quickReject(rect_);
356 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800357 }
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400358
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000359 static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
Narayan Kamath017546e2014-02-06 11:50:31 +0000360 jlong pathHandle) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000361 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
Narayan Kamath017546e2014-02-06 11:50:31 +0000362 bool result = canvas->quickReject(*reinterpret_cast<SkPath*>(pathHandle));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000363 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800364 }
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400365
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000366 static jboolean quickReject__FFFF(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800367 jfloat left, jfloat top, jfloat right,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400368 jfloat bottom) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000369 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800370 SkRect r;
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400371 r.set(left, top, right, bottom);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000372 bool result = canvas->quickReject(r);
373 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800374 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000375
376 static void drawRGB(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 jint r, jint g, jint b) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000378 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800379 canvas->drawARGB(0xFF, r, g, b);
380 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000381
382 static void drawARGB(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 jint a, jint r, jint g, jint b) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000384 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 canvas->drawARGB(a, r, g, b);
386 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000387
388 static void drawColor__I(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800389 jint color) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000390 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800391 canvas->drawColor(color);
392 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000393
394 static void drawColor__II(JNIEnv* env, jobject, jlong canvasHandle,
395 jint color, jint modeHandle) {
396 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
397 SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
Mike Reed47c0d4e2009-06-22 22:53:52 -0400398 canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000400
401 static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle,
402 jlong paintHandle) {
403 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
404 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 canvas->drawPaint(*paint);
406 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800408 static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
409 jint offset, jint count, jobject jpaint,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000410 jint modeHandle) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800411 NPE_CHECK_RETURN_VOID(env, jcanvas);
412 NPE_CHECK_RETURN_VOID(env, jptsArray);
413 NPE_CHECK_RETURN_VOID(env, jpaint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000414 SkCanvas::PointMode mode = static_cast<SkCanvas::PointMode>(modeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800415 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
416 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000417
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800418 AutoJavaFloatArray autoPts(env, jptsArray);
419 float* floats = autoPts.ptr();
420 const int length = autoPts.length();
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000421
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800422 if ((offset | count) < 0 || offset + count > length) {
423 doThrowAIOOBE(env);
424 return;
425 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000426
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800427 // now convert the floats into SkPoints
428 count >>= 1; // now it is the number of points
429 SkAutoSTMalloc<32, SkPoint> storage(count);
430 SkPoint* pts = storage.get();
431 const float* src = floats + offset;
432 for (int i = 0; i < count; i++) {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400433 pts[i].set(src[0], src[1]);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 src += 2;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800436 canvas->drawPoints(mode, count, pts, paint);
437 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
440 jint offset, jint count, jobject jpaint) {
441 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
442 SkCanvas::kPoints_PointMode);
443 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000444
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800445 static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
446 jint offset, jint count, jobject jpaint) {
447 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
448 SkCanvas::kLines_PointMode);
449 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000450
451 static void drawPoint(JNIEnv* env, jobject jcanvas, jfloat x, jfloat y,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 jobject jpaint) {
453 NPE_CHECK_RETURN_VOID(env, jcanvas);
454 NPE_CHECK_RETURN_VOID(env, jpaint);
455 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
456 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000457
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400458 canvas->drawPoint(x, y, paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000460
461 static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800462 jfloat startX, jfloat startY, jfloat stopX,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000463 jfloat stopY, jlong paintHandle) {
464 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
465 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400466 canvas->drawLine(startX, startY, stopX, stopY, *paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000468
469 static void drawRect__RectFPaint(JNIEnv* env, jobject, jlong canvasHandle,
470 jobject rect, jlong paintHandle) {
471 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
472 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800473 SkRect rect_;
474 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
475 canvas->drawRect(rect_, *paint);
476 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000477
478 static void drawRect__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 jfloat left, jfloat top, jfloat right,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000480 jfloat bottom, jlong paintHandle) {
481 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
482 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400483 canvas->drawRectCoords(left, top, right, bottom, *paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000485
486 static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
487 jlong paintHandle) {
488 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
489 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800490 SkRect oval;
491 GraphicsJNI::jrectf_to_rect(env, joval, &oval);
492 canvas->drawOval(oval, *paint);
493 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000494
495 static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx,
496 jfloat cy, jfloat radius, jlong paintHandle) {
497 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
498 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400499 canvas->drawCircle(cx, cy, radius, *paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800500 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000501
502 static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800503 jfloat startAngle, jfloat sweepAngle,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000504 jboolean useCenter, jlong paintHandle) {
505 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
506 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800507 SkRect oval;
508 GraphicsJNI::jrectf_to_rect(env, joval, &oval);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400509 canvas->drawArc(oval, startAngle, sweepAngle, useCenter, *paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800510 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000511
512 static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
Chris Craik4d1c1532014-04-24 14:13:40 -0700513 jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat rx, jfloat ry,
514 jlong paintHandle) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000515 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
516 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Chris Craik4d1c1532014-04-24 14:13:40 -0700517 SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400518 canvas->drawRoundRect(rect, rx, ry, *paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000520
521 static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
522 jlong paintHandle) {
523 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
524 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
525 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 canvas->drawPath(*path, *paint);
527 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000528
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800529 static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000530 jlong canvasHandle, jlong bitmapHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800531 jfloat left, jfloat top,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000532 jlong paintHandle, jint canvasDensity,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700533 jint screenDensity, jint bitmapDensity) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000534 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
535 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
536 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700538 if (canvasDensity == bitmapDensity || canvasDensity == 0
539 || bitmapDensity == 0) {
Dianne Hackborn0d221012009-07-29 15:41:19 -0700540 if (screenDensity != 0 && screenDensity != bitmapDensity) {
541 SkPaint filteredPaint;
542 if (paint) {
543 filteredPaint = *paint;
544 }
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500545 filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400546 canvas->drawBitmap(*bitmap, left, top, &filteredPaint);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700547 } else {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400548 canvas->drawBitmap(*bitmap, left, top, paint);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700549 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800550 } else {
551 canvas->save();
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400552 SkScalar scale = canvasDensity / (float)bitmapDensity;
553 canvas->translate(left, top);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800554 canvas->scale(scale, scale);
555
556 SkPaint filteredPaint;
557 if (paint) {
558 filteredPaint = *paint;
559 }
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500560 filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800561
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700562 canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563
564 canvas->restore();
565 }
566 }
567
568 static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700569 jobject srcIRect, const SkRect& dst, SkPaint* paint,
570 jint screenDensity, jint bitmapDensity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 SkIRect src, *srcPtr = NULL;
572
573 if (NULL != srcIRect) {
574 GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
575 srcPtr = &src;
576 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000577
Dianne Hackborn0d221012009-07-29 15:41:19 -0700578 if (screenDensity != 0 && screenDensity != bitmapDensity) {
579 SkPaint filteredPaint;
580 if (paint) {
581 filteredPaint = *paint;
582 }
Derek Sollenbergerb644a3b2014-01-17 15:45:10 -0500583 filteredPaint.setFilterLevel(SkPaint::kLow_FilterLevel);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700584 canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
585 } else {
586 canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
587 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800588 }
589
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000590 static void drawBitmapRF(JNIEnv* env, jobject, jlong canvasHandle,
591 jlong bitmapHandle, jobject srcIRect,
592 jobject dstRectF, jlong paintHandle,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700593 jint screenDensity, jint bitmapDensity) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000594 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
595 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
596 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800597 SkRect dst;
598 GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700599 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
600 screenDensity, bitmapDensity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000602
603 static void drawBitmapRR(JNIEnv* env, jobject, jlong canvasHandle,
604 jlong bitmapHandle, jobject srcIRect,
605 jobject dstRect, jlong paintHandle,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700606 jint screenDensity, jint bitmapDensity) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000607 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
608 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
609 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800610 SkRect dst;
611 GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700612 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
613 screenDensity, bitmapDensity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000615
616 static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
617 jintArray jcolors, jint offset, jint stride,
618 jfloat x, jfloat y, jint width, jint height,
619 jboolean hasAlpha, jlong paintHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000621 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
622 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 SkBitmap bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
625 SkBitmap::kRGB_565_Config, width, height);
626 if (!bitmap.allocPixels()) {
627 return;
628 }
Chris Craik1abf5d62013-08-16 12:47:03 -0700629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
Chris Craik1abf5d62013-08-16 12:47:03 -0700631 0, 0, width, height, bitmap, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800632 return;
633 }
Chris Craik1abf5d62013-08-16 12:47:03 -0700634
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400635 canvas->drawBitmap(bitmap, x, y, paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000637
638 static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle,
639 jlong bitmapHandle, jlong matrixHandle,
640 jlong paintHandle) {
641 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
642 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
643 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
644 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
646 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000647
648 static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle,
649 jlong bitmapHandle, jint meshWidth, jint meshHeight,
650 jfloatArray jverts, jint vertIndex, jintArray jcolors,
651 jint colorIndex, jlong paintHandle) {
652 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
653 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
654 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800655
656 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
657 const int indexCount = meshWidth * meshHeight * 6;
658
659 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
660 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000661
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 /* Our temp storage holds 2 or 3 arrays.
663 texture points [ptCount * sizeof(SkPoint)]
664 optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
665 copy to convert from float to fixed
666 indices [ptCount * sizeof(uint16_t)]
667 */
668 ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 storageSize += indexCount * sizeof(uint16_t); // indices[]
670
671 SkAutoMalloc storage(storageSize);
672 SkPoint* texs = (SkPoint*)storage.get();
673 SkPoint* verts;
674 uint16_t* indices;
675#ifdef SK_SCALAR_IS_FLOAT
676 verts = (SkPoint*)(vertA.ptr() + vertIndex);
677 indices = (uint16_t*)(texs + ptCount);
678#else
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500679 SkASSERT(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800680#endif
681
682 // cons up texture coordinates and indices
683 {
684 const SkScalar w = SkIntToScalar(bitmap->width());
685 const SkScalar h = SkIntToScalar(bitmap->height());
686 const SkScalar dx = w / meshWidth;
687 const SkScalar dy = h / meshHeight;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800689 SkPoint* texsPtr = texs;
690 SkScalar y = 0;
691 for (int i = 0; i <= meshHeight; i++) {
692 if (i == meshHeight) {
693 y = h; // to ensure numerically we hit h exactly
694 }
695 SkScalar x = 0;
696 for (int j = 0; j < meshWidth; j++) {
697 texsPtr->set(x, y);
698 texsPtr += 1;
699 x += dx;
700 }
701 texsPtr->set(w, y);
702 texsPtr += 1;
703 y += dy;
704 }
705 SkASSERT(texsPtr - texs == ptCount);
706 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 // cons up indices
709 {
710 uint16_t* indexPtr = indices;
711 int index = 0;
712 for (int i = 0; i < meshHeight; i++) {
713 for (int j = 0; j < meshWidth; j++) {
714 // lower-left triangle
715 *indexPtr++ = index;
716 *indexPtr++ = index + meshWidth + 1;
717 *indexPtr++ = index + meshWidth + 2;
718 // upper-right triangle
719 *indexPtr++ = index;
720 *indexPtr++ = index + meshWidth + 2;
721 *indexPtr++ = index + 1;
722 // bump to the next cell
723 index += 1;
724 }
725 // bump to the next row
726 index += 1;
727 }
728 SkASSERT(indexPtr - indices == indexCount);
729 SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
730 }
731
732 // double-check that we have legal indices
733#ifdef SK_DEBUG
734 {
735 for (int i = 0; i < indexCount; i++) {
736 SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
737 }
738 }
739#endif
740
741 // cons-up a shader for the bitmap
742 SkPaint tmpPaint;
743 if (paint) {
744 tmpPaint = *paint;
745 }
746 SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
747 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
Derek Sollenberger6062c592011-02-22 13:55:04 -0500748 SkSafeUnref(tmpPaint.setShader(shader));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800749
750 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
751 texs, (const SkColor*)colorA.ptr(), NULL, indices,
752 indexCount, tmpPaint);
753 }
754
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000755 static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
756 jint modeHandle, jint vertexCount,
757 jfloatArray jverts, jint vertIndex,
758 jfloatArray jtexs, jint texIndex,
759 jintArray jcolors, jint colorIndex,
760 jshortArray jindices, jint indexIndex,
761 jint indexCount, jlong paintHandle) {
762 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
763 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
764 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800765
766 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
767 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
768 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
769 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
770
771 const int ptCount = vertexCount >> 1;
772
773 SkPoint* verts;
774 SkPoint* texs = NULL;
775#ifdef SK_SCALAR_IS_FLOAT
776 verts = (SkPoint*)(vertA.ptr() + vertIndex);
777 if (jtexs != NULL) {
778 texs = (SkPoint*)(texA.ptr() + texIndex);
779 }
780#else
Leon Scroggins46cb9bd2014-03-06 15:36:39 -0500781 SkASSERT(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800782#endif
783
784 const SkColor* colors = NULL;
785 const uint16_t* indices = NULL;
786 if (jcolors != NULL) {
787 colors = (const SkColor*)(colorA.ptr() + colorIndex);
788 }
789 if (jindices != NULL) {
790 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
791 }
792
793 canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
794 indices, indexCount, *paint);
795 }
Doug Feltf47d7402010-04-21 16:01:52 -0700796
Doug Felt0c702b82010-05-14 10:55:42 -0700797
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000798 static void drawText___CIIFFIPaintTypeface(JNIEnv* env, jobject, jlong canvasHandle,
799 jcharArray text, jint index, jint count,
800 jfloat x, jfloat y, jint flags,
801 jlong paintHandle, jlong typefaceHandle) {
802 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
803 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
804 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700805 jchar* textArray = env->GetCharArrayElements(text, NULL);
Raph Leviena0336302013-05-22 16:16:59 -0700806 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -0700807 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800808 }
Doug Felt0c702b82010-05-14 10:55:42 -0700809
Raph Leviena0336302013-05-22 16:16:59 -0700810 static void drawText__StringIIFFIPaintTypeface(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000811 jlong canvasHandle, jstring text,
812 jint start, jint end,
813 jfloat x, jfloat y, jint flags,
814 jlong paintHandle, jlong typefaceHandle) {
815 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
816 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
817 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700818 const jchar* textArray = env->GetStringChars(text, NULL);
Raph Leviena0336302013-05-22 16:16:59 -0700819 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -0700820 env->ReleaseStringChars(text, textArray);
821 }
Doug Felt0c702b82010-05-14 10:55:42 -0700822
Raph Leviena0336302013-05-22 16:16:59 -0700823#ifdef USE_MINIKIN
Raph Levien1a73f7322014-01-30 16:06:28 -0800824 static void drawGlyphsToSkia(SkCanvas* canvas, SkPaint* paint, Layout* layout, float x, float y) {
Raph Leviena0336302013-05-22 16:16:59 -0700825 size_t nGlyphs = layout->nGlyphs();
826 uint16_t *glyphs = new uint16_t[nGlyphs];
827 SkPoint *pos = new SkPoint[nGlyphs];
828 SkTypeface *lastFace = NULL;
829 SkTypeface *skFace = NULL;
830 size_t start = 0;
831
832 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
833 for (size_t i = 0; i < nGlyphs; i++) {
834 MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
835 skFace = mfs->GetSkTypeface();
836 glyphs[i] = layout->getGlyphId(i);
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400837 pos[i].fX = x + layout->getX(i);
838 pos[i].fY = y + layout->getY(i);
Raph Leviena0336302013-05-22 16:16:59 -0700839 if (i > 0 && skFace != lastFace) {
840 paint->setTypeface(lastFace);
841 canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
842 start = i;
843 }
844 lastFace = skFace;
845 }
846 if (skFace != NULL) {
847 paint->setTypeface(skFace);
848 canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
849 }
850 delete[] glyphs;
851 delete[] pos;
852 }
853#endif
854
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700855 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
856 int start, int end,
Raph Leviena0336302013-05-22 16:16:59 -0700857 jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700858
859 jint count = end - start;
Raph Leviena0336302013-05-22 16:16:59 -0700860 drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint, typeface);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700861 }
862
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700863 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
864 int start, int count, int contextCount,
Raph Leviena0336302013-05-22 16:16:59 -0700865 jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700866
Raph Leviena0336302013-05-22 16:16:59 -0700867#ifdef USE_MINIKIN
868 Layout layout;
Raph Levien1a73f7322014-01-30 16:06:28 -0800869 MinikinUtils::SetLayoutProperties(&layout, paint, typeface);
Raph Leviena0336302013-05-22 16:16:59 -0700870 layout.doLayout(textArray + start, count);
871 drawGlyphsToSkia(canvas, paint, &layout, x, y);
872#else
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800873 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700874 textArray, start, count, contextCount, flags);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700875 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800876 return;
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700877 }
Raph Levien2301d322012-07-17 16:39:49 -0700878 SkPaint::Align align = paint->getTextAlign();
879 if (align == SkPaint::kCenter_Align) {
880 x -= 0.5 * value->getTotalAdvance();
881 } else if (align == SkPaint::kRight_Align) {
882 x -= value->getTotalAdvance();
883 }
884 paint->setTextAlign(SkPaint::kLeft_Align);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700885 doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
Raph Levien2301d322012-07-17 16:39:49 -0700886 doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
887 paint->setTextAlign(align);
Raph Leviena0336302013-05-22 16:16:59 -0700888#endif
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700889 }
890
Raph Levien2301d322012-07-17 16:39:49 -0700891// Same values used by Skia
892#define kStdStrikeThru_Offset (-6.0f / 21.0f)
893#define kStdUnderline_Offset (1.0f / 9.0f)
894#define kStdUnderline_Thickness (1.0f / 18.0f)
895
896static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length, SkPaint* paint) {
Raph Leviene174ae22012-10-03 15:26:47 -0700897 uint32_t flags;
898 SkDrawFilter* drawFilter = canvas->getDrawFilter();
899 if (drawFilter) {
900 SkPaint paintCopy(*paint);
901 drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
902 flags = paintCopy.getFlags();
903 } else {
904 flags = paint->getFlags();
905 }
Raph Levien2301d322012-07-17 16:39:49 -0700906 if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400907 SkScalar left = x;
908 SkScalar right = x + length;
Raph Levien2301d322012-07-17 16:39:49 -0700909 float textSize = paint->getTextSize();
910 float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
911 if (flags & SkPaint::kUnderlineText_Flag) {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400912 SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
913 SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
Raph Levien2301d322012-07-17 16:39:49 -0700914 canvas->drawRectCoords(left, top, right, bottom, *paint);
915 }
916 if (flags & SkPaint::kStrikeThruText_Flag) {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400917 SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
918 SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
Raph Levien2301d322012-07-17 16:39:49 -0700919 canvas->drawRectCoords(left, top, right, bottom, *paint);
920 }
921 }
922}
923
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700924 static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
925 jfloat x, jfloat y, int flags, SkPaint* paint) {
926 // Beware: this needs Glyph encoding (already done on the Paint constructor)
927 canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
928 }
929
Raph Levien2301d322012-07-17 16:39:49 -0700930 static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700931 int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
Raph Levien2301d322012-07-17 16:39:49 -0700932 SkPoint* posPtr = new SkPoint[count];
933 for (int indx = 0; indx < count; indx++) {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400934 posPtr[indx].fX = x + posArray[indx * 2];
935 posPtr[indx].fY = y + posArray[indx * 2 + 1];
Raph Levien2301d322012-07-17 16:39:49 -0700936 }
937 canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
938 delete[] posPtr;
939 }
940
Raph Leviena0336302013-05-22 16:16:59 -0700941 static void drawTextRun___CIIIIFFIPaintTypeface(
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000942 JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
943 jint count, jint contextIndex, jint contextCount,
944 jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
945 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
946 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
947 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700948
Doug Feltf47d7402010-04-21 16:01:52 -0700949 jchar* chars = env->GetCharArrayElements(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700950 drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
Raph Leviena0336302013-05-22 16:16:59 -0700951 count, contextCount, x, y, dirFlags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -0700952 env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
953 }
954
Raph Leviena0336302013-05-22 16:16:59 -0700955 static void drawTextRun__StringIIIIFFIPaintTypeface(
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000956 JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
Doug Felt0c702b82010-05-14 10:55:42 -0700957 jint end, jint contextStart, jint contextEnd,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000958 jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
959 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
960 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
961 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700962
Doug Felt0c702b82010-05-14 10:55:42 -0700963 jint count = end - start;
964 jint contextCount = contextEnd - contextStart;
Doug Feltf47d7402010-04-21 16:01:52 -0700965 const jchar* chars = env->GetStringChars(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700966 drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
Raph Leviena0336302013-05-22 16:16:59 -0700967 count, contextCount, x, y, dirFlags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -0700968 env->ReleaseStringChars(text, chars);
969 }
970
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000971 static void drawPosText___CII_FPaint(JNIEnv* env, jobject, jlong canvasHandle,
972 jcharArray text, jint index, jint count,
973 jfloatArray pos, jlong paintHandle) {
974 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
975 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800976 jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
977 jsize textCount = text ? env->GetArrayLength(text) : NULL;
978 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
979 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
980 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
981 int indx;
982 for (indx = 0; indx < posCount; indx++) {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -0400983 posPtr[indx].fX = posArray[indx << 1];
984 posPtr[indx].fY = posArray[(indx << 1) + 1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800985 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000986
Romain Guy62b6eaa2012-01-17 14:52:13 -0800987 SkPaint::TextEncoding encoding = paint->getTextEncoding();
988 paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
Mike Reedad8b8f52009-05-01 08:24:01 -0400989 canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
Romain Guy62b6eaa2012-01-17 14:52:13 -0800990 paint->setTextEncoding(encoding);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800992 if (text) {
993 env->ReleaseCharArrayElements(text, textArray, 0);
994 }
995 if (pos) {
996 env->ReleaseFloatArrayElements(pos, posArray, 0);
997 }
998 delete[] posPtr;
999 }
Doug Felt0c702b82010-05-14 10:55:42 -07001000
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001001 static void drawPosText__String_FPaint(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001002 jlong canvasHandle, jstring text,
Doug Felt4beb8ff72010-06-09 13:53:24 -07001003 jfloatArray pos,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001004 jlong paintHandle) {
1005 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1006 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001007 const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
1008 int byteLength = text ? env->GetStringLength(text) : 0;
1009 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
1010 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
1011 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
1012
1013 for (int indx = 0; indx < posCount; indx++) {
Leon Scroggins III2e0103e2014-04-04 17:05:24 -04001014 posPtr[indx].fX = posArray[indx << 1];
1015 posPtr[indx].fY = posArray[(indx << 1) + 1];
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 }
Romain Guy62b6eaa2012-01-17 14:52:13 -08001017
1018 SkPaint::TextEncoding encoding = paint->getTextEncoding();
1019 paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
Romain Guy62b6eaa2012-01-17 14:52:13 -08001021 paint->setTextEncoding(encoding);
1022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001023 if (text) {
1024 env->ReleaseStringChars(text, (const jchar*) text_);
1025 }
1026 if (pos) {
1027 env->ReleaseFloatArrayElements(pos, posArray, 0);
1028 }
1029 delete[] posPtr;
1030 }
Doug Felt0c702b82010-05-14 10:55:42 -07001031
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001033 jlong canvasHandle, jcharArray text, jint index, jint count,
1034 jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
1035 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1036 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1037 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038
1039 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001040 TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
1041 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001042 env->ReleaseCharArrayElements(text, textArray, 0);
1043 }
Doug Felt0c702b82010-05-14 10:55:42 -07001044
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001045 static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001046 jlong canvasHandle, jstring text, jlong pathHandle,
1047 jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
1048 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1049 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1050 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 const jchar* text_ = env->GetStringChars(text, NULL);
Doug Felt4beb8ff72010-06-09 13:53:24 -07001052 int count = env->GetStringLength(text);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001053 TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
1054 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001055 env->ReleaseStringChars(text, text_);
1056 }
Doug Felt0c702b82010-05-14 10:55:42 -07001057
Derek Sollenberger00a33a82013-05-16 09:31:27 -04001058
1059 // This function is a mirror of SkCanvas::getClipBounds except that it does
1060 // not outset the edge of the clip to account for anti-aliasing. There is
1061 // a skia bug to investigate pushing this logic into back into skia.
1062 // (see https://code.google.com/p/skia/issues/detail?id=1303)
1063 static bool getHardClipBounds(SkCanvas* canvas, SkRect* bounds) {
1064 SkIRect ibounds;
1065 if (!canvas->getClipDeviceBounds(&ibounds)) {
1066 return false;
1067 }
1068
1069 SkMatrix inverse;
1070 // if we can't invert the CTM, we can't return local clip bounds
1071 if (!canvas->getTotalMatrix().invert(&inverse)) {
1072 if (bounds) {
1073 bounds->setEmpty();
1074 }
1075 return false;
1076 }
1077
1078 if (NULL != bounds) {
1079 SkRect r = SkRect::Make(ibounds);
1080 inverse.mapRect(bounds, r);
1081 }
1082 return true;
1083 }
1084
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001085 static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle,
1086 jobject bounds) {
1087 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 SkRect r;
1089 SkIRect ir;
Derek Sollenberger00a33a82013-05-16 09:31:27 -04001090 bool result = getHardClipBounds(canvas, &r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091
Chet Haase6a2d17f2012-09-30 12:14:13 -07001092 if (!result) {
1093 r.setEmpty();
1094 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 r.round(&ir);
Derek Sollenbergerca79cf62012-08-14 16:44:52 -04001096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001097 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001098 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001099 }
1100
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001101 static void getCTM(JNIEnv* env, jobject, jlong canvasHandle,
1102 jlong matrixHandle) {
1103 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1104 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001105 *matrix = canvas->getTotalMatrix();
1106 }
1107};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001108
1109static JNINativeMethod gCanvasMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001110 {"finalizer", "(J)V", (void*) SkCanvasGlue::finalizer},
1111 {"initRaster","(J)J", (void*) SkCanvasGlue::initRaster},
1112 {"copyNativeCanvasState","(JJ)V", (void*) SkCanvasGlue::copyCanvasState},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001113 {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
1114 {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
1115 {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001116 {"save","()I", (void*) SkCanvasGlue::saveAll},
1117 {"save","(I)I", (void*) SkCanvasGlue::save},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001118 {"native_saveLayer","(JLandroid/graphics/RectF;JI)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001119 (void*) SkCanvasGlue::saveLayer},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001120 {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer4F},
1121 {"native_saveLayerAlpha","(JLandroid/graphics/RectF;II)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001122 (void*) SkCanvasGlue::saveLayerAlpha},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001123 {"native_saveLayerAlpha","(JFFFFII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001124 (void*) SkCanvasGlue::saveLayerAlpha4F},
1125 {"restore","()V", (void*) SkCanvasGlue::restore},
1126 {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
1127 {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
1128 {"translate","(FF)V", (void*) SkCanvasGlue::translate},
1129 {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
1130 {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
1131 {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001132 {"native_concat","(JJ)V", (void*) SkCanvasGlue::concat},
1133 {"native_setMatrix","(JJ)V", (void*) SkCanvasGlue::setMatrix},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001134 {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
1135 {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
1136 {"clipRect","(Landroid/graphics/RectF;)Z",
1137 (void*) SkCanvasGlue::clipRect_RectF},
1138 {"clipRect","(Landroid/graphics/Rect;)Z",
1139 (void*) SkCanvasGlue::clipRect_Rect},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001140 {"native_clipRect","(JFFFFI)Z", (void*) SkCanvasGlue::clipRect},
1141 {"native_clipPath","(JJI)Z", (void*) SkCanvasGlue::clipPath},
1142 {"native_clipRegion","(JJI)Z", (void*) SkCanvasGlue::clipRegion},
1143 {"nativeSetDrawFilter", "(JJ)V", (void*) SkCanvasGlue::setDrawFilter},
1144 {"native_getClipBounds","(JLandroid/graphics/Rect;)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 (void*) SkCanvasGlue::getClipBounds},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001146 {"native_getCTM", "(JJ)V", (void*)SkCanvasGlue::getCTM},
1147 {"native_quickReject","(JLandroid/graphics/RectF;)Z",
Derek Sollenbergerca79cf62012-08-14 16:44:52 -04001148 (void*) SkCanvasGlue::quickReject__RectF},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001149 {"native_quickReject","(JJ)Z", (void*) SkCanvasGlue::quickReject__Path},
1150 {"native_quickReject","(JFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
1151 {"native_drawRGB","(JIII)V", (void*) SkCanvasGlue::drawRGB},
1152 {"native_drawARGB","(JIIII)V", (void*) SkCanvasGlue::drawARGB},
1153 {"native_drawColor","(JI)V", (void*) SkCanvasGlue::drawColor__I},
1154 {"native_drawColor","(JII)V", (void*) SkCanvasGlue::drawColor__II},
1155 {"native_drawPaint","(JJ)V", (void*) SkCanvasGlue::drawPaint},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001156 {"drawPoint", "(FFLandroid/graphics/Paint;)V",
1157 (void*) SkCanvasGlue::drawPoint},
1158 {"drawPoints", "([FIILandroid/graphics/Paint;)V",
1159 (void*) SkCanvasGlue::drawPoints},
1160 {"drawLines", "([FIILandroid/graphics/Paint;)V",
1161 (void*) SkCanvasGlue::drawLines},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001162 {"native_drawLine","(JFFFFJ)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
1163 {"native_drawRect","(JLandroid/graphics/RectF;J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164 (void*) SkCanvasGlue::drawRect__RectFPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001165 {"native_drawRect","(JFFFFJ)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
1166 {"native_drawOval","(JLandroid/graphics/RectF;J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001167 (void*) SkCanvasGlue::drawOval},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001168 {"native_drawCircle","(JFFFJ)V", (void*) SkCanvasGlue::drawCircle},
1169 {"native_drawArc","(JLandroid/graphics/RectF;FFZJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001170 (void*) SkCanvasGlue::drawArc},
Chris Craik4d1c1532014-04-24 14:13:40 -07001171 {"native_drawRoundRect","(JFFFFFFJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 (void*) SkCanvasGlue::drawRoundRect},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001173 {"native_drawPath","(JJJ)V", (void*) SkCanvasGlue::drawPath},
1174 {"native_drawBitmap","(JJFFJIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001176 {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/RectF;JII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 (void*) SkCanvasGlue::drawBitmapRF},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001178 {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/Rect;JII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 (void*) SkCanvasGlue::drawBitmapRR},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001180 {"native_drawBitmap", "(J[IIIFFIIZJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 (void*)SkCanvasGlue::drawBitmapArray},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001182 {"nativeDrawBitmapMatrix", "(JJJJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001183 (void*)SkCanvasGlue::drawBitmapMatrix},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001184 {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001185 (void*)SkCanvasGlue::drawBitmapMesh},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001186 {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001187 (void*)SkCanvasGlue::drawVertices},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001188 {"native_drawText","(J[CIIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001189 (void*) SkCanvasGlue::drawText___CIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001190 {"native_drawText","(JLjava/lang/String;IIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001191 (void*) SkCanvasGlue::drawText__StringIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001192 {"native_drawTextRun","(J[CIIIIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001193 (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001194 {"native_drawTextRun","(JLjava/lang/String;IIIIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001195 (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001196 {"native_drawPosText","(J[CII[FJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 (void*) SkCanvasGlue::drawPosText___CII_FPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001198 {"native_drawPosText","(JLjava/lang/String;[FJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 (void*) SkCanvasGlue::drawPosText__String_FPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001200 {"native_drawTextOnPath","(J[CIIJFFIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001202 {"native_drawTextOnPath","(JLjava/lang/String;JFFIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001203 (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204
Fabrice Di Meglio30ca5cd2012-05-07 17:45:44 -07001205 {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
1206
1207 {"freeTextLayoutCaches", "()V", (void*) SkCanvasGlue::freeTextLayoutCaches}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208};
1209
Mike Reedc04851f2009-10-28 15:09:45 -04001210///////////////////////////////////////////////////////////////////////////////
1211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212#include <android_runtime/AndroidRuntime.h>
1213
1214#define REG(env, name, array) \
1215 result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
1216 SK_ARRAY_COUNT(array)); \
1217 if (result < 0) return result
1218
1219int register_android_graphics_Canvas(JNIEnv* env) {
1220 int result;
1221
1222 REG(env, "android/graphics/Canvas", gCanvasMethods);
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001224 return result;
1225}
1226
1227}