blob: 89490bc94c7110e2e044ffaa57b87fc1686659cc [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
Doug Feltf7cb1f72010-07-01 16:20:43 -070030#include "TextLayout.h"
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -070031#include "TextLayoutCache.h"
Doug Feltf7cb1f72010-07-01 16:20:43 -070032
Doug Feltf47d7402010-04-21 16:01:52 -070033#include "unicode/ubidi.h"
Doug Felt0c702b82010-05-14 10:55:42 -070034#include "unicode/ushape.h"
35
Doug Felt0c702b82010-05-14 10:55:42 -070036#include <utils/Log.h>
Doug Feltf47d7402010-04-21 16:01:52 -070037
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038static uint32_t get_thread_msec() {
39#if defined(HAVE_POSIX_CLOCKS)
40 struct timespec tm;
Ashok Bhata0398432014-01-20 20:08:01 +000041
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080042 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
Ashok Bhata0398432014-01-20 20:08:01 +000043
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044 return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
45#else
46 struct timeval tv;
Ashok Bhata0398432014-01-20 20:08:01 +000047
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080048 gettimeofday(&tv, NULL);
49 return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
50#endif
51}
52
53namespace android {
54
Derek Sollenberger5b6591c2013-02-28 11:18:50 -050055class ClipCopier : public SkCanvas::ClipVisitor {
56public:
57 ClipCopier(SkCanvas* dstCanvas) : m_dstCanvas(dstCanvas) {}
58
59 virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
60 m_dstCanvas->clipRect(rect, op, antialias);
61 }
62 virtual void clipPath(const SkPath& path, SkRegion::Op op, bool antialias) {
63 m_dstCanvas->clipPath(path, op, antialias);
64 }
65
66private:
67 SkCanvas* m_dstCanvas;
68};
69
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080070class SkCanvasGlue {
71public:
72
Ashok Bhata0398432014-01-20 20:08:01 +000073 static void finalizer(JNIEnv* env, jobject clazz, jlong canvasHandle) {
74 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080075 canvas->unref();
76 }
77
Ashok Bhata0398432014-01-20 20:08:01 +000078 static jlong initRaster(JNIEnv* env, jobject, jlong bitmapHandle) {
79 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040080 if (bitmap) {
Ashok Bhata0398432014-01-20 20:08:01 +000081 return reinterpret_cast<jlong>(new SkCanvas(*bitmap));
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040082 } else {
83 // Create an empty bitmap device to prevent callers from crashing
84 // if they attempt to draw into this canvas.
85 SkBitmap emptyBitmap;
Ashok Bhata0398432014-01-20 20:08:01 +000086 return reinterpret_cast<jlong>(new SkCanvas(emptyBitmap));
Derek Sollenberger45fa0cb2013-04-09 16:36:55 -040087 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080088 }
Ashok Bhata0398432014-01-20 20:08:01 +000089
Derek Sollenberger1b63e602013-02-21 13:05:09 -050090 static void copyCanvasState(JNIEnv* env, jobject clazz,
Ashok Bhata0398432014-01-20 20:08:01 +000091 jlong srcCanvasHandle, jlong dstCanvasHandle) {
92 SkCanvas* srcCanvas = reinterpret_cast<SkCanvas*>(srcCanvasHandle);
93 SkCanvas* dstCanvas = reinterpret_cast<SkCanvas*>(dstCanvasHandle);
Derek Sollenberger1b63e602013-02-21 13:05:09 -050094 if (srcCanvas && dstCanvas) {
Derek Sollenberger1b63e602013-02-21 13:05:09 -050095 dstCanvas->setMatrix(srcCanvas->getTotalMatrix());
Derek Sollenberger5b6591c2013-02-28 11:18:50 -050096 if (NULL != srcCanvas->getDevice() && NULL != dstCanvas->getDevice()) {
97 ClipCopier copier(dstCanvas);
98 srcCanvas->replayClips(&copier);
99 }
Derek Sollenberger1b63e602013-02-21 13:05:09 -0500100 }
101 }
102
Derek Sollenberger5b6591c2013-02-28 11:18:50 -0500103
Mike Reedcaf0df12009-04-27 14:32:05 -0400104 static void freeCaches(JNIEnv* env, jobject) {
105 // these are called in no particular order
Mike Reedcaf0df12009-04-27 14:32:05 -0400106 SkImageRef_GlobalPool::SetRAMUsed(0);
Derek Sollenberger889a3fa2012-01-31 14:08:22 -0500107 SkGraphics::PurgeFontCache();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800108 }
Fabrice Di Meglio30ca5cd2012-05-07 17:45:44 -0700109
110 static void freeTextLayoutCaches(JNIEnv* env, jobject) {
111 TextLayoutEngine::getInstance().purgeCaches();
112 }
113
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
115 NPE_CHECK_RETURN_ZERO(env, jcanvas);
116 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
Ashok Bhata0398432014-01-20 20:08:01 +0000117 bool result = canvas->getDevice()->accessBitmap(false).isOpaque();
118 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800119 }
120
Ashok Bhata0398432014-01-20 20:08:01 +0000121 static jint getWidth(JNIEnv* env, jobject jcanvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800122 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhata0398432014-01-20 20:08:01 +0000123 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
124 int width = canvas->getDevice()->accessBitmap(false).width();
125 return static_cast<jint>(width);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 }
Ashok Bhata0398432014-01-20 20:08:01 +0000127
128 static jint getHeight(JNIEnv* env, jobject jcanvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhata0398432014-01-20 20:08:01 +0000130 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
131 int height = canvas->getDevice()->accessBitmap(false).height();
132 return static_cast<jint>(height);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800133 }
Ashok Bhata0398432014-01-20 20:08:01 +0000134
135 static jint saveAll(JNIEnv* env, jobject jcanvas) {
136 NPE_CHECK_RETURN_ZERO(env, jcanvas);
137 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
138 return static_cast<jint>(result);
139 }
140
141 static jint save(JNIEnv* env, jobject jcanvas, jint flagsHandle) {
142 SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
143 NPE_CHECK_RETURN_ZERO(env, jcanvas);
144 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
145 return static_cast<jint>(result);
146 }
147
148 static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds,
149 jlong paintHandle, jint flags) {
150 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
151 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 SkRect* bounds_ = NULL;
153 SkRect storage;
154 if (bounds != NULL) {
155 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
156 bounds_ = &storage;
157 }
Ashok Bhata0398432014-01-20 20:08:01 +0000158 return canvas->saveLayer(bounds_, paint, static_cast<SkCanvas::SaveFlags>(flags));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800159 }
Ashok Bhata0398432014-01-20 20:08:01 +0000160
161 static jint saveLayer4F(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800162 jfloat l, jfloat t, jfloat r, jfloat b,
Ashok Bhata0398432014-01-20 20:08:01 +0000163 jlong paintHandle, jint flags) {
164 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
165 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800166 SkRect bounds;
167 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
168 SkFloatToScalar(b));
Ashok Bhata0398432014-01-20 20:08:01 +0000169 int result = canvas->saveLayer(&bounds, paint,
170 static_cast<SkCanvas::SaveFlags>(flags));
171 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800172 }
Ashok Bhata0398432014-01-20 20:08:01 +0000173
174 static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle,
175 jobject bounds, jint alpha, jint flags) {
176 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800177 SkRect* bounds_ = NULL;
178 SkRect storage;
179 if (bounds != NULL) {
180 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
181 bounds_ = &storage;
182 }
Ashok Bhata0398432014-01-20 20:08:01 +0000183 int result = canvas->saveLayerAlpha(bounds_, alpha,
184 static_cast<SkCanvas::SaveFlags>(flags));
185 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800186 }
Ashok Bhata0398432014-01-20 20:08:01 +0000187
188 static jint saveLayerAlpha4F(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 jfloat l, jfloat t, jfloat r, jfloat b,
Ashok Bhata0398432014-01-20 20:08:01 +0000190 jint alpha, jint flags) {
191 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800192 SkRect bounds;
193 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
194 SkFloatToScalar(b));
Ashok Bhata0398432014-01-20 20:08:01 +0000195 int result = canvas->saveLayerAlpha(&bounds, alpha,
196 static_cast<SkCanvas::SaveFlags>(flags));
197 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 }
Ashok Bhata0398432014-01-20 20:08:01 +0000199
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 static void restore(JNIEnv* env, jobject jcanvas) {
201 NPE_CHECK_RETURN_VOID(env, jcanvas);
202 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
203 if (canvas->getSaveCount() <= 1) { // cannot restore anymore
204 doThrowISE(env, "Underflow in restore");
205 return;
206 }
207 canvas->restore();
208 }
Ashok Bhata0398432014-01-20 20:08:01 +0000209
210 static jint getSaveCount(JNIEnv* env, jobject jcanvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 NPE_CHECK_RETURN_ZERO(env, jcanvas);
Ashok Bhata0398432014-01-20 20:08:01 +0000212 int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
213 return static_cast<jint>(result);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800214 }
Ashok Bhata0398432014-01-20 20:08:01 +0000215
216 static void restoreToCount(JNIEnv* env, jobject jcanvas, jint restoreCount) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800217 NPE_CHECK_RETURN_VOID(env, jcanvas);
218 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
219 if (restoreCount < 1) {
220 doThrowIAE(env, "Underflow in restoreToCount");
221 return;
222 }
223 canvas->restoreToCount(restoreCount);
224 }
Ashok Bhata0398432014-01-20 20:08:01 +0000225
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800226 static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
227 NPE_CHECK_RETURN_VOID(env, jcanvas);
228 SkScalar dx_ = SkFloatToScalar(dx);
229 SkScalar dy_ = SkFloatToScalar(dy);
230 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_);
231 }
Ashok Bhata0398432014-01-20 20:08:01 +0000232
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
234 NPE_CHECK_RETURN_VOID(env, jcanvas);
235 SkScalar sx_ = SkFloatToScalar(sx);
236 SkScalar sy_ = SkFloatToScalar(sy);
237 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_);
238 }
Ashok Bhata0398432014-01-20 20:08:01 +0000239
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800240 static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
241 NPE_CHECK_RETURN_VOID(env, jcanvas);
242 SkScalar degrees_ = SkFloatToScalar(degrees);
243 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_);
244 }
Ashok Bhata0398432014-01-20 20:08:01 +0000245
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800246 static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
247 NPE_CHECK_RETURN_VOID(env, jcanvas);
248 SkScalar sx_ = SkFloatToScalar(sx);
249 SkScalar sy_ = SkFloatToScalar(sy);
250 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_);
251 }
Ashok Bhata0398432014-01-20 20:08:01 +0000252
253 static void concat(JNIEnv* env, jobject, jlong canvasHandle,
254 jlong matrixHandle) {
255 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
256 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 canvas->concat(*matrix);
258 }
Ashok Bhata0398432014-01-20 20:08:01 +0000259
260 static void setMatrix(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 if (NULL == matrix) {
265 canvas->resetMatrix();
266 } else {
267 canvas->setMatrix(*matrix);
268 }
269 }
Ashok Bhata0398432014-01-20 20:08:01 +0000270
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800271 static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
272 jfloat top, jfloat right, jfloat bottom) {
273 NPE_CHECK_RETURN_ZERO(env, jcanvas);
274 SkRect r;
275 r.set(SkFloatToScalar(left), SkFloatToScalar(top),
276 SkFloatToScalar(right), SkFloatToScalar(bottom));
277 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
Ashok Bhata0398432014-01-20 20:08:01 +0000278 bool result = c->clipRect(r);
279 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800280 }
Ashok Bhata0398432014-01-20 20:08:01 +0000281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800282 static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
283 jint top, jint right, jint bottom) {
284 NPE_CHECK_RETURN_ZERO(env, jcanvas);
285 SkRect r;
286 r.set(SkIntToScalar(left), SkIntToScalar(top),
287 SkIntToScalar(right), SkIntToScalar(bottom));
Ashok Bhata0398432014-01-20 20:08:01 +0000288 bool result = GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
289 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800290 }
Ashok Bhata0398432014-01-20 20:08:01 +0000291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800292 static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
293 NPE_CHECK_RETURN_ZERO(env, jcanvas);
294 NPE_CHECK_RETURN_ZERO(env, rectf);
295 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
296 SkRect tmp;
Ashok Bhata0398432014-01-20 20:08:01 +0000297 bool result = c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
298 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800299 }
Ashok Bhata0398432014-01-20 20:08:01 +0000300
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800301 static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
302 NPE_CHECK_RETURN_ZERO(env, jcanvas);
303 NPE_CHECK_RETURN_ZERO(env, rect);
304 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
305 SkRect tmp;
Ashok Bhata0398432014-01-20 20:08:01 +0000306 bool result = c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
307 return result ? JNI_TRUE : JNI_FALSE;
308
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800309 }
Ashok Bhata0398432014-01-20 20:08:01 +0000310
311 static jboolean clipRect(JNIEnv* env, jobject, jlong canvasHandle,
312 jfloat left, jfloat top, jfloat right, jfloat bottom,
313 jint op) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800314 SkRect rect;
Ashok Bhata0398432014-01-20 20:08:01 +0000315 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800316 rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
317 SkFloatToScalar(right), SkFloatToScalar(bottom));
Ashok Bhata0398432014-01-20 20:08:01 +0000318 bool result = canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
319 return result ? JNI_TRUE : JNI_FALSE;
320
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800321 }
Ashok Bhata0398432014-01-20 20:08:01 +0000322
323 static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
324 SkPath* path, jint op) {
325 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
326 bool result = canvas->clipPath(*path, static_cast<SkRegion::Op>(op));
327 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800328 }
Ashok Bhata0398432014-01-20 20:08:01 +0000329
330 static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle,
331 jlong deviceRgnHandle, jint op) {
332 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
333 SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle);
334 bool result = canvas->clipRegion(*deviceRgn, static_cast<SkRegion::Op>(op));
335 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800336 }
Ashok Bhata0398432014-01-20 20:08:01 +0000337
338 static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800339 SkDrawFilter* filter) {
Ashok Bhata0398432014-01-20 20:08:01 +0000340 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800341 canvas->setDrawFilter(filter);
342 }
Ashok Bhata0398432014-01-20 20:08:01 +0000343
344 static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400345 jobject rect) {
Ashok Bhata0398432014-01-20 20:08:01 +0000346 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800347 SkRect rect_;
348 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400349 return canvas->quickReject(rect_);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800350 }
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400351
Ashok Bhata0398432014-01-20 20:08:01 +0000352 static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400353 SkPath* path) {
Ashok Bhata0398432014-01-20 20:08:01 +0000354 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
355 bool result = canvas->quickReject(*path);
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 Bhata0398432014-01-20 20:08:01 +0000359 static jboolean quickReject__FFFF(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800360 jfloat left, jfloat top, jfloat right,
Derek Sollenbergerca79cf62012-08-14 16:44:52 -0400361 jfloat bottom) {
Ashok Bhata0398432014-01-20 20:08:01 +0000362 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800363 SkRect r;
364 r.set(SkFloatToScalar(left), SkFloatToScalar(top),
365 SkFloatToScalar(right), SkFloatToScalar(bottom));
Ashok Bhata0398432014-01-20 20:08:01 +0000366 bool result = canvas->quickReject(r);
367 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800368 }
Ashok Bhata0398432014-01-20 20:08:01 +0000369
370 static void drawRGB(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800371 jint r, jint g, jint b) {
Ashok Bhata0398432014-01-20 20:08:01 +0000372 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800373 canvas->drawARGB(0xFF, r, g, b);
374 }
Ashok Bhata0398432014-01-20 20:08:01 +0000375
376 static void drawARGB(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800377 jint a, jint r, jint g, jint b) {
Ashok Bhata0398432014-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(a, r, g, b);
380 }
Ashok Bhata0398432014-01-20 20:08:01 +0000381
382 static void drawColor__I(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800383 jint color) {
Ashok Bhata0398432014-01-20 20:08:01 +0000384 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800385 canvas->drawColor(color);
386 }
Ashok Bhata0398432014-01-20 20:08:01 +0000387
388 static void drawColor__II(JNIEnv* env, jobject, jlong canvasHandle,
389 jint color, jint modeHandle) {
390 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
391 SkPorterDuff::Mode mode = static_cast<SkPorterDuff::Mode>(modeHandle);
Mike Reed47c0d4e2009-06-22 22:53:52 -0400392 canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800393 }
Ashok Bhata0398432014-01-20 20:08:01 +0000394
395 static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle,
396 jlong paintHandle) {
397 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
398 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800399 canvas->drawPaint(*paint);
400 }
Ashok Bhata0398432014-01-20 20:08:01 +0000401
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800402 static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
403 jint offset, jint count, jobject jpaint,
Ashok Bhata0398432014-01-20 20:08:01 +0000404 jint modeHandle) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800405 NPE_CHECK_RETURN_VOID(env, jcanvas);
406 NPE_CHECK_RETURN_VOID(env, jptsArray);
407 NPE_CHECK_RETURN_VOID(env, jpaint);
Ashok Bhata0398432014-01-20 20:08:01 +0000408 SkCanvas::PointMode mode = static_cast<SkCanvas::PointMode>(modeHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800409 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
410 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
Ashok Bhata0398432014-01-20 20:08:01 +0000411
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800412 AutoJavaFloatArray autoPts(env, jptsArray);
413 float* floats = autoPts.ptr();
414 const int length = autoPts.length();
Ashok Bhata0398432014-01-20 20:08:01 +0000415
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800416 if ((offset | count) < 0 || offset + count > length) {
417 doThrowAIOOBE(env);
418 return;
419 }
Ashok Bhata0398432014-01-20 20:08:01 +0000420
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800421 // now convert the floats into SkPoints
422 count >>= 1; // now it is the number of points
423 SkAutoSTMalloc<32, SkPoint> storage(count);
424 SkPoint* pts = storage.get();
425 const float* src = floats + offset;
426 for (int i = 0; i < count; i++) {
427 pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1]));
428 src += 2;
Ashok Bhata0398432014-01-20 20:08:01 +0000429 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800430 canvas->drawPoints(mode, count, pts, paint);
431 }
Ashok Bhata0398432014-01-20 20:08:01 +0000432
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
434 jint offset, jint count, jobject jpaint) {
435 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
436 SkCanvas::kPoints_PointMode);
437 }
Ashok Bhata0398432014-01-20 20:08:01 +0000438
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800439 static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
440 jint offset, jint count, jobject jpaint) {
441 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
442 SkCanvas::kLines_PointMode);
443 }
Ashok Bhata0398432014-01-20 20:08:01 +0000444
445 static void drawPoint(JNIEnv* env, jobject jcanvas, jfloat x, jfloat y,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800446 jobject jpaint) {
447 NPE_CHECK_RETURN_VOID(env, jcanvas);
448 NPE_CHECK_RETURN_VOID(env, jpaint);
449 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
450 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
Ashok Bhata0398432014-01-20 20:08:01 +0000451
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800452 canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint);
453 }
Ashok Bhata0398432014-01-20 20:08:01 +0000454
455 static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800456 jfloat startX, jfloat startY, jfloat stopX,
Ashok Bhata0398432014-01-20 20:08:01 +0000457 jfloat stopY, jlong paintHandle) {
458 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
459 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800460 canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY),
461 SkFloatToScalar(stopX), SkFloatToScalar(stopY),
462 *paint);
463 }
Ashok Bhata0398432014-01-20 20:08:01 +0000464
465 static void drawRect__RectFPaint(JNIEnv* env, jobject, jlong canvasHandle,
466 jobject rect, jlong paintHandle) {
467 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
468 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800469 SkRect rect_;
470 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
471 canvas->drawRect(rect_, *paint);
472 }
Ashok Bhata0398432014-01-20 20:08:01 +0000473
474 static void drawRect__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800475 jfloat left, jfloat top, jfloat right,
Ashok Bhata0398432014-01-20 20:08:01 +0000476 jfloat bottom, jlong paintHandle) {
477 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
478 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800479 SkScalar left_ = SkFloatToScalar(left);
480 SkScalar top_ = SkFloatToScalar(top);
481 SkScalar right_ = SkFloatToScalar(right);
482 SkScalar bottom_ = SkFloatToScalar(bottom);
483 canvas->drawRectCoords(left_, top_, right_, bottom_, *paint);
484 }
Ashok Bhata0398432014-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 Bhata0398432014-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);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800499 canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy),
500 SkFloatToScalar(radius), *paint);
501 }
Ashok Bhata0398432014-01-20 20:08:01 +0000502
503 static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jobject joval,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800504 jfloat startAngle, jfloat sweepAngle,
Ashok Bhata0398432014-01-20 20:08:01 +0000505 jboolean useCenter, jlong paintHandle) {
506 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
507 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800508 SkRect oval;
509 GraphicsJNI::jrectf_to_rect(env, joval, &oval);
510 canvas->drawArc(oval, SkFloatToScalar(startAngle),
511 SkFloatToScalar(sweepAngle), useCenter, *paint);
512 }
Ashok Bhata0398432014-01-20 20:08:01 +0000513
514 static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800515 jobject jrect, jfloat rx, jfloat ry,
Ashok Bhata0398432014-01-20 20:08:01 +0000516 jlong paintHandle) {
517 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
518 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800519 SkRect rect;
520 GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
521 canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry),
522 *paint);
523 }
Ashok Bhata0398432014-01-20 20:08:01 +0000524
525 static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle,
526 jlong paintHandle) {
527 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
528 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
529 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800530 canvas->drawPath(*path, *paint);
531 }
Ashok Bhata0398432014-01-20 20:08:01 +0000532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
Ashok Bhata0398432014-01-20 20:08:01 +0000534 jlong canvasHandle, jlong bitmapHandle,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 jfloat left, jfloat top,
Ashok Bhata0398432014-01-20 20:08:01 +0000536 jlong paintHandle, jint canvasDensity,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700537 jint screenDensity, jint bitmapDensity) {
Ashok Bhata0398432014-01-20 20:08:01 +0000538 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
539 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
540 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800541 SkScalar left_ = SkFloatToScalar(left);
542 SkScalar top_ = SkFloatToScalar(top);
543
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700544 if (canvasDensity == bitmapDensity || canvasDensity == 0
545 || bitmapDensity == 0) {
Dianne Hackborn0d221012009-07-29 15:41:19 -0700546 if (screenDensity != 0 && screenDensity != bitmapDensity) {
547 SkPaint filteredPaint;
548 if (paint) {
549 filteredPaint = *paint;
550 }
551 filteredPaint.setFilterBitmap(true);
552 canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
553 } else {
554 canvas->drawBitmap(*bitmap, left_, top_, paint);
555 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800556 } else {
557 canvas->save();
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700558 SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
559 canvas->translate(left_, top_);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800560 canvas->scale(scale, scale);
561
562 SkPaint filteredPaint;
563 if (paint) {
564 filteredPaint = *paint;
565 }
566 filteredPaint.setFilterBitmap(true);
567
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700568 canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800569
570 canvas->restore();
571 }
572 }
573
574 static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700575 jobject srcIRect, const SkRect& dst, SkPaint* paint,
576 jint screenDensity, jint bitmapDensity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800577 SkIRect src, *srcPtr = NULL;
578
579 if (NULL != srcIRect) {
580 GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
581 srcPtr = &src;
582 }
Ashok Bhata0398432014-01-20 20:08:01 +0000583
Dianne Hackborn0d221012009-07-29 15:41:19 -0700584 if (screenDensity != 0 && screenDensity != bitmapDensity) {
585 SkPaint filteredPaint;
586 if (paint) {
587 filteredPaint = *paint;
588 }
589 filteredPaint.setFilterBitmap(true);
590 canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
591 } else {
592 canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
593 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800594 }
595
Ashok Bhata0398432014-01-20 20:08:01 +0000596 static void drawBitmapRF(JNIEnv* env, jobject, jlong canvasHandle,
597 jlong bitmapHandle, jobject srcIRect,
598 jobject dstRectF, jlong paintHandle,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700599 jint screenDensity, jint bitmapDensity) {
Ashok Bhata0398432014-01-20 20:08:01 +0000600 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
601 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
602 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800603 SkRect dst;
604 GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700605 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
606 screenDensity, bitmapDensity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800607 }
Ashok Bhata0398432014-01-20 20:08:01 +0000608
609 static void drawBitmapRR(JNIEnv* env, jobject, jlong canvasHandle,
610 jlong bitmapHandle, jobject srcIRect,
611 jobject dstRect, jlong paintHandle,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700612 jint screenDensity, jint bitmapDensity) {
Ashok Bhata0398432014-01-20 20:08:01 +0000613 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
614 SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
615 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800616 SkRect dst;
617 GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700618 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
619 screenDensity, bitmapDensity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800620 }
Ashok Bhata0398432014-01-20 20:08:01 +0000621
622 static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle,
623 jintArray jcolors, jint offset, jint stride,
624 jfloat x, jfloat y, jint width, jint height,
625 jboolean hasAlpha, jlong paintHandle)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800626 {
Ashok Bhata0398432014-01-20 20:08:01 +0000627 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
628 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800629 SkBitmap bitmap;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800630 bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
631 SkBitmap::kRGB_565_Config, width, height);
632 if (!bitmap.allocPixels()) {
633 return;
634 }
Chris Craik1abf5d62013-08-16 12:47:03 -0700635
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800636 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
Chris Craik1abf5d62013-08-16 12:47:03 -0700637 0, 0, width, height, bitmap, true)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800638 return;
639 }
Chris Craik1abf5d62013-08-16 12:47:03 -0700640
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
642 paint);
643 }
Ashok Bhata0398432014-01-20 20:08:01 +0000644
645 static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle,
646 jlong bitmapHandle, jlong matrixHandle,
647 jlong paintHandle) {
648 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
649 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
650 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
651 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800652 canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
653 }
Ashok Bhata0398432014-01-20 20:08:01 +0000654
655 static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle,
656 jlong bitmapHandle, jint meshWidth, jint meshHeight,
657 jfloatArray jverts, jint vertIndex, jintArray jcolors,
658 jint colorIndex, jlong paintHandle) {
659 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
660 const SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapHandle);
661 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662
663 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
664 const int indexCount = meshWidth * meshHeight * 6;
665
666 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
667 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
Ashok Bhata0398432014-01-20 20:08:01 +0000668
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800669 /* Our temp storage holds 2 or 3 arrays.
670 texture points [ptCount * sizeof(SkPoint)]
671 optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
672 copy to convert from float to fixed
673 indices [ptCount * sizeof(uint16_t)]
674 */
675 ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
676#ifdef SK_SCALAR_IS_FIXED
677 storageSize += ptCount * sizeof(SkPoint); // storage for verts
678#endif
679 storageSize += indexCount * sizeof(uint16_t); // indices[]
680
681 SkAutoMalloc storage(storageSize);
682 SkPoint* texs = (SkPoint*)storage.get();
683 SkPoint* verts;
684 uint16_t* indices;
685#ifdef SK_SCALAR_IS_FLOAT
686 verts = (SkPoint*)(vertA.ptr() + vertIndex);
687 indices = (uint16_t*)(texs + ptCount);
688#else
689 verts = texs + ptCount;
690 indices = (uint16_t*)(verts + ptCount);
691 // convert floats to fixed
692 {
693 const float* src = vertA.ptr() + vertIndex;
694 for (int i = 0; i < ptCount; i++) {
695 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
696 src += 2;
697 }
698 }
699#endif
700
701 // cons up texture coordinates and indices
702 {
703 const SkScalar w = SkIntToScalar(bitmap->width());
704 const SkScalar h = SkIntToScalar(bitmap->height());
705 const SkScalar dx = w / meshWidth;
706 const SkScalar dy = h / meshHeight;
Ashok Bhata0398432014-01-20 20:08:01 +0000707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800708 SkPoint* texsPtr = texs;
709 SkScalar y = 0;
710 for (int i = 0; i <= meshHeight; i++) {
711 if (i == meshHeight) {
712 y = h; // to ensure numerically we hit h exactly
713 }
714 SkScalar x = 0;
715 for (int j = 0; j < meshWidth; j++) {
716 texsPtr->set(x, y);
717 texsPtr += 1;
718 x += dx;
719 }
720 texsPtr->set(w, y);
721 texsPtr += 1;
722 y += dy;
723 }
724 SkASSERT(texsPtr - texs == ptCount);
725 }
Ashok Bhata0398432014-01-20 20:08:01 +0000726
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 // cons up indices
728 {
729 uint16_t* indexPtr = indices;
730 int index = 0;
731 for (int i = 0; i < meshHeight; i++) {
732 for (int j = 0; j < meshWidth; j++) {
733 // lower-left triangle
734 *indexPtr++ = index;
735 *indexPtr++ = index + meshWidth + 1;
736 *indexPtr++ = index + meshWidth + 2;
737 // upper-right triangle
738 *indexPtr++ = index;
739 *indexPtr++ = index + meshWidth + 2;
740 *indexPtr++ = index + 1;
741 // bump to the next cell
742 index += 1;
743 }
744 // bump to the next row
745 index += 1;
746 }
747 SkASSERT(indexPtr - indices == indexCount);
748 SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
749 }
750
751 // double-check that we have legal indices
752#ifdef SK_DEBUG
753 {
754 for (int i = 0; i < indexCount; i++) {
755 SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
756 }
757 }
758#endif
759
760 // cons-up a shader for the bitmap
761 SkPaint tmpPaint;
762 if (paint) {
763 tmpPaint = *paint;
764 }
765 SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
766 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
Derek Sollenberger6062c592011-02-22 13:55:04 -0500767 SkSafeUnref(tmpPaint.setShader(shader));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800768
769 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
770 texs, (const SkColor*)colorA.ptr(), NULL, indices,
771 indexCount, tmpPaint);
772 }
773
Ashok Bhata0398432014-01-20 20:08:01 +0000774 static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle,
775 jint modeHandle, jint vertexCount,
776 jfloatArray jverts, jint vertIndex,
777 jfloatArray jtexs, jint texIndex,
778 jintArray jcolors, jint colorIndex,
779 jshortArray jindices, jint indexIndex,
780 jint indexCount, jlong paintHandle) {
781 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
782 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle);
783 const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800784
785 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
786 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
787 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
788 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
789
790 const int ptCount = vertexCount >> 1;
791
792 SkPoint* verts;
793 SkPoint* texs = NULL;
794#ifdef SK_SCALAR_IS_FLOAT
795 verts = (SkPoint*)(vertA.ptr() + vertIndex);
796 if (jtexs != NULL) {
797 texs = (SkPoint*)(texA.ptr() + texIndex);
798 }
799#else
800 int count = ptCount; // for verts
801 if (jtexs != NULL) {
802 count += ptCount; // += for texs
803 }
804 SkAutoMalloc storage(count * sizeof(SkPoint));
Ashok Bhata0398432014-01-20 20:08:01 +0000805 verts = (SkPoint*)storage.get();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800806 const float* src = vertA.ptr() + vertIndex;
807 for (int i = 0; i < ptCount; i++) {
808 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
809 src += 2;
810 }
811 if (jtexs != NULL) {
812 texs = verts + ptCount;
813 src = texA.ptr() + texIndex;
814 for (int i = 0; i < ptCount; i++) {
815 texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
816 src += 2;
817 }
818 }
819#endif
820
821 const SkColor* colors = NULL;
822 const uint16_t* indices = NULL;
823 if (jcolors != NULL) {
824 colors = (const SkColor*)(colorA.ptr() + colorIndex);
825 }
826 if (jindices != NULL) {
827 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
828 }
829
830 canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
831 indices, indexCount, *paint);
832 }
Doug Feltf47d7402010-04-21 16:01:52 -0700833
Doug Felt0c702b82010-05-14 10:55:42 -0700834
Ashok Bhata0398432014-01-20 20:08:01 +0000835 static void drawText___CIIFFIPaint(JNIEnv* env, jobject, jlong canvasHandle,
836 jcharArray text, jint index, jint count,
837 jfloat x, jfloat y, jint flags, jlong paintHandle) {
838 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
839 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700840 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700841 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint);
Doug Feltf47d7402010-04-21 16:01:52 -0700842 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800843 }
Doug Felt0c702b82010-05-14 10:55:42 -0700844
Fabrice Di Meglio19f46b02013-03-15 11:26:23 -0700845 static void drawText__StringIIFFIPaint(JNIEnv* env, jobject,
Ashok Bhata0398432014-01-20 20:08:01 +0000846 jlong canvasHandle, jstring text,
847 jint start, jint end,
848 jfloat x, jfloat y, jint flags, jlong paintHandle) {
849 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
850 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700851 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700852 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint);
Doug Feltf47d7402010-04-21 16:01:52 -0700853 env->ReleaseStringChars(text, textArray);
854 }
Doug Felt0c702b82010-05-14 10:55:42 -0700855
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700856 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
857 int start, int end,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700858 jfloat x, jfloat y, int flags, SkPaint* paint) {
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700859
860 jint count = end - start;
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700861 drawTextWithGlyphs(canvas, textArray + start, 0, count, count, x, y, flags, paint);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700862 }
863
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700864 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
865 int start, int count, int contextCount,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700866 jfloat x, jfloat y, int flags, SkPaint* paint) {
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700867
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800868 sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700869 textArray, start, count, contextCount, flags);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700870 if (value == NULL) {
Fabrice Di Meglioa731b082012-01-23 18:18:45 -0800871 return;
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700872 }
Raph Levien2301d322012-07-17 16:39:49 -0700873 SkPaint::Align align = paint->getTextAlign();
874 if (align == SkPaint::kCenter_Align) {
875 x -= 0.5 * value->getTotalAdvance();
876 } else if (align == SkPaint::kRight_Align) {
877 x -= value->getTotalAdvance();
878 }
879 paint->setTextAlign(SkPaint::kLeft_Align);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700880 doDrawGlyphsPos(canvas, value->getGlyphs(), value->getPos(), 0, value->getGlyphsCount(), x, y, flags, paint);
Raph Levien2301d322012-07-17 16:39:49 -0700881 doDrawTextDecorations(canvas, x, y, value->getTotalAdvance(), paint);
882 paint->setTextAlign(align);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700883 }
884
Raph Levien2301d322012-07-17 16:39:49 -0700885// Same values used by Skia
886#define kStdStrikeThru_Offset (-6.0f / 21.0f)
887#define kStdUnderline_Offset (1.0f / 9.0f)
888#define kStdUnderline_Thickness (1.0f / 18.0f)
889
890static void doDrawTextDecorations(SkCanvas* canvas, jfloat x, jfloat y, jfloat length, SkPaint* paint) {
Raph Leviene174ae22012-10-03 15:26:47 -0700891 uint32_t flags;
892 SkDrawFilter* drawFilter = canvas->getDrawFilter();
893 if (drawFilter) {
894 SkPaint paintCopy(*paint);
895 drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
896 flags = paintCopy.getFlags();
897 } else {
898 flags = paint->getFlags();
899 }
Raph Levien2301d322012-07-17 16:39:49 -0700900 if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
901 SkScalar left = SkFloatToScalar(x);
902 SkScalar right = SkFloatToScalar(x + length);
903 float textSize = paint->getTextSize();
904 float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
905 if (flags & SkPaint::kUnderlineText_Flag) {
906 SkScalar top = SkFloatToScalar(y + textSize * kStdUnderline_Offset
907 - 0.5f * strokeWidth);
908 SkScalar bottom = SkFloatToScalar(y + textSize * kStdUnderline_Offset
909 + 0.5f * strokeWidth);
910 canvas->drawRectCoords(left, top, right, bottom, *paint);
911 }
912 if (flags & SkPaint::kStrikeThruText_Flag) {
913 SkScalar top = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
914 - 0.5f * strokeWidth);
915 SkScalar bottom = SkFloatToScalar(y + textSize * kStdStrikeThru_Offset
916 + 0.5f * strokeWidth);
917 canvas->drawRectCoords(left, top, right, bottom, *paint);
918 }
919 }
920}
921
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700922 static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
923 jfloat x, jfloat y, int flags, SkPaint* paint) {
924 // Beware: this needs Glyph encoding (already done on the Paint constructor)
925 canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
926 }
927
Raph Levien2301d322012-07-17 16:39:49 -0700928 static void doDrawGlyphsPos(SkCanvas* canvas, const jchar* glyphArray, const jfloat* posArray,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700929 int index, int count, jfloat x, jfloat y, int flags, SkPaint* paint) {
Raph Levien2301d322012-07-17 16:39:49 -0700930 SkPoint* posPtr = new SkPoint[count];
931 for (int indx = 0; indx < count; indx++) {
932 posPtr[indx].fX = SkFloatToScalar(x + posArray[indx * 2]);
933 posPtr[indx].fY = SkFloatToScalar(y + posArray[indx * 2 + 1]);
934 }
935 canvas->drawPosText(glyphArray, count << 1, posPtr, *paint);
936 delete[] posPtr;
937 }
938
Fabrice Di Meglio19f46b02013-03-15 11:26:23 -0700939 static void drawTextRun___CIIIIFFIPaint(
Ashok Bhata0398432014-01-20 20:08:01 +0000940 JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index,
941 jint count, jint contextIndex, jint contextCount,
942 jfloat x, jfloat y, jint dirFlags, jlong paintHandle) {
943 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
944 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700945
Doug Feltf47d7402010-04-21 16:01:52 -0700946 jchar* chars = env->GetCharArrayElements(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700947 drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700948 count, contextCount, x, y, dirFlags, paint);
Doug Feltf47d7402010-04-21 16:01:52 -0700949 env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
950 }
951
Fabrice Di Meglio19f46b02013-03-15 11:26:23 -0700952 static void drawTextRun__StringIIIIFFIPaint(
Ashok Bhata0398432014-01-20 20:08:01 +0000953 JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, jint start,
Doug Felt0c702b82010-05-14 10:55:42 -0700954 jint end, jint contextStart, jint contextEnd,
Ashok Bhata0398432014-01-20 20:08:01 +0000955 jfloat x, jfloat y, jint dirFlags, jlong paintHandle) {
956 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
957 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
Doug Feltf47d7402010-04-21 16:01:52 -0700958
Doug Felt0c702b82010-05-14 10:55:42 -0700959 jint count = end - start;
960 jint contextCount = contextEnd - contextStart;
Doug Feltf47d7402010-04-21 16:01:52 -0700961 const jchar* chars = env->GetStringChars(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700962 drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
Fabrice Di Meglioda12f382013-03-15 11:26:56 -0700963 count, contextCount, x, y, dirFlags, paint);
Doug Feltf47d7402010-04-21 16:01:52 -0700964 env->ReleaseStringChars(text, chars);
965 }
966
Ashok Bhata0398432014-01-20 20:08:01 +0000967 static void drawPosText___CII_FPaint(JNIEnv* env, jobject, jlong canvasHandle,
968 jcharArray text, jint index, jint count,
969 jfloatArray pos, jlong paintHandle) {
970 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
971 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800972 jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
973 jsize textCount = text ? env->GetArrayLength(text) : NULL;
974 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
975 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
976 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
977 int indx;
978 for (indx = 0; indx < posCount; indx++) {
979 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
980 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
981 }
Ashok Bhata0398432014-01-20 20:08:01 +0000982
Romain Guy62b6eaa2012-01-17 14:52:13 -0800983 SkPaint::TextEncoding encoding = paint->getTextEncoding();
984 paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
Mike Reedad8b8f52009-05-01 08:24:01 -0400985 canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
Romain Guy62b6eaa2012-01-17 14:52:13 -0800986 paint->setTextEncoding(encoding);
Ashok Bhata0398432014-01-20 20:08:01 +0000987
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800988 if (text) {
989 env->ReleaseCharArrayElements(text, textArray, 0);
990 }
991 if (pos) {
992 env->ReleaseFloatArrayElements(pos, posArray, 0);
993 }
994 delete[] posPtr;
995 }
Doug Felt0c702b82010-05-14 10:55:42 -0700996
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800997 static void drawPosText__String_FPaint(JNIEnv* env, jobject,
Ashok Bhata0398432014-01-20 20:08:01 +0000998 jlong canvasHandle, jstring text,
Doug Felt4beb8ff72010-06-09 13:53:24 -0700999 jfloatArray pos,
Ashok Bhata0398432014-01-20 20:08:01 +00001000 jlong paintHandle) {
1001 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1002 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001003 const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
1004 int byteLength = text ? env->GetStringLength(text) : 0;
1005 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
1006 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
1007 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
1008
1009 for (int indx = 0; indx < posCount; indx++) {
1010 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
1011 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
1012 }
Romain Guy62b6eaa2012-01-17 14:52:13 -08001013
1014 SkPaint::TextEncoding encoding = paint->getTextEncoding();
1015 paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001016 canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
Romain Guy62b6eaa2012-01-17 14:52:13 -08001017 paint->setTextEncoding(encoding);
1018
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 if (text) {
1020 env->ReleaseStringChars(text, (const jchar*) text_);
1021 }
1022 if (pos) {
1023 env->ReleaseFloatArrayElements(pos, posArray, 0);
1024 }
1025 delete[] posPtr;
1026 }
Doug Felt0c702b82010-05-14 10:55:42 -07001027
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001028 static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
Ashok Bhata0398432014-01-20 20:08:01 +00001029 jlong canvasHandle, jcharArray text, jint index, jint count,
1030 jlong pathHandle, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
1031 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1032 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1033 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001034
1035 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001036 TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
1037 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001038 env->ReleaseCharArrayElements(text, textArray, 0);
1039 }
Doug Felt0c702b82010-05-14 10:55:42 -07001040
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
Ashok Bhata0398432014-01-20 20:08:01 +00001042 jlong canvasHandle, jstring text, jlong pathHandle,
1043 jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintHandle) {
1044 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1045 SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
1046 SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001047 const jchar* text_ = env->GetStringChars(text, NULL);
Doug Felt4beb8ff72010-06-09 13:53:24 -07001048 int count = env->GetStringLength(text);
Fabrice Di Meglioda12f382013-03-15 11:26:56 -07001049 TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
1050 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001051 env->ReleaseStringChars(text, text_);
1052 }
Doug Felt0c702b82010-05-14 10:55:42 -07001053
Derek Sollenberger00a33a82013-05-16 09:31:27 -04001054
1055 // This function is a mirror of SkCanvas::getClipBounds except that it does
1056 // not outset the edge of the clip to account for anti-aliasing. There is
1057 // a skia bug to investigate pushing this logic into back into skia.
1058 // (see https://code.google.com/p/skia/issues/detail?id=1303)
1059 static bool getHardClipBounds(SkCanvas* canvas, SkRect* bounds) {
1060 SkIRect ibounds;
1061 if (!canvas->getClipDeviceBounds(&ibounds)) {
1062 return false;
1063 }
1064
1065 SkMatrix inverse;
1066 // if we can't invert the CTM, we can't return local clip bounds
1067 if (!canvas->getTotalMatrix().invert(&inverse)) {
1068 if (bounds) {
1069 bounds->setEmpty();
1070 }
1071 return false;
1072 }
1073
1074 if (NULL != bounds) {
1075 SkRect r = SkRect::Make(ibounds);
1076 inverse.mapRect(bounds, r);
1077 }
1078 return true;
1079 }
1080
Ashok Bhata0398432014-01-20 20:08:01 +00001081 static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle,
1082 jobject bounds) {
1083 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 SkRect r;
1085 SkIRect ir;
Derek Sollenberger00a33a82013-05-16 09:31:27 -04001086 bool result = getHardClipBounds(canvas, &r);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001087
Chet Haase6a2d17f2012-09-30 12:14:13 -07001088 if (!result) {
1089 r.setEmpty();
1090 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001091 r.round(&ir);
Derek Sollenbergerca79cf62012-08-14 16:44:52 -04001092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
Ashok Bhata0398432014-01-20 20:08:01 +00001094 return result ? JNI_TRUE : JNI_FALSE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001095 }
1096
Ashok Bhata0398432014-01-20 20:08:01 +00001097 static void getCTM(JNIEnv* env, jobject, jlong canvasHandle,
1098 jlong matrixHandle) {
1099 SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
1100 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 *matrix = canvas->getTotalMatrix();
1102 }
1103};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001104
1105static JNINativeMethod gCanvasMethods[] = {
Ashok Bhata0398432014-01-20 20:08:01 +00001106 {"finalizer", "(J)V", (void*) SkCanvasGlue::finalizer},
1107 {"initRaster","(J)J", (void*) SkCanvasGlue::initRaster},
1108 {"copyNativeCanvasState","(JJ)V", (void*) SkCanvasGlue::copyCanvasState},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001109 {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
1110 {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
1111 {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001112 {"save","()I", (void*) SkCanvasGlue::saveAll},
1113 {"save","(I)I", (void*) SkCanvasGlue::save},
Ashok Bhata0398432014-01-20 20:08:01 +00001114 {"native_saveLayer","(JLandroid/graphics/RectF;JI)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001115 (void*) SkCanvasGlue::saveLayer},
Ashok Bhata0398432014-01-20 20:08:01 +00001116 {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer4F},
1117 {"native_saveLayerAlpha","(JLandroid/graphics/RectF;II)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001118 (void*) SkCanvasGlue::saveLayerAlpha},
Ashok Bhata0398432014-01-20 20:08:01 +00001119 {"native_saveLayerAlpha","(JFFFFII)I",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 (void*) SkCanvasGlue::saveLayerAlpha4F},
1121 {"restore","()V", (void*) SkCanvasGlue::restore},
1122 {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
1123 {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
1124 {"translate","(FF)V", (void*) SkCanvasGlue::translate},
1125 {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
1126 {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
1127 {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
Ashok Bhata0398432014-01-20 20:08:01 +00001128 {"native_concat","(JJ)V", (void*) SkCanvasGlue::concat},
1129 {"native_setMatrix","(JJ)V", (void*) SkCanvasGlue::setMatrix},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
1131 {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
1132 {"clipRect","(Landroid/graphics/RectF;)Z",
1133 (void*) SkCanvasGlue::clipRect_RectF},
1134 {"clipRect","(Landroid/graphics/Rect;)Z",
1135 (void*) SkCanvasGlue::clipRect_Rect},
Ashok Bhata0398432014-01-20 20:08:01 +00001136 {"native_clipRect","(JFFFFI)Z", (void*) SkCanvasGlue::clipRect},
1137 {"native_clipPath","(JJI)Z", (void*) SkCanvasGlue::clipPath},
1138 {"native_clipRegion","(JJI)Z", (void*) SkCanvasGlue::clipRegion},
1139 {"nativeSetDrawFilter", "(JJ)V", (void*) SkCanvasGlue::setDrawFilter},
1140 {"native_getClipBounds","(JLandroid/graphics/Rect;)Z",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001141 (void*) SkCanvasGlue::getClipBounds},
Ashok Bhata0398432014-01-20 20:08:01 +00001142 {"native_getCTM", "(JJ)V", (void*)SkCanvasGlue::getCTM},
1143 {"native_quickReject","(JLandroid/graphics/RectF;)Z",
Derek Sollenbergerca79cf62012-08-14 16:44:52 -04001144 (void*) SkCanvasGlue::quickReject__RectF},
Ashok Bhata0398432014-01-20 20:08:01 +00001145 {"native_quickReject","(JJ)Z", (void*) SkCanvasGlue::quickReject__Path},
1146 {"native_quickReject","(JFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
1147 {"native_drawRGB","(JIII)V", (void*) SkCanvasGlue::drawRGB},
1148 {"native_drawARGB","(JIIII)V", (void*) SkCanvasGlue::drawARGB},
1149 {"native_drawColor","(JI)V", (void*) SkCanvasGlue::drawColor__I},
1150 {"native_drawColor","(JII)V", (void*) SkCanvasGlue::drawColor__II},
1151 {"native_drawPaint","(JJ)V", (void*) SkCanvasGlue::drawPaint},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 {"drawPoint", "(FFLandroid/graphics/Paint;)V",
1153 (void*) SkCanvasGlue::drawPoint},
1154 {"drawPoints", "([FIILandroid/graphics/Paint;)V",
1155 (void*) SkCanvasGlue::drawPoints},
1156 {"drawLines", "([FIILandroid/graphics/Paint;)V",
1157 (void*) SkCanvasGlue::drawLines},
Ashok Bhata0398432014-01-20 20:08:01 +00001158 {"native_drawLine","(JFFFFJ)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
1159 {"native_drawRect","(JLandroid/graphics/RectF;J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001160 (void*) SkCanvasGlue::drawRect__RectFPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001161 {"native_drawRect","(JFFFFJ)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
1162 {"native_drawOval","(JLandroid/graphics/RectF;J)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001163 (void*) SkCanvasGlue::drawOval},
Ashok Bhata0398432014-01-20 20:08:01 +00001164 {"native_drawCircle","(JFFFJ)V", (void*) SkCanvasGlue::drawCircle},
1165 {"native_drawArc","(JLandroid/graphics/RectF;FFZJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 (void*) SkCanvasGlue::drawArc},
Ashok Bhata0398432014-01-20 20:08:01 +00001167 {"native_drawRoundRect","(JLandroid/graphics/RectF;FFJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001168 (void*) SkCanvasGlue::drawRoundRect},
Ashok Bhata0398432014-01-20 20:08:01 +00001169 {"native_drawPath","(JJJ)V", (void*) SkCanvasGlue::drawPath},
1170 {"native_drawBitmap","(JJFFJIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001171 (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001172 {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/RectF;JII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 (void*) SkCanvasGlue::drawBitmapRF},
Ashok Bhata0398432014-01-20 20:08:01 +00001174 {"native_drawBitmap","(JJLandroid/graphics/Rect;Landroid/graphics/Rect;JII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001175 (void*) SkCanvasGlue::drawBitmapRR},
Ashok Bhata0398432014-01-20 20:08:01 +00001176 {"native_drawBitmap", "(J[IIIFFIIZJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001177 (void*)SkCanvasGlue::drawBitmapArray},
Ashok Bhata0398432014-01-20 20:08:01 +00001178 {"nativeDrawBitmapMatrix", "(JJJJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001179 (void*)SkCanvasGlue::drawBitmapMatrix},
Ashok Bhata0398432014-01-20 20:08:01 +00001180 {"nativeDrawBitmapMesh", "(JJII[FI[IIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 (void*)SkCanvasGlue::drawBitmapMesh},
Ashok Bhata0398432014-01-20 20:08:01 +00001182 {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001183 (void*)SkCanvasGlue::drawVertices},
Ashok Bhata0398432014-01-20 20:08:01 +00001184 {"native_drawText","(J[CIIFFIJ)V",
Fabrice Di Meglio19f46b02013-03-15 11:26:23 -07001185 (void*) SkCanvasGlue::drawText___CIIFFIPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001186 {"native_drawText","(JLjava/lang/String;IIFFIJ)V",
Fabrice Di Meglio19f46b02013-03-15 11:26:23 -07001187 (void*) SkCanvasGlue::drawText__StringIIFFIPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001188 {"native_drawTextRun","(J[CIIIIFFIJ)V",
Fabrice Di Meglio19f46b02013-03-15 11:26:23 -07001189 (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001190 {"native_drawTextRun","(JLjava/lang/String;IIIIFFIJ)V",
Fabrice Di Meglio19f46b02013-03-15 11:26:23 -07001191 (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001192 {"native_drawPosText","(J[CII[FJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001193 (void*) SkCanvasGlue::drawPosText___CII_FPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001194 {"native_drawPosText","(JLjava/lang/String;[FJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001195 (void*) SkCanvasGlue::drawPosText__String_FPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001196 {"native_drawTextOnPath","(J[CIIJFFIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
Ashok Bhata0398432014-01-20 20:08:01 +00001198 {"native_drawTextOnPath","(JLjava/lang/String;JFFIJ)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001199 (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001200
Fabrice Di Meglio30ca5cd2012-05-07 17:45:44 -07001201 {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches},
1202
1203 {"freeTextLayoutCaches", "()V", (void*) SkCanvasGlue::freeTextLayoutCaches}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001204};
1205
Mike Reedc04851f2009-10-28 15:09:45 -04001206///////////////////////////////////////////////////////////////////////////////
1207
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001208#include <android_runtime/AndroidRuntime.h>
1209
1210#define REG(env, name, array) \
1211 result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
1212 SK_ARRAY_COUNT(array)); \
1213 if (result < 0) return result
1214
1215int register_android_graphics_Canvas(JNIEnv* env) {
1216 int result;
1217
1218 REG(env, "android/graphics/Canvas", gCanvasMethods);
Ashok Bhata0398432014-01-20 20:08:01 +00001219
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001220 return result;
1221}
1222
1223}