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 Bitmap* bitmap = reinterpret_cast<Bitmap*>(bitmapHandle); 345 SkBitmap skiaBitmap; 346 bitmap->getSkBitmap(&skiaBitmap); 347 const android::Res_png_9patch* chunk = reinterpret_cast<android::Res_png_9patch*>(chunkHandle); 348 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 349 350 if (CC_LIKELY(dstDensity == srcDensity || dstDensity == 0 || srcDensity == 0)) { 351 canvas->drawNinePatch(skiaBitmap, *chunk, left, top, right, bottom, paint); 352 } else { 353 canvas->save(SaveFlags::MatrixClip); 354 355 SkScalar scale = dstDensity / (float)srcDensity; 356 canvas->translate(left, top); 357 canvas->scale(scale, scale); 358 359 Paint filteredPaint; 360 if (paint) { 361 filteredPaint = *paint; 362 } 363 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 364 365 canvas->drawNinePatch(skiaBitmap, *chunk, 0, 0, (right-left)/scale, (bottom-top)/scale, 366 &filteredPaint); 367 368 canvas->restore(); 369 } 370} 371 372static void drawBitmap(JNIEnv* env, jobject jcanvas, jlong canvasHandle, jobject jbitmap, 373 jfloat left, jfloat top, jlong paintHandle, jint canvasDensity, 374 jint screenDensity, jint bitmapDensity) { 375 Canvas* canvas = get_canvas(canvasHandle); 376 SkBitmap bitmap; 377 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 378 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 379 380 if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) { 381 if (screenDensity != 0 && screenDensity != bitmapDensity) { 382 Paint filteredPaint; 383 if (paint) { 384 filteredPaint = *paint; 385 } 386 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 387 canvas->drawBitmap(bitmap, left, top, &filteredPaint); 388 } else { 389 canvas->drawBitmap(bitmap, left, top, paint); 390 } 391 } else { 392 canvas->save(SaveFlags::MatrixClip); 393 SkScalar scale = canvasDensity / (float)bitmapDensity; 394 canvas->translate(left, top); 395 canvas->scale(scale, scale); 396 397 Paint filteredPaint; 398 if (paint) { 399 filteredPaint = *paint; 400 } 401 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 402 403 canvas->drawBitmap(bitmap, 0, 0, &filteredPaint); 404 canvas->restore(); 405 } 406} 407 408static void drawBitmapMatrix(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 409 jlong matrixHandle, jlong paintHandle) { 410 const SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixHandle); 411 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 412 SkBitmap bitmap; 413 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 414 get_canvas(canvasHandle)->drawBitmap(bitmap, *matrix, paint); 415} 416 417static void drawBitmapRect(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 418 float srcLeft, float srcTop, float srcRight, float srcBottom, 419 float dstLeft, float dstTop, float dstRight, float dstBottom, 420 jlong paintHandle, jint screenDensity, jint bitmapDensity) { 421 Canvas* canvas = get_canvas(canvasHandle); 422 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 423 424 SkBitmap bitmap; 425 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 426 if (screenDensity != 0 && screenDensity != bitmapDensity) { 427 Paint filteredPaint; 428 if (paint) { 429 filteredPaint = *paint; 430 } 431 filteredPaint.setFilterQuality(kLow_SkFilterQuality); 432 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 433 dstLeft, dstTop, dstRight, dstBottom, &filteredPaint); 434 } else { 435 canvas->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, 436 dstLeft, dstTop, dstRight, dstBottom, paint); 437 } 438} 439 440static void drawBitmapArray(JNIEnv* env, jobject, jlong canvasHandle, 441 jintArray jcolors, jint offset, jint stride, 442 jfloat x, jfloat y, jint width, jint height, 443 jboolean hasAlpha, jlong paintHandle) { 444 // Note: If hasAlpha is false, kRGB_565_SkColorType will be used, which will 445 // correct the alphaType to kOpaque_SkAlphaType. 446 SkImageInfo info = SkImageInfo::Make(width, height, 447 hasAlpha ? kN32_SkColorType : kRGB_565_SkColorType, 448 kPremul_SkAlphaType); 449 SkBitmap bitmap; 450 bitmap.setInfo(info); 451 if (!GraphicsJNI::allocatePixels(env, &bitmap, NULL)) { 452 return; 453 } 454 455 if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) { 456 return; 457 } 458 459 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 460 get_canvas(canvasHandle)->drawBitmap(bitmap, x, y, paint); 461} 462 463static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbitmap, 464 jint meshWidth, jint meshHeight, jfloatArray jverts, 465 jint vertIndex, jintArray jcolors, jint colorIndex, jlong paintHandle) { 466 const int ptCount = (meshWidth + 1) * (meshHeight + 1); 467 AutoJavaFloatArray vertA(env, jverts, vertIndex + (ptCount << 1)); 468 AutoJavaIntArray colorA(env, jcolors, colorIndex + ptCount); 469 470 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 471 SkBitmap bitmap; 472 GraphicsJNI::getSkBitmap(env, jbitmap, &bitmap); 473 get_canvas(canvasHandle)->drawBitmapMesh(bitmap, meshWidth, meshHeight, 474 vertA.ptr(), colorA.ptr(), paint); 475} 476 477static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 478 jint index, jint count, jfloat x, jfloat y, jint bidiFlags, 479 jlong paintHandle, jlong typefaceHandle) { 480 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 481 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 482 jchar* jchars = env->GetCharArrayElements(text, NULL); 483 get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y, 484 bidiFlags, *paint, typeface); 485 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 486} 487 488static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 489 jint start, jint end, jfloat x, jfloat y, jint bidiFlags, 490 jlong paintHandle, jlong typefaceHandle) { 491 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 492 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 493 const int count = end - start; 494 const jchar* jchars = env->GetStringChars(text, NULL); 495 get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y, 496 bidiFlags, *paint, typeface); 497 env->ReleaseStringChars(text, jchars); 498} 499 500static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, jint index, 501 jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y, 502 jboolean isRtl, jlong paintHandle, jlong typefaceHandle) { 503 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 504 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 505 506 const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; 507 jchar* jchars = env->GetCharArrayElements(text, NULL); 508 get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count, 509 contextCount, x, y, bidiFlags, *paint, typeface); 510 env->ReleaseCharArrayElements(text, jchars, JNI_ABORT); 511} 512 513static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstring text, 514 jint start, jint end, jint contextStart, jint contextEnd, 515 jfloat x, jfloat y, jboolean isRtl, jlong paintHandle, 516 jlong typefaceHandle) { 517 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 518 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 519 520 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; 521 jint count = end - start; 522 jint contextCount = contextEnd - contextStart; 523 const jchar* jchars = env->GetStringChars(text, NULL); 524 get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count, 525 contextCount, x, y, bidiFlags, *paint, typeface); 526 env->ReleaseStringChars(text, jchars); 527} 528 529static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text, 530 jint index, jint count, jlong pathHandle, jfloat hOffset, 531 jfloat vOffset, jint bidiFlags, jlong paintHandle, 532 jlong typefaceHandle) { 533 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 534 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 535 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 536 537 jchar* jchars = env->GetCharArrayElements(text, NULL); 538 539 get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count, bidiFlags, *path, 540 hOffset, vOffset, *paint, typeface); 541 542 env->ReleaseCharArrayElements(text, jchars, 0); 543} 544 545static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstring text, 546 jlong pathHandle, jfloat hOffset, jfloat vOffset, 547 jint bidiFlags, jlong paintHandle, jlong typefaceHandle) { 548 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 549 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 550 Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle); 551 552 const jchar* jchars = env->GetStringChars(text, NULL); 553 int count = env->GetStringLength(text); 554 555 get_canvas(canvasHandle)->drawTextOnPath(jchars, count, bidiFlags, *path, 556 hOffset, vOffset, *paint, typeface); 557 558 env->ReleaseStringChars(text, jchars); 559} 560 561static void setDrawFilter(JNIEnv* env, jobject, jlong canvasHandle, jlong filterHandle) { 562 get_canvas(canvasHandle)->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle)); 563} 564 565static void freeCaches(JNIEnv* env, jobject) { 566 SkGraphics::PurgeFontCache(); 567} 568 569static void freeTextLayoutCaches(JNIEnv* env, jobject) { 570 Layout::purgeCaches(); 571} 572 573}; // namespace CanvasJNI 574 575static const JNINativeMethod gMethods[] = { 576 {"getNativeFinalizer", "()J", (void*) CanvasJNI::getNativeFinalizer}, 577 {"initRaster", "(Landroid/graphics/Bitmap;)J", (void*) CanvasJNI::initRaster}, 578 {"native_setBitmap", "!(JLandroid/graphics/Bitmap;)V", (void*) CanvasJNI::setBitmap}, 579 {"native_isOpaque","!(J)Z", (void*) CanvasJNI::isOpaque}, 580 {"native_getWidth","!(J)I", (void*) CanvasJNI::getWidth}, 581 {"native_getHeight","!(J)I", (void*) CanvasJNI::getHeight}, 582 {"native_setHighContrastText","!(JZ)V", (void*) CanvasJNI::setHighContrastText}, 583 {"native_save","!(JI)I", (void*) CanvasJNI::save}, 584 {"native_saveLayer","!(JFFFFJI)I", (void*) CanvasJNI::saveLayer}, 585 {"native_saveLayerAlpha","!(JFFFFII)I", (void*) CanvasJNI::saveLayerAlpha}, 586 {"native_getSaveCount","!(J)I", (void*) CanvasJNI::getSaveCount}, 587 {"native_restore","!(JZ)V", (void*) CanvasJNI::restore}, 588 {"native_restoreToCount","!(JIZ)V", (void*) CanvasJNI::restoreToCount}, 589 {"native_getCTM", "!(JJ)V", (void*)CanvasJNI::getCTM}, 590 {"native_setMatrix","!(JJ)V", (void*) CanvasJNI::setMatrix}, 591 {"native_concat","!(JJ)V", (void*) CanvasJNI::concat}, 592 {"native_rotate","!(JF)V", (void*) CanvasJNI::rotate}, 593 {"native_scale","!(JFF)V", (void*) CanvasJNI::scale}, 594 {"native_skew","!(JFF)V", (void*) CanvasJNI::skew}, 595 {"native_translate","!(JFF)V", (void*) CanvasJNI::translate}, 596 {"native_getClipBounds","!(JLandroid/graphics/Rect;)Z", (void*) CanvasJNI::getClipBounds}, 597 {"native_quickReject","!(JJ)Z", (void*) CanvasJNI::quickRejectPath}, 598 {"native_quickReject","!(JFFFF)Z", (void*)CanvasJNI::quickRejectRect}, 599 {"native_clipRect","!(JFFFFI)Z", (void*) CanvasJNI::clipRect}, 600 {"native_clipPath","!(JJI)Z", (void*) CanvasJNI::clipPath}, 601 {"native_clipRegion","!(JJI)Z", (void*) CanvasJNI::clipRegion}, 602 {"native_drawColor","!(JII)V", (void*) CanvasJNI::drawColor}, 603 {"native_drawPaint","!(JJ)V", (void*) CanvasJNI::drawPaint}, 604 {"native_drawPoint", "!(JFFJ)V", (void*) CanvasJNI::drawPoint}, 605 {"native_drawPoints", "!(J[FIIJ)V", (void*) CanvasJNI::drawPoints}, 606 {"native_drawLine", "!(JFFFFJ)V", (void*) CanvasJNI::drawLine}, 607 {"native_drawLines", "!(J[FIIJ)V", (void*) CanvasJNI::drawLines}, 608 {"native_drawRect","!(JFFFFJ)V", (void*) CanvasJNI::drawRect}, 609 {"native_drawRegion", "!(JJJ)V", (void*) CanvasJNI::drawRegion }, 610 {"native_drawRoundRect","!(JFFFFFFJ)V", (void*) CanvasJNI::drawRoundRect}, 611 {"native_drawCircle","!(JFFFJ)V", (void*) CanvasJNI::drawCircle}, 612 {"native_drawOval","!(JFFFFJ)V", (void*) CanvasJNI::drawOval}, 613 {"native_drawArc","!(JFFFFFFZJ)V", (void*) CanvasJNI::drawArc}, 614 {"native_drawPath","!(JJJ)V", (void*) CanvasJNI::drawPath}, 615 {"nativeDrawVertices", "!(JII[FI[FI[II[SIIJ)V", (void*)CanvasJNI::drawVertices}, 616 {"native_drawNinePatch", "!(JJJFFFFJII)V", (void*)CanvasJNI::drawNinePatch}, 617 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFJIII)V", (void*) CanvasJNI::drawBitmap}, 618 {"nativeDrawBitmapMatrix", "!(JLandroid/graphics/Bitmap;JJ)V", (void*)CanvasJNI::drawBitmapMatrix}, 619 {"native_drawBitmap","(JLandroid/graphics/Bitmap;FFFFFFFFJII)V", (void*) CanvasJNI::drawBitmapRect}, 620 {"native_drawBitmap", "(J[IIIFFIIZJ)V", (void*)CanvasJNI::drawBitmapArray}, 621 {"nativeDrawBitmapMesh", "!(JLandroid/graphics/Bitmap;II[FI[IIJ)V", (void*)CanvasJNI::drawBitmapMesh}, 622 {"native_drawText","!(J[CIIFFIJJ)V", (void*) CanvasJNI::drawTextChars}, 623 {"native_drawText","!(JLjava/lang/String;IIFFIJJ)V", (void*) CanvasJNI::drawTextString}, 624 {"native_drawTextRun","!(J[CIIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunChars}, 625 {"native_drawTextRun","!(JLjava/lang/String;IIIIFFZJJ)V", (void*) CanvasJNI::drawTextRunString}, 626 {"native_drawTextOnPath","!(J[CIIJFFIJJ)V", (void*) CanvasJNI::drawTextOnPathChars}, 627 {"native_drawTextOnPath","!(JLjava/lang/String;JFFIJJ)V", (void*) CanvasJNI::drawTextOnPathString}, 628 {"nativeSetDrawFilter", "!(JJ)V", (void*) CanvasJNI::setDrawFilter}, 629 {"freeCaches", "()V", (void*) CanvasJNI::freeCaches}, 630 {"freeTextLayoutCaches", "()V", (void*) CanvasJNI::freeTextLayoutCaches} 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