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