Canvas.cpp revision af033caf26ef4eca99c4024e59def7e42c3fa4cd
1/* 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" 23#include "SkGraphics.h" 24#include "SkImageRef_GlobalPool.h" 25#include "SkPorterDuff.h" 26#include "SkShader.h" 27#include "SkTemplates.h" 28 29#include "TextLayout.h" 30#include "TextLayoutCache.h" 31 32#include "unicode/ubidi.h" 33#include "unicode/ushape.h" 34 35#include <utils/Log.h> 36 37#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 67 static void freeCaches(JNIEnv* env, jobject) { 68 // these are called in no particular order 69 SkImageRef_GlobalPool::SetRAMUsed(0); 70 SkGraphics::SetFontCacheUsed(0); 71 } 72 73 static jboolean isOpaque(JNIEnv* env, jobject jcanvas) { 74 NPE_CHECK_RETURN_ZERO(env, jcanvas); 75 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); 76 return canvas->getDevice()->accessBitmap(false).isOpaque(); 77 } 78 79 static int getWidth(JNIEnv* env, jobject jcanvas) { 80 NPE_CHECK_RETURN_ZERO(env, jcanvas); 81 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); 82 return canvas->getDevice()->accessBitmap(false).width(); 83 } 84 85 static int getHeight(JNIEnv* env, jobject jcanvas) { 86 NPE_CHECK_RETURN_ZERO(env, jcanvas); 87 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); 88 return canvas->getDevice()->accessBitmap(false).height(); 89 } 90 91 static void setBitmap(JNIEnv* env, jobject, SkCanvas* canvas, 92 SkBitmap* bitmap) { 93 canvas->setBitmapDevice(*bitmap); 94 } 95 96 static int saveAll(JNIEnv* env, jobject jcanvas) { 97 NPE_CHECK_RETURN_ZERO(env, jcanvas); 98 return GraphicsJNI::getNativeCanvas(env, jcanvas)->save(); 99 } 100 101 static int save(JNIEnv* env, jobject jcanvas, SkCanvas::SaveFlags flags) { 102 NPE_CHECK_RETURN_ZERO(env, jcanvas); 103 return GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags); 104 } 105 106 static int saveLayer(JNIEnv* env, jobject, SkCanvas* canvas, jobject bounds, 107 SkPaint* paint, int flags) { 108 SkRect* bounds_ = NULL; 109 SkRect storage; 110 if (bounds != NULL) { 111 GraphicsJNI::jrectf_to_rect(env, bounds, &storage); 112 bounds_ = &storage; 113 } 114 return canvas->saveLayer(bounds_, paint, (SkCanvas::SaveFlags)flags); 115 } 116 117 static int saveLayer4F(JNIEnv* env, jobject, SkCanvas* canvas, 118 jfloat l, jfloat t, jfloat r, jfloat b, 119 SkPaint* paint, int flags) { 120 SkRect bounds; 121 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r), 122 SkFloatToScalar(b)); 123 return canvas->saveLayer(&bounds, paint, (SkCanvas::SaveFlags)flags); 124 } 125 126 static int saveLayerAlpha(JNIEnv* env, jobject, SkCanvas* canvas, 127 jobject bounds, int alpha, int flags) { 128 SkRect* bounds_ = NULL; 129 SkRect storage; 130 if (bounds != NULL) { 131 GraphicsJNI::jrectf_to_rect(env, bounds, &storage); 132 bounds_ = &storage; 133 } 134 return canvas->saveLayerAlpha(bounds_, alpha, 135 (SkCanvas::SaveFlags)flags); 136 } 137 138 static int saveLayerAlpha4F(JNIEnv* env, jobject, SkCanvas* canvas, 139 jfloat l, jfloat t, jfloat r, jfloat b, 140 int alpha, int flags) { 141 SkRect bounds; 142 bounds.set(SkFloatToScalar(l), SkFloatToScalar(t), SkFloatToScalar(r), 143 SkFloatToScalar(b)); 144 return canvas->saveLayerAlpha(&bounds, alpha, 145 (SkCanvas::SaveFlags)flags); 146 } 147 148 static void restore(JNIEnv* env, jobject jcanvas) { 149 NPE_CHECK_RETURN_VOID(env, jcanvas); 150 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); 151 if (canvas->getSaveCount() <= 1) { // cannot restore anymore 152 doThrowISE(env, "Underflow in restore"); 153 return; 154 } 155 canvas->restore(); 156 } 157 158 static int getSaveCount(JNIEnv* env, jobject jcanvas) { 159 NPE_CHECK_RETURN_ZERO(env, jcanvas); 160 return GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount(); 161 } 162 163 static void restoreToCount(JNIEnv* env, jobject jcanvas, int restoreCount) { 164 NPE_CHECK_RETURN_VOID(env, jcanvas); 165 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); 166 if (restoreCount < 1) { 167 doThrowIAE(env, "Underflow in restoreToCount"); 168 return; 169 } 170 canvas->restoreToCount(restoreCount); 171 } 172 173 static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) { 174 NPE_CHECK_RETURN_VOID(env, jcanvas); 175 SkScalar dx_ = SkFloatToScalar(dx); 176 SkScalar dy_ = SkFloatToScalar(dy); 177 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx_, dy_); 178 } 179 180 static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) { 181 NPE_CHECK_RETURN_VOID(env, jcanvas); 182 SkScalar sx_ = SkFloatToScalar(sx); 183 SkScalar sy_ = SkFloatToScalar(sy); 184 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx_, sy_); 185 } 186 187 static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) { 188 NPE_CHECK_RETURN_VOID(env, jcanvas); 189 SkScalar degrees_ = SkFloatToScalar(degrees); 190 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees_); 191 } 192 193 static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) { 194 NPE_CHECK_RETURN_VOID(env, jcanvas); 195 SkScalar sx_ = SkFloatToScalar(sx); 196 SkScalar sy_ = SkFloatToScalar(sy); 197 (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx_, sy_); 198 } 199 200 static void concat(JNIEnv* env, jobject, SkCanvas* canvas, 201 const SkMatrix* matrix) { 202 canvas->concat(*matrix); 203 } 204 205 static void setMatrix(JNIEnv* env, jobject, SkCanvas* canvas, 206 const SkMatrix* matrix) { 207 if (NULL == matrix) { 208 canvas->resetMatrix(); 209 } else { 210 canvas->setMatrix(*matrix); 211 } 212 } 213 214 static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left, 215 jfloat top, jfloat right, jfloat bottom) { 216 NPE_CHECK_RETURN_ZERO(env, jcanvas); 217 SkRect r; 218 r.set(SkFloatToScalar(left), SkFloatToScalar(top), 219 SkFloatToScalar(right), SkFloatToScalar(bottom)); 220 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas); 221 return c->clipRect(r); 222 } 223 224 static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left, 225 jint top, jint right, jint bottom) { 226 NPE_CHECK_RETURN_ZERO(env, jcanvas); 227 SkRect r; 228 r.set(SkIntToScalar(left), SkIntToScalar(top), 229 SkIntToScalar(right), SkIntToScalar(bottom)); 230 return GraphicsJNI::getNativeCanvas(env, jcanvas)->clipRect(r); 231 } 232 233 static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) { 234 NPE_CHECK_RETURN_ZERO(env, jcanvas); 235 NPE_CHECK_RETURN_ZERO(env, rectf); 236 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas); 237 SkRect tmp; 238 return c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp)); 239 } 240 241 static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) { 242 NPE_CHECK_RETURN_ZERO(env, jcanvas); 243 NPE_CHECK_RETURN_ZERO(env, rect); 244 SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas); 245 SkRect tmp; 246 return c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp)); 247 } 248 249 static jboolean clipRect(JNIEnv* env, jobject, SkCanvas* canvas, 250 float left, float top, float right, float bottom, 251 int op) { 252 SkRect rect; 253 rect.set(SkFloatToScalar(left), SkFloatToScalar(top), 254 SkFloatToScalar(right), SkFloatToScalar(bottom)); 255 return canvas->clipRect(rect, (SkRegion::Op)op); 256 } 257 258 static jboolean clipPath(JNIEnv* env, jobject, SkCanvas* canvas, 259 SkPath* path, int op) { 260 return canvas->clipPath(*path, (SkRegion::Op)op); 261 } 262 263 static jboolean clipRegion(JNIEnv* env, jobject, SkCanvas* canvas, 264 SkRegion* deviceRgn, int op) { 265 return canvas->clipRegion(*deviceRgn, (SkRegion::Op)op); 266 } 267 268 static void setDrawFilter(JNIEnv* env, jobject, SkCanvas* canvas, 269 SkDrawFilter* filter) { 270 canvas->setDrawFilter(filter); 271 } 272 273 static jboolean quickReject__RectFI(JNIEnv* env, jobject, SkCanvas* canvas, 274 jobject rect, int edgetype) { 275 SkRect rect_; 276 GraphicsJNI::jrectf_to_rect(env, rect, &rect_); 277 return canvas->quickReject(rect_, (SkCanvas::EdgeType)edgetype); 278 } 279 280 static jboolean quickReject__PathI(JNIEnv* env, jobject, SkCanvas* canvas, 281 SkPath* path, int edgetype) { 282 return canvas->quickReject(*path, (SkCanvas::EdgeType)edgetype); 283 } 284 285 static jboolean quickReject__FFFFI(JNIEnv* env, jobject, SkCanvas* canvas, 286 jfloat left, jfloat top, jfloat right, 287 jfloat bottom, int edgetype) { 288 SkRect r; 289 r.set(SkFloatToScalar(left), SkFloatToScalar(top), 290 SkFloatToScalar(right), SkFloatToScalar(bottom)); 291 return canvas->quickReject(r, (SkCanvas::EdgeType)edgetype); 292 } 293 294 static void drawRGB(JNIEnv* env, jobject, SkCanvas* canvas, 295 jint r, jint g, jint b) { 296 canvas->drawARGB(0xFF, r, g, b); 297 } 298 299 static void drawARGB(JNIEnv* env, jobject, SkCanvas* canvas, 300 jint a, jint r, jint g, jint b) { 301 canvas->drawARGB(a, r, g, b); 302 } 303 304 static void drawColor__I(JNIEnv* env, jobject, SkCanvas* canvas, 305 jint color) { 306 canvas->drawColor(color); 307 } 308 309 static void drawColor__II(JNIEnv* env, jobject, SkCanvas* canvas, 310 jint color, SkPorterDuff::Mode mode) { 311 canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode)); 312 } 313 314 static void drawPaint(JNIEnv* env, jobject, SkCanvas* canvas, 315 SkPaint* paint) { 316 canvas->drawPaint(*paint); 317 } 318 319 static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray, 320 jint offset, jint count, jobject jpaint, 321 SkCanvas::PointMode mode) { 322 NPE_CHECK_RETURN_VOID(env, jcanvas); 323 NPE_CHECK_RETURN_VOID(env, jptsArray); 324 NPE_CHECK_RETURN_VOID(env, jpaint); 325 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); 326 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint); 327 328 AutoJavaFloatArray autoPts(env, jptsArray); 329 float* floats = autoPts.ptr(); 330 const int length = autoPts.length(); 331 332 if ((offset | count) < 0 || offset + count > length) { 333 doThrowAIOOBE(env); 334 return; 335 } 336 337 // now convert the floats into SkPoints 338 count >>= 1; // now it is the number of points 339 SkAutoSTMalloc<32, SkPoint> storage(count); 340 SkPoint* pts = storage.get(); 341 const float* src = floats + offset; 342 for (int i = 0; i < count; i++) { 343 pts[i].set(SkFloatToScalar(src[0]), SkFloatToScalar(src[1])); 344 src += 2; 345 } 346 canvas->drawPoints(mode, count, pts, paint); 347 } 348 349 static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray, 350 jint offset, jint count, jobject jpaint) { 351 doPoints(env, jcanvas, jptsArray, offset, count, jpaint, 352 SkCanvas::kPoints_PointMode); 353 } 354 355 static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray, 356 jint offset, jint count, jobject jpaint) { 357 doPoints(env, jcanvas, jptsArray, offset, count, jpaint, 358 SkCanvas::kLines_PointMode); 359 } 360 361 static void drawPoint(JNIEnv* env, jobject jcanvas, float x, float y, 362 jobject jpaint) { 363 NPE_CHECK_RETURN_VOID(env, jcanvas); 364 NPE_CHECK_RETURN_VOID(env, jpaint); 365 SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas); 366 const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint); 367 368 canvas->drawPoint(SkFloatToScalar(x), SkFloatToScalar(y), paint); 369 } 370 371 static void drawLine__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas, 372 jfloat startX, jfloat startY, jfloat stopX, 373 jfloat stopY, SkPaint* paint) { 374 canvas->drawLine(SkFloatToScalar(startX), SkFloatToScalar(startY), 375 SkFloatToScalar(stopX), SkFloatToScalar(stopY), 376 *paint); 377 } 378 379 static void drawRect__RectFPaint(JNIEnv* env, jobject, SkCanvas* canvas, 380 jobject rect, SkPaint* paint) { 381 SkRect rect_; 382 GraphicsJNI::jrectf_to_rect(env, rect, &rect_); 383 canvas->drawRect(rect_, *paint); 384 } 385 386 static void drawRect__FFFFPaint(JNIEnv* env, jobject, SkCanvas* canvas, 387 jfloat left, jfloat top, jfloat right, 388 jfloat bottom, SkPaint* paint) { 389 SkScalar left_ = SkFloatToScalar(left); 390 SkScalar top_ = SkFloatToScalar(top); 391 SkScalar right_ = SkFloatToScalar(right); 392 SkScalar bottom_ = SkFloatToScalar(bottom); 393 canvas->drawRectCoords(left_, top_, right_, bottom_, *paint); 394 } 395 396 static void drawOval(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval, 397 SkPaint* paint) { 398 SkRect oval; 399 GraphicsJNI::jrectf_to_rect(env, joval, &oval); 400 canvas->drawOval(oval, *paint); 401 } 402 403 static void drawCircle(JNIEnv* env, jobject, SkCanvas* canvas, jfloat cx, 404 jfloat cy, jfloat radius, SkPaint* paint) { 405 canvas->drawCircle(SkFloatToScalar(cx), SkFloatToScalar(cy), 406 SkFloatToScalar(radius), *paint); 407 } 408 409 static void drawArc(JNIEnv* env, jobject, SkCanvas* canvas, jobject joval, 410 jfloat startAngle, jfloat sweepAngle, 411 jboolean useCenter, SkPaint* paint) { 412 SkRect oval; 413 GraphicsJNI::jrectf_to_rect(env, joval, &oval); 414 canvas->drawArc(oval, SkFloatToScalar(startAngle), 415 SkFloatToScalar(sweepAngle), useCenter, *paint); 416 } 417 418 static void drawRoundRect(JNIEnv* env, jobject, SkCanvas* canvas, 419 jobject jrect, jfloat rx, jfloat ry, 420 SkPaint* paint) { 421 SkRect rect; 422 GraphicsJNI::jrectf_to_rect(env, jrect, &rect); 423 canvas->drawRoundRect(rect, SkFloatToScalar(rx), SkFloatToScalar(ry), 424 *paint); 425 } 426 427 static void drawPath(JNIEnv* env, jobject, SkCanvas* canvas, SkPath* path, 428 SkPaint* paint) { 429 canvas->drawPath(*path, *paint); 430 } 431 432 static void drawPicture(JNIEnv* env, jobject, SkCanvas* canvas, 433 SkPicture* picture) { 434 SkASSERT(canvas); 435 SkASSERT(picture); 436 437#ifdef TIME_DRAW 438 SkMSec now = get_thread_msec(); //SkTime::GetMSecs(); 439#endif 440 canvas->drawPicture(*picture); 441#ifdef TIME_DRAW 442 LOGD("---- picture playback %d ms\n", get_thread_msec() - now); 443#endif 444 } 445 446 static void drawBitmap__BitmapFFPaint(JNIEnv* env, jobject jcanvas, 447 SkCanvas* canvas, SkBitmap* bitmap, 448 jfloat left, jfloat top, 449 SkPaint* paint, jint canvasDensity, 450 jint screenDensity, jint bitmapDensity) { 451 SkScalar left_ = SkFloatToScalar(left); 452 SkScalar top_ = SkFloatToScalar(top); 453 454 if (canvasDensity == bitmapDensity || canvasDensity == 0 455 || bitmapDensity == 0) { 456 if (screenDensity != 0 && screenDensity != bitmapDensity) { 457 SkPaint filteredPaint; 458 if (paint) { 459 filteredPaint = *paint; 460 } 461 filteredPaint.setFilterBitmap(true); 462 canvas->drawBitmap(*bitmap, left_, top_, &filteredPaint); 463 } else { 464 canvas->drawBitmap(*bitmap, left_, top_, paint); 465 } 466 } else { 467 canvas->save(); 468 SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity); 469 canvas->translate(left_, top_); 470 canvas->scale(scale, scale); 471 472 SkPaint filteredPaint; 473 if (paint) { 474 filteredPaint = *paint; 475 } 476 filteredPaint.setFilterBitmap(true); 477 478 canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint); 479 480 canvas->restore(); 481 } 482 } 483 484 static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap, 485 jobject srcIRect, const SkRect& dst, SkPaint* paint, 486 jint screenDensity, jint bitmapDensity) { 487 SkIRect src, *srcPtr = NULL; 488 489 if (NULL != srcIRect) { 490 GraphicsJNI::jrect_to_irect(env, srcIRect, &src); 491 srcPtr = &src; 492 } 493 494 if (screenDensity != 0 && screenDensity != bitmapDensity) { 495 SkPaint filteredPaint; 496 if (paint) { 497 filteredPaint = *paint; 498 } 499 filteredPaint.setFilterBitmap(true); 500 canvas->drawBitmapRect(*bitmap, srcPtr, dst, &filteredPaint); 501 } else { 502 canvas->drawBitmapRect(*bitmap, srcPtr, dst, paint); 503 } 504 } 505 506 static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas, 507 SkBitmap* bitmap, jobject srcIRect, 508 jobject dstRectF, SkPaint* paint, 509 jint screenDensity, jint bitmapDensity) { 510 SkRect dst; 511 GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst); 512 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint, 513 screenDensity, bitmapDensity); 514 } 515 516 static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas, 517 SkBitmap* bitmap, jobject srcIRect, 518 jobject dstRect, SkPaint* paint, 519 jint screenDensity, jint bitmapDensity) { 520 SkRect dst; 521 GraphicsJNI::jrect_to_rect(env, dstRect, &dst); 522 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint, 523 screenDensity, bitmapDensity); 524 } 525 526 static void drawBitmapArray(JNIEnv* env, jobject, SkCanvas* canvas, 527 jintArray jcolors, int offset, int stride, 528 jfloat x, jfloat y, int width, int height, 529 jboolean hasAlpha, SkPaint* paint) 530 { 531 SkBitmap bitmap; 532 533 bitmap.setConfig(hasAlpha ? SkBitmap::kARGB_8888_Config : 534 SkBitmap::kRGB_565_Config, width, height); 535 if (!bitmap.allocPixels()) { 536 return; 537 } 538 539 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 540 0, 0, width, height, bitmap)) { 541 return; 542 } 543 544 canvas->drawBitmap(bitmap, SkFloatToScalar(x), SkFloatToScalar(y), 545 paint); 546 } 547 548 static void drawBitmapMatrix(JNIEnv* env, jobject, SkCanvas* canvas, 549 const SkBitmap* bitmap, const SkMatrix* matrix, 550 const SkPaint* paint) { 551 canvas->drawBitmapMatrix(*bitmap, *matrix, paint); 552 } 553 554 static void drawBitmapMesh(JNIEnv* env, jobject, SkCanvas* canvas, 555 const SkBitmap* bitmap, int meshWidth, int meshHeight, 556 jfloatArray jverts, int vertIndex, jintArray jcolors, 557 int colorIndex, const SkPaint* paint) { 558 559 const int ptCount = (meshWidth + 1) * (meshHeight + 1); 560 const int indexCount = meshWidth * meshHeight * 6; 561 562 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1)); 563 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount); 564 565 /* Our temp storage holds 2 or 3 arrays. 566 texture points [ptCount * sizeof(SkPoint)] 567 optionally vertex points [ptCount * sizeof(SkPoint)] if we need a 568 copy to convert from float to fixed 569 indices [ptCount * sizeof(uint16_t)] 570 */ 571 ssize_t storageSize = ptCount * sizeof(SkPoint); // texs[] 572#ifdef SK_SCALAR_IS_FIXED 573 storageSize += ptCount * sizeof(SkPoint); // storage for verts 574#endif 575 storageSize += indexCount * sizeof(uint16_t); // indices[] 576 577 SkAutoMalloc storage(storageSize); 578 SkPoint* texs = (SkPoint*)storage.get(); 579 SkPoint* verts; 580 uint16_t* indices; 581#ifdef SK_SCALAR_IS_FLOAT 582 verts = (SkPoint*)(vertA.ptr() + vertIndex); 583 indices = (uint16_t*)(texs + ptCount); 584#else 585 verts = texs + ptCount; 586 indices = (uint16_t*)(verts + ptCount); 587 // convert floats to fixed 588 { 589 const float* src = vertA.ptr() + vertIndex; 590 for (int i = 0; i < ptCount; i++) { 591 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1])); 592 src += 2; 593 } 594 } 595#endif 596 597 // cons up texture coordinates and indices 598 { 599 const SkScalar w = SkIntToScalar(bitmap->width()); 600 const SkScalar h = SkIntToScalar(bitmap->height()); 601 const SkScalar dx = w / meshWidth; 602 const SkScalar dy = h / meshHeight; 603 604 SkPoint* texsPtr = texs; 605 SkScalar y = 0; 606 for (int i = 0; i <= meshHeight; i++) { 607 if (i == meshHeight) { 608 y = h; // to ensure numerically we hit h exactly 609 } 610 SkScalar x = 0; 611 for (int j = 0; j < meshWidth; j++) { 612 texsPtr->set(x, y); 613 texsPtr += 1; 614 x += dx; 615 } 616 texsPtr->set(w, y); 617 texsPtr += 1; 618 y += dy; 619 } 620 SkASSERT(texsPtr - texs == ptCount); 621 } 622 623 // cons up indices 624 { 625 uint16_t* indexPtr = indices; 626 int index = 0; 627 for (int i = 0; i < meshHeight; i++) { 628 for (int j = 0; j < meshWidth; j++) { 629 // lower-left triangle 630 *indexPtr++ = index; 631 *indexPtr++ = index + meshWidth + 1; 632 *indexPtr++ = index + meshWidth + 2; 633 // upper-right triangle 634 *indexPtr++ = index; 635 *indexPtr++ = index + meshWidth + 2; 636 *indexPtr++ = index + 1; 637 // bump to the next cell 638 index += 1; 639 } 640 // bump to the next row 641 index += 1; 642 } 643 SkASSERT(indexPtr - indices == indexCount); 644 SkASSERT((char*)indexPtr - (char*)storage.get() == storageSize); 645 } 646 647 // double-check that we have legal indices 648#ifdef SK_DEBUG 649 { 650 for (int i = 0; i < indexCount; i++) { 651 SkASSERT((unsigned)indices[i] < (unsigned)ptCount); 652 } 653 } 654#endif 655 656 // cons-up a shader for the bitmap 657 SkPaint tmpPaint; 658 if (paint) { 659 tmpPaint = *paint; 660 } 661 SkShader* shader = SkShader::CreateBitmapShader(*bitmap, 662 SkShader::kClamp_TileMode, SkShader::kClamp_TileMode); 663 SkSafeUnref(tmpPaint.setShader(shader)); 664 665 canvas->drawVertices(SkCanvas::kTriangles_VertexMode, ptCount, verts, 666 texs, (const SkColor*)colorA.ptr(), NULL, indices, 667 indexCount, tmpPaint); 668 } 669 670 static void drawVertices(JNIEnv* env, jobject, SkCanvas* canvas, 671 SkCanvas::VertexMode mode, int vertexCount, 672 jfloatArray jverts, int vertIndex, 673 jfloatArray jtexs, int texIndex, 674 jintArray jcolors, int colorIndex, 675 jshortArray jindices, int indexIndex, 676 int indexCount, const SkPaint* paint) { 677 678 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount); 679 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount); 680 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount); 681 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount); 682 683 const int ptCount = vertexCount >> 1; 684 685 SkPoint* verts; 686 SkPoint* texs = NULL; 687#ifdef SK_SCALAR_IS_FLOAT 688 verts = (SkPoint*)(vertA.ptr() + vertIndex); 689 if (jtexs != NULL) { 690 texs = (SkPoint*)(texA.ptr() + texIndex); 691 } 692#else 693 int count = ptCount; // for verts 694 if (jtexs != NULL) { 695 count += ptCount; // += for texs 696 } 697 SkAutoMalloc storage(count * sizeof(SkPoint)); 698 verts = (SkPoint*)storage.get(); 699 const float* src = vertA.ptr() + vertIndex; 700 for (int i = 0; i < ptCount; i++) { 701 verts[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1])); 702 src += 2; 703 } 704 if (jtexs != NULL) { 705 texs = verts + ptCount; 706 src = texA.ptr() + texIndex; 707 for (int i = 0; i < ptCount; i++) { 708 texs[i].set(SkFloatToFixed(src[0]), SkFloatToFixed(src[1])); 709 src += 2; 710 } 711 } 712#endif 713 714 const SkColor* colors = NULL; 715 const uint16_t* indices = NULL; 716 if (jcolors != NULL) { 717 colors = (const SkColor*)(colorA.ptr() + colorIndex); 718 } 719 if (jindices != NULL) { 720 indices = (const uint16_t*)(indexA.ptr() + indexIndex); 721 } 722 723 canvas->drawVertices(mode, ptCount, verts, texs, colors, NULL, 724 indices, indexCount, *paint); 725 } 726 727 728 static void drawText___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, 729 jcharArray text, int index, int count, 730 jfloat x, jfloat y, int flags, SkPaint* paint) { 731 jchar* textArray = env->GetCharArrayElements(text, NULL); 732#if RTL_USE_HARFBUZZ 733 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); 734#else 735 TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas); 736#endif 737 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 738 } 739 740 static void drawText__StringIIFFIPaint(JNIEnv* env, jobject, 741 SkCanvas* canvas, jstring text, 742 int start, int end, 743 jfloat x, jfloat y, int flags, SkPaint* paint) { 744 const jchar* textArray = env->GetStringChars(text, NULL); 745#if RTL_USE_HARFBUZZ 746 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint); 747#else 748 TextLayout::drawText(paint, textArray + start, end - start, flags, x, y, canvas); 749#endif 750 env->ReleaseStringChars(text, textArray); 751 } 752 753 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray, 754 int start, int end, 755 jfloat x, jfloat y, int flags, SkPaint* paint) { 756 757 jint count = end - start; 758 sp<TextLayoutCacheValue> value; 759#if USE_TEXT_LAYOUT_CACHE 760 value = gTextLayoutCache.getValue(paint, textArray, start, count, end, flags); 761 if (value == NULL) { 762 LOGE("Cannot get TextLayoutCache value"); 763 return ; 764 } 765#else 766 value = new TextLayoutCacheValue(); 767 value->computeValues(paint, textArray, start, count, end, flags); 768#endif 769 770#if DEBUG_GLYPHS 771 logGlyphs(value); 772#endif 773 774 doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), 775 x, y, flags, paint); 776 } 777 778 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray, 779 int start, int count, int contextCount, 780 jfloat x, jfloat y, int flags, SkPaint* paint) { 781 782 sp<TextLayoutCacheValue> value; 783#if USE_TEXT_LAYOUT_CACHE 784 value = gTextLayoutCache.getValue(paint, textArray, start, count, contextCount, flags); 785 if (value == NULL) { 786 LOGE("Cannot get TextLayoutCache value"); 787 return ; 788 } 789#else 790 value = new TextLayoutCacheValue(); 791 value->computeValues(paint, textArray, start, count, contextCount, flags); 792#endif 793 794#if DEBUG_GLYPHS 795 logGlyphs(value); 796#endif 797 798 doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), 799 x, y, flags, paint); 800 } 801 802 static void drawTextWithGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, 803 jcharArray text, int index, int count, 804 jfloat x, jfloat y, int flags, SkPaint* paint) { 805 jchar* textArray = env->GetCharArrayElements(text, NULL); 806 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); 807 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 808 } 809 810 static void drawTextWithGlyphs__StringIIFFIPaint(JNIEnv* env, jobject, 811 SkCanvas* canvas, jstring text, 812 int start, int end, 813 jfloat x, jfloat y, int flags, SkPaint* paint) { 814 815 const jchar* textArray = env->GetStringChars(text, NULL); 816 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint); 817 env->ReleaseStringChars(text, textArray); 818 } 819 820 static void doDrawGlyphs(SkCanvas* canvas, const jchar* glyphArray, int index, int count, 821 jfloat x, jfloat y, int flags, SkPaint* paint) { 822 // TODO: need to suppress this code after the GL renderer is modified for not 823 // copying the paint 824 825 // Save old text encoding 826 SkPaint::TextEncoding oldEncoding = paint->getTextEncoding(); 827 // Define Glyph encoding 828 paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding); 829 830 canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint); 831 832 // Get back old encoding 833 paint->setTextEncoding(oldEncoding); 834 } 835 836 static void drawGlyphs___CIIFFIPaint(JNIEnv* env, jobject, SkCanvas* canvas, 837 jcharArray glyphs, int index, int count, 838 jfloat x, jfloat y, int flags, SkPaint* paint) { 839 jchar* glyphArray = env->GetCharArrayElements(glyphs, NULL); 840 841 doDrawGlyphs(canvas, glyphArray, index, count, x, y, flags, paint); 842 843 env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); 844 } 845 846 static void drawTextRun___CIIIIFFIPaint( 847 JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, 848 int count, int contextIndex, int contextCount, 849 jfloat x, jfloat y, int dirFlags, SkPaint* paint) { 850 851 jchar* chars = env->GetCharArrayElements(text, NULL); 852#if RTL_USE_HARFBUZZ 853 drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex, 854 count, contextCount, x, y, dirFlags, paint); 855#else 856 TextLayout::drawTextRun(paint, chars + contextIndex, index - contextIndex, 857 count, contextCount, dirFlags, x, y, canvas); 858#endif 859 env->ReleaseCharArrayElements(text, chars, JNI_ABORT); 860 } 861 862 static void drawTextRun__StringIIIIFFIPaint( 863 JNIEnv* env, jobject obj, SkCanvas* canvas, jstring text, jint start, 864 jint end, jint contextStart, jint contextEnd, 865 jfloat x, jfloat y, jint dirFlags, SkPaint* paint) { 866 867 jint count = end - start; 868 jint contextCount = contextEnd - contextStart; 869 const jchar* chars = env->GetStringChars(text, NULL); 870#if RTL_USE_HARFBUZZ 871 drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart, 872 count, contextCount, x, y, dirFlags, paint); 873#else 874 TextLayout::drawTextRun(paint, chars + contextStart, start - contextStart, 875 count, contextCount, dirFlags, x, y, canvas); 876#endif 877 env->ReleaseStringChars(text, chars); 878 } 879 880 static void drawPosText___CII_FPaint(JNIEnv* env, jobject, SkCanvas* canvas, 881 jcharArray text, int index, int count, 882 jfloatArray pos, SkPaint* paint) { 883 jchar* textArray = text ? env->GetCharArrayElements(text, NULL) : NULL; 884 jsize textCount = text ? env->GetArrayLength(text) : NULL; 885 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL; 886 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0; 887 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL; 888 int indx; 889 for (indx = 0; indx < posCount; indx++) { 890 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]); 891 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]); 892 } 893 canvas->drawPosText(textArray + index, count << 1, posPtr, *paint); 894 if (text) { 895 env->ReleaseCharArrayElements(text, textArray, 0); 896 } 897 if (pos) { 898 env->ReleaseFloatArrayElements(pos, posArray, 0); 899 } 900 delete[] posPtr; 901 } 902 903 static void drawPosText__String_FPaint(JNIEnv* env, jobject, 904 SkCanvas* canvas, jstring text, 905 jfloatArray pos, 906 SkPaint* paint) { 907 const void* text_ = text ? env->GetStringChars(text, NULL) : NULL; 908 int byteLength = text ? env->GetStringLength(text) : 0; 909 float* posArray = pos ? env->GetFloatArrayElements(pos, NULL) : NULL; 910 int posCount = pos ? env->GetArrayLength(pos) >> 1: 0; 911 SkPoint* posPtr = posCount > 0 ? new SkPoint[posCount] : NULL; 912 913 for (int indx = 0; indx < posCount; indx++) { 914 posPtr[indx].fX = SkFloatToScalar(posArray[indx << 1]); 915 posPtr[indx].fY = SkFloatToScalar(posArray[(indx << 1) + 1]); 916 } 917 canvas->drawPosText(text_, byteLength << 1, posPtr, *paint); 918 if (text) { 919 env->ReleaseStringChars(text, (const jchar*) text_); 920 } 921 if (pos) { 922 env->ReleaseFloatArrayElements(pos, posArray, 0); 923 } 924 delete[] posPtr; 925 } 926 927 static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject, 928 SkCanvas* canvas, jcharArray text, int index, int count, 929 SkPath* path, jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) { 930 931 jchar* textArray = env->GetCharArrayElements(text, NULL); 932 TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset, 933 path, canvas); 934 env->ReleaseCharArrayElements(text, textArray, 0); 935 } 936 937 static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject, 938 SkCanvas* canvas, jstring text, SkPath* path, 939 jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) { 940 const jchar* text_ = env->GetStringChars(text, NULL); 941 int count = env->GetStringLength(text); 942 TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset, 943 path, canvas); 944 env->ReleaseStringChars(text, text_); 945 } 946 947 static bool getClipBounds(JNIEnv* env, jobject, SkCanvas* canvas, 948 jobject bounds) { 949 SkRect r; 950 SkIRect ir; 951 bool result = canvas->getClipBounds(&r, SkCanvas::kBW_EdgeType); 952 953 r.round(&ir); 954 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds); 955 return result; 956 } 957 958 static void getCTM(JNIEnv* env, jobject, SkCanvas* canvas, 959 SkMatrix* matrix) { 960 *matrix = canvas->getTotalMatrix(); 961 } 962}; 963 964static JNINativeMethod gCanvasMethods[] = { 965 {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer}, 966 {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster}, 967 {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque}, 968 {"getWidth","()I", (void*) SkCanvasGlue::getWidth}, 969 {"getHeight","()I", (void*) SkCanvasGlue::getHeight}, 970 {"native_setBitmap","(II)V", (void*) SkCanvasGlue::setBitmap}, 971 {"save","()I", (void*) SkCanvasGlue::saveAll}, 972 {"save","(I)I", (void*) SkCanvasGlue::save}, 973 {"native_saveLayer","(ILandroid/graphics/RectF;II)I", 974 (void*) SkCanvasGlue::saveLayer}, 975 {"native_saveLayer","(IFFFFII)I", (void*) SkCanvasGlue::saveLayer4F}, 976 {"native_saveLayerAlpha","(ILandroid/graphics/RectF;II)I", 977 (void*) SkCanvasGlue::saveLayerAlpha}, 978 {"native_saveLayerAlpha","(IFFFFII)I", 979 (void*) SkCanvasGlue::saveLayerAlpha4F}, 980 {"restore","()V", (void*) SkCanvasGlue::restore}, 981 {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount}, 982 {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount}, 983 {"translate","(FF)V", (void*) SkCanvasGlue::translate}, 984 {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF}, 985 {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F}, 986 {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF}, 987 {"native_concat","(II)V", (void*) SkCanvasGlue::concat}, 988 {"native_setMatrix","(II)V", (void*) SkCanvasGlue::setMatrix}, 989 {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF}, 990 {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII}, 991 {"clipRect","(Landroid/graphics/RectF;)Z", 992 (void*) SkCanvasGlue::clipRect_RectF}, 993 {"clipRect","(Landroid/graphics/Rect;)Z", 994 (void*) SkCanvasGlue::clipRect_Rect}, 995 {"native_clipRect","(IFFFFI)Z", (void*) SkCanvasGlue::clipRect}, 996 {"native_clipPath","(III)Z", (void*) SkCanvasGlue::clipPath}, 997 {"native_clipRegion","(III)Z", (void*) SkCanvasGlue::clipRegion}, 998 {"nativeSetDrawFilter", "(II)V", (void*) SkCanvasGlue::setDrawFilter}, 999 {"native_getClipBounds","(ILandroid/graphics/Rect;)Z", 1000 (void*) SkCanvasGlue::getClipBounds}, 1001 {"native_getCTM", "(II)V", (void*)SkCanvasGlue::getCTM}, 1002 {"native_quickReject","(ILandroid/graphics/RectF;I)Z", 1003 (void*) SkCanvasGlue::quickReject__RectFI}, 1004 {"native_quickReject","(III)Z", (void*) SkCanvasGlue::quickReject__PathI}, 1005 {"native_quickReject","(IFFFFI)Z", (void*)SkCanvasGlue::quickReject__FFFFI}, 1006 {"native_drawRGB","(IIII)V", (void*) SkCanvasGlue::drawRGB}, 1007 {"native_drawARGB","(IIIII)V", (void*) SkCanvasGlue::drawARGB}, 1008 {"native_drawColor","(II)V", (void*) SkCanvasGlue::drawColor__I}, 1009 {"native_drawColor","(III)V", (void*) SkCanvasGlue::drawColor__II}, 1010 {"native_drawPaint","(II)V", (void*) SkCanvasGlue::drawPaint}, 1011 {"drawPoint", "(FFLandroid/graphics/Paint;)V", 1012 (void*) SkCanvasGlue::drawPoint}, 1013 {"drawPoints", "([FIILandroid/graphics/Paint;)V", 1014 (void*) SkCanvasGlue::drawPoints}, 1015 {"drawLines", "([FIILandroid/graphics/Paint;)V", 1016 (void*) SkCanvasGlue::drawLines}, 1017 {"native_drawLine","(IFFFFI)V", (void*) SkCanvasGlue::drawLine__FFFFPaint}, 1018 {"native_drawRect","(ILandroid/graphics/RectF;I)V", 1019 (void*) SkCanvasGlue::drawRect__RectFPaint}, 1020 {"native_drawRect","(IFFFFI)V", (void*) SkCanvasGlue::drawRect__FFFFPaint}, 1021 {"native_drawOval","(ILandroid/graphics/RectF;I)V", 1022 (void*) SkCanvasGlue::drawOval}, 1023 {"native_drawCircle","(IFFFI)V", (void*) SkCanvasGlue::drawCircle}, 1024 {"native_drawArc","(ILandroid/graphics/RectF;FFZI)V", 1025 (void*) SkCanvasGlue::drawArc}, 1026 {"native_drawRoundRect","(ILandroid/graphics/RectF;FFI)V", 1027 (void*) SkCanvasGlue::drawRoundRect}, 1028 {"native_drawPath","(III)V", (void*) SkCanvasGlue::drawPath}, 1029 {"native_drawBitmap","(IIFFIIII)V", 1030 (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint}, 1031 {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;III)V", 1032 (void*) SkCanvasGlue::drawBitmapRF}, 1033 {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;III)V", 1034 (void*) SkCanvasGlue::drawBitmapRR}, 1035 {"native_drawBitmap", "(I[IIIFFIIZI)V", 1036 (void*)SkCanvasGlue::drawBitmapArray}, 1037 {"nativeDrawBitmapMatrix", "(IIII)V", 1038 (void*)SkCanvasGlue::drawBitmapMatrix}, 1039 {"nativeDrawBitmapMesh", "(IIII[FI[III)V", 1040 (void*)SkCanvasGlue::drawBitmapMesh}, 1041 {"nativeDrawVertices", "(III[FI[FI[II[SIII)V", 1042 (void*)SkCanvasGlue::drawVertices}, 1043 {"native_drawText","(I[CIIFFII)V", 1044 (void*) SkCanvasGlue::drawText___CIIFFIPaint}, 1045 {"native_drawText","(ILjava/lang/String;IIFFII)V", 1046 (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, 1047 {"native_drawTextWithGlyphs","(I[CIIFFII)V", 1048 (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint}, 1049 {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V", 1050 (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint}, 1051 {"native_drawGlyphs","(I[CIIFFII)V", 1052 (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, 1053 {"native_drawTextRun","(I[CIIIIFFII)V", 1054 (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint}, 1055 {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V", 1056 (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaint}, 1057 {"native_drawPosText","(I[CII[FI)V", 1058 (void*) SkCanvasGlue::drawPosText___CII_FPaint}, 1059 {"native_drawPosText","(ILjava/lang/String;[FI)V", 1060 (void*) SkCanvasGlue::drawPosText__String_FPaint}, 1061 {"native_drawTextOnPath","(I[CIIIFFII)V", 1062 (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint}, 1063 {"native_drawTextOnPath","(ILjava/lang/String;IFFII)V", 1064 (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint}, 1065 {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture}, 1066 1067 {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches} 1068}; 1069 1070/////////////////////////////////////////////////////////////////////////////// 1071 1072#include <android_runtime/AndroidRuntime.h> 1073 1074#define REG(env, name, array) \ 1075 result = android::AndroidRuntime::registerNativeMethods(env, name, array, \ 1076 SK_ARRAY_COUNT(array)); \ 1077 if (result < 0) return result 1078 1079int register_android_graphics_Canvas(JNIEnv* env) { 1080 int result; 1081 1082 REG(env, "android/graphics/Canvas", gCanvasMethods); 1083 1084 return result; 1085} 1086 1087} 1088