blob: e98d45b1eebaf00fe722b920d29050bbf8862542 [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"
33#endif
34
Doug Feltf7cb1f72010-07-01 16:20:43 -070035#include "TextLayout.h"
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -070036#include "TextLayoutCache.h"
Raph Leviena0336302013-05-22 16:16:59 -070037#include "TypefaceImpl.h"
Doug Feltf7cb1f72010-07-01 16:20:43 -070038
Doug Feltf47d7402010-04-21 16:01:52 -070039#include "unicode/ubidi.h"
Doug Felt0c702b82010-05-14 10:55:42 -070040#include "unicode/ushape.h"
41
Doug Felt0c702b82010-05-14 10:55:42 -070042#include <utils/Log.h>
Doug Feltf47d7402010-04-21 16:01:52 -070043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044static uint32_t get_thread_msec() {
45#if defined(HAVE_POSIX_CLOCKS)
46 struct timespec tm;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
Ashok Bhat36bef0b2014-01-20 20:08:01 +000049
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
51#else
52 struct timeval tv;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000053
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054 gettimeofday(&tv, NULL);
55 return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
56#endif
57}
58
59namespace android {
60
Derek Sollenberger5b6591c2013-02-28 11:18:50 -050061class ClipCopier : public SkCanvas::ClipVisitor {
62public:
63 ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
64
65 virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
66 m_dstCanvas->clipRect(rect, op, antialias);
67 }
68 virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
69 m_dstCanvas->clipPath(path, op, antialias);
70 }
71
72private:
73 SkCanvas* m_dstCanvas;
74};
75
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076class SkCanvasGlue {
77public:
78
Ashok Bhat36bef0b2014-01-20 20:08:01 +000079 static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
80 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080081 canvas->unref();
82 }
83
Ashok Bhat36bef0b2014-01-20 20:08:01 +000084 static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
85 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040086 if (bitmap) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +000087 return reinterpret_cast<jlong>(new SkCanvas(*bitmap));
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040088 } else {
89 // Create an empty bitmap device to prevent callers from crashing
90 // if they attempt to draw into this canvas.
91 SkBitmap emptyBitmap;
Ashok Bhat36bef0b2014-01-20 20:08:01 +000092 return reinterpret_cast<jlong>(new SkCanvas(emptyBitmap));
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040093 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080094 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +000095
Derek Sollenberger1b63e602013-02-21 13:05:09 -050096 static void copyCanvasState(JNIEnv* env, jobject clazz,
Ashok Bhat36bef0b2014-01-20 20:08:01 +000097 jlong srcCanvasHandle, jlong dstCanvasHandle) {
98 SkCanvas* srcCanvas = reinterpret_cast<SkCanvas*>(srcCanvasHandle);
99 SkCanvas* dstCanvas = reinterpret_cast<SkCanvas*>(dstCanvasHandle);
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500100 if (srcCanvas && dstCanvas) {
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500101 dstCanvas->setMatrix(srcCanvas->getTotalMatrix());
Derek Sollenberger5b6591c2013-02-28 11:18:50 -0500102 if (NULL != srcCanvas->getDevice() && NULL != dstCanvas->getDevice()) {
103 ClipCopier copier(dstCanvas);
104 srcCanvas->replayClips(&copier);
105 }
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500106 }
107 }
108
Derek Sollenberger5b6591c2013-02-28 11:18:50 -0500109
Mike Reedcaf0df12009-04-27 14:32:05 -0400110 static void freeCaches(JNIEnv* env, jobject) {
111 // these are called in no particular order
Mike Reedcaf0df12009-04-27 14:32:05 -0400112 SkImageRef_GlobalPool::SetRAMUsed(0);
Derek Sollenberger889a3fa2012-01-31 14:08:22 -0500113 SkGraphics::PurgeFontCache();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 }
Fabrice Di Meglio30ca5cd2012-05-07 17:45:44 -0700115
116 static void freeTextLayoutCaches(JNIEnv* env, jobject) {
117 TextLayoutEngine::getInstance().purgeCaches();
118 }
119
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800120 static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
121 NPE_CHECK_RETURN_ZERO(env, jcanvas);
122 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000123 bool result = canvas->getDevice()->accessBitmap(false).isOpaque();
124 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800125 }
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000126
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000127 static jint getWidth(JNIEnv* env, jobject jcanvas) {
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000128 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000129 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
130 int width = canvas->getDevice()->accessBitmap(false).width();
131 return static_cast<jint>(width);
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000132 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000133
134 static jint getHeight(JNIEnv* env, jobject jcanvas) {
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000135 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000136 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
137 int height = canvas->getDevice()->accessBitmap(false).height();
138 return static_cast<jint>(height);
Ashok Bhat18b4cbe2014-01-20 20:08:01 +0000139 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000140
141 static jint saveAll(JNIEnv* env, jobject jcanvas) {
142 NPE_CHECK_RETURN_ZERO(env, jcanvas);
143 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
144 return static_cast<jint>(result);
145 }
146
147 static jint save(JNIEnv* env, jobject jcanvas, jint flagsHandle) {
148 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
149 NPE_CHECK_RETURN_ZERO(env, jcanvas);
150 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
151 return static_cast<jint>(result);
152 }
153
154 static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds,
155 jlong paintHandle, jint flags) {
156 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
157 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800158 SkRect* bounds_ = NULL;
159 SkRect storage;
160 if (bounds != NULL) {
161 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
162 bounds_ = &storage;
163 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000164 return canvas->saveLayer(bounds_, paint, static_cast<SkCanvas::SaveFlags>(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800165 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000166
167 static jint saveLayer4F(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800168 jfloat l, jfloat t, jfloat r, jfloat b,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000169 jlong paintHandle, jint flags) {
170 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
171 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 SkRect bounds;
173 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
174 SkFloatToScalar(b));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000175 int result = canvas->saveLayer(&bounds, paint,
176 static_cast<SkCanvas::SaveFlags>(flags));
177 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800178 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000179
180 static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle,
181 jobject bounds, jint alpha, jint flags) {
182 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 SkRect* bounds_ = NULL;
184 SkRect storage;
185 if (bounds != NULL) {
186 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
187 bounds_ = &storage;
188 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000189 int result = canvas->saveLayerAlpha(bounds_, alpha,
190 static_cast<SkCanvas::SaveFlags>(flags));
191 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000193
194 static jint saveLayerAlpha4F(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 jfloat l, jfloat t, jfloat r, jfloat b,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000196 jint alpha, jint flags) {
197 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 SkRect bounds;
199 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
200 SkFloatToScalar(b));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000201 int result = canvas->saveLayerAlpha(&bounds, alpha,
202 static_cast<SkCanvas::SaveFlags>(flags));
203 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800204 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 static void restore(JNIEnv* env, jobject jcanvas) {
207 NPE_CHECK_RETURN_VOID(env, jcanvas);
208 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
209 if (canvas->getSaveCount() <= 1) { // cannot restore anymore
210 doThrowISE(env, "Underflow in restore");
211 return;
212 }
213 canvas->restore();
214 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000215
216 static jint getSaveCount(JNIEnv* env, jobject jcanvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000218 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
219 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000221
222 static void restoreToCount(JNIEnv* env, jobject jcanvas, jint restoreCount) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800223 NPE_CHECK_RETURN_VOID(env, jcanvas);
224 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
225 if (restoreCount < 1) {
226 doThrowIAE(env, "Underflow in restoreToCount");
227 return;
228 }
229 canvas->restoreToCount(restoreCount);
230 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000231
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
233 NPE_CHECK_RETURN_VOID(env, jcanvas);
234 SkScalar dx_ = SkFloatToScalar(dx);
235 SkScalar dy_ = SkFloatToScalar(dy);
236 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_);
237 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800239 static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
240 NPE_CHECK_RETURN_VOID(env, jcanvas);
241 SkScalar sx_ = SkFloatToScalar(sx);
242 SkScalar sy_ = SkFloatToScalar(sy);
243 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_);
244 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
247 NPE_CHECK_RETURN_VOID(env, jcanvas);
248 SkScalar degrees_ = SkFloatToScalar(degrees);
249 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_);
250 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800252 static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
253 NPE_CHECK_RETURN_VOID(env, jcanvas);
254 SkScalar sx_ = SkFloatToScalar(sx);
255 SkScalar sy_ = SkFloatToScalar(sy);
256 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_);
257 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000258
259 static void concat(JNIEnv* env, jobject, jlong canvasHandle,
260 jlong matrixHandle) {
261 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
262 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800263 canvas->concat(*matrix);
264 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000265
266 static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle,
267 jlong matrixHandle) {
268 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
269 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800270 if (NULL == matrix) {
271 canvas->resetMatrix();
272 } else {
273 canvas->setMatrix(*matrix);
274 }
275 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000276
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800277 static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
278 jfloat top, jfloat right, jfloat bottom) {
279 NPE_CHECK_RETURN_ZERO(env, jcanvas);
280 SkRect r;
281 r.set(SkFloatToScalar(left), SkFloatToScalar(top),
282 SkFloatToScalar(right), SkFloatToScalar(bottom));
283 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000284 bool result = c->clipRect(r);
285 return result ? JNI_TRUE : JNI_FALSE;
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));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000294 bool result = GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
295 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800296 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000297
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800298 static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
299 NPE_CHECK_RETURN_ZERO(env, jcanvas);
300 NPE_CHECK_RETURN_ZERO(env, rectf);
301 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
302 SkRect tmp;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000303 bool result = c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
304 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800305 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000306
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800307 static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
308 NPE_CHECK_RETURN_ZERO(env, jcanvas);
309 NPE_CHECK_RETURN_ZERO(env, rect);
310 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
311 SkRect tmp;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000312 bool result = c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
313 return result ? JNI_TRUE : JNI_FALSE;
314
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800315 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000316
317 static jboolean clipRect(JNIEnv* env, jobject, jlong canvasHandle,
318 jfloat left, jfloat top, jfloat right, jfloat bottom,
319 jint op) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800320 SkRect rect;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000321 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800322 rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
323 SkFloatToScalar(right), SkFloatToScalar(bottom));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000324 bool result = canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
325 return result ? JNI_TRUE : JNI_FALSE;
326
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800327 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000328
329 static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
Narayan Kamath017546e2014-02-06 11:50:31 +0000330 jlong pathHandle, jint op) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000331 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
Narayan Kamath017546e2014-02-06 11:50:31 +0000332 bool result = canvas->clipPath(*reinterpret_cast<SkPath*>(pathHandle),
333 static_cast<SkRegion::Op>(op));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000334 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800335 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000336
337 static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
338 jlong deviceRgnHandle, jint op) {
339 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
340 SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
341 bool result = canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
342 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800343 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000344
345 static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
Narayan Kamath017546e2014-02-06 11:50:31 +0000346 jlong filterHandle) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000347 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
Narayan Kamath017546e2014-02-06 11:50:31 +0000348 canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800349 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000350
351 static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400352 jobject rect) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000353 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800354 SkRect rect_;
355 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400356 return canvas->quickReject(rect_);
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;
371 r.set(SkFloatToScalar(left), SkFloatToScalar(top),
372 SkFloatToScalar(right), SkFloatToScalar(bottom));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000373 bool result = canvas->quickReject(r);
374 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800375 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000376
377 static void drawRGB(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800378 jint r, jint g, jint b) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000379 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800380 canvas->drawARGB(0xFF, r, g, b);
381 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000382
383 static void drawARGB(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800384 jint a, jint r, jint g, jint b) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000385 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800386 canvas->drawARGB(a, r, g, b);
387 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000388
389 static void drawColor__I(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800390 jint color) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000391 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800392 canvas->drawColor(color);
393 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000394
395 static void drawColor__II(JNIEnv* env, jobject, jlong canvasHandle,
396 jint color, jint modeHandle) {
397 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
398 SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
Mike Reed47c0d4e2009-06-22 22:53:52 -0400399 canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800400 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000401
402 static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle,
403 jlong paintHandle) {
404 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
405 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800406 canvas->drawPaint(*paint);
407 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000408
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
410 jint offset, jint count, jobject jpaint,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000411 jint modeHandle) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 NPE_CHECK_RETURN_VOID(env, jcanvas);
413 NPE_CHECK_RETURN_VOID(env, jptsArray);
414 NPE_CHECK_RETURN_VOID(env, jpaint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000415 SkCanvas::PointMode mode = static_cast<SkCanvas::PointMode>(modeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
417 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000418
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800419 AutoJavaFloatArray autoPts(env, jptsArray);
420 float* floats = autoPts.ptr();
421 const int length = autoPts.length();
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000422
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800423 if ((offset | count) < 0 || offset + count > length) {
424 doThrowAIOOBE(env);
425 return;
426 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000427
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800428 // now convert the floats into SkPoints
429 count >>= 1; // now it is the number of points
430 SkAutoSTMalloc<32, SkPoint> storage(count);
431 SkPoint* pts = storage.get();
432 const float* src = floats + offset;
433 for (int i = 0; i < count; i++) {
434 pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1]));
435 src += 2;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000436 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800437 canvas->drawPoints(mode, count, pts, paint);
438 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000439
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800440 static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
441 jint offset, jint count, jobject jpaint) {
442 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
443 SkCanvas::kPoints_PointMode);
444 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
447 jint offset, jint count, jobject jpaint) {
448 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
449 SkCanvas::kLines_PointMode);
450 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000451
452 static void drawPoint(JNIEnv* env, jobject jcanvas, jfloat x, jfloat y,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800453 jobject jpaint) {
454 NPE_CHECK_RETURN_VOID(env, jcanvas);
455 NPE_CHECK_RETURN_VOID(env, jpaint);
456 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
457 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000458
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800459 canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint);
460 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000461
462 static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800463 jfloat startX, jfloat startY, jfloat stopX,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000464 jfloat stopY, jlong paintHandle) {
465 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
466 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800467 canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY),
468 SkFloatToScalar(stopX), SkFloatToScalar(stopY),
469 *paint);
470 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000471
472 static void drawRect__RectFPaint(JNIEnv* env, jobject, jlong canvasHandle,
473 jobject rect, jlong paintHandle) {
474 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
475 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800476 SkRect rect_;
477 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
478 canvas->drawRect(rect_, *paint);
479 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000480
481 static void drawRect__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800482 jfloat left, jfloat top, jfloat right,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000483 jfloat bottom, jlong paintHandle) {
484 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
485 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800486 SkScalar left_ = SkFloatToScalar(left);
487 SkScalar top_ = SkFloatToScalar(top);
488 SkScalar right_ = SkFloatToScalar(right);
489 SkScalar bottom_ = SkFloatToScalar(bottom);
490 canvas->drawRectCoords(left_, top_, right_, bottom_, *paint);
491 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000492
493 static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
494 jlong paintHandle) {
495 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
496 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800497 SkRect oval;
498 GraphicsJNI::jrectf_to_rect(env, joval, &oval);
499 canvas->drawOval(oval, *paint);
500 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000501
502 static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx,
503 jfloat cy, jfloat radius, jlong paintHandle) {
504 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
505 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800506 canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy),
507 SkFloatToScalar(radius), *paint);
508 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000509
510 static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800511 jfloat startAngle, jfloat sweepAngle,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000512 jboolean useCenter, jlong paintHandle) {
513 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
514 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 SkRect oval;
516 GraphicsJNI::jrectf_to_rect(env, joval, &oval);
517 canvas->drawArc(oval, SkFloatToScalar(startAngle),
518 SkFloatToScalar(sweepAngle), useCenter, *paint);
519 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000520
521 static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800522 jobject jrect, jfloat rx, jfloat ry,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000523 jlong paintHandle) {
524 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
525 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800526 SkRect rect;
527 GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
528 canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry),
529 *paint);
530 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000531
532 static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
533 jlong paintHandle) {
534 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
535 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
536 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800537 canvas->drawPath(*path, *paint);
538 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800540 static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000541 jlong canvasHandle, jlong bitmapHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800542 jfloat left, jfloat top,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000543 jlong paintHandle, jint canvasDensity,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700544 jint screenDensity, jint bitmapDensity) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000545 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
546 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
547 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800548 SkScalar left_ = SkFloatToScalar(left);
549 SkScalar top_ = SkFloatToScalar(top);
550
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700551 if (canvasDensity == bitmapDensity || canvasDensity == 0
552 || bitmapDensity == 0) {
Dianne Hackborn0d221012009-07-29 15:41:19 -0700553 if (screenDensity != 0 && screenDensity != bitmapDensity) {
554 SkPaint filteredPaint;
555 if (paint) {
556 filteredPaint = *paint;
557 }
558 filteredPaint.setFilterBitmap(true);
559 canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
560 } else {
561 canvas->drawBitmap(*bitmap, left_, top_, paint);
562 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800563 } else {
564 canvas->save();
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700565 SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
566 canvas->translate(left_, top_);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800567 canvas->scale(scale, scale);
568
569 SkPaint filteredPaint;
570 if (paint) {
571 filteredPaint = *paint;
572 }
573 filteredPaint.setFilterBitmap(true);
574
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700575 canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800576
577 canvas->restore();
578 }
579 }
580
581 static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700582 jobject srcIRect, const SkRect& dst, SkPaint* paint,
583 jint screenDensity, jint bitmapDensity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800584 SkIRect src, *srcPtr = NULL;
585
586 if (NULL != srcIRect) {
587 GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
588 srcPtr = &src;
589 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000590
Dianne Hackborn0d221012009-07-29 15:41:19 -0700591 if (screenDensity != 0 && screenDensity != bitmapDensity) {
592 SkPaint filteredPaint;
593 if (paint) {
594 filteredPaint = *paint;
595 }
596 filteredPaint.setFilterBitmap(true);
597 canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
598 } else {
599 canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
600 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800601 }
602
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000603 static void drawBitmapRF(JNIEnv* env, jobject, jlong canvasHandle,
604 jlong bitmapHandle, jobject srcIRect,
605 jobject dstRectF, 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::jrectf_to_rect(env, dstRectF, &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 drawBitmapRR(JNIEnv* env, jobject, jlong canvasHandle,
617 jlong bitmapHandle, jobject srcIRect,
618 jobject dstRect, jlong paintHandle,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700619 jint screenDensity, jint bitmapDensity) {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000620 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
621 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
622 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 SkRect dst;
624 GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700625 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
626 screenDensity, bitmapDensity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800627 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000628
629 static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
630 jintArray jcolors, jint offset, jint stride,
631 jfloat x, jfloat y, jint width, jint height,
632 jboolean hasAlpha, jlong paintHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800633 {
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000634 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
635 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 SkBitmap bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800637 bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
638 SkBitmap::kRGB_565_Config, width, height);
639 if (!bitmap.allocPixels()) {
640 return;
641 }
Chris Craik1abf5d62013-08-16 12:47:03 -0700642
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800643 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
Chris Craik1abf5d62013-08-16 12:47:03 -0700644 0, 0, width, height, bitmap, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800645 return;
646 }
Chris Craik1abf5d62013-08-16 12:47:03 -0700647
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
649 paint);
650 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000651
652 static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle,
653 jlong bitmapHandle, jlong matrixHandle,
654 jlong paintHandle) {
655 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
656 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
657 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
658 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800659 canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
660 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000661
662 static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle,
663 jlong bitmapHandle, jint meshWidth, jint meshHeight,
664 jfloatArray jverts, jint vertIndex, jintArray jcolors,
665 jint colorIndex, jlong paintHandle) {
666 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
667 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
668 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669
670 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
671 const int indexCount = meshWidth * meshHeight * 6;
672
673 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
674 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000675
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800676 /* Our temp storage holds 2 or 3 arrays.
677 texture points [ptCount * sizeof(SkPoint)]
678 optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
679 copy to convert from float to fixed
680 indices [ptCount * sizeof(uint16_t)]
681 */
682 ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
683#ifdef SK_SCALAR_IS_FIXED
684 storageSize += ptCount * sizeof(SkPoint); // storage for verts
685#endif
686 storageSize += indexCount * sizeof(uint16_t); // indices[]
687
688 SkAutoMalloc storage(storageSize);
689 SkPoint* texs = (SkPoint*)storage.get();
690 SkPoint* verts;
691 uint16_t* indices;
692#ifdef SK_SCALAR_IS_FLOAT
693 verts = (SkPoint*)(vertA.ptr() + vertIndex);
694 indices = (uint16_t*)(texs + ptCount);
695#else
696 verts = texs + ptCount;
697 indices = (uint16_t*)(verts + ptCount);
698 // convert floats to fixed
699 {
700 const float* src = vertA.ptr() + vertIndex;
701 for (int i = 0; i < ptCount; i++) {
702 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
703 src += 2;
704 }
705 }
706#endif
707
708 // cons up texture coordinates and indices
709 {
710 const SkScalar w = SkIntToScalar(bitmap->width());
711 const SkScalar h = SkIntToScalar(bitmap->height());
712 const SkScalar dx = w / meshWidth;
713 const SkScalar dy = h / meshHeight;
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000714
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800715 SkPoint* texsPtr = texs;
716 SkScalar y = 0;
717 for (int i = 0; i <= meshHeight; i++) {
718 if (i == meshHeight) {
719 y = h; // to ensure numerically we hit h exactly
720 }
721 SkScalar x = 0;
722 for (int j = 0; j < meshWidth; j++) {
723 texsPtr->set(x, y);
724 texsPtr += 1;
725 x += dx;
726 }
727 texsPtr->set(w, y);
728 texsPtr += 1;
729 y += dy;
730 }
731 SkASSERT(texsPtr - texs == ptCount);
732 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000733
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800734 // cons up indices
735 {
736 uint16_t* indexPtr = indices;
737 int index = 0;
738 for (int i = 0; i < meshHeight; i++) {
739 for (int j = 0; j < meshWidth; j++) {
740 // lower-left triangle
741 *indexPtr++ = index;
742 *indexPtr++ = index + meshWidth + 1;
743 *indexPtr++ = index + meshWidth + 2;
744 // upper-right triangle
745 *indexPtr++ = index;
746 *indexPtr++ = index + meshWidth + 2;
747 *indexPtr++ = index + 1;
748 // bump to the next cell
749 index += 1;
750 }
751 // bump to the next row
752 index += 1;
753 }
754 SkASSERT(indexPtr - indices == indexCount);
755 SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
756 }
757
758 // double-check that we have legal indices
759#ifdef SK_DEBUG
760 {
761 for (int i = 0; i < indexCount; i++) {
762 SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
763 }
764 }
765#endif
766
767 // cons-up a shader for the bitmap
768 SkPaint tmpPaint;
769 if (paint) {
770 tmpPaint = *paint;
771 }
772 SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
773 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
Derek Sollenberger6062c592011-02-22 13:55:04 -0500774 SkSafeUnref(tmpPaint.setShader(shader));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800775
776 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
777 texs, (const SkColor*)colorA.ptr(), NULL, indices,
778 indexCount, tmpPaint);
779 }
780
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000781 static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
782 jint modeHandle, jint vertexCount,
783 jfloatArray jverts, jint vertIndex,
784 jfloatArray jtexs, jint texIndex,
785 jintArray jcolors, jint colorIndex,
786 jshortArray jindices, jint indexIndex,
787 jint indexCount, jlong paintHandle) {
788 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
789 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
790 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800791
792 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
793 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
794 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
795 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
796
797 const int ptCount = vertexCount >> 1;
798
799 SkPoint* verts;
800 SkPoint* texs = NULL;
801#ifdef SK_SCALAR_IS_FLOAT
802 verts = (SkPoint*)(vertA.ptr() + vertIndex);
803 if (jtexs != NULL) {
804 texs = (SkPoint*)(texA.ptr() + texIndex);
805 }
806#else
807 int count = ptCount; // for verts
808 if (jtexs != NULL) {
809 count += ptCount; // += for texs
810 }
811 SkAutoMalloc storage(count * sizeof(SkPoint));
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000812 verts = (SkPoint*)storage.get();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800813 const float* src = vertA.ptr() + vertIndex;
814 for (int i = 0; i < ptCount; i++) {
815 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
816 src += 2;
817 }
818 if (jtexs != NULL) {
819 texs = verts + ptCount;
820 src = texA.ptr() + texIndex;
821 for (int i = 0; i < ptCount; i++) {
822 texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
823 src += 2;
824 }
825 }
826#endif
827
828 const SkColor* colors = NULL;
829 const uint16_t* indices = NULL;
830 if (jcolors != NULL) {
831 colors = (const SkColor*)(colorA.ptr() + colorIndex);
832 }
833 if (jindices != NULL) {
834 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
835 }
836
837 canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
838 indices, indexCount, *paint);
839 }
Doug Feltf47d7402010-04-21 16:01:52 -0700840
Doug Felt0c702b82010-05-14 10:55:42 -0700841
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000842 static void drawText___CIIFFIPaintTypeface(JNIEnv* env, jobject, jlong canvasHandle,
843 jcharArray text, jint index, jint count,
844 jfloat x, jfloat y, jint flags,
845 jlong paintHandle, jlong typefaceHandle) {
846 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
847 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
848 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700849 jchar* textArray = env->GetCharArrayElements(text, NULL);
Raph Leviena0336302013-05-22 16:16:59 -0700850 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -0700851 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800852 }
Doug Felt0c702b82010-05-14 10:55:42 -0700853
Raph Leviena0336302013-05-22 16:16:59 -0700854 static void drawText__StringIIFFIPaintTypeface(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000855 jlong canvasHandle, jstring text,
856 jint start, jint end,
857 jfloat x, jfloat y, jint flags,
858 jlong paintHandle, jlong typefaceHandle) {
859 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
860 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
861 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700862 const jchar* textArray = env->GetStringChars(text, NULL);
Raph Leviena0336302013-05-22 16:16:59 -0700863 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -0700864 env->ReleaseStringChars(text, textArray);
865 }
Doug Felt0c702b82010-05-14 10:55:42 -0700866
Raph Leviena0336302013-05-22 16:16:59 -0700867#ifdef USE_MINIKIN
868 static void drawGlyphsToSkia(SkCanvas *canvas, SkPaint *paint, Layout *layout, float x, float y) {
869 size_t nGlyphs = layout->nGlyphs();
870 uint16_t *glyphs = new uint16_t[nGlyphs];
871 SkPoint *pos = new SkPoint[nGlyphs];
872 SkTypeface *lastFace = NULL;
873 SkTypeface *skFace = NULL;
874 size_t start = 0;
875
876 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
877 for (size_t i = 0; i < nGlyphs; i++) {
878 MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
879 skFace = mfs->GetSkTypeface();
880 glyphs[i] = layout->getGlyphId(i);
881 pos[i].fX = SkFloatToScalar(x + layout->getX(i));
882 pos[i].fY = SkFloatToScalar(y + layout->getY(i));
883 if (i > 0 && skFace != lastFace) {
884 paint->setTypeface(lastFace);
885 canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
886 start = i;
887 }
888 lastFace = skFace;
889 }
890 if (skFace != NULL) {
891 paint->setTypeface(skFace);
892 canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
893 }
894 delete[] glyphs;
895 delete[] pos;
896 }
897#endif
898
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700899 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
900 int start, int end,
Raph Leviena0336302013-05-22 16:16:59 -0700901 jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700902
903 jint count = end - start;
Raph Leviena0336302013-05-22 16:16:59 -0700904 drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint, typeface);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700905 }
906
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700907 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
908 int start, int count, int contextCount,
Raph Leviena0336302013-05-22 16:16:59 -0700909 jfloat x, jfloat y, int flags, SkPaint* paint, TypefaceImpl* typeface) {
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700910
Raph Leviena0336302013-05-22 16:16:59 -0700911#ifdef USE_MINIKIN
912 Layout layout;
913 TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
914 layout.setFontCollection(resolvedFace->fFontCollection);
915 FontStyle style = resolvedFace->fStyle;
916 char css[256];
917 sprintf(css, "font-size: %d; font-weight: %d; font-style: %s",
918 (int)paint->getTextSize(),
919 style.getWeight() * 100,
920 style.getItalic() ? "italic" : "normal");
921 layout.setProperties(css);
922 layout.doLayout(textArray + start, count);
923 drawGlyphsToSkia(canvas, paint, &layout, x, y);
924#else
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800925 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700926 textArray, start, count, contextCount, flags);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700927 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800928 return;
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700929 }
Raph Levien2301d322012-07-17 16:39:49 -0700930 SkPaint::Align align = paint->getTextAlign();
931 if (align == SkPaint::kCenter_Align) {
932 x -= 0.5 * value->getTotalAdvance();
933 } else if (align == SkPaint::kRight_Align) {
934 x -= value->getTotalAdvance();
935 }
936 paint->setTextAlign(SkPaint::kLeft_Align);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700937 doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
Raph Levien2301d322012-07-17 16:39:49 -0700938 doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
939 paint->setTextAlign(align);
Raph Leviena0336302013-05-22 16:16:59 -0700940#endif
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700941 }
942
Raph Levien2301d322012-07-17 16:39:49 -0700943// Same values used by Skia
944#define kStdStrikeThru_Offset (-6.0f / 21.0f)
945#define kStdUnderline_Offset (1.0f / 9.0f)
946#define kStdUnderline_Thickness (1.0f / 18.0f)
947
948static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length, SkPaint* paint) {
Raph Leviene174ae22012-10-03 15:26:47 -0700949 uint32_t flags;
950 SkDrawFilter* drawFilter = canvas->getDrawFilter();
951 if (drawFilter) {
952 SkPaint paintCopy(*paint);
953 drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
954 flags = paintCopy.getFlags();
955 } else {
956 flags = paint->getFlags();
957 }
Raph Levien2301d322012-07-17 16:39:49 -0700958 if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
959 SkScalar left = SkFloatToScalar(x);
960 SkScalar right = SkFloatToScalar(x + length);
961 float textSize = paint->getTextSize();
962 float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
963 if (flags & SkPaint::kUnderlineText_Flag) {
964 SkScalar top = SkFloatToScalar(y + textSize * kStdUnderline_Offset
965 - 0.5f * strokeWidth);
966 SkScalar bottom = SkFloatToScalar(y + textSize * kStdUnderline_Offset
967 + 0.5f * strokeWidth);
968 canvas->drawRectCoords(left, top, right, bottom, *paint);
969 }
970 if (flags & SkPaint::kStrikeThruText_Flag) {
971 SkScalar top = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
972 - 0.5f * strokeWidth);
973 SkScalar bottom = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
974 + 0.5f * strokeWidth);
975 canvas->drawRectCoords(left, top, right, bottom, *paint);
976 }
977 }
978}
979
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700980 static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
981 jfloat x, jfloat y, int flags, SkPaint* paint) {
982 // Beware: this needs Glyph encoding (already done on the Paint constructor)
983 canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
984 }
985
Raph Levien2301d322012-07-17 16:39:49 -0700986 static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700987 int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
Raph Levien2301d322012-07-17 16:39:49 -0700988 SkPoint* posPtr = new SkPoint[count];
989 for (int indx = 0; indx < count; indx++) {
990 posPtr[indx].fX = SkFloatToScalar(x + posArray[indx * 2]);
991 posPtr[indx].fY = SkFloatToScalar(y + posArray[indx * 2 + 1]);
992 }
993 canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
994 delete[] posPtr;
995 }
996
Raph Leviena0336302013-05-22 16:16:59 -0700997 static void drawTextRun___CIIIIFFIPaintTypeface(
Ashok Bhat36bef0b2014-01-20 20:08:01 +0000998 JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
999 jint count, jint contextIndex, jint contextCount,
1000 jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
1001 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1002 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
1003 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -07001004
Doug Feltf47d7402010-04-21 16:01:52 -07001005 jchar* chars = env->GetCharArrayElements(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -07001006 drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
Raph Leviena0336302013-05-22 16:16:59 -07001007 count, contextCount, x, y, dirFlags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -07001008 env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
1009 }
1010
Raph Leviena0336302013-05-22 16:16:59 -07001011 static void drawTextRun__StringIIIIFFIPaintTypeface(
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001012 JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
Doug Felt0c702b82010-05-14 10:55:42 -07001013 jint end, jint contextStart, jint contextEnd,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001014 jfloat x, jfloat y, jint dirFlags, jlong paintHandle, jlong typefaceHandle) {
1015 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1016 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
1017 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
Doug Feltf47d7402010-04-21 16:01:52 -07001018
Doug Felt0c702b82010-05-14 10:55:42 -07001019 jint count = end - start;
1020 jint contextCount = contextEnd - contextStart;
Doug Feltf47d7402010-04-21 16:01:52 -07001021 const jchar* chars = env->GetStringChars(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -07001022 drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
Raph Leviena0336302013-05-22 16:16:59 -07001023 count, contextCount, x, y, dirFlags, paint, typeface);
Doug Feltf47d7402010-04-21 16:01:52 -07001024 env->ReleaseStringChars(text, chars);
1025 }
1026
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001027 static void drawPosText___CII_FPaint(JNIEnv* env, jobject, jlong canvasHandle,
1028 jcharArray text, jint index, jint count,
1029 jfloatArray pos, jlong paintHandle) {
1030 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1031 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001032 jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
1033 jsize textCount = text ? env->GetArrayLength(text) : NULL;
1034 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
1035 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
1036 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
1037 int indx;
1038 for (indx = 0; indx < posCount; indx++) {
1039 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
1040 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
1041 }
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001042
Romain Guy62b6eaa2012-01-17 14:52:13 -08001043 SkPaint::TextEncoding encoding = paint->getTextEncoding();
1044 paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
Mike Reedad8b8f52009-05-01 08:24:01 -04001045 canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
Romain Guy62b6eaa2012-01-17 14:52:13 -08001046 paint->setTextEncoding(encoding);
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001048 if (text) {
1049 env->ReleaseCharArrayElements(text, textArray, 0);
1050 }
1051 if (pos) {
1052 env->ReleaseFloatArrayElements(pos, posArray, 0);
1053 }
1054 delete[] posPtr;
1055 }
Doug Felt0c702b82010-05-14 10:55:42 -07001056
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001057 static void drawPosText__String_FPaint(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001058 jlong canvasHandle, jstring text,
Doug Felt4beb8ff72010-06-09 13:53:24 -07001059 jfloatArray pos,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001060 jlong paintHandle) {
1061 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1062 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001063 const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
1064 int byteLength = text ? env->GetStringLength(text) : 0;
1065 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
1066 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
1067 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
1068
1069 for (int indx = 0; indx < posCount; indx++) {
1070 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
1071 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
1072 }
Romain Guy62b6eaa2012-01-17 14:52:13 -08001073
1074 SkPaint::TextEncoding encoding = paint->getTextEncoding();
1075 paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001076 canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
Romain Guy62b6eaa2012-01-17 14:52:13 -08001077 paint->setTextEncoding(encoding);
1078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079 if (text) {
1080 env->ReleaseStringChars(text, (const jchar*) text_);
1081 }
1082 if (pos) {
1083 env->ReleaseFloatArrayElements(pos, posArray, 0);
1084 }
1085 delete[] posPtr;
1086 }
Doug Felt0c702b82010-05-14 10:55:42 -07001087
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001088 static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001089 jlong canvasHandle, jcharArray text, jint index, jint count,
1090 jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
1091 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1092 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1093 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001094
1095 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001096 TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
1097 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001098 env->ReleaseCharArrayElements(text, textArray, 0);
1099 }
Doug Felt0c702b82010-05-14 10:55:42 -07001100
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001102 jlong canvasHandle, jstring text, jlong pathHandle,
1103 jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
1104 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1105 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1106 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001107 const jchar* text_ = env->GetStringChars(text, NULL);
Doug Felt4beb8ff72010-06-09 13:53:24 -07001108 int count = env->GetStringLength(text);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001109 TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
1110 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 env->ReleaseStringChars(text, text_);
1112 }
Doug Felt0c702b82010-05-14 10:55:42 -07001113
Derek Sollenberger00a33a82013-05-16 09:31:27 -04001114
1115 // This function is a mirror of SkCanvas::getClipBounds except that it does
1116 // not outset the edge of the clip to account for anti-aliasing. There is
1117 // a skia bug to investigate pushing this logic into back into skia.
1118 // (see https://code.google.com/p/skia/issues/detail?id=1303)
1119 static bool getHardClipBounds(SkCanvas* canvas, SkRect* bounds) {
1120 SkIRect ibounds;
1121 if (!canvas->getClipDeviceBounds(&ibounds)) {
1122 return false;
1123 }
1124
1125 SkMatrix inverse;
1126 // if we can't invert the CTM, we can't return local clip bounds
1127 if (!canvas->getTotalMatrix().invert(&inverse)) {
1128 if (bounds) {
1129 bounds->setEmpty();
1130 }
1131 return false;
1132 }
1133
1134 if (NULL != bounds) {
1135 SkRect r = SkRect::Make(ibounds);
1136 inverse.mapRect(bounds, r);
1137 }
1138 return true;
1139 }
1140
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001141 static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle,
1142 jobject bounds) {
1143 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 SkRect r;
1145 SkIRect ir;
Derek Sollenberger00a33a82013-05-16 09:31:27 -04001146 bool result = getHardClipBounds(canvas, &r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001147
Chet Haase6a2d17f2012-09-30 12:14:13 -07001148 if (!result) {
1149 r.setEmpty();
1150 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 r.round(&ir);
Derek Sollenbergerca79cf62012-08-14 16:44:52 -04001152
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001153 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001154 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001155 }
1156
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001157 static void getCTM(JNIEnv* env, jobject, jlong canvasHandle,
1158 jlong matrixHandle) {
1159 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1160 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001161 *matrix = canvas->getTotalMatrix();
1162 }
1163};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001164
1165static JNINativeMethod gCanvasMethods[] = {
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001166 {"finalizer", "(J)V", (void*) SkCanvasGlue::finalizer},
1167 {"initRaster","(J)J", (void*) SkCanvasGlue::initRaster},
1168 {"copyNativeCanvasState","(JJ)V", (void*) SkCanvasGlue::copyCanvasState},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001169 {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
1170 {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
1171 {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 {"save","()I", (void*) SkCanvasGlue::saveAll},
1173 {"save","(I)I", (void*) SkCanvasGlue::save},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001174 {"native_saveLayer","(JLandroid/graphics/RectF;JI)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 (void*) SkCanvasGlue::saveLayer},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001176 {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer4F},
1177 {"native_saveLayerAlpha","(JLandroid/graphics/RectF;II)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001178 (void*) SkCanvasGlue::saveLayerAlpha},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001179 {"native_saveLayerAlpha","(JFFFFII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001180 (void*) SkCanvasGlue::saveLayerAlpha4F},
1181 {"restore","()V", (void*) SkCanvasGlue::restore},
1182 {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
1183 {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
1184 {"translate","(FF)V", (void*) SkCanvasGlue::translate},
1185 {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
1186 {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
1187 {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001188 {"native_concat","(JJ)V", (void*) SkCanvasGlue::concat},
1189 {"native_setMatrix","(JJ)V", (void*) SkCanvasGlue::setMatrix},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
1191 {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
1192 {"clipRect","(Landroid/graphics/RectF;)Z",
1193 (void*) SkCanvasGlue::clipRect_RectF},
1194 {"clipRect","(Landroid/graphics/Rect;)Z",
1195 (void*) SkCanvasGlue::clipRect_Rect},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001196 {"native_clipRect","(JFFFFI)Z", (void*) SkCanvasGlue::clipRect},
1197 {"native_clipPath","(JJI)Z", (void*) SkCanvasGlue::clipPath},
1198 {"native_clipRegion","(JJI)Z", (void*) SkCanvasGlue::clipRegion},
1199 {"nativeSetDrawFilter", "(JJ)V", (void*) SkCanvasGlue::setDrawFilter},
1200 {"native_getClipBounds","(JLandroid/graphics/Rect;)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001201 (void*) SkCanvasGlue::getClipBounds},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001202 {"native_getCTM", "(JJ)V", (void*)SkCanvasGlue::getCTM},
1203 {"native_quickReject","(JLandroid/graphics/RectF;)Z",
Derek Sollenbergerca79cf62012-08-14 16:44:52 -04001204 (void*) SkCanvasGlue::quickReject__RectF},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001205 {"native_quickReject","(JJ)Z", (void*) SkCanvasGlue::quickReject__Path},
1206 {"native_quickReject","(JFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
1207 {"native_drawRGB","(JIII)V", (void*) SkCanvasGlue::drawRGB},
1208 {"native_drawARGB","(JIIII)V", (void*) SkCanvasGlue::drawARGB},
1209 {"native_drawColor","(JI)V", (void*) SkCanvasGlue::drawColor__I},
1210 {"native_drawColor","(JII)V", (void*) SkCanvasGlue::drawColor__II},
1211 {"native_drawPaint","(JJ)V", (void*) SkCanvasGlue::drawPaint},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001212 {"drawPoint", "(FFLandroid/graphics/Paint;)V",
1213 (void*) SkCanvasGlue::drawPoint},
1214 {"drawPoints", "([FIILandroid/graphics/Paint;)V",
1215 (void*) SkCanvasGlue::drawPoints},
1216 {"drawLines", "([FIILandroid/graphics/Paint;)V",
1217 (void*) SkCanvasGlue::drawLines},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001218 {"native_drawLine","(JFFFFJ)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
1219 {"native_drawRect","(JLandroid/graphics/RectF;J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001220 (void*) SkCanvasGlue::drawRect__RectFPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001221 {"native_drawRect","(JFFFFJ)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
1222 {"native_drawOval","(JLandroid/graphics/RectF;J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 (void*) SkCanvasGlue::drawOval},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001224 {"native_drawCircle","(JFFFJ)V", (void*) SkCanvasGlue::drawCircle},
1225 {"native_drawArc","(JLandroid/graphics/RectF;FFZJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001226 (void*) SkCanvasGlue::drawArc},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001227 {"native_drawRoundRect","(JLandroid/graphics/RectF;FFJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001228 (void*) SkCanvasGlue::drawRoundRect},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001229 {"native_drawPath","(JJJ)V", (void*) SkCanvasGlue::drawPath},
1230 {"native_drawBitmap","(JJFFJIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001231 (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001232 {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/RectF;JII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001233 (void*) SkCanvasGlue::drawBitmapRF},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001234 {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/Rect;JII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001235 (void*) SkCanvasGlue::drawBitmapRR},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001236 {"native_drawBitmap", "(J[IIIFFIIZJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 (void*)SkCanvasGlue::drawBitmapArray},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001238 {"nativeDrawBitmapMatrix", "(JJJJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001239 (void*)SkCanvasGlue::drawBitmapMatrix},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001240 {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001241 (void*)SkCanvasGlue::drawBitmapMesh},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001242 {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001243 (void*)SkCanvasGlue::drawVertices},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001244 {"native_drawText","(J[CIIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001245 (void*) SkCanvasGlue::drawText___CIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001246 {"native_drawText","(JLjava/lang/String;IIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001247 (void*) SkCanvasGlue::drawText__StringIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001248 {"native_drawTextRun","(J[CIIIIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001249 (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001250 {"native_drawTextRun","(JLjava/lang/String;IIIIFFIJJ)V",
Raph Leviena0336302013-05-22 16:16:59 -07001251 (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaintTypeface},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001252 {"native_drawPosText","(J[CII[FJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 (void*) SkCanvasGlue::drawPosText___CII_FPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001254 {"native_drawPosText","(JLjava/lang/String;[FJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001255 (void*) SkCanvasGlue::drawPosText__String_FPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001256 {"native_drawTextOnPath","(J[CIIJFFIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001257 (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001258 {"native_drawTextOnPath","(JLjava/lang/String;JFFIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001259 (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260
Fabrice Di Meglio30ca5cd2012-05-07 17:45:44 -07001261 {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
1262
1263 {"freeTextLayoutCaches", "()V", (void*) SkCanvasGlue::freeTextLayoutCaches}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001264};
1265
Mike Reedc04851f2009-10-28 15:09:45 -04001266///////////////////////////////////////////////////////////////////////////////
1267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001268#include <android_runtime/AndroidRuntime.h>
1269
1270#define REG(env, name, array) \
1271 result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
1272 SK_ARRAY_COUNT(array)); \
1273 if (result < 0) return result
1274
1275int register_android_graphics_Canvas(JNIEnv* env) {
1276 int result;
1277
1278 REG(env, "android/graphics/Canvas", gCanvasMethods);
Ashok Bhat36bef0b2014-01-20 20:08:01 +00001279
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001280 return result;
1281}
1282
1283}