Canvas.cpp revision 8fb507171f68d4170cfeb1187ee7d1f70f98917d
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 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, end, 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 792 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 809 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); 813 drawTextWithGlyphs(canvas, textArray + index, 0, count, x, y, flags, paint); 814 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 815 } 816 817 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); 823 drawTextWithGlyphs(canvas, textArray, start, end, x, y, flags, paint); 824 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) { 829 // 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 837 canvas->drawText(glyphArray + index * 2, count * 2, x, y, *paint); 838 839 // Get back old encoding 840 paint->setTextEncoding(oldEncoding); 841 } 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); 849 850 env->ReleaseCharArrayElements(glyphs, glyphArray, JNI_ABORT); 851 } 852 853 static void drawTextRun___CIIIIFFIPaint( 854 JNIEnv* env, jobject, SkCanvas* canvas, jcharArray text, int index, 855 int count, int contextIndex, int contextCount, 856 jfloat x, jfloat y, int dirFlags, SkPaint* paint) { 857 858 jchar* chars = env->GetCharArrayElements(text, NULL); 859#if RTL_USE_HARFBUZZ 860 drawTextWithGlyphs(canvas, chars + contextIndex, index - contextIndex, 861 count, contextCount, x, y, dirFlags, paint); 862#else 863 TextLayout::drawTextRun(paint, chars + contextIndex, index - contextIndex, 864 count, contextCount, dirFlags, x, y, canvas); 865#endif 866 env->ReleaseCharArrayElements(text, chars, JNI_ABORT); 867 } 868 869 static void drawTextRun__StringIIIIFFIPaint( 870 JNIEnv* env, jobject obj, SkCanvas* canvas, jstring text, jint start, 871 jint end, jint contextStart, jint contextEnd, 872 jfloat x, jfloat y, jint dirFlags, SkPaint* paint) { 873 874 jint count = end - start; 875 jint contextCount = contextEnd - contextStart; 876 const jchar* chars = env->GetStringChars(text, NULL); 877#if RTL_USE_HARFBUZZ 878 drawTextWithGlyphs(canvas, chars + contextStart, start - contextStart, 879 count, contextCount, x, y, dirFlags, paint); 880#else 881 TextLayout::drawTextRun(paint, chars + contextStart, start - contextStart, 882 count, contextCount, dirFlags, x, y, canvas); 883#endif 884 env->ReleaseStringChars(text, chars); 885 } 886 887 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 } 900 canvas->drawPosText(textArray + index, count << 1, posPtr, *paint); 901 if (text) { 902 env->ReleaseCharArrayElements(text, textArray, 0); 903 } 904 if (pos) { 905 env->ReleaseFloatArrayElements(pos, posArray, 0); 906 } 907 delete[] posPtr; 908 } 909 910 static void drawPosText__String_FPaint(JNIEnv* env, jobject, 911 SkCanvas* canvas, jstring text, 912 jfloatArray pos, 913 SkPaint* paint) { 914 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 } 933 934 static void drawTextOnPath___CIIPathFFPaint(JNIEnv* env, jobject, 935 SkCanvas* canvas, jcharArray text, int index, int count, 936 SkPath* path, jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) { 937 938 jchar* textArray = env->GetCharArrayElements(text, NULL); 939 TextLayout::drawTextOnPath(paint, textArray + index, count, bidiFlags, hOffset, vOffset, 940 path, canvas); 941 env->ReleaseCharArrayElements(text, textArray, 0); 942 } 943 944 static void drawTextOnPath__StringPathFFPaint(JNIEnv* env, jobject, 945 SkCanvas* canvas, jstring text, SkPath* path, 946 jfloat hOffset, jfloat vOffset, jint bidiFlags, SkPaint* paint) { 947 const jchar* text_ = env->GetStringChars(text, NULL); 948 int count = env->GetStringLength(text); 949 TextLayout::drawTextOnPath(paint, text_, count, bidiFlags, hOffset, vOffset, 950 path, canvas); 951 env->ReleaseStringChars(text, text_); 952 } 953 954 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}; 970 971static JNINativeMethod gCanvasMethods[] = { 972 {"finalizer", "(I)V", (void*) SkCanvasGlue::finalizer}, 973 {"initRaster","(I)I", (void*) SkCanvasGlue::initRaster}, 974 {"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}, 978 {"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}, 1036 {"native_drawBitmap","(IIFFIIII)V", 1037 (void*) SkCanvasGlue::drawBitmap__BitmapFFPaint}, 1038 {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/RectF;III)V", 1039 (void*) SkCanvasGlue::drawBitmapRF}, 1040 {"native_drawBitmap","(IILandroid/graphics/Rect;Landroid/graphics/Rect;III)V", 1041 (void*) SkCanvasGlue::drawBitmapRR}, 1042 {"native_drawBitmap", "(I[IIIFFIIZI)V", 1043 (void*)SkCanvasGlue::drawBitmapArray}, 1044 {"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}, 1050 {"native_drawText","(I[CIIFFII)V", 1051 (void*) SkCanvasGlue::drawText___CIIFFIPaint}, 1052 {"native_drawText","(ILjava/lang/String;IIFFII)V", 1053 (void*) SkCanvasGlue::drawText__StringIIFFIPaint}, 1054 {"native_drawTextWithGlyphs","(I[CIIFFII)V", 1055 (void*) SkCanvasGlue::drawTextWithGlyphs___CIIFFIPaint}, 1056 {"native_drawTextWithGlyphs","(ILjava/lang/String;IIFFII)V", 1057 (void*) SkCanvasGlue::drawTextWithGlyphs__StringIIFFIPaint}, 1058 {"native_drawGlyphs","(I[CIIFFII)V", 1059 (void*) SkCanvasGlue::drawGlyphs___CIIFFIPaint}, 1060 {"native_drawTextRun","(I[CIIIIFFII)V", 1061 (void*) SkCanvasGlue::drawTextRun___CIIIIFFIPaint}, 1062 {"native_drawTextRun","(ILjava/lang/String;IIIIFFII)V", 1063 (void*) SkCanvasGlue::drawTextRun__StringIIIIFFIPaint}, 1064 {"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}, 1068 {"native_drawTextOnPath","(I[CIIIFFII)V", 1069 (void*) SkCanvasGlue::drawTextOnPath___CIIPathFFPaint}, 1070 {"native_drawTextOnPath","(ILjava/lang/String;IFFII)V", 1071 (void*) SkCanvasGlue::drawTextOnPath__StringPathFFPaint}, 1072 {"native_drawPicture", "(II)V", (void*) SkCanvasGlue::drawPicture}, 1073 1074 {"freeCaches", "()V", (void*) SkCanvasGlue::freeCaches} 1075}; 1076 1077/////////////////////////////////////////////////////////////////////////////// 1078 1079#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); 1090 1091 return result; 1092} 1093 1094} 1095