android_graphics_Canvas.cpp revision c36bd6c16ddfc160732ff7e4518564714c8aa66e
1/* 2 * Copyright (C) 2014 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 "core_jni_helpers.h" 20 21#include <androidfw/ResourceTypes.h> 22#include <hwui/Canvas.h> 23#include <hwui/Paint.h> 24#include <hwui/Typeface.h> 25#include <minikin/Layout.h> 26 27#include "Bitmap.h" 28#include "SkDrawFilter.h" 29#include "SkGraphics.h" 30 31namespace android { 32 33namespace CanvasJNI { 34 35static Canvas* get_canvas(jlong canvasHandle) { 36 return reinterpret_cast<Canvas*>(canvasHandle); 37} 38 39static void delete_canvas(Canvas* canvas) { 40 delete canvas; 41} 42 43static jlong getNativeFinalizer(JNIEnv* env, jobject clazz) { 44 return static_cast<jlong>(reinterpret_cast<uintptr_t>(&delete_canvas)); 45} 46 47// Native wrapper constructor used by Canvas(Bitmap) 48static jlong initRaster(JNIEnv* env, jobject, jobject jbitmap) { 49 SkBitmap bitmap; 50 if (jbitmap != NULL) { 51 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 52 } 53 return reinterpret_cast<jlong>(Canvas::create_canvas(bitmap)); 54} 55 56// Set the given bitmap as the new draw target (wrapped in a new SkCanvas), 57// optionally copying canvas matrix & clip state. 58static void setBitmap(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap) { 59 SkBitmap bitmap; 60 if (jbitmap != NULL) { 61 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 62 } 63 get_canvas(canvasHandle)->setBitmap(bitmap); 64} 65 66static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) { 67 return get_canvas(canvasHandle)->isOpaque() ? JNI_TRUE : JNI_FALSE; 68} 69 70static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) { 71 return static_cast<jint>(get_canvas(canvasHandle)->width()); 72} 73 74static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) { 75 return static_cast<jint>(get_canvas(canvasHandle)->height()); 76} 77 78static void setHighContrastText(JNIEnv*, jobject, jlong canvasHandle, jboolean highContrastText) { 79 Canvas* canvas = get_canvas(canvasHandle); 80 canvas->setHighContrastText(highContrastText); 81} 82 83static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) { 84 return static_cast<jint>(get_canvas(canvasHandle)->getSaveCount()); 85} 86 87static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) { 88 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle); 89 return static_cast<jint>(get_canvas(canvasHandle)->save(flags)); 90} 91 92static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t, 93 jfloat r, jfloat b, jlong paintHandle, jint flagsHandle) { 94 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 95 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle); 96 return static_cast<jint>(get_canvas(canvasHandle)->saveLayer(l, t, r, b, paint, flags)); 97} 98 99static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle, jfloat l, jfloat t, 100 jfloat r, jfloat b, jint alpha, jint flagsHandle) { 101 SaveFlags::Flags flags = static_cast<SaveFlags::Flags>(flagsHandle); 102 return static_cast<jint>(get_canvas(canvasHandle)->saveLayerAlpha(l, t, r, b, alpha, flags)); 103} 104 105static void restore(JNIEnv* env, jobject, jlong canvasHandle, jboolean throwOnUnderflow) { 106 Canvas* canvas = get_canvas(canvasHandle); 107 if (canvas->getSaveCount() <= 1) { // cannot restore anymore 108 if (throwOnUnderflow) { 109 doThrowISE(env, "Underflow in restore - more restores than saves"); 110 } 111 return; // compat behavior - return without throwing 112 } 113 canvas->restore(); 114} 115 116static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle, jint restoreCount, 117 jboolean throwOnUnderflow) { 118 Canvas* canvas = get_canvas(canvasHandle); 119 if (restoreCount < 1 || restoreCount > canvas->getSaveCount()) { 120 if (throwOnUnderflow) { 121 doThrowIAE(env, "Underflow in restoreToCount - more restores than saves"); 122 return; 123 } 124 restoreCount = 1; // compat behavior - restore as far as possible 125 } 126 canvas->restoreToCount(restoreCount); 127} 128 129static void getCTM(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) { 130 SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 131 get_canvas(canvasHandle)->getMatrix(matrix); 132} 133 134static void setMatrix(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) { 135 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 136 get_canvas(canvasHandle)->setMatrix(matrix ? *matrix : SkMatrix::I()); 137} 138 139static void concat(JNIEnv* env, jobject, jlong canvasHandle, jlong matrixHandle) { 140 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 141 get_canvas(canvasHandle)->concat(*matrix); 142} 143 144static void rotate(JNIEnv*, jobject, jlong canvasHandle, jfloat degrees) { 145 get_canvas(canvasHandle)->rotate(degrees); 146} 147 148static void scale(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) { 149 get_canvas(canvasHandle)->scale(sx, sy); 150} 151 152static void skew(JNIEnv*, jobject, jlong canvasHandle, jfloat sx, jfloat sy) { 153 get_canvas(canvasHandle)->skew(sx, sy); 154} 155 156static void translate(JNIEnv*, jobject, jlong canvasHandle, jfloat dx, jfloat dy) { 157 get_canvas(canvasHandle)->translate(dx, dy); 158} 159 160static jboolean getClipBounds(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds) { 161 SkRect r; 162 SkIRect ir; 163 bool result = get_canvas(canvasHandle)->getClipBounds(&r); 164 165 if (!result) { 166 r.setEmpty(); 167 } 168 r.round(&ir); 169 170 (void)GraphicsJNI::irect_to_jrect(ir, env, bounds); 171 return result ? JNI_TRUE : JNI_FALSE; 172} 173 174static jboolean quickRejectRect(JNIEnv* env, jobject, jlong canvasHandle, 175 jfloat left, jfloat top, jfloat right, jfloat bottom) { 176 bool result = get_canvas(canvasHandle)->quickRejectRect(left, top, right, bottom); 177 return result ? JNI_TRUE : JNI_FALSE; 178} 179 180static jboolean quickRejectPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle) { 181 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 182 bool result = get_canvas(canvasHandle)->quickRejectPath(*path); 183 return result ? JNI_TRUE : JNI_FALSE; 184} 185 186static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle, jfloat l, jfloat t, 187 jfloat r, jfloat b, jint opHandle) { 188 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle); 189 bool nonEmptyClip = get_canvas(canvasHandle)->clipRect(l, t, r, b, op); 190 return nonEmptyClip ? JNI_TRUE : JNI_FALSE; 191} 192 193static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle, 194 jint opHandle) { 195 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 196 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle); 197 bool nonEmptyClip = get_canvas(canvasHandle)->clipPath(path, op); 198 return nonEmptyClip ? JNI_TRUE : JNI_FALSE; 199} 200 201static jboolean clipRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong deviceRgnHandle, 202 jint opHandle) { 203 SkRegion* deviceRgn = reinterpret_cast<SkRegion*>(deviceRgnHandle); 204 SkRegion::Op op = static_cast<SkRegion::Op>(opHandle); 205 bool nonEmptyClip = get_canvas(canvasHandle)->clipRegion(deviceRgn, op); 206 return nonEmptyClip ? JNI_TRUE : JNI_FALSE; 207} 208 209static void drawColor(JNIEnv* env, jobject, jlong canvasHandle, jint color, jint modeHandle) { 210 SkXfermode::Mode mode = static_cast<SkXfermode::Mode>(modeHandle); 211 get_canvas(canvasHandle)->drawColor(color, mode); 212} 213 214static void drawPaint(JNIEnv* env, jobject, jlong canvasHandle, jlong paintHandle) { 215 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 216 get_canvas(canvasHandle)->drawPaint(*paint); 217} 218 219static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y, 220 jlong paintHandle) { 221 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 222 get_canvas(canvasHandle)->drawPoint(x, y, *paint); 223} 224 225static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray, 226 jint offset, jint count, jlong paintHandle) { 227 NPE_CHECK_RETURN_VOID(env, jptsArray); 228 AutoJavaFloatArray autoPts(env, jptsArray); 229 float* floats = autoPts.ptr(); 230 const int length = autoPts.length(); 231 232 if ((offset | count) < 0 || offset + count > length) { 233 doThrowAIOOBE(env); 234 return; 235 } 236 237 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 238 get_canvas(canvasHandle)->drawPoints(floats + offset, count, *paint); 239} 240 241static void drawLine(JNIEnv* env, jobject, jlong canvasHandle, jfloat startX, jfloat startY, 242 jfloat stopX, jfloat stopY, jlong paintHandle) { 243 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 244 get_canvas(canvasHandle)->drawLine(startX, startY, stopX, stopY, *paint); 245} 246 247static void drawLines(JNIEnv* env, jobject, jlong canvasHandle, jfloatArray jptsArray, 248 jint offset, jint count, jlong paintHandle) { 249 NPE_CHECK_RETURN_VOID(env, jptsArray); 250 AutoJavaFloatArray autoPts(env, jptsArray); 251 float* floats = autoPts.ptr(); 252 const int length = autoPts.length(); 253 254 if ((offset | count) < 0 || offset + count > length) { 255 doThrowAIOOBE(env); 256 return; 257 } 258 259 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 260 get_canvas(canvasHandle)->drawLines(floats + offset, count, *paint); 261} 262 263static void drawRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 264 jfloat right, jfloat bottom, jlong paintHandle) { 265 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 266 get_canvas(canvasHandle)->drawRect(left, top, right, bottom, *paint); 267} 268 269static void drawRegion(JNIEnv* env, jobject, jlong canvasHandle, jlong regionHandle, 270 jlong paintHandle) { 271 const SkRegion* region = reinterpret_cast<SkRegion*>(regionHandle); 272 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 273 get_canvas(canvasHandle)->drawRegion(*region, *paint); 274} 275 276static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 277 jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintHandle) { 278 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 279 get_canvas(canvasHandle)->drawRoundRect(left, top, right, bottom, rx, ry, *paint); 280} 281 282static void drawCircle(JNIEnv* env, jobject, jlong canvasHandle, jfloat cx, jfloat cy, 283 jfloat radius, jlong paintHandle) { 284 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 285 get_canvas(canvasHandle)->drawCircle(cx, cy, radius, *paint); 286} 287 288static void drawOval(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 289 jfloat right, jfloat bottom, jlong paintHandle) { 290 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 291 get_canvas(canvasHandle)->drawOval(left, top, right, bottom, *paint); 292} 293 294static void drawArc(JNIEnv* env, jobject, jlong canvasHandle, jfloat left, jfloat top, 295 jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, 296 jboolean useCenter, jlong paintHandle) { 297 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 298 get_canvas(canvasHandle)->drawArc(left, top, right, bottom, startAngle, sweepAngle, 299 useCenter, *paint); 300} 301 302static void drawPath(JNIEnv* env, jobject, jlong canvasHandle, jlong pathHandle, 303 jlong paintHandle) { 304 const SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 305 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 306 get_canvas(canvasHandle)->drawPath(*path, *paint); 307} 308 309static void drawVertices(JNIEnv* env, jobject, jlong canvasHandle, 310 jint modeHandle, jint vertexCount, 311 jfloatArray jverts, jint vertIndex, 312 jfloatArray jtexs, jint texIndex, 313 jintArray jcolors, jint colorIndex, 314 jshortArray jindices, jint indexIndex, 315 jint indexCount, jlong paintHandle) { 316 AutoJavaFloatArray vertA(env, jverts, vertIndex + vertexCount); 317 AutoJavaFloatArray texA(env, jtexs, texIndex + vertexCount); 318 AutoJavaIntArray colorA(env, jcolors, colorIndex + vertexCount); 319 AutoJavaShortArray indexA(env, jindices, indexIndex + indexCount); 320 321 const float* verts = vertA.ptr() + vertIndex; 322 const float* texs = texA.ptr() + vertIndex; 323 const int* colors = NULL; 324 const uint16_t* indices = NULL; 325 326 if (jcolors != NULL) { 327 colors = colorA.ptr() + colorIndex; 328 } 329 if (jindices != NULL) { 330 indices = (const uint16_t*)(indexA.ptr() + indexIndex); 331 } 332 333 SkCanvas::VertexMode mode = static_cast<SkCanvas::VertexMode>(modeHandle); 334 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 335 get_canvas(canvasHandle)->drawVertices(mode, vertexCount, verts, texs, colors, 336 indices, indexCount, *paint); 337} 338 339static void drawNinePatch(JNIEnv* env, jobject, jlong canvasHandle, jlong bitmapHandle, 340 jlong chunkHandle, jfloat left, jfloat top, jfloat right, jfloat bottom, 341 jlong paintHandle, jint dstDensity, jint srcDensity) { 342 343 Canvas* canvas = get_canvas(canvasHandle); 344 SkBitmap skiaBitmap; 345 bitmap::toSkBitmap(bitmapHandle, &skiaBitmap); 346 const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle); 347 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 348 349 if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) { 350 canvas->drawNinePatch(skiaBitmap, *chunk, left, top, right, bottom, paint); 351 } else { 352 canvas->save(SaveFlags::MatrixClip); 353 354 SkScalar scale = dstDensity / (float)srcDensity; 355 canvas->translate(left, top); 356 canvas->scale(scale, scale); 357 358 Paint filteredPaint; 359 if (paint) { 360 filteredPaint = *paint; 361 } 362 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 363 364 canvas->drawNinePatch(skiaBitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale, 365 &filteredPaint); 366 367 canvas->restore(); 368 } 369} 370 371static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap, 372 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity, 373 jint screenDensity, jint bitmapDensity) { 374 Canvas* canvas = get_canvas(canvasHandle); 375 SkBitmap bitmap; 376 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 377 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 378 379 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { 380 if (screenDensity != 0 && screenDensity != bitmapDensity) { 381 Paint filteredPaint; 382 if (paint) { 383 filteredPaint = *paint; 384 } 385 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 386 canvas->drawBitmap(bitmap, left, top, &filteredPaint); 387 } else { 388 canvas->drawBitmap(bitmap, left, top, paint); 389 } 390 } else { 391 canvas->save(SaveFlags::MatrixClip); 392 SkScalar scale = canvasDensity / (float)bitmapDensity; 393 canvas->translate(left, top); 394 canvas->scale(scale, scale); 395 396 Paint filteredPaint; 397 if (paint) { 398 filteredPaint = *paint; 399 } 400 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 401 402 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint); 403 canvas->restore(); 404 } 405} 406 407static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 408 jlong matrixHandle, jlong paintHandle) { 409 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 410 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 411 SkBitmap bitmap; 412 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 413 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint); 414} 415 416static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 417 float srcLeft, float srcTop, float srcRight, float srcBottom, 418 float dstLeft, float dstTop, float dstRight, float dstBottom, 419 jlong paintHandle, jint screenDensity, jint bitmapDensity) { 420 Canvas* canvas = get_canvas(canvasHandle); 421 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 422 423 SkBitmap bitmap; 424 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 425 if (screenDensity != 0 && screenDensity != bitmapDensity) { 426 Paint filteredPaint; 427 if (paint) { 428 filteredPaint = *paint; 429 } 430 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 431 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 432 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint); 433 } else { 434 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 435 dstLeft, dstTop, dstRight, dstBottom, paint); 436 } 437} 438 439static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle, 440 jintArray jcolors, jint offset, jint stride, 441 jfloat x, jfloat y, jint width, jint height, 442 jboolean hasAlpha, jlong paintHandle) { 443 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will 444 // correct the alphaType to kOpaque_SkAlphaType. 445 SkImageInfo info = SkImageInfo::MakeN32(width, height, kPremul_SkAlphaType, 446 GraphicsJNI::defaultColorSpace()); 447 SkBitmap bitmap; 448 bitmap.setInfo(info); 449 sk_sp<PixelRef> pixelRef = PixelRef::allocateHeapPixelRef(&bitmap, NULL); 450 if (!pixelRef) { 451 return; 452 } 453 454 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) { 455 return; 456 } 457 458 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 459 get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint); 460} 461 462static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 463 jint meshWidth, jint meshHeight, jfloatArray jverts, 464 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) { 465 const int ptCount = (meshWidth + 1) * (meshHeight + 1); 466 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1)); 467 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount); 468 469 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 470 SkBitmap bitmap; 471 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 472 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight, 473 vertA.ptr(), colorA.ptr(), paint); 474} 475 476static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 477 jint index, jint count, jfloat x, jfloat y, jint bidiFlags, 478 jlong paintHandle, jlong typefaceHandle) { 479 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 480 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 481 jchar* jchars = env->GetCharArrayElements(text, NULL); 482 get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y, 483 bidiFlags, *paint, typeface); 484 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 485} 486 487static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 488 jint start, jint end, jfloat x, jfloat y, jint bidiFlags, 489 jlong paintHandle, jlong typefaceHandle) { 490 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 491 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 492 const int count = end - start; 493 const jchar* jchars = env->GetStringChars(text, NULL); 494 get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y, 495 bidiFlags, *paint, typeface); 496 env->ReleaseStringChars(text, jchars); 497} 498 499static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index, 500 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y, 501 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) { 502 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 503 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 504 505 const int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR; 506 jchar* jchars = env->GetCharArrayElements(text, NULL); 507 get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count, 508 contextCount, x, y, bidiFlags, *paint, typeface); 509 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 510} 511 512static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, 513 jint start, jint end, jint contextStart, jint contextEnd, 514 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, 515 jlong typefaceHandle) { 516 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 517 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 518 519 int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR; 520 jint count = end - start; 521 jint contextCount = contextEnd - contextStart; 522 const jchar* jchars = env->GetStringChars(text, NULL); 523 get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count, 524 contextCount, x, y, bidiFlags, *paint, typeface); 525 env->ReleaseStringChars(text, jchars); 526} 527 528static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 529 jint index, jint count, jlong pathHandle, jfloat hOffset, 530 jfloat vOffset, jint bidiFlags, jlong paintHandle, 531 jlong typefaceHandle) { 532 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 533 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 534 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 535 536 jchar* jchars = env->GetCharArrayElements(text, NULL); 537 538 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count, bidiFlags, *path, 539 hOffset, vOffset, *paint, typeface); 540 541 env->ReleaseCharArrayElements(text, jchars, 0); 542} 543 544static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 545 jlong pathHandle, jfloat hOffset, jfloat vOffset, 546 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) { 547 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 548 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 549 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 550 551 const jchar* jchars = env->GetStringChars(text, NULL); 552 int count = env->GetStringLength(text); 553 554 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, bidiFlags, *path, 555 hOffset, vOffset, *paint, typeface); 556 557 env->ReleaseStringChars(text, jchars); 558} 559 560static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) { 561 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle)); 562} 563 564static void freeCaches(JNIEnv* env, jobject) { 565 SkGraphics::PurgeFontCache(); 566} 567 568static void freeTextLayoutCaches(JNIEnv* env, jobject) { 569 minikin::Layout::purgeCaches(); 570} 571 572}; // namespace CanvasJNI 573 574static const JNINativeMethod gMethods[] = { 575 {"getNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer}, 576 {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster}, 577 {"freeCaches", "()V", (void*) CanvasJNI::freeCaches}, 578 {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}, 579 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, 580 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, 581 {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, 582 583 // ------------ @FastNative ---------------- 584 {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap}, 585 {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque}, 586 {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth}, 587 {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight}, 588 {"native_setHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText}, 589 {"native_save","(JI)I", (void*) CanvasJNI::save}, 590 {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer}, 591 {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha}, 592 {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount}, 593 {"native_restore","(JZ)V", (void*) CanvasJNI::restore}, 594 {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount}, 595 {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM}, 596 {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix}, 597 {"native_concat","(JJ)V", (void*) CanvasJNI::concat}, 598 {"native_rotate","(JF)V", (void*) CanvasJNI::rotate}, 599 {"native_scale","(JFF)V", (void*) CanvasJNI::scale}, 600 {"native_skew","(JFF)V", (void*) CanvasJNI::skew}, 601 {"native_translate","(JFF)V", (void*) CanvasJNI::translate}, 602 {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds}, 603 {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath}, 604 {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, 605 {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, 606 {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, 607 {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion}, 608 {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor}, 609 {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint}, 610 {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint}, 611 {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints}, 612 {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine}, 613 {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines}, 614 {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect}, 615 {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion }, 616 {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect}, 617 {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle}, 618 {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval}, 619 {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc}, 620 {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath}, 621 {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices}, 622 {"native_drawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch}, 623 {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix}, 624 {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, 625 {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars}, 626 {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString}, 627 {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars}, 628 {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString}, 629 {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars}, 630 {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString}, 631 {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter}, 632}; 633 634int register_android_graphics_Canvas(JNIEnv* env) { 635 return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods)); 636} 637 638}; // namespace android 639