Canvas.cpp revision 35844a3a4e6f7383d4e77f4426fbd71d5990bf6e
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 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 105 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) { 325 canvas->drawColor(color, SkPorterDuff::ToXfermodeMode(mode)); 326 } 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, 463 SkPaint* paint, jint canvasDensity, 464 jint screenDensity, jint bitmapDensity) { 465 SkScalar left_ = SkFloatToScalar(left); 466 SkScalar top_ = SkFloatToScalar(top); 467 468 if (canvasDensity == bitmapDensity || canvasDensity == 0 469 || bitmapDensity == 0) { 470 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 } 480 } else { 481 canvas->save(); 482 SkScalar scale = SkFloatToScalar(canvasDensity / (float)bitmapDensity); 483 canvas->translate(left_, top_); 484 canvas->scale(scale, scale); 485 486 SkPaint filteredPaint; 487 if (paint) { 488 filteredPaint = *paint; 489 } 490 filteredPaint.setFilterBitmap(true); 491 492 canvas->drawBitmap(*bitmap, 0, 0, &filteredPaint); 493 494 canvas->restore(); 495 } 496 } 497 498 static void doDrawBitmap(JNIEnv* env, SkCanvas* canvas, SkBitmap* bitmap, 499 jobject srcIRect, const SkRect& dst, SkPaint* paint, 500 jint screenDensity, jint bitmapDensity) { 501 SkIRect src, *srcPtr = NULL; 502 503 if (NULL != srcIRect) { 504 GraphicsJNI::jrect_to_irect(env, srcIRect, &src); 505 srcPtr = &src; 506 } 507 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 } 518 } 519 520 static void drawBitmapRF(JNIEnv* env, jobject, SkCanvas* canvas, 521 SkBitmap* bitmap, jobject srcIRect, 522 jobject dstRectF, SkPaint* paint, 523 jint screenDensity, jint bitmapDensity) { 524 SkRect dst; 525 GraphicsJNI::jrectf_to_rect(env, dstRectF, &dst); 526 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint, 527 screenDensity, bitmapDensity); 528 } 529 530 static void drawBitmapRR(JNIEnv* env, jobject, SkCanvas* canvas, 531 SkBitmap* bitmap, jobject srcIRect, 532 jobject dstRect, SkPaint* paint, 533 jint screenDensity, jint bitmapDensity) { 534 SkRect dst; 535 GraphicsJNI::jrect_to_rect(env, dstRect, &dst); 536 doDrawBitmap(env, canvas, bitmap, srcIRect, dst, paint, 537 screenDensity, bitmapDensity); 538 } 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); 677 SkSafeUnref(tmpPaint.setShader(shader)); 678 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 } 740 741 742 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); 746#if RTL_USE_HARFBUZZ 747 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); 748#else 749 TextLayout::drawText(paint, textArray + index, count, flags, x, y, canvas); 750#endif 751 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 752 } 753 754 static void drawText__StringIIFFIPaint(JNIEnv* env, jobject, 755 SkCanvas* canvas, jstring text, 756 int start, int end, 757 jfloat x, jfloat y, int flags, SkPaint* paint) { 758 const jchar* textArray = env->GetStringChars(text, NULL); 759#if RTL_USE_HARFBUZZ 760 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint); 761#else 762 TextLayout::drawText(paint, textArray + start, end - start, flags, x, y, canvas); 763#endif 764 env->ReleaseStringChars(text, textArray); 765 } 766 767 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray, 768 int start, int end, 769 jfloat x, jfloat y, int flags, SkPaint* paint) { 770 771 jint count = end - start; 772 sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue( 773 paint, textArray, start, count, end, flags); 774 if (value == NULL) { 775 LOGE("Cannot get TextLayoutCache value"); 776 return ; 777 } 778#if DEBUG_GLYPHS 779 logGlyphs(value); 780#endif 781 doDrawGlyphs(canvas, value->getGlyphs(), 0, value->getGlyphsCount(), 782 x, y, flags, paint); 783 } 784 785 static void drawTextWithGlyphs(SkCanvas* canvas, const jchar* textArray, 786 int start, int count, int contextCount, 787 jfloat x, jfloat y, int flags, SkPaint* paint) { 788 789 sp<TextLayoutCacheValue> value = gTextLayoutCache.getValue( 790 paint, textArray, start, count, contextCount, flags); 791 if (value == NULL) { 792 LOGE("Cannot get TextLayoutCache value"); 793 return ; 794 } 795#if DEBUG_GLYPHS 796 logGlyphs(value); 797#endif 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