android_graphics_Canvas.cpp revision 253f2c213f6ecda63b6872aee77bd30d5ec07c82
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 if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) { 450 return; 451 } 452 453 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) { 454 return; 455 } 456 457 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 458 get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint); 459} 460 461static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 462 jint meshWidth, jint meshHeight, jfloatArray jverts, 463 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) { 464 const int ptCount = (meshWidth + 1) * (meshHeight + 1); 465 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1)); 466 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount); 467 468 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 469 SkBitmap bitmap; 470 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 471 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight, 472 vertA.ptr(), colorA.ptr(), paint); 473} 474 475static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 476 jint index, jint count, jfloat x, jfloat y, jint bidiFlags, 477 jlong paintHandle, jlong typefaceHandle) { 478 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 479 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 480 jchar* jchars = env->GetCharArrayElements(text, NULL); 481 get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y, 482 bidiFlags, *paint, typeface); 483 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 484} 485 486static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 487 jint start, jint end, jfloat x, jfloat y, jint bidiFlags, 488 jlong paintHandle, jlong typefaceHandle) { 489 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 490 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 491 const int count = end - start; 492 const jchar* jchars = env->GetStringChars(text, NULL); 493 get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y, 494 bidiFlags, *paint, typeface); 495 env->ReleaseStringChars(text, jchars); 496} 497 498static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index, 499 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y, 500 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) { 501 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 502 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 503 504 const int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR; 505 jchar* jchars = env->GetCharArrayElements(text, NULL); 506 get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count, 507 contextCount, x, y, bidiFlags, *paint, typeface); 508 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 509} 510 511static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, 512 jint start, jint end, jint contextStart, jint contextEnd, 513 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, 514 jlong typefaceHandle) { 515 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 516 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 517 518 int bidiFlags = isRtl ? minikin::kBidi_Force_RTL : minikin::kBidi_Force_LTR; 519 jint count = end - start; 520 jint contextCount = contextEnd - contextStart; 521 const jchar* jchars = env->GetStringChars(text, NULL); 522 get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count, 523 contextCount, x, y, bidiFlags, *paint, typeface); 524 env->ReleaseStringChars(text, jchars); 525} 526 527static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 528 jint index, jint count, jlong pathHandle, jfloat hOffset, 529 jfloat vOffset, jint bidiFlags, jlong paintHandle, 530 jlong typefaceHandle) { 531 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 532 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 533 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 534 535 jchar* jchars = env->GetCharArrayElements(text, NULL); 536 537 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count, bidiFlags, *path, 538 hOffset, vOffset, *paint, typeface); 539 540 env->ReleaseCharArrayElements(text, jchars, 0); 541} 542 543static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 544 jlong pathHandle, jfloat hOffset, jfloat vOffset, 545 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) { 546 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 547 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 548 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 549 550 const jchar* jchars = env->GetStringChars(text, NULL); 551 int count = env->GetStringLength(text); 552 553 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, bidiFlags, *path, 554 hOffset, vOffset, *paint, typeface); 555 556 env->ReleaseStringChars(text, jchars); 557} 558 559static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) { 560 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle)); 561} 562 563static void freeCaches(JNIEnv* env, jobject) { 564 SkGraphics::PurgeFontCache(); 565} 566 567static void freeTextLayoutCaches(JNIEnv* env, jobject) { 568 minikin::Layout::purgeCaches(); 569} 570 571}; // namespace CanvasJNI 572 573static const JNINativeMethod gMethods[] = { 574 {"getNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer}, 575 {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster}, 576 {"freeCaches", "()V", (void*) CanvasJNI::freeCaches}, 577 {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches}, 578 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, 579 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, 580 {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, 581 582 // ------------ @FastNative ---------------- 583 {"native_setBitmap", "(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap}, 584 {"native_isOpaque","(J)Z", (void*) CanvasJNI::isOpaque}, 585 {"native_getWidth","(J)I", (void*) CanvasJNI::getWidth}, 586 {"native_getHeight","(J)I", (void*) CanvasJNI::getHeight}, 587 {"native_setHighContrastText","(JZ)V", (void*) CanvasJNI::setHighContrastText}, 588 {"native_save","(JI)I", (void*) CanvasJNI::save}, 589 {"native_saveLayer","(JFFFFJI)I", (void*) CanvasJNI::saveLayer}, 590 {"native_saveLayerAlpha","(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha}, 591 {"native_getSaveCount","(J)I", (void*) CanvasJNI::getSaveCount}, 592 {"native_restore","(JZ)V", (void*) CanvasJNI::restore}, 593 {"native_restoreToCount","(JIZ)V", (void*) CanvasJNI::restoreToCount}, 594 {"native_getCTM", "(JJ)V", (void*)CanvasJNI::getCTM}, 595 {"native_setMatrix","(JJ)V", (void*) CanvasJNI::setMatrix}, 596 {"native_concat","(JJ)V", (void*) CanvasJNI::concat}, 597 {"native_rotate","(JF)V", (void*) CanvasJNI::rotate}, 598 {"native_scale","(JFF)V", (void*) CanvasJNI::scale}, 599 {"native_skew","(JFF)V", (void*) CanvasJNI::skew}, 600 {"native_translate","(JFF)V", (void*) CanvasJNI::translate}, 601 {"native_getClipBounds","(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds}, 602 {"native_quickReject","(JJ)Z", (void*) CanvasJNI::quickRejectPath}, 603 {"native_quickReject","(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, 604 {"native_clipRect","(JFFFFI)Z", (void*) CanvasJNI::clipRect}, 605 {"native_clipPath","(JJI)Z", (void*) CanvasJNI::clipPath}, 606 {"native_clipRegion","(JJI)Z", (void*) CanvasJNI::clipRegion}, 607 {"native_drawColor","(JII)V", (void*) CanvasJNI::drawColor}, 608 {"native_drawPaint","(JJ)V", (void*) CanvasJNI::drawPaint}, 609 {"native_drawPoint", "(JFFJ)V", (void*) CanvasJNI::drawPoint}, 610 {"native_drawPoints", "(J[FIIJ)V", (void*) CanvasJNI::drawPoints}, 611 {"native_drawLine", "(JFFFFJ)V", (void*) CanvasJNI::drawLine}, 612 {"native_drawLines", "(J[FIIJ)V", (void*) CanvasJNI::drawLines}, 613 {"native_drawRect","(JFFFFJ)V", (void*) CanvasJNI::drawRect}, 614 {"native_drawRegion", "(JJJ)V", (void*) CanvasJNI::drawRegion }, 615 {"native_drawRoundRect","(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect}, 616 {"native_drawCircle","(JFFFJ)V", (void*) CanvasJNI::drawCircle}, 617 {"native_drawOval","(JFFFFJ)V", (void*) CanvasJNI::drawOval}, 618 {"native_drawArc","(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc}, 619 {"native_drawPath","(JJJ)V", (void*) CanvasJNI::drawPath}, 620 {"nativeDrawVertices", "(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices}, 621 {"native_drawNinePatch", "(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch}, 622 {"nativeDrawBitmapMatrix", "(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix}, 623 {"nativeDrawBitmapMesh", "(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, 624 {"native_drawText","(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars}, 625 {"native_drawText","(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString}, 626 {"native_drawTextRun","(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars}, 627 {"native_drawTextRun","(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString}, 628 {"native_drawTextOnPath","(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars}, 629 {"native_drawTextOnPath","(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString}, 630 {"nativeSetDrawFilter", "(JJ)V", (void*) CanvasJNI::setDrawFilter}, 631}; 632 633int register_android_graphics_Canvas(JNIEnv* env) { 634 return RegisterMethodsOrDie(env, "android/graphics/Canvas", gMethods, NELEM(gMethods)); 635} 636 637}; // namespace android 638