Paint.cpp revision 0b8606266c1afc69cbeb73acda67c85d87943318
1/* libs/android_runtime/android/graphics/Paint.cpp 2** 3** Copyright 2006, The Android Open Source Project 4** 5** Licensed under the Apache License, Version 2.0 (the "License"); 6** you may not use this file except in compliance with the License. 7** You may obtain a copy of the License at 8** 9** http://www.apache.org/licenses/LICENSE-2.0 10** 11** Unless required by applicable law or agreed to in writing, software 12** distributed under the License is distributed on an "AS IS" BASIS, 13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14** See the License for the specific language governing permissions and 15** limitations under the License. 16*/ 17 18#define LOG_TAG "Paint" 19 20#include <utils/Log.h> 21 22#include "jni.h" 23#include "GraphicsJNI.h" 24#include "core_jni_helpers.h" 25#include <ScopedUtfChars.h> 26 27#include "SkBlurDrawLooper.h" 28#include "SkColorFilter.h" 29#include "SkMaskFilter.h" 30#include "SkRasterizer.h" 31#include "SkShader.h" 32#include "SkTypeface.h" 33#include "SkXfermode.h" 34#include "unicode/uloc.h" 35#include "unicode/ushape.h" 36#include "utils/Blur.h" 37 38#include <minikin/GraphemeBreak.h> 39#include "MinikinSkia.h" 40#include "MinikinUtils.h" 41#include "Paint.h" 42#include "TypefaceImpl.h" 43 44// temporary for debugging 45#include <Caches.h> 46#include <utils/Log.h> 47 48namespace android { 49 50struct JMetricsID { 51 jfieldID top; 52 jfieldID ascent; 53 jfieldID descent; 54 jfieldID bottom; 55 jfieldID leading; 56}; 57 58static jclass gFontMetrics_class; 59static JMetricsID gFontMetrics_fieldID; 60 61static jclass gFontMetricsInt_class; 62static JMetricsID gFontMetricsInt_fieldID; 63 64static jclass gPaint_class; 65static jfieldID gPaint_nativeInstanceID; 66static jfieldID gPaint_nativeTypefaceID; 67 68static void defaultSettingsForAndroid(Paint* paint) { 69 // GlyphID encoding is required because we are using Harfbuzz shaping 70 paint->setTextEncoding(Paint::kGlyphID_TextEncoding); 71} 72 73class PaintGlue { 74public: 75 enum MoveOpt { 76 AFTER, AT_OR_AFTER, BEFORE, AT_OR_BEFORE, AT 77 }; 78 79 static Paint* getNativePaint(JNIEnv* env, jobject paint) { 80 SkASSERT(env); 81 SkASSERT(paint); 82 SkASSERT(env->IsInstanceOf(paint, gPaint_class)); 83 jlong paintHandle = env->GetLongField(paint, gPaint_nativeInstanceID); 84 android::Paint* p = reinterpret_cast<android::Paint*>(paintHandle); 85 SkASSERT(p); 86 return p; 87 } 88 89 static TypefaceImpl* getNativeTypeface(JNIEnv* env, jobject paint) { 90 SkASSERT(env); 91 SkASSERT(paint); 92 SkASSERT(env->IsInstanceOf(paint, gPaint_class)); 93 jlong typefaceHandle = env->GetLongField(paint, gPaint_nativeTypefaceID); 94 android::TypefaceImpl* p = reinterpret_cast<android::TypefaceImpl*>(typefaceHandle); 95 return p; 96 } 97 98 static void finalizer(JNIEnv* env, jobject clazz, jlong objHandle) { 99 Paint* obj = reinterpret_cast<Paint*>(objHandle); 100 delete obj; 101 } 102 103 static jlong init(JNIEnv* env, jobject clazz) { 104 SK_COMPILE_ASSERT(1 << 0 == SkPaint::kAntiAlias_Flag, paint_flags_mismatch); 105 SK_COMPILE_ASSERT(1 << 2 == SkPaint::kDither_Flag, paint_flags_mismatch); 106 SK_COMPILE_ASSERT(1 << 3 == SkPaint::kUnderlineText_Flag, paint_flags_mismatch); 107 SK_COMPILE_ASSERT(1 << 4 == SkPaint::kStrikeThruText_Flag, paint_flags_mismatch); 108 SK_COMPILE_ASSERT(1 << 5 == SkPaint::kFakeBoldText_Flag, paint_flags_mismatch); 109 SK_COMPILE_ASSERT(1 << 6 == SkPaint::kLinearText_Flag, paint_flags_mismatch); 110 SK_COMPILE_ASSERT(1 << 7 == SkPaint::kSubpixelText_Flag, paint_flags_mismatch); 111 SK_COMPILE_ASSERT(1 << 8 == SkPaint::kDevKernText_Flag, paint_flags_mismatch); 112 SK_COMPILE_ASSERT(1 << 10 == SkPaint::kEmbeddedBitmapText_Flag, paint_flags_mismatch); 113 114 Paint* obj = new Paint(); 115 defaultSettingsForAndroid(obj); 116 return reinterpret_cast<jlong>(obj); 117 } 118 119 static jlong initWithPaint(JNIEnv* env, jobject clazz, jlong paintHandle) { 120 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 121 Paint* obj = new Paint(*paint); 122 return reinterpret_cast<jlong>(obj); 123 } 124 125 static void reset(JNIEnv* env, jobject clazz, jlong objHandle) { 126 Paint* obj = reinterpret_cast<Paint*>(objHandle); 127 obj->reset(); 128 defaultSettingsForAndroid(obj); 129 } 130 131 static void assign(JNIEnv* env, jobject clazz, jlong dstPaintHandle, jlong srcPaintHandle) { 132 Paint* dst = reinterpret_cast<Paint*>(dstPaintHandle); 133 const Paint* src = reinterpret_cast<Paint*>(srcPaintHandle); 134 *dst = *src; 135 } 136 137 // Equivalent to the Java Paint's FILTER_BITMAP_FLAG. 138 static const uint32_t sFilterBitmapFlag = 0x02; 139 140 static jint getFlags(JNIEnv* env, jobject paint) { 141 NPE_CHECK_RETURN_ZERO(env, paint); 142 Paint* nativePaint = getNativePaint(env, paint); 143 uint32_t result = nativePaint->getFlags(); 144 result &= ~sFilterBitmapFlag; // Filtering no longer stored in this bit. Mask away. 145 if (nativePaint->getFilterQuality() != kNone_SkFilterQuality) { 146 result |= sFilterBitmapFlag; 147 } 148 return static_cast<jint>(result); 149 } 150 151 static void setFlags(JNIEnv* env, jobject paint, jint flags) { 152 NPE_CHECK_RETURN_VOID(env, paint); 153 Paint* nativePaint = getNativePaint(env, paint); 154 // Instead of modifying 0x02, change the filter level. 155 nativePaint->setFilterQuality(flags & sFilterBitmapFlag 156 ? kLow_SkFilterQuality 157 : kNone_SkFilterQuality); 158 // Don't pass through filter flag, which is no longer stored in paint's flags. 159 flags &= ~sFilterBitmapFlag; 160 // Use the existing value for 0x02. 161 const uint32_t existing0x02Flag = nativePaint->getFlags() & sFilterBitmapFlag; 162 flags |= existing0x02Flag; 163 nativePaint->setFlags(flags); 164 } 165 166 static jint getHinting(JNIEnv* env, jobject paint) { 167 NPE_CHECK_RETURN_ZERO(env, paint); 168 return getNativePaint(env, paint)->getHinting() 169 == Paint::kNo_Hinting ? 0 : 1; 170 } 171 172 static void setHinting(JNIEnv* env, jobject paint, jint mode) { 173 NPE_CHECK_RETURN_VOID(env, paint); 174 getNativePaint(env, paint)->setHinting( 175 mode == 0 ? Paint::kNo_Hinting : Paint::kNormal_Hinting); 176 } 177 178 static void setAntiAlias(JNIEnv* env, jobject paint, jboolean aa) { 179 NPE_CHECK_RETURN_VOID(env, paint); 180 getNativePaint(env, paint)->setAntiAlias(aa); 181 } 182 183 static void setLinearText(JNIEnv* env, jobject paint, jboolean linearText) { 184 NPE_CHECK_RETURN_VOID(env, paint); 185 getNativePaint(env, paint)->setLinearText(linearText); 186 } 187 188 static void setSubpixelText(JNIEnv* env, jobject paint, jboolean subpixelText) { 189 NPE_CHECK_RETURN_VOID(env, paint); 190 getNativePaint(env, paint)->setSubpixelText(subpixelText); 191 } 192 193 static void setUnderlineText(JNIEnv* env, jobject paint, jboolean underlineText) { 194 NPE_CHECK_RETURN_VOID(env, paint); 195 getNativePaint(env, paint)->setUnderlineText(underlineText); 196 } 197 198 static void setStrikeThruText(JNIEnv* env, jobject paint, jboolean strikeThruText) { 199 NPE_CHECK_RETURN_VOID(env, paint); 200 getNativePaint(env, paint)->setStrikeThruText(strikeThruText); 201 } 202 203 static void setFakeBoldText(JNIEnv* env, jobject paint, jboolean fakeBoldText) { 204 NPE_CHECK_RETURN_VOID(env, paint); 205 getNativePaint(env, paint)->setFakeBoldText(fakeBoldText); 206 } 207 208 static void setFilterBitmap(JNIEnv* env, jobject paint, jboolean filterBitmap) { 209 NPE_CHECK_RETURN_VOID(env, paint); 210 getNativePaint(env, paint)->setFilterQuality( 211 filterBitmap ? kLow_SkFilterQuality : kNone_SkFilterQuality); 212 } 213 214 static void setDither(JNIEnv* env, jobject paint, jboolean dither) { 215 NPE_CHECK_RETURN_VOID(env, paint); 216 getNativePaint(env, paint)->setDither(dither); 217 } 218 219 static jint getStyle(JNIEnv* env, jobject clazz,jlong objHandle) { 220 Paint* obj = reinterpret_cast<Paint*>(objHandle); 221 return static_cast<jint>(obj->getStyle()); 222 } 223 224 static void setStyle(JNIEnv* env, jobject clazz, jlong objHandle, jint styleHandle) { 225 Paint* obj = reinterpret_cast<Paint*>(objHandle); 226 Paint::Style style = static_cast<Paint::Style>(styleHandle); 227 obj->setStyle(style); 228 } 229 230 static jint getColor(JNIEnv* env, jobject paint) { 231 NPE_CHECK_RETURN_ZERO(env, paint); 232 int color; 233 color = getNativePaint(env, paint)->getColor(); 234 return static_cast<jint>(color); 235 } 236 237 static jint getAlpha(JNIEnv* env, jobject paint) { 238 NPE_CHECK_RETURN_ZERO(env, paint); 239 int alpha; 240 alpha = getNativePaint(env, paint)->getAlpha(); 241 return static_cast<jint>(alpha); 242 } 243 244 static void setColor(JNIEnv* env, jobject paint, jint color) { 245 NPE_CHECK_RETURN_VOID(env, paint); 246 getNativePaint(env, paint)->setColor(color); 247 } 248 249 static void setAlpha(JNIEnv* env, jobject paint, jint a) { 250 NPE_CHECK_RETURN_VOID(env, paint); 251 getNativePaint(env, paint)->setAlpha(a); 252 } 253 254 static jfloat getStrokeWidth(JNIEnv* env, jobject paint) { 255 NPE_CHECK_RETURN_ZERO(env, paint); 256 return SkScalarToFloat(getNativePaint(env, paint)->getStrokeWidth()); 257 } 258 259 static void setStrokeWidth(JNIEnv* env, jobject paint, jfloat width) { 260 NPE_CHECK_RETURN_VOID(env, paint); 261 getNativePaint(env, paint)->setStrokeWidth(width); 262 } 263 264 static jfloat getStrokeMiter(JNIEnv* env, jobject paint) { 265 NPE_CHECK_RETURN_ZERO(env, paint); 266 return SkScalarToFloat(getNativePaint(env, paint)->getStrokeMiter()); 267 } 268 269 static void setStrokeMiter(JNIEnv* env, jobject paint, jfloat miter) { 270 NPE_CHECK_RETURN_VOID(env, paint); 271 getNativePaint(env, paint)->setStrokeMiter(miter); 272 } 273 274 static jint getStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle) { 275 Paint* obj = reinterpret_cast<Paint*>(objHandle); 276 return static_cast<jint>(obj->getStrokeCap()); 277 } 278 279 static void setStrokeCap(JNIEnv* env, jobject clazz, jlong objHandle, jint capHandle) { 280 Paint* obj = reinterpret_cast<Paint*>(objHandle); 281 Paint::Cap cap = static_cast<Paint::Cap>(capHandle); 282 obj->setStrokeCap(cap); 283 } 284 285 static jint getStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle) { 286 Paint* obj = reinterpret_cast<Paint*>(objHandle); 287 return static_cast<jint>(obj->getStrokeJoin()); 288 } 289 290 static void setStrokeJoin(JNIEnv* env, jobject clazz, jlong objHandle, jint joinHandle) { 291 Paint* obj = reinterpret_cast<Paint*>(objHandle); 292 Paint::Join join = (Paint::Join) joinHandle; 293 obj->setStrokeJoin(join); 294 } 295 296 static jboolean getFillPath(JNIEnv* env, jobject clazz, jlong objHandle, jlong srcHandle, jlong dstHandle) { 297 Paint* obj = reinterpret_cast<Paint*>(objHandle); 298 SkPath* src = reinterpret_cast<SkPath*>(srcHandle); 299 SkPath* dst = reinterpret_cast<SkPath*>(dstHandle); 300 return obj->getFillPath(*src, dst) ? JNI_TRUE : JNI_FALSE; 301 } 302 303 static jlong setShader(JNIEnv* env, jobject clazz, jlong objHandle, jlong shaderHandle) { 304 Paint* obj = reinterpret_cast<Paint*>(objHandle); 305 SkShader* shader = reinterpret_cast<SkShader*>(shaderHandle); 306 return reinterpret_cast<jlong>(obj->setShader(shader)); 307 } 308 309 static jlong setColorFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong filterHandle) { 310 Paint* obj = reinterpret_cast<Paint *>(objHandle); 311 SkColorFilter* filter = reinterpret_cast<SkColorFilter *>(filterHandle); 312 return reinterpret_cast<jlong>(obj->setColorFilter(filter)); 313 } 314 315 static jlong setXfermode(JNIEnv* env, jobject clazz, jlong objHandle, jlong xfermodeHandle) { 316 Paint* obj = reinterpret_cast<Paint*>(objHandle); 317 SkXfermode* xfermode = reinterpret_cast<SkXfermode*>(xfermodeHandle); 318 return reinterpret_cast<jlong>(obj->setXfermode(xfermode)); 319 } 320 321 static jlong setPathEffect(JNIEnv* env, jobject clazz, jlong objHandle, jlong effectHandle) { 322 Paint* obj = reinterpret_cast<Paint*>(objHandle); 323 SkPathEffect* effect = reinterpret_cast<SkPathEffect*>(effectHandle); 324 return reinterpret_cast<jlong>(obj->setPathEffect(effect)); 325 } 326 327 static jlong setMaskFilter(JNIEnv* env, jobject clazz, jlong objHandle, jlong maskfilterHandle) { 328 Paint* obj = reinterpret_cast<Paint*>(objHandle); 329 SkMaskFilter* maskfilter = reinterpret_cast<SkMaskFilter*>(maskfilterHandle); 330 return reinterpret_cast<jlong>(obj->setMaskFilter(maskfilter)); 331 } 332 333 static jlong setTypeface(JNIEnv* env, jobject clazz, jlong objHandle, jlong typefaceHandle) { 334 // TODO: in Paint refactoring, set typeface on android Paint, not Paint 335 return NULL; 336 } 337 338 static jlong setRasterizer(JNIEnv* env, jobject clazz, jlong objHandle, jlong rasterizerHandle) { 339 Paint* obj = reinterpret_cast<Paint*>(objHandle); 340 SkAutoTUnref<SkRasterizer> rasterizer(GraphicsJNI::refNativeRasterizer(rasterizerHandle)); 341 return reinterpret_cast<jlong>(obj->setRasterizer(rasterizer)); 342 } 343 344 static jint getTextAlign(JNIEnv* env, jobject clazz, jlong objHandle) { 345 Paint* obj = reinterpret_cast<Paint*>(objHandle); 346 return static_cast<jint>(obj->getTextAlign()); 347 } 348 349 static void setTextAlign(JNIEnv* env, jobject clazz, jlong objHandle, jint alignHandle) { 350 Paint* obj = reinterpret_cast<Paint*>(objHandle); 351 Paint::Align align = static_cast<Paint::Align>(alignHandle); 352 obj->setTextAlign(align); 353 } 354 355 // generate bcp47 identifier for the supplied locale 356 static void toLanguageTag(char* output, size_t outSize, 357 const char* locale) { 358 if (output == NULL || outSize <= 0) { 359 return; 360 } 361 if (locale == NULL) { 362 output[0] = '\0'; 363 return; 364 } 365 char canonicalChars[ULOC_FULLNAME_CAPACITY]; 366 UErrorCode uErr = U_ZERO_ERROR; 367 uloc_canonicalize(locale, canonicalChars, ULOC_FULLNAME_CAPACITY, 368 &uErr); 369 if (U_SUCCESS(uErr)) { 370 char likelyChars[ULOC_FULLNAME_CAPACITY]; 371 uErr = U_ZERO_ERROR; 372 uloc_addLikelySubtags(canonicalChars, likelyChars, 373 ULOC_FULLNAME_CAPACITY, &uErr); 374 if (U_SUCCESS(uErr)) { 375 uErr = U_ZERO_ERROR; 376 uloc_toLanguageTag(likelyChars, output, outSize, FALSE, &uErr); 377 if (U_SUCCESS(uErr)) { 378 return; 379 } else { 380 ALOGD("uloc_toLanguageTag(\"%s\") failed: %s", likelyChars, 381 u_errorName(uErr)); 382 } 383 } else { 384 ALOGD("uloc_addLikelySubtags(\"%s\") failed: %s", 385 canonicalChars, u_errorName(uErr)); 386 } 387 } else { 388 ALOGD("uloc_canonicalize(\"%s\") failed: %s", locale, 389 u_errorName(uErr)); 390 } 391 // unable to build a proper language identifier 392 output[0] = '\0'; 393 } 394 395 static void setTextLocale(JNIEnv* env, jobject clazz, jlong objHandle, jstring locale) { 396 Paint* obj = reinterpret_cast<Paint*>(objHandle); 397 ScopedUtfChars localeChars(env, locale); 398 char langTag[ULOC_FULLNAME_CAPACITY]; 399 toLanguageTag(langTag, ULOC_FULLNAME_CAPACITY, localeChars.c_str()); 400 401 obj->setTextLocale(langTag); 402 } 403 404 static jboolean isElegantTextHeight(JNIEnv* env, jobject paint) { 405 NPE_CHECK_RETURN_ZERO(env, paint); 406 Paint* obj = getNativePaint(env, paint); 407 return obj->getFontVariant() == VARIANT_ELEGANT; 408 } 409 410 static void setElegantTextHeight(JNIEnv* env, jobject paint, jboolean aa) { 411 NPE_CHECK_RETURN_VOID(env, paint); 412 Paint* obj = getNativePaint(env, paint); 413 obj->setFontVariant(aa ? VARIANT_ELEGANT : VARIANT_DEFAULT); 414 } 415 416 static jfloat getTextSize(JNIEnv* env, jobject paint) { 417 NPE_CHECK_RETURN_ZERO(env, paint); 418 return SkScalarToFloat(getNativePaint(env, paint)->getTextSize()); 419 } 420 421 static void setTextSize(JNIEnv* env, jobject paint, jfloat textSize) { 422 NPE_CHECK_RETURN_VOID(env, paint); 423 getNativePaint(env, paint)->setTextSize(textSize); 424 } 425 426 static jfloat getTextScaleX(JNIEnv* env, jobject paint) { 427 NPE_CHECK_RETURN_ZERO(env, paint); 428 return SkScalarToFloat(getNativePaint(env, paint)->getTextScaleX()); 429 } 430 431 static void setTextScaleX(JNIEnv* env, jobject paint, jfloat scaleX) { 432 NPE_CHECK_RETURN_VOID(env, paint); 433 getNativePaint(env, paint)->setTextScaleX(scaleX); 434 } 435 436 static jfloat getTextSkewX(JNIEnv* env, jobject paint) { 437 NPE_CHECK_RETURN_ZERO(env, paint); 438 return SkScalarToFloat(getNativePaint(env, paint)->getTextSkewX()); 439 } 440 441 static void setTextSkewX(JNIEnv* env, jobject paint, jfloat skewX) { 442 NPE_CHECK_RETURN_VOID(env, paint); 443 getNativePaint(env, paint)->setTextSkewX(skewX); 444 } 445 446 static jfloat getLetterSpacing(JNIEnv* env, jobject clazz, jlong paintHandle) { 447 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 448 return paint->getLetterSpacing(); 449 } 450 451 static void setLetterSpacing(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat letterSpacing) { 452 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 453 paint->setLetterSpacing(letterSpacing); 454 } 455 456 static void setFontFeatureSettings(JNIEnv* env, jobject clazz, jlong paintHandle, jstring settings) { 457 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 458 if (!settings) { 459 paint->setFontFeatureSettings(std::string()); 460 } else { 461 ScopedUtfChars settingsChars(env, settings); 462 paint->setFontFeatureSettings(std::string(settingsChars.c_str(), settingsChars.size())); 463 } 464 } 465 466 static jint getHyphenEdit(JNIEnv* env, jobject clazz, jlong paintHandle, jint hyphen) { 467 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 468 return paint->getHyphenEdit(); 469 } 470 471 static void setHyphenEdit(JNIEnv* env, jobject clazz, jlong paintHandle, jint hyphen) { 472 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 473 paint->setHyphenEdit((uint32_t)hyphen); 474 } 475 476 static SkScalar getMetricsInternal(JNIEnv* env, jobject jpaint, Paint::FontMetrics *metrics) { 477 const int kElegantTop = 2500; 478 const int kElegantBottom = -1000; 479 const int kElegantAscent = 1900; 480 const int kElegantDescent = -500; 481 const int kElegantLeading = 0; 482 Paint* paint = getNativePaint(env, jpaint); 483 TypefaceImpl* typeface = getNativeTypeface(env, jpaint); 484 typeface = TypefaceImpl_resolveDefault(typeface); 485 FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle); 486 float saveSkewX = paint->getTextSkewX(); 487 bool savefakeBold = paint->isFakeBoldText(); 488 MinikinFontSkia::populateSkPaint(paint, baseFont.font, baseFont.fakery); 489 SkScalar spacing = paint->getFontMetrics(metrics); 490 // The populateSkPaint call may have changed fake bold / text skew 491 // because we want to measure with those effects applied, so now 492 // restore the original settings. 493 paint->setTextSkewX(saveSkewX); 494 paint->setFakeBoldText(savefakeBold); 495 if (paint->getFontVariant() == VARIANT_ELEGANT) { 496 SkScalar size = paint->getTextSize(); 497 metrics->fTop = -size * kElegantTop / 2048; 498 metrics->fBottom = -size * kElegantBottom / 2048; 499 metrics->fAscent = -size * kElegantAscent / 2048; 500 metrics->fDescent = -size * kElegantDescent / 2048; 501 metrics->fLeading = size * kElegantLeading / 2048; 502 spacing = metrics->fDescent - metrics->fAscent + metrics->fLeading; 503 } 504 return spacing; 505 } 506 507 static jfloat ascent(JNIEnv* env, jobject paint) { 508 NPE_CHECK_RETURN_ZERO(env, paint); 509 Paint::FontMetrics metrics; 510 getMetricsInternal(env, paint, &metrics); 511 return SkScalarToFloat(metrics.fAscent); 512 } 513 514 static jfloat descent(JNIEnv* env, jobject paint) { 515 NPE_CHECK_RETURN_ZERO(env, paint); 516 Paint::FontMetrics metrics; 517 getMetricsInternal(env, paint, &metrics); 518 return SkScalarToFloat(metrics.fDescent); 519 } 520 521 static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) { 522 NPE_CHECK_RETURN_ZERO(env, paint); 523 Paint::FontMetrics metrics; 524 SkScalar spacing = getMetricsInternal(env, paint, &metrics); 525 526 if (metricsObj) { 527 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class)); 528 env->SetFloatField(metricsObj, gFontMetrics_fieldID.top, SkScalarToFloat(metrics.fTop)); 529 env->SetFloatField(metricsObj, gFontMetrics_fieldID.ascent, SkScalarToFloat(metrics.fAscent)); 530 env->SetFloatField(metricsObj, gFontMetrics_fieldID.descent, SkScalarToFloat(metrics.fDescent)); 531 env->SetFloatField(metricsObj, gFontMetrics_fieldID.bottom, SkScalarToFloat(metrics.fBottom)); 532 env->SetFloatField(metricsObj, gFontMetrics_fieldID.leading, SkScalarToFloat(metrics.fLeading)); 533 } 534 return SkScalarToFloat(spacing); 535 } 536 537 static jint getFontMetricsInt(JNIEnv* env, jobject paint, jobject metricsObj) { 538 NPE_CHECK_RETURN_ZERO(env, paint); 539 Paint::FontMetrics metrics; 540 541 getMetricsInternal(env, paint, &metrics); 542 int ascent = SkScalarRoundToInt(metrics.fAscent); 543 int descent = SkScalarRoundToInt(metrics.fDescent); 544 int leading = SkScalarRoundToInt(metrics.fLeading); 545 546 if (metricsObj) { 547 SkASSERT(env->IsInstanceOf(metricsObj, gFontMetricsInt_class)); 548 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.top, SkScalarFloorToInt(metrics.fTop)); 549 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.ascent, ascent); 550 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.descent, descent); 551 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.bottom, SkScalarCeilToInt(metrics.fBottom)); 552 env->SetIntField(metricsObj, gFontMetricsInt_fieldID.leading, leading); 553 } 554 return descent - ascent + leading; 555 } 556 557 static jfloat measureText_CIII(JNIEnv* env, jobject jpaint, jcharArray text, jint index, jint count, 558 jint bidiFlags) { 559 NPE_CHECK_RETURN_ZERO(env, jpaint); 560 NPE_CHECK_RETURN_ZERO(env, text); 561 562 size_t textLength = env->GetArrayLength(text); 563 if ((index | count) < 0 || (size_t)(index + count) > textLength) { 564 doThrowAIOOBE(env); 565 return 0; 566 } 567 if (count == 0) { 568 return 0; 569 } 570 571 Paint* paint = getNativePaint(env, jpaint); 572 const jchar* textArray = env->GetCharArrayElements(text, NULL); 573 jfloat result = 0; 574 575 Layout layout; 576 TypefaceImpl* typeface = getNativeTypeface(env, jpaint); 577 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray, index, count, textLength); 578 result = layout.getAdvance(); 579 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT); 580 return result; 581 } 582 583 static jfloat measureText_StringIII(JNIEnv* env, jobject jpaint, jstring text, jint start, jint end, 584 jint bidiFlags) { 585 NPE_CHECK_RETURN_ZERO(env, jpaint); 586 NPE_CHECK_RETURN_ZERO(env, text); 587 588 size_t textLength = env->GetStringLength(text); 589 int count = end - start; 590 if ((start | count) < 0 || (size_t)end > textLength) { 591 doThrowAIOOBE(env); 592 return 0; 593 } 594 if (count == 0) { 595 return 0; 596 } 597 598 const jchar* textArray = env->GetStringChars(text, NULL); 599 Paint* paint = getNativePaint(env, jpaint); 600 jfloat width = 0; 601 602 Layout layout; 603 TypefaceImpl* typeface = getNativeTypeface(env, jpaint); 604 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray, start, count, textLength); 605 width = layout.getAdvance(); 606 607 env->ReleaseStringChars(text, textArray); 608 return width; 609 } 610 611 static jfloat measureText_StringI(JNIEnv* env, jobject jpaint, jstring text, jint bidiFlags) { 612 NPE_CHECK_RETURN_ZERO(env, jpaint); 613 NPE_CHECK_RETURN_ZERO(env, text); 614 615 size_t textLength = env->GetStringLength(text); 616 if (textLength == 0) { 617 return 0; 618 } 619 620 const jchar* textArray = env->GetStringChars(text, NULL); 621 Paint* paint = getNativePaint(env, jpaint); 622 jfloat width = 0; 623 624 Layout layout; 625 TypefaceImpl* typeface = getNativeTypeface(env, jpaint); 626 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, textArray, 0, textLength, textLength); 627 width = layout.getAdvance(); 628 629 env->ReleaseStringChars(text, textArray); 630 return width; 631 } 632 633 static int dotextwidths(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar text[], int count, 634 jfloatArray widths, jint bidiFlags) { 635 NPE_CHECK_RETURN_ZERO(env, paint); 636 NPE_CHECK_RETURN_ZERO(env, text); 637 638 if (count < 0 || !widths) { 639 doThrowAIOOBE(env); 640 return 0; 641 } 642 if (count == 0) { 643 return 0; 644 } 645 size_t widthsLength = env->GetArrayLength(widths); 646 if ((size_t)count > widthsLength) { 647 doThrowAIOOBE(env); 648 return 0; 649 } 650 651 AutoJavaFloatArray autoWidths(env, widths, count); 652 jfloat* widthsArray = autoWidths.ptr(); 653 654 Layout layout; 655 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count); 656 layout.getAdvances(widthsArray); 657 658 return count; 659 } 660 661 static jint getTextWidths___CIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray text, 662 jint index, jint count, jint bidiFlags, jfloatArray widths) { 663 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 664 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 665 const jchar* textArray = env->GetCharArrayElements(text, NULL); 666 count = dotextwidths(env, paint, typeface, textArray + index, count, widths, bidiFlags); 667 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), 668 JNI_ABORT); 669 return count; 670 } 671 672 static jint getTextWidths__StringIII_F(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring text, 673 jint start, jint end, jint bidiFlags, jfloatArray widths) { 674 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 675 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 676 const jchar* textArray = env->GetStringChars(text, NULL); 677 int count = dotextwidths(env, paint, typeface, textArray + start, end - start, widths, bidiFlags); 678 env->ReleaseStringChars(text, textArray); 679 return count; 680 } 681 682 static jfloat doTextRunAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface, const jchar *text, 683 jint start, jint count, jint contextCount, jboolean isRtl, 684 jfloatArray advances, jint advancesIndex) { 685 NPE_CHECK_RETURN_ZERO(env, paint); 686 NPE_CHECK_RETURN_ZERO(env, text); 687 688 if ((start | count | contextCount | advancesIndex) < 0 || contextCount < count) { 689 doThrowAIOOBE(env); 690 return 0; 691 } 692 if (count == 0) { 693 return 0; 694 } 695 if (advances) { 696 size_t advancesLength = env->GetArrayLength(advances); 697 if ((size_t)count > advancesLength) { 698 doThrowAIOOBE(env); 699 return 0; 700 } 701 } 702 jfloat* advancesArray = new jfloat[count]; 703 jfloat totalAdvance = 0; 704 705 int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR; 706 707 Layout layout; 708 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, start, count, contextCount); 709 layout.getAdvances(advancesArray); 710 totalAdvance = layout.getAdvance(); 711 712 if (advances != NULL) { 713 env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray); 714 } 715 delete [] advancesArray; 716 return totalAdvance; 717 } 718 719 static jfloat getTextRunAdvances___CIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle, 720 jlong typefaceHandle, 721 jcharArray text, jint index, jint count, jint contextIndex, jint contextCount, 722 jboolean isRtl, jfloatArray advances, jint advancesIndex) { 723 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 724 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 725 jchar* textArray = env->GetCharArrayElements(text, NULL); 726 jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextIndex, 727 index - contextIndex, count, contextCount, isRtl, advances, advancesIndex); 728 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 729 return result; 730 } 731 732 static jfloat getTextRunAdvances__StringIIIIZ_FI(JNIEnv* env, jobject clazz, jlong paintHandle, 733 jlong typefaceHandle, 734 jstring text, jint start, jint end, jint contextStart, jint contextEnd, jboolean isRtl, 735 jfloatArray advances, jint advancesIndex) { 736 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 737 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 738 const jchar* textArray = env->GetStringChars(text, NULL); 739 jfloat result = doTextRunAdvances(env, paint, typeface, textArray + contextStart, 740 start - contextStart, end - start, contextEnd - contextStart, isRtl, 741 advances, advancesIndex); 742 env->ReleaseStringChars(text, textArray); 743 return result; 744 } 745 746 static jint doTextRunCursor(JNIEnv *env, Paint* paint, const jchar *text, jint start, 747 jint count, jint flags, jint offset, jint opt) { 748 GraphemeBreak::MoveOpt moveOpt = GraphemeBreak::MoveOpt(opt); 749 size_t result = GraphemeBreak::getTextRunCursor(text, start, count, offset, moveOpt); 750 return static_cast<jint>(result); 751 } 752 753 static jint getTextRunCursor___C(JNIEnv* env, jobject clazz, jlong paintHandle, jcharArray text, 754 jint contextStart, jint contextCount, jint dir, jint offset, jint cursorOpt) { 755 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 756 jchar* textArray = env->GetCharArrayElements(text, NULL); 757 jint result = doTextRunCursor(env, paint, textArray, contextStart, contextCount, dir, 758 offset, cursorOpt); 759 env->ReleaseCharArrayElements(text, textArray, JNI_ABORT); 760 return result; 761 } 762 763 static jint getTextRunCursor__String(JNIEnv* env, jobject clazz, jlong paintHandle, jstring text, 764 jint contextStart, jint contextEnd, jint dir, jint offset, jint cursorOpt) { 765 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 766 const jchar* textArray = env->GetStringChars(text, NULL); 767 jint result = doTextRunCursor(env, paint, textArray, contextStart, 768 contextEnd - contextStart, dir, offset, cursorOpt); 769 env->ReleaseStringChars(text, textArray); 770 return result; 771 } 772 773 class GetTextFunctor { 774 public: 775 GetTextFunctor(const Layout& layout, SkPath* path, jfloat x, jfloat y, Paint* paint, 776 uint16_t* glyphs, SkPoint* pos) 777 : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) { 778 } 779 780 void operator()(size_t start, size_t end) { 781 for (size_t i = start; i < end; i++) { 782 glyphs[i] = layout.getGlyphId(i); 783 pos[i].fX = x + layout.getX(i); 784 pos[i].fY = y + layout.getY(i); 785 } 786 if (start == 0) { 787 paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path); 788 } else { 789 paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath); 790 path->addPath(tmpPath); 791 } 792 } 793 private: 794 const Layout& layout; 795 SkPath* path; 796 jfloat x; 797 jfloat y; 798 Paint* paint; 799 uint16_t* glyphs; 800 SkPoint* pos; 801 SkPath tmpPath; 802 }; 803 804 static void getTextPath(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar* text, 805 jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) { 806 Layout layout; 807 MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count); 808 size_t nGlyphs = layout.nGlyphs(); 809 uint16_t* glyphs = new uint16_t[nGlyphs]; 810 SkPoint* pos = new SkPoint[nGlyphs]; 811 812 x += MinikinUtils::xOffsetForTextAlign(paint, layout); 813 Paint::Align align = paint->getTextAlign(); 814 paint->setTextAlign(Paint::kLeft_Align); 815 paint->setTextEncoding(Paint::kGlyphID_TextEncoding); 816 GetTextFunctor f(layout, path, x, y, paint, glyphs, pos); 817 MinikinUtils::forFontRun(layout, paint, f); 818 paint->setTextAlign(align); 819 delete[] glyphs; 820 delete[] pos; 821 } 822 823 static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle, 824 jlong typefaceHandle, jint bidiFlags, 825 jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) { 826 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 827 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 828 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 829 const jchar* textArray = env->GetCharArrayElements(text, NULL); 830 getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path); 831 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT); 832 } 833 834 static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle, 835 jlong typefaceHandle, jint bidiFlags, 836 jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) { 837 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 838 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 839 SkPath* path = reinterpret_cast<SkPath*>(pathHandle); 840 const jchar* textArray = env->GetStringChars(text, NULL); 841 getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path); 842 env->ReleaseStringChars(text, textArray); 843 } 844 845 static void setShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle, jfloat radius, 846 jfloat dx, jfloat dy, jint color) { 847 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 848 if (radius <= 0) { 849 paint->setLooper(NULL); 850 } 851 else { 852 SkScalar sigma = android::uirenderer::Blur::convertRadiusToSigma(radius); 853 paint->setLooper(SkBlurDrawLooper::Create((SkColor)color, sigma, dx, dy))->unref(); 854 } 855 } 856 857 static jboolean hasShadowLayer(JNIEnv* env, jobject clazz, jlong paintHandle) { 858 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 859 return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL); 860 } 861 862 static int breakText(JNIEnv* env, const Paint& paint, TypefaceImpl* typeface, const jchar text[], 863 int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured, 864 const bool forwardScan) { 865 size_t measuredCount = 0; 866 float measured = 0; 867 868 Layout layout; 869 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count); 870 float* advances = new float[count]; 871 layout.getAdvances(advances); 872 873 for (int i = 0; i < count; i++) { 874 // traverse in the given direction 875 int index = forwardScan ? i : (count - i - 1); 876 float width = advances[index]; 877 if (measured + width > maxWidth) { 878 break; 879 } 880 // properly handle clusters when scanning backwards 881 if (forwardScan || width != 0.0f) { 882 measuredCount = i + 1; 883 } 884 measured += width; 885 } 886 delete[] advances; 887 888 if (jmeasured && env->GetArrayLength(jmeasured) > 0) { 889 AutoJavaFloatArray autoMeasured(env, jmeasured, 1); 890 jfloat* array = autoMeasured.ptr(); 891 array[0] = measured; 892 } 893 return measuredCount; 894 } 895 896 static jint breakTextC(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jcharArray jtext, 897 jint index, jint count, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) { 898 NPE_CHECK_RETURN_ZERO(env, jtext); 899 900 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 901 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 902 903 bool forwardTextDirection; 904 if (count < 0) { 905 forwardTextDirection = false; 906 count = -count; 907 } 908 else { 909 forwardTextDirection = true; 910 } 911 912 if ((index < 0) || (index + count > env->GetArrayLength(jtext))) { 913 doThrowAIOOBE(env); 914 return 0; 915 } 916 917 const jchar* text = env->GetCharArrayElements(jtext, NULL); 918 count = breakText(env, *paint, typeface, text + index, count, maxWidth, 919 bidiFlags, jmeasuredWidth, forwardTextDirection); 920 env->ReleaseCharArrayElements(jtext, const_cast<jchar*>(text), 921 JNI_ABORT); 922 return count; 923 } 924 925 static jint breakTextS(JNIEnv* env, jobject clazz, jlong paintHandle, jlong typefaceHandle, jstring jtext, 926 jboolean forwards, jfloat maxWidth, jint bidiFlags, jfloatArray jmeasuredWidth) { 927 NPE_CHECK_RETURN_ZERO(env, jtext); 928 929 Paint* paint = reinterpret_cast<Paint*>(paintHandle); 930 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 931 932 int count = env->GetStringLength(jtext); 933 const jchar* text = env->GetStringChars(jtext, NULL); 934 count = breakText(env, *paint, typeface, text, count, maxWidth, bidiFlags, jmeasuredWidth, forwards); 935 env->ReleaseStringChars(jtext, text); 936 return count; 937 } 938 939 static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds, 940 const Paint& paint, TypefaceImpl* typeface, jint bidiFlags) { 941 SkRect r; 942 SkIRect ir; 943 944 Layout layout; 945 MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, 0, count, count); 946 MinikinRect rect; 947 layout.getBounds(&rect); 948 r.fLeft = rect.mLeft; 949 r.fTop = rect.mTop; 950 r.fRight = rect.mRight; 951 r.fBottom = rect.mBottom; 952 r.roundOut(&ir); 953 GraphicsJNI::irect_to_jrect(ir, env, bounds); 954 } 955 956 static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle, 957 jstring text, jint start, jint end, jint bidiFlags, jobject bounds) { 958 const Paint* paint = reinterpret_cast<Paint*>(paintHandle);; 959 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 960 const jchar* textArray = env->GetStringChars(text, NULL); 961 doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags); 962 env->ReleaseStringChars(text, textArray); 963 } 964 965 static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle, 966 jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) { 967 const Paint* paint = reinterpret_cast<Paint*>(paintHandle); 968 TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle); 969 const jchar* textArray = env->GetCharArrayElements(text, NULL); 970 doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags); 971 env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), 972 JNI_ABORT); 973 } 974 975}; 976 977static JNINativeMethod methods[] = { 978 {"finalizer", "(J)V", (void*) PaintGlue::finalizer}, 979 {"native_init","()J", (void*) PaintGlue::init}, 980 {"native_initWithPaint","(J)J", (void*) PaintGlue::initWithPaint}, 981 982 {"native_reset","!(J)V", (void*) PaintGlue::reset}, 983 {"native_set","!(JJ)V", (void*) PaintGlue::assign}, 984 {"getFlags","!()I", (void*) PaintGlue::getFlags}, 985 {"setFlags","!(I)V", (void*) PaintGlue::setFlags}, 986 {"getHinting","!()I", (void*) PaintGlue::getHinting}, 987 {"setHinting","!(I)V", (void*) PaintGlue::setHinting}, 988 {"setAntiAlias","!(Z)V", (void*) PaintGlue::setAntiAlias}, 989 {"setSubpixelText","!(Z)V", (void*) PaintGlue::setSubpixelText}, 990 {"setLinearText","!(Z)V", (void*) PaintGlue::setLinearText}, 991 {"setUnderlineText","!(Z)V", (void*) PaintGlue::setUnderlineText}, 992 {"setStrikeThruText","!(Z)V", (void*) PaintGlue::setStrikeThruText}, 993 {"setFakeBoldText","!(Z)V", (void*) PaintGlue::setFakeBoldText}, 994 {"setFilterBitmap","!(Z)V", (void*) PaintGlue::setFilterBitmap}, 995 {"setDither","!(Z)V", (void*) PaintGlue::setDither}, 996 {"native_getStyle","!(J)I", (void*) PaintGlue::getStyle}, 997 {"native_setStyle","!(JI)V", (void*) PaintGlue::setStyle}, 998 {"getColor","!()I", (void*) PaintGlue::getColor}, 999 {"setColor","!(I)V", (void*) PaintGlue::setColor}, 1000 {"getAlpha","!()I", (void*) PaintGlue::getAlpha}, 1001 {"setAlpha","!(I)V", (void*) PaintGlue::setAlpha}, 1002 {"getStrokeWidth","!()F", (void*) PaintGlue::getStrokeWidth}, 1003 {"setStrokeWidth","!(F)V", (void*) PaintGlue::setStrokeWidth}, 1004 {"getStrokeMiter","!()F", (void*) PaintGlue::getStrokeMiter}, 1005 {"setStrokeMiter","!(F)V", (void*) PaintGlue::setStrokeMiter}, 1006 {"native_getStrokeCap","!(J)I", (void*) PaintGlue::getStrokeCap}, 1007 {"native_setStrokeCap","!(JI)V", (void*) PaintGlue::setStrokeCap}, 1008 {"native_getStrokeJoin","!(J)I", (void*) PaintGlue::getStrokeJoin}, 1009 {"native_setStrokeJoin","!(JI)V", (void*) PaintGlue::setStrokeJoin}, 1010 {"native_getFillPath","!(JJJ)Z", (void*) PaintGlue::getFillPath}, 1011 {"native_setShader","!(JJ)J", (void*) PaintGlue::setShader}, 1012 {"native_setColorFilter","!(JJ)J", (void*) PaintGlue::setColorFilter}, 1013 {"native_setXfermode","!(JJ)J", (void*) PaintGlue::setXfermode}, 1014 {"native_setPathEffect","!(JJ)J", (void*) PaintGlue::setPathEffect}, 1015 {"native_setMaskFilter","!(JJ)J", (void*) PaintGlue::setMaskFilter}, 1016 {"native_setTypeface","!(JJ)J", (void*) PaintGlue::setTypeface}, 1017 {"native_setRasterizer","!(JJ)J", (void*) PaintGlue::setRasterizer}, 1018 {"native_getTextAlign","!(J)I", (void*) PaintGlue::getTextAlign}, 1019 {"native_setTextAlign","!(JI)V", (void*) PaintGlue::setTextAlign}, 1020 {"native_setTextLocale","!(JLjava/lang/String;)V", (void*) PaintGlue::setTextLocale}, 1021 {"isElegantTextHeight","!()Z", (void*) PaintGlue::isElegantTextHeight}, 1022 {"setElegantTextHeight","!(Z)V", (void*) PaintGlue::setElegantTextHeight}, 1023 {"getTextSize","!()F", (void*) PaintGlue::getTextSize}, 1024 {"setTextSize","!(F)V", (void*) PaintGlue::setTextSize}, 1025 {"getTextScaleX","!()F", (void*) PaintGlue::getTextScaleX}, 1026 {"setTextScaleX","!(F)V", (void*) PaintGlue::setTextScaleX}, 1027 {"getTextSkewX","!()F", (void*) PaintGlue::getTextSkewX}, 1028 {"setTextSkewX","!(F)V", (void*) PaintGlue::setTextSkewX}, 1029 {"native_getLetterSpacing","!(J)F", (void*) PaintGlue::getLetterSpacing}, 1030 {"native_setLetterSpacing","!(JF)V", (void*) PaintGlue::setLetterSpacing}, 1031 {"native_setFontFeatureSettings","(JLjava/lang/String;)V", (void*) PaintGlue::setFontFeatureSettings}, 1032 {"native_getHyphenEdit", "!(J)I", (void*) PaintGlue::getHyphenEdit}, 1033 {"native_setHyphenEdit", "!(JI)V", (void*) PaintGlue::setHyphenEdit}, 1034 {"ascent","!()F", (void*) PaintGlue::ascent}, 1035 {"descent","!()F", (void*) PaintGlue::descent}, 1036 1037 {"getFontMetrics", "(Landroid/graphics/Paint$FontMetrics;)F", (void*)PaintGlue::getFontMetrics}, 1038 {"getFontMetricsInt", "(Landroid/graphics/Paint$FontMetricsInt;)I", (void*)PaintGlue::getFontMetricsInt}, 1039 {"native_measureText","([CIII)F", (void*) PaintGlue::measureText_CIII}, 1040 {"native_measureText","(Ljava/lang/String;I)F", (void*) PaintGlue::measureText_StringI}, 1041 {"native_measureText","(Ljava/lang/String;III)F", (void*) PaintGlue::measureText_StringIII}, 1042 {"native_breakText","(JJ[CIIFI[F)I", (void*) PaintGlue::breakTextC}, 1043 {"native_breakText","(JJLjava/lang/String;ZFI[F)I", (void*) PaintGlue::breakTextS}, 1044 {"native_getTextWidths","(JJ[CIII[F)I", (void*) PaintGlue::getTextWidths___CIII_F}, 1045 {"native_getTextWidths","(JJLjava/lang/String;III[F)I", (void*) PaintGlue::getTextWidths__StringIII_F}, 1046 {"native_getTextRunAdvances","(JJ[CIIIIZ[FI)F", 1047 (void*) PaintGlue::getTextRunAdvances___CIIIIZ_FI}, 1048 {"native_getTextRunAdvances","(JJLjava/lang/String;IIIIZ[FI)F", 1049 (void*) PaintGlue::getTextRunAdvances__StringIIIIZ_FI}, 1050 1051 {"native_getTextRunCursor", "(J[CIIIII)I", (void*) PaintGlue::getTextRunCursor___C}, 1052 {"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I", 1053 (void*) PaintGlue::getTextRunCursor__String}, 1054 {"native_getTextPath","(JJI[CIIFFJ)V", (void*) PaintGlue::getTextPath___C}, 1055 {"native_getTextPath","(JJILjava/lang/String;IIFFJ)V", (void*) PaintGlue::getTextPath__String}, 1056 {"nativeGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V", 1057 (void*) PaintGlue::getStringBounds }, 1058 {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V", 1059 (void*) PaintGlue::getCharArrayBounds }, 1060 1061 {"native_setShadowLayer", "!(JFFFI)V", (void*)PaintGlue::setShadowLayer}, 1062 {"native_hasShadowLayer", "!(J)Z", (void*)PaintGlue::hasShadowLayer} 1063}; 1064 1065int register_android_graphics_Paint(JNIEnv* env) { 1066 gFontMetrics_class = FindClassOrDie(env, "android/graphics/Paint$FontMetrics"); 1067 gFontMetrics_class = MakeGlobalRefOrDie(env, gFontMetrics_class); 1068 1069 gFontMetrics_fieldID.top = GetFieldIDOrDie(env, gFontMetrics_class, "top", "F"); 1070 gFontMetrics_fieldID.ascent = GetFieldIDOrDie(env, gFontMetrics_class, "ascent", "F"); 1071 gFontMetrics_fieldID.descent = GetFieldIDOrDie(env, gFontMetrics_class, "descent", "F"); 1072 gFontMetrics_fieldID.bottom = GetFieldIDOrDie(env, gFontMetrics_class, "bottom", "F"); 1073 gFontMetrics_fieldID.leading = GetFieldIDOrDie(env, gFontMetrics_class, "leading", "F"); 1074 1075 gFontMetricsInt_class = FindClassOrDie(env, "android/graphics/Paint$FontMetricsInt"); 1076 gFontMetricsInt_class = MakeGlobalRefOrDie(env, gFontMetricsInt_class); 1077 1078 gFontMetricsInt_fieldID.top = GetFieldIDOrDie(env, gFontMetricsInt_class, "top", "I"); 1079 gFontMetricsInt_fieldID.ascent = GetFieldIDOrDie(env, gFontMetricsInt_class, "ascent", "I"); 1080 gFontMetricsInt_fieldID.descent = GetFieldIDOrDie(env, gFontMetricsInt_class, "descent", "I"); 1081 gFontMetricsInt_fieldID.bottom = GetFieldIDOrDie(env, gFontMetricsInt_class, "bottom", "I"); 1082 gFontMetricsInt_fieldID.leading = GetFieldIDOrDie(env, gFontMetricsInt_class, "leading", "I"); 1083 1084 gPaint_class = MakeGlobalRefOrDie(env, FindClassOrDie(env, "android/graphics/Paint")); 1085 gPaint_nativeInstanceID = GetFieldIDOrDie(env, gPaint_class, "mNativePaint", "J"); 1086 gPaint_nativeTypefaceID = GetFieldIDOrDie(env, gPaint_class, "mNativeTypeface", "J"); 1087 1088 return RegisterMethodsOrDie(env, "android/graphics/Paint", methods, NELEM(methods)); 1089} 1090 1091} 1092