blob: 2dceab9b4007d712b193e80d95428a80d97d6fe9 [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"
Mike Reedcaf0df12009-04-27 14:32:05 -040023#include "SkGraphics.h"
24#include "SkImageRef_GlobalPool.h"
Mike Reed47c0d4e2009-06-22 22:53:52 -040025#include "SkPorterDuff.h"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026#include "SkShader.h"
27#include "SkTemplates.h"
28
Doug Feltf7cb1f72010-07-01 16:20:43 -070029#include "TextLayout.h"
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -070030#include "TextLayoutCache.h"
Doug Feltf7cb1f72010-07-01 16:20:43 -070031
Doug Feltf47d7402010-04-21 16:01:52 -070032#include "unicode/ubidi.h"
Doug Felt0c702b82010-05-14 10:55:42 -070033#include "unicode/ushape.h"
34
Doug Felt0c702b82010-05-14 10:55:42 -070035#include <utils/Log.h>
Doug Feltf47d7402010-04-21 16:01:52 -070036
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037#define TIME_DRAWx
38
39static uint32_t get_thread_msec() {
40#if defined(HAVE_POSIX_CLOCKS)
41 struct timespec tm;
42
43 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tm);
44
45 return tm.tv_sec * 1000LL + tm.tv_nsec / 1000000;
46#else
47 struct timeval tv;
48
49 gettimeofday(&tv, NULL);
50 return tv.tv_sec * 1000LL + tv.tv_usec / 1000;
51#endif
52}
53
54namespace android {
55
56class SkCanvasGlue {
57public:
58
59 static void finalizer(JNIEnv* env, jobject clazz, SkCanvas* canvas) {
60 canvas->unref();
61 }
62
63 static SkCanvas* initRaster(JNIEnv* env, jobject, SkBitmap* bitmap) {
64 return bitmap ? new SkCanvas(*bitmap) : new SkCanvas;
65 }
66
Mike Reedcaf0df12009-04-27 14:32:05 -040067 static void freeCaches(JNIEnv* env, jobject) {
68 // these are called in no particular order
Mike Reedcaf0df12009-04-27 14:32:05 -040069 SkImageRef_GlobalPool::SetRAMUsed(0);
70 SkGraphics::SetFontCacheUsed(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071 }
72
73 static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
74 NPE_CHECK_RETURN_ZERO(env, jcanvas);
75 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
76
77 /*
78 Currently we cannot support transparency in GL-based canvas' at
79 the view level. Therefore we cannot base our answer on the device's
80 bitmap, but need to hard-code the answer. If we relax this
81 limitation in views, we can simplify the following code as well.
82
83 Use the getViewport() call to find out if we're gl-based...
84 */
85 if (canvas->getViewport(NULL)) {
86 return true;
87 }
88
89 // normal technique, rely on the device's bitmap for the answer
90 return canvas->getDevice()->accessBitmap(false).isOpaque();
91 }
92
93 static int getWidth(JNIEnv* env, jobject jcanvas) {
94 NPE_CHECK_RETURN_ZERO(env, jcanvas);
95 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
96 return canvas->getDevice()->accessBitmap(false).width();
97 }
98
99 static int getHeight(JNIEnv* env, jobject jcanvas) {
100 NPE_CHECK_RETURN_ZERO(env, jcanvas);
101 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
102 return canvas->getDevice()->accessBitmap(false).height();
103 }
104
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800105 static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas,
106 SkBitmap* bitmap) {
107 canvas->setBitmapDevice(*bitmap);
108 }
109
110 static int saveAll(JNIEnv* env, jobject jcanvas) {
111 NPE_CHECK_RETURN_ZERO(env, jcanvas);
112 return GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
113 }
114
115 static int save(JNIEnv* env, jobject jcanvas, SkCanvas::SaveFlags flags) {
116 NPE_CHECK_RETURN_ZERO(env, jcanvas);
117 return GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
118 }
119
120 static int saveLayer(JNIEnv* env, jobject, SkCanvas* canvas, jobject bounds,
121 SkPaint* paint, int flags) {
122 SkRect* bounds_ = NULL;
123 SkRect storage;
124 if (bounds != NULL) {
125 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
126 bounds_ = &storage;
127 }
128 return canvas->saveLayer(bounds_, paint, (SkCanvas::SaveFlags)flags);
129 }
130
131 static int saveLayer4F(JNIEnv* env, jobject, SkCanvas* canvas,
132 jfloat l, jfloat t, jfloat r, jfloat b,
133 SkPaint* paint, int flags) {
134 SkRect bounds;
135 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
136 SkFloatToScalar(b));
137 return canvas->saveLayer(&bounds, paint, (SkCanvas::SaveFlags)flags);
138 }
139
140 static int saveLayerAlpha(JNIEnv* env, jobject, SkCanvas* canvas,
141 jobject bounds, int alpha, int flags) {
142 SkRect* bounds_ = NULL;
143 SkRect storage;
144 if (bounds != NULL) {
145 GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
146 bounds_ = &storage;
147 }
148 return canvas->saveLayerAlpha(bounds_, alpha,
149 (SkCanvas::SaveFlags)flags);
150 }
151
152 static int saveLayerAlpha4F(JNIEnv* env, jobject, SkCanvas* canvas,
153 jfloat l, jfloat t, jfloat r, jfloat b,
154 int alpha, int flags) {
155 SkRect bounds;
156 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r),
157 SkFloatToScalar(b));
158 return canvas->saveLayerAlpha(&bounds, alpha,
159 (SkCanvas::SaveFlags)flags);
160 }
161
162 static void restore(JNIEnv* env, jobject jcanvas) {
163 NPE_CHECK_RETURN_VOID(env, jcanvas);
164 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
165 if (canvas->getSaveCount() <= 1) { // cannot restore anymore
166 doThrowISE(env, "Underflow in restore");
167 return;
168 }
169 canvas->restore();
170 }
171
172 static int getSaveCount(JNIEnv* env, jobject jcanvas) {
173 NPE_CHECK_RETURN_ZERO(env, jcanvas);
174 return GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
175 }
176
177 static void restoreToCount(JNIEnv* env, jobject jcanvas, int restoreCount) {
178 NPE_CHECK_RETURN_VOID(env, jcanvas);
179 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
180 if (restoreCount < 1) {
181 doThrowIAE(env, "Underflow in restoreToCount");
182 return;
183 }
184 canvas->restoreToCount(restoreCount);
185 }
186
187 static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
188 NPE_CHECK_RETURN_VOID(env, jcanvas);
189 SkScalar dx_ = SkFloatToScalar(dx);
190 SkScalar dy_ = SkFloatToScalar(dy);
191 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_);
192 }
193
194 static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
195 NPE_CHECK_RETURN_VOID(env, jcanvas);
196 SkScalar sx_ = SkFloatToScalar(sx);
197 SkScalar sy_ = SkFloatToScalar(sy);
198 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_);
199 }
200
201 static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
202 NPE_CHECK_RETURN_VOID(env, jcanvas);
203 SkScalar degrees_ = SkFloatToScalar(degrees);
204 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_);
205 }
206
207 static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
208 NPE_CHECK_RETURN_VOID(env, jcanvas);
209 SkScalar sx_ = SkFloatToScalar(sx);
210 SkScalar sy_ = SkFloatToScalar(sy);
211 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_);
212 }
213
214 static void concat(JNIEnv* env, jobject, SkCanvas* canvas,
215 const SkMatrix* matrix) {
216 canvas->concat(*matrix);
217 }
218
219 static void setMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
220 const SkMatrix* matrix) {
221 if (NULL == matrix) {
222 canvas->resetMatrix();
223 } else {
224 canvas->setMatrix(*matrix);
225 }
226 }
227
228 static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
229 jfloat top, jfloat right, jfloat bottom) {
230 NPE_CHECK_RETURN_ZERO(env, jcanvas);
231 SkRect r;
232 r.set(SkFloatToScalar(left), SkFloatToScalar(top),
233 SkFloatToScalar(right), SkFloatToScalar(bottom));
234 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
235 return c->clipRect(r);
236 }
237
238 static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
239 jint top, jint right, jint bottom) {
240 NPE_CHECK_RETURN_ZERO(env, jcanvas);
241 SkRect r;
242 r.set(SkIntToScalar(left), SkIntToScalar(top),
243 SkIntToScalar(right), SkIntToScalar(bottom));
244 return GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r);
245 }
246
247 static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
248 NPE_CHECK_RETURN_ZERO(env, jcanvas);
249 NPE_CHECK_RETURN_ZERO(env, rectf);
250 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
251 SkRect tmp;
252 return c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
253 }
254
255 static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
256 NPE_CHECK_RETURN_ZERO(env, jcanvas);
257 NPE_CHECK_RETURN_ZERO(env, rect);
258 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
259 SkRect tmp;
260 return c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
261 }
262
263 static jboolean clipRect(JNIEnv* env, jobject, SkCanvas* canvas,
264 float left, float top, float right, float bottom,
265 int op) {
266 SkRect rect;
267 rect.set(SkFloatToScalar(left), SkFloatToScalar(top),
268 SkFloatToScalar(right), SkFloatToScalar(bottom));
269 return canvas->clipRect(rect, (SkRegion::Op)op);
270 }
271
272 static jboolean clipPath(JNIEnv* env, jobject, SkCanvas* canvas,
273 SkPath* path, int op) {
274 return canvas->clipPath(*path, (SkRegion::Op)op);
275 }
276
277 static jboolean clipRegion(JNIEnv* env, jobject, SkCanvas* canvas,
278 SkRegion* deviceRgn, int op) {
279 return canvas->clipRegion(*deviceRgn, (SkRegion::Op)op);
280 }
281
282 static void setDrawFilter(JNIEnv* env, jobject, SkCanvas* canvas,
283 SkDrawFilter* filter) {
284 canvas->setDrawFilter(filter);
285 }
286
287 static jboolean quickReject__RectFI(JNIEnv* env, jobject, SkCanvas* canvas,
288 jobject rect, int edgetype) {
289 SkRect rect_;
290 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
291 return canvas->quickReject(rect_, (SkCanvas::EdgeType)edgetype);
292 }
293
294 static jboolean quickReject__PathI(JNIEnv* env, jobject, SkCanvas* canvas,
295 SkPath* path, int edgetype) {
296 return canvas->quickReject(*path, (SkCanvas::EdgeType)edgetype);
297 }
298
299 static jboolean quickReject__FFFFI(JNIEnv* env, jobject, SkCanvas* canvas,
300 jfloat left, jfloat top, jfloat right,
301 jfloat bottom, int edgetype) {
302 SkRect r;
303 r.set(SkFloatToScalar(left), SkFloatToScalar(top),
304 SkFloatToScalar(right), SkFloatToScalar(bottom));
305 return canvas->quickReject(r, (SkCanvas::EdgeType)edgetype);
306 }
307
308 static void drawRGB(JNIEnv* env, jobject, SkCanvas* canvas,
309 jint r, jint g, jint b) {
310 canvas->drawARGB(0xFF, r, g, b);
311 }
312
313 static void drawARGB(JNIEnv* env, jobject, SkCanvas* canvas,
314 jint a, jint r, jint g, jint b) {
315 canvas->drawARGB(a, r, g, b);
316 }
317
318 static void drawColor__I(JNIEnv* env, jobject, SkCanvas* canvas,
319 jint color) {
320 canvas->drawColor(color);
321 }
322
323 static void drawColor__II(JNIEnv* env, jobject, SkCanvas* canvas,
324 jint color, SkPorterDuff::Mode mode) {
Mike Reed47c0d4e2009-06-22 22:53:52 -0400325 canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800326 }
327
328 static void drawPaint(JNIEnv* env, jobject, SkCanvas* canvas,
329 SkPaint* paint) {
330 canvas->drawPaint(*paint);
331 }
332
333 static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
334 jint offset, jint count, jobject jpaint,
335 SkCanvas::PointMode mode) {
336 NPE_CHECK_RETURN_VOID(env, jcanvas);
337 NPE_CHECK_RETURN_VOID(env, jptsArray);
338 NPE_CHECK_RETURN_VOID(env, jpaint);
339 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
340 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
341
342 AutoJavaFloatArray autoPts(env, jptsArray);
343 float* floats = autoPts.ptr();
344 const int length = autoPts.length();
345
346 if ((offset | count) < 0 || offset + count > length) {
347 doThrowAIOOBE(env);
348 return;
349 }
350
351 // now convert the floats into SkPoints
352 count >>= 1; // now it is the number of points
353 SkAutoSTMalloc<32, SkPoint> storage(count);
354 SkPoint* pts = storage.get();
355 const float* src = floats + offset;
356 for (int i = 0; i < count; i++) {
357 pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1]));
358 src += 2;
359 }
360 canvas->drawPoints(mode, count, pts, paint);
361 }
362
363 static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
364 jint offset, jint count, jobject jpaint) {
365 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
366 SkCanvas::kPoints_PointMode);
367 }
368
369 static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
370 jint offset, jint count, jobject jpaint) {
371 doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
372 SkCanvas::kLines_PointMode);
373 }
374
375 static void drawPoint(JNIEnv* env, jobject jcanvas, float x, float y,
376 jobject jpaint) {
377 NPE_CHECK_RETURN_VOID(env, jcanvas);
378 NPE_CHECK_RETURN_VOID(env, jpaint);
379 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
380 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
381
382 canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint);
383 }
384
385 static void drawLine__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
386 jfloat startX, jfloat startY, jfloat stopX,
387 jfloat stopY, SkPaint* paint) {
388 canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY),
389 SkFloatToScalar(stopX), SkFloatToScalar(stopY),
390 *paint);
391 }
392
393 static void drawRect__RectFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
394 jobject rect, SkPaint* paint) {
395 SkRect rect_;
396 GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
397 canvas->drawRect(rect_, *paint);
398 }
399
400 static void drawRect__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas,
401 jfloat left, jfloat top, jfloat right,
402 jfloat bottom, SkPaint* paint) {
403 SkScalar left_ = SkFloatToScalar(left);
404 SkScalar top_ = SkFloatToScalar(top);
405 SkScalar right_ = SkFloatToScalar(right);
406 SkScalar bottom_ = SkFloatToScalar(bottom);
407 canvas->drawRectCoords(left_, top_, right_, bottom_, *paint);
408 }
409
410 static void drawOval(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
411 SkPaint* paint) {
412 SkRect oval;
413 GraphicsJNI::jrectf_to_rect(env, joval, &oval);
414 canvas->drawOval(oval, *paint);
415 }
416
417 static void drawCircle(JNIEnv* env, jobject, SkCanvas* canvas, jfloat cx,
418 jfloat cy, jfloat radius, SkPaint* paint) {
419 canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy),
420 SkFloatToScalar(radius), *paint);
421 }
422
423 static void drawArc(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval,
424 jfloat startAngle, jfloat sweepAngle,
425 jboolean useCenter, SkPaint* paint) {
426 SkRect oval;
427 GraphicsJNI::jrectf_to_rect(env, joval, &oval);
428 canvas->drawArc(oval, SkFloatToScalar(startAngle),
429 SkFloatToScalar(sweepAngle), useCenter, *paint);
430 }
431
432 static void drawRoundRect(JNIEnv* env, jobject, SkCanvas* canvas,
433 jobject jrect, jfloat rx, jfloat ry,
434 SkPaint* paint) {
435 SkRect rect;
436 GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
437 canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry),
438 *paint);
439 }
440
441 static void drawPath(JNIEnv* env, jobject, SkCanvas* canvas, SkPath* path,
442 SkPaint* paint) {
443 canvas->drawPath(*path, *paint);
444 }
445
446 static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas,
447 SkPicture* picture) {
448 SkASSERT(canvas);
449 SkASSERT(picture);
450
451#ifdef TIME_DRAW
452 SkMSec now = get_thread_msec(); //SkTime::GetMSecs();
453#endif
454 canvas->drawPicture(*picture);
455#ifdef TIME_DRAW
456 LOGD("---- picture playback %d ms\n", get_thread_msec() - now);
457#endif
458 }
459
460 static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas,
461 SkCanvas* canvas, SkBitmap* bitmap,
462 jfloat left, jfloat top,
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700463 SkPaint* paint, jint canvasDensity,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700464 jint screenDensity, jint bitmapDensity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800465 SkScalar left_ = SkFloatToScalar(left);
466 SkScalar top_ = SkFloatToScalar(top);
467
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700468 if (canvasDensity == bitmapDensity || canvasDensity == 0
469 || bitmapDensity == 0) {
Dianne Hackborn0d221012009-07-29 15:41:19 -0700470 if (screenDensity != 0 && screenDensity != bitmapDensity) {
471 SkPaint filteredPaint;
472 if (paint) {
473 filteredPaint = *paint;
474 }
475 filteredPaint.setFilterBitmap(true);
476 canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint);
477 } else {
478 canvas->drawBitmap(*bitmap, left_, top_, paint);
479 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800480 } else {
481 canvas->save();
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700482 SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity);
483 canvas->translate(left_, top_);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800484 canvas->scale(scale, scale);
485
486 SkPaint filteredPaint;
487 if (paint) {
488 filteredPaint = *paint;
489 }
490 filteredPaint.setFilterBitmap(true);
491
Dianne Hackborn11ea3342009-07-22 21:48:55 -0700492 canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800493
494 canvas->restore();
495 }
496 }
497
498 static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700499 jobject srcIRect, const SkRect& dst, SkPaint* paint,
500 jint screenDensity, jint bitmapDensity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 SkIRect src, *srcPtr = NULL;
502
503 if (NULL != srcIRect) {
504 GraphicsJNI::jrect_to_irect(env, srcIRect, &src);
505 srcPtr = &src;
506 }
Dianne Hackborn0d221012009-07-29 15:41:19 -0700507
508 if (screenDensity != 0 && screenDensity != bitmapDensity) {
509 SkPaint filteredPaint;
510 if (paint) {
511 filteredPaint = *paint;
512 }
513 filteredPaint.setFilterBitmap(true);
514 canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint);
515 } else {
516 canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint);
517 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800518 }
519
520 static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas,
521 SkBitmap* bitmap, jobject srcIRect,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700522 jobject dstRectF, SkPaint* paint,
523 jint screenDensity, jint bitmapDensity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800524 SkRect dst;
525 GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700526 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
527 screenDensity, bitmapDensity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800528 }
529
530 static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas,
531 SkBitmap* bitmap, jobject srcIRect,
Dianne Hackborn0d221012009-07-29 15:41:19 -0700532 jobject dstRect, SkPaint* paint,
533 jint screenDensity, jint bitmapDensity) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 SkRect dst;
535 GraphicsJNI::jrect_to_rect(env, dstRect, &dst);
Dianne Hackborn0d221012009-07-29 15:41:19 -0700536 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint,
537 screenDensity, bitmapDensity);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800538 }
539
540 static void drawBitmapArray(JNIEnv* env, jobject, SkCanvas* canvas,
541 jintArray jcolors, int offset, int stride,
542 jfloat x, jfloat y, int width, int height,
543 jboolean hasAlpha, SkPaint* paint)
544 {
545 SkBitmap bitmap;
546
547 bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config :
548 SkBitmap::kRGB_565_Config, width, height);
549 if (!bitmap.allocPixels()) {
550 return;
551 }
552
553 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride,
554 0, 0, width, height, bitmap)) {
555 return;
556 }
557
558 canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y),
559 paint);
560 }
561
562 static void drawBitmapMatrix(JNIEnv* env, jobject, SkCanvas* canvas,
563 const SkBitmap* bitmap, const SkMatrix* matrix,
564 const SkPaint* paint) {
565 canvas->drawBitmapMatrix(*bitmap, *matrix, paint);
566 }
567
568 static void drawBitmapMesh(JNIEnv* env, jobject, SkCanvas* canvas,
569 const SkBitmap* bitmap, int meshWidth, int meshHeight,
570 jfloatArray jverts, int vertIndex, jintArray jcolors,
571 int colorIndex, const SkPaint* paint) {
572
573 const int ptCount = (meshWidth + 1) * (meshHeight + 1);
574 const int indexCount = meshWidth * meshHeight * 6;
575
576 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1));
577 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount);
578
579 /* Our temp storage holds 2 or 3 arrays.
580 texture points [ptCount * sizeof(SkPoint)]
581 optionally vertex points [ptCount * sizeof(SkPoint)] if we need a
582 copy to convert from float to fixed
583 indices [ptCount * sizeof(uint16_t)]
584 */
585 ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[]
586#ifdef SK_SCALAR_IS_FIXED
587 storageSize += ptCount * sizeof(SkPoint); // storage for verts
588#endif
589 storageSize += indexCount * sizeof(uint16_t); // indices[]
590
591 SkAutoMalloc storage(storageSize);
592 SkPoint* texs = (SkPoint*)storage.get();
593 SkPoint* verts;
594 uint16_t* indices;
595#ifdef SK_SCALAR_IS_FLOAT
596 verts = (SkPoint*)(vertA.ptr() + vertIndex);
597 indices = (uint16_t*)(texs + ptCount);
598#else
599 verts = texs + ptCount;
600 indices = (uint16_t*)(verts + ptCount);
601 // convert floats to fixed
602 {
603 const float* src = vertA.ptr() + vertIndex;
604 for (int i = 0; i < ptCount; i++) {
605 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
606 src += 2;
607 }
608 }
609#endif
610
611 // cons up texture coordinates and indices
612 {
613 const SkScalar w = SkIntToScalar(bitmap->width());
614 const SkScalar h = SkIntToScalar(bitmap->height());
615 const SkScalar dx = w / meshWidth;
616 const SkScalar dy = h / meshHeight;
617
618 SkPoint* texsPtr = texs;
619 SkScalar y = 0;
620 for (int i = 0; i <= meshHeight; i++) {
621 if (i == meshHeight) {
622 y = h; // to ensure numerically we hit h exactly
623 }
624 SkScalar x = 0;
625 for (int j = 0; j < meshWidth; j++) {
626 texsPtr->set(x, y);
627 texsPtr += 1;
628 x += dx;
629 }
630 texsPtr->set(w, y);
631 texsPtr += 1;
632 y += dy;
633 }
634 SkASSERT(texsPtr - texs == ptCount);
635 }
636
637 // cons up indices
638 {
639 uint16_t* indexPtr = indices;
640 int index = 0;
641 for (int i = 0; i < meshHeight; i++) {
642 for (int j = 0; j < meshWidth; j++) {
643 // lower-left triangle
644 *indexPtr++ = index;
645 *indexPtr++ = index + meshWidth + 1;
646 *indexPtr++ = index + meshWidth + 2;
647 // upper-right triangle
648 *indexPtr++ = index;
649 *indexPtr++ = index + meshWidth + 2;
650 *indexPtr++ = index + 1;
651 // bump to the next cell
652 index += 1;
653 }
654 // bump to the next row
655 index += 1;
656 }
657 SkASSERT(indexPtr - indices == indexCount);
658 SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize);
659 }
660
661 // double-check that we have legal indices
662#ifdef SK_DEBUG
663 {
664 for (int i = 0; i < indexCount; i++) {
665 SkASSERT((unsigned)indices[i] < (unsigned)ptCount);
666 }
667 }
668#endif
669
670 // cons-up a shader for the bitmap
671 SkPaint tmpPaint;
672 if (paint) {
673 tmpPaint = *paint;
674 }
675 SkShader* shader = SkShader::CreateBitmapShader(*bitmap,
676 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode);
Derek Sollenberger6062c592011-02-22 13:55:04 -0500677 SkSafeUnref(tmpPaint.setShader(shader));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800678
679 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts,
680 texs, (const SkColor*)colorA.ptr(), NULL, indices,
681 indexCount, tmpPaint);
682 }
683
684 static void drawVertices(JNIEnv* env, jobject, SkCanvas* canvas,
685 SkCanvas::VertexMode mode, int vertexCount,
686 jfloatArray jverts, int vertIndex,
687 jfloatArray jtexs, int texIndex,
688 jintArray jcolors, int colorIndex,
689 jshortArray jindices, int indexIndex,
690 int indexCount, const SkPaint* paint) {
691
692 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount);
693 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount);
694 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount);
695 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount);
696
697 const int ptCount = vertexCount >> 1;
698
699 SkPoint* verts;
700 SkPoint* texs = NULL;
701#ifdef SK_SCALAR_IS_FLOAT
702 verts = (SkPoint*)(vertA.ptr() + vertIndex);
703 if (jtexs != NULL) {
704 texs = (SkPoint*)(texA.ptr() + texIndex);
705 }
706#else
707 int count = ptCount; // for verts
708 if (jtexs != NULL) {
709 count += ptCount; // += for texs
710 }
711 SkAutoMalloc storage(count * sizeof(SkPoint));
712 verts = (SkPoint*)storage.get();
713 const float* src = vertA.ptr() + vertIndex;
714 for (int i = 0; i < ptCount; i++) {
715 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
716 src += 2;
717 }
718 if (jtexs != NULL) {
719 texs = verts + ptCount;
720 src = texA.ptr() + texIndex;
721 for (int i = 0; i < ptCount; i++) {
722 texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1]));
723 src += 2;
724 }
725 }
726#endif
727
728 const SkColor* colors = NULL;
729 const uint16_t* indices = NULL;
730 if (jcolors != NULL) {
731 colors = (const SkColor*)(colorA.ptr() + colorIndex);
732 }
733 if (jindices != NULL) {
734 indices = (const uint16_t*)(indexA.ptr() + indexIndex);
735 }
736
737 canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL,
738 indices, indexCount, *paint);
739 }
Doug Feltf47d7402010-04-21 16:01:52 -0700740
Doug Felt0c702b82010-05-14 10:55:42 -0700741
Doug Feltf47d7402010-04-21 16:01:52 -0700742 static void drawText___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas,
743 jcharArray text, int index, int count,
744 jfloat x, jfloat y, int flags, SkPaint* paint) {
745 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700746#if RTL_USE_HARFBUZZ
747 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint);
748#else
Doug Feltf7cb1f72010-07-01 16:20:43 -0700749 TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700750#endif
Doug Feltf47d7402010-04-21 16:01:52 -0700751 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800752 }
Doug Felt0c702b82010-05-14 10:55:42 -0700753
Doug Feltf47d7402010-04-21 16:01:52 -0700754 static void drawText__StringIIFFIPaint(JNIEnv* env, jobject,
Doug Felt0c702b82010-05-14 10:55:42 -0700755 SkCanvas* canvas, jstring text,
Doug Feltf47d7402010-04-21 16:01:52 -0700756 int start, int end,
757 jfloat x, jfloat y, int flags, SkPaint* paint) {
758 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700759#if RTL_USE_HARFBUZZ
760 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint);
761#else
Doug Feltf7cb1f72010-07-01 16:20:43 -0700762 TextLayout::drawText(paint, textArray + start, end - start, flags, x, y, canvas);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700763#endif
Doug Feltf47d7402010-04-21 16:01:52 -0700764 env->ReleaseStringChars(text, textArray);
765 }
Doug Felt0c702b82010-05-14 10:55:42 -0700766
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700767 static void logGlyphs(sp<TextLayoutCacheValue> value) {
768 LOGD("drawTextWithGlyphs -- got glyphs - count=%d", value->getGlyphsCount());
769 for (size_t i = 0; i < value->getGlyphsCount(); i++) {
770 LOGD(" glyphs[%d]=%d", i, value->getGlyphs()[i]);
771 }
772 }
773
774 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
775 int start, int end,
776 jfloat x, jfloat y, int flags, SkPaint* paint) {
777
778 jint count = end - start;
779 sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue(
780 paint, textArray, start, count, count, flags);
781 if (value == NULL) {
782 LOGE("drawTextWithGlyphs -- cannot get Cache value");
783 return ;
784 }
785#if DEBUG_GLYPHS
786 logGlyphs(value);
787#endif
788 doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(),
789 x, y, flags, paint);
790 }
791
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700792 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray,
793 int start, int count, int contextCount,
794 jfloat x, jfloat y, int flags, SkPaint* paint) {
795
796 sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue(
797 paint, textArray, start, count, contextCount, flags);
798 if (value == NULL) {
799 LOGE("drawTextWithGlyphs -- cannot get Cache value");
800 return ;
801 }
802#if DEBUG_GLYPHS
803 logGlyphs(value);
804#endif
805 doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(),
806 x, y, flags, paint);
807 }
808
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700809 static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas,
810 jcharArray text, int index, int count,
811 jfloat x, jfloat y, int flags, SkPaint* paint) {
812 jchar* textArray = env->GetCharArrayElements(text, NULL);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700813 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint);
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700814 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT);
815 }
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800816
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700817 static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject,
818 SkCanvas* canvas, jstring text,
819 int start, int end,
820 jfloat x, jfloat y, int flags, SkPaint* paint) {
821
822 const jchar* textArray = env->GetStringChars(text, NULL);
Fabrice Di Meglio689e5152011-04-13 16:07:37 -0700823 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint);
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700824 env->ReleaseStringChars(text, textArray);
825 }
826
827 static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count,
828 jfloat x, jfloat y, int flags, SkPaint* paint) {
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800829 // TODO: need to suppress this code after the GL renderer is modified for not
830 // copying the paint
831
832 // Save old text encoding
833 SkPaint::TextEncoding oldEncoding = paint->getTextEncoding();
834 // Define Glyph encoding
835 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
836
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700837 canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800838
839 // Get back old encoding
840 paint->setTextEncoding(oldEncoding);
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -0700841 }
842
843 static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas,
844 jcharArray glyphs, int index, int count,
845 jfloat x, jfloat y, int flags, SkPaint* paint) {
846 jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL);
847
848 doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint);
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -0800849
850 env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT);
851 }
852
Doug Felt0c702b82010-05-14 10:55:42 -0700853 static void drawTextRun___CIIIIFFIPaint(
Doug Feltf47d7402010-04-21 16:01:52 -0700854 JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index,
Doug Felt0c702b82010-05-14 10:55:42 -0700855 int count, int contextIndex, int contextCount,
Doug Felt4beb8ff72010-06-09 13:53:24 -0700856 jfloat x, jfloat y, int dirFlags, SkPaint* paint) {
Doug Feltf47d7402010-04-21 16:01:52 -0700857
Doug Feltf47d7402010-04-21 16:01:52 -0700858 jchar* chars = env->GetCharArrayElements(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700859#if RTL_USE_HARFBUZZ
860 drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex,
861 count, contextCount, x, y, dirFlags, paint);
862#else
Doug Feltf7cb1f72010-07-01 16:20:43 -0700863 TextLayout::drawTextRun(paint, chars + contextIndex, index - contextIndex,
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700864 count, contextCount, dirFlags, x, y, canvas);
865#endif
Doug Feltf47d7402010-04-21 16:01:52 -0700866 env->ReleaseCharArrayElements(text, chars, JNI_ABORT);
867 }
868
Doug Felt0c702b82010-05-14 10:55:42 -0700869 static void drawTextRun__StringIIIIFFIPaint(
870 JNIEnv* env, jobject obj, SkCanvas* canvas, jstring text, jint start,
871 jint end, jint contextStart, jint contextEnd,
Doug Felt4beb8ff72010-06-09 13:53:24 -0700872 jfloat x, jfloat y, jint dirFlags, SkPaint* paint) {
Doug Feltf47d7402010-04-21 16:01:52 -0700873
Doug Felt0c702b82010-05-14 10:55:42 -0700874 jint count = end - start;
875 jint contextCount = contextEnd - contextStart;
Doug Feltf47d7402010-04-21 16:01:52 -0700876 const jchar* chars = env->GetStringChars(text, NULL);
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700877#if RTL_USE_HARFBUZZ
878 drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart,
879 count, contextCount, x, y, dirFlags, paint);
880#else
Doug Feltf7cb1f72010-07-01 16:20:43 -0700881 TextLayout::drawTextRun(paint, chars + contextStart, start - contextStart,
Fabrice Di Megliob39d8972011-04-18 18:33:48 -0700882 count, contextCount, dirFlags, x, y, canvas);
883#endif
Doug Feltf47d7402010-04-21 16:01:52 -0700884 env->ReleaseStringChars(text, chars);
885 }
886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800887 static void drawPosText___CII_FPaint(JNIEnv* env, jobject, SkCanvas* canvas,
888 jcharArray text, int index, int count,
889 jfloatArray pos, SkPaint* paint) {
890 jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL;
891 jsize textCount = text ? env->GetArrayLength(text) : NULL;
892 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
893 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
894 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
895 int indx;
896 for (indx = 0; indx < posCount; indx++) {
897 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
898 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
899 }
Mike Reedad8b8f52009-05-01 08:24:01 -0400900 canvas->drawPosText(textArray + index, count << 1, posPtr, *paint);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800901 if (text) {
902 env->ReleaseCharArrayElements(text, textArray, 0);
903 }
904 if (pos) {
905 env->ReleaseFloatArrayElements(pos, posArray, 0);
906 }
907 delete[] posPtr;
908 }
Doug Felt0c702b82010-05-14 10:55:42 -0700909
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800910 static void drawPosText__String_FPaint(JNIEnv* env, jobject,
911 SkCanvas* canvas, jstring text,
Doug Felt4beb8ff72010-06-09 13:53:24 -0700912 jfloatArray pos,
913 SkPaint* paint) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800914 const void* text_ = text ? env->GetStringChars(text, NULL) : NULL;
915 int byteLength = text ? env->GetStringLength(text) : 0;
916 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL;
917 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0;
918 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL;
919
920 for (int indx = 0; indx < posCount; indx++) {
921 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]);
922 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]);
923 }
924 canvas->drawPosText(text_, byteLength << 1, posPtr, *paint);
925 if (text) {
926 env->ReleaseStringChars(text, (const jchar*) text_);
927 }
928 if (pos) {
929 env->ReleaseFloatArrayElements(pos, posArray, 0);
930 }
931 delete[] posPtr;
932 }
Doug Felt0c702b82010-05-14 10:55:42 -0700933
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800934 static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject,
Doug Felt4beb8ff72010-06-09 13:53:24 -0700935 SkCanvas* canvas, jcharArray text, int index, int count,
936 SkPath* path, jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800937
938 jchar* textArray = env->GetCharArrayElements(text, NULL);
Romain Guy8f67eae2011-04-26 11:24:42 -0700939 TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset,
Doug Feltf7cb1f72010-07-01 16:20:43 -0700940 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800941 env->ReleaseCharArrayElements(text, textArray, 0);
942 }
Doug Felt0c702b82010-05-14 10:55:42 -0700943
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800944 static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject,
Doug Felt4beb8ff72010-06-09 13:53:24 -0700945 SkCanvas* canvas, jstring text, SkPath* path,
946 jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800947 const jchar* text_ = env->GetStringChars(text, NULL);
Doug Felt4beb8ff72010-06-09 13:53:24 -0700948 int count = env->GetStringLength(text);
Doug Feltf7cb1f72010-07-01 16:20:43 -0700949 TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset,
950 path, canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800951 env->ReleaseStringChars(text, text_);
952 }
Doug Felt0c702b82010-05-14 10:55:42 -0700953
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800954 static bool getClipBounds(JNIEnv* env, jobject, SkCanvas* canvas,
955 jobject bounds) {
956 SkRect r;
957 SkIRect ir;
958 bool result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType);
959
960 r.round(&ir);
961 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds);
962 return result;
963 }
964
965 static void getCTM(JNIEnv* env, jobject, SkCanvas* canvas,
966 SkMatrix* matrix) {
967 *matrix = canvas->getTotalMatrix();
968 }
969};
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800970
971static JNINativeMethod gCanvasMethods[] = {
972 {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer},
973 {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800974 {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
975 {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
976 {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
977 {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800978 {"save","()I", (void*) SkCanvasGlue::saveAll},
979 {"save","(I)I", (void*) SkCanvasGlue::save},
980 {"native_saveLayer","(ILandroid/graphics/RectF;II)I",
981 (void*) SkCanvasGlue::saveLayer},
982 {"native_saveLayer","(IFFFFII)I", (void*) SkCanvasGlue::saveLayer4F},
983 {"native_saveLayerAlpha","(ILandroid/graphics/RectF;II)I",
984 (void*) SkCanvasGlue::saveLayerAlpha},
985 {"native_saveLayerAlpha","(IFFFFII)I",
986 (void*) SkCanvasGlue::saveLayerAlpha4F},
987 {"restore","()V", (void*) SkCanvasGlue::restore},
988 {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
989 {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
990 {"translate","(FF)V", (void*) SkCanvasGlue::translate},
991 {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
992 {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
993 {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
994 {"native_concat","(II)V", (void*) SkCanvasGlue::concat},
995 {"native_setMatrix","(II)V", (void*) SkCanvasGlue::setMatrix},
996 {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
997 {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
998 {"clipRect","(Landroid/graphics/RectF;)Z",
999 (void*) SkCanvasGlue::clipRect_RectF},
1000 {"clipRect","(Landroid/graphics/Rect;)Z",
1001 (void*) SkCanvasGlue::clipRect_Rect},
1002 {"native_clipRect","(IFFFFI)Z", (void*) SkCanvasGlue::clipRect},
1003 {"native_clipPath","(III)Z", (void*) SkCanvasGlue::clipPath},
1004 {"native_clipRegion","(III)Z", (void*) SkCanvasGlue::clipRegion},
1005 {"nativeSetDrawFilter", "(II)V", (void*) SkCanvasGlue::setDrawFilter},
1006 {"native_getClipBounds","(ILandroid/graphics/Rect;)Z",
1007 (void*) SkCanvasGlue::getClipBounds},
1008 {"native_getCTM", "(II)V", (void*)SkCanvasGlue::getCTM},
1009 {"native_quickReject","(ILandroid/graphics/RectF;I)Z",
1010 (void*) SkCanvasGlue::quickReject__RectFI},
1011 {"native_quickReject","(III)Z", (void*) SkCanvasGlue::quickReject__PathI},
1012 {"native_quickReject","(IFFFFI)Z", (void*)SkCanvasGlue::quickReject__FFFFI},
1013 {"native_drawRGB","(IIII)V", (void*) SkCanvasGlue::drawRGB},
1014 {"native_drawARGB","(IIIII)V", (void*) SkCanvasGlue::drawARGB},
1015 {"native_drawColor","(II)V", (void*) SkCanvasGlue::drawColor__I},
1016 {"native_drawColor","(III)V", (void*) SkCanvasGlue::drawColor__II},
1017 {"native_drawPaint","(II)V", (void*) SkCanvasGlue::drawPaint},
1018 {"drawPoint", "(FFLandroid/graphics/Paint;)V",
1019 (void*) SkCanvasGlue::drawPoint},
1020 {"drawPoints", "([FIILandroid/graphics/Paint;)V",
1021 (void*) SkCanvasGlue::drawPoints},
1022 {"drawLines", "([FIILandroid/graphics/Paint;)V",
1023 (void*) SkCanvasGlue::drawLines},
1024 {"native_drawLine","(IFFFFI)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
1025 {"native_drawRect","(ILandroid/graphics/RectF;I)V",
1026 (void*) SkCanvasGlue::drawRect__RectFPaint},
1027 {"native_drawRect","(IFFFFI)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
1028 {"native_drawOval","(ILandroid/graphics/RectF;I)V",
1029 (void*) SkCanvasGlue::drawOval},
1030 {"native_drawCircle","(IFFFI)V", (void*) SkCanvasGlue::drawCircle},
1031 {"native_drawArc","(ILandroid/graphics/RectF;FFZI)V",
1032 (void*) SkCanvasGlue::drawArc},
1033 {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V",
1034 (void*) SkCanvasGlue::drawRoundRect},
1035 {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath},
Dianne Hackborn0d221012009-07-29 15:41:19 -07001036 {"native_drawBitmap","(IIFFIIII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001037 (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint},
Dianne Hackborn0d221012009-07-29 15:41:19 -07001038 {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;III)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001039 (void*) SkCanvasGlue::drawBitmapRF},
Dianne Hackborn0d221012009-07-29 15:41:19 -07001040 {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;III)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 (void*) SkCanvasGlue::drawBitmapRR},
1042 {"native_drawBitmap", "(I[IIIFFIIZI)V",
1043 (void*)SkCanvasGlue::drawBitmapArray},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001044 {"nativeDrawBitmapMatrix", "(IIII)V",
1045 (void*)SkCanvasGlue::drawBitmapMatrix},
1046 {"nativeDrawBitmapMesh", "(IIII[FI[III)V",
1047 (void*)SkCanvasGlue::drawBitmapMesh},
1048 {"nativeDrawVertices", "(III[FI[FI[II[SIII)V",
1049 (void*)SkCanvasGlue::drawVertices},
Doug Feltf47d7402010-04-21 16:01:52 -07001050 {"native_drawText","(I[CIIFFII)V",
1051 (void*) SkCanvasGlue::drawText___CIIFFIPaint},
1052 {"native_drawText","(ILjava/lang/String;IIFFII)V",
1053 (void*) SkCanvasGlue::drawText__StringIIFFIPaint},
Fabrice Di Megliofcf2be12011-04-05 17:02:36 -07001054 {"native_drawTextWithGlyphs","(I[CIIFFII)V",
1055 (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint},
1056 {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V",
1057 (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint},
Fabrice Di Meglio9f82b582011-03-08 12:02:59 -08001058 {"native_drawGlyphs","(I[CIIFFII)V",
1059 (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint},
Doug Felt0c702b82010-05-14 10:55:42 -07001060 {"native_drawTextRun","(I[CIIIIFFII)V",
1061 (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint},
1062 {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V",
1063 (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaint},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001064 {"native_drawPosText","(I[CII[FI)V",
1065 (void*) SkCanvasGlue::drawPosText___CII_FPaint},
1066 {"native_drawPosText","(ILjava/lang/String;[FI)V",
1067 (void*) SkCanvasGlue::drawPosText__String_FPaint},
Doug Felt4beb8ff72010-06-09 13:53:24 -07001068 {"native_drawTextOnPath","(I[CIIIFFII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001069 (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint},
Doug Felt4beb8ff72010-06-09 13:53:24 -07001070 {"native_drawTextOnPath","(ILjava/lang/String;IFFII)V",
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint},
1072 {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture},
1073
Mike Reedcaf0df12009-04-27 14:32:05 -04001074 {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001075};
1076
Mike Reedc04851f2009-10-28 15:09:45 -04001077///////////////////////////////////////////////////////////////////////////////
1078
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001079#include <android_runtime/AndroidRuntime.h>
1080
1081#define REG(env, name, array) \
1082 result = android::AndroidRuntime::registerNativeMethods(env, name, array, \
1083 SK_ARRAY_COUNT(array)); \
1084 if (result < 0) return result
1085
1086int register_android_graphics_Canvas(JNIEnv* env) {
1087 int result;
1088
1089 REG(env, "android/graphics/Canvas", gCanvasMethods);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001090
1091 return result;
1092}
1093
1094}