1 /* 2 * Copyright (C) 2017 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 #define LOG_TAG "MeasuredParagraph" 18 19 #include "GraphicsJNI.h" 20 #include "ScopedIcuLocale.h" 21 #include "unicode/locid.h" 22 #include "unicode/brkiter.h" 23 #include "utils/misc.h" 24 #include "utils/Log.h" 25 #include <nativehelper/ScopedStringChars.h> 26 #include <nativehelper/ScopedPrimitiveArray.h> 27 #include <nativehelper/JNIHelp.h> 28 #include "core_jni_helpers.h" 29 #include <cstdint> 30 #include <vector> 31 #include <list> 32 #include <algorithm> 33 34 #include "SkPaint.h" 35 #include "SkTypeface.h" 36 #include <hwui/MinikinSkia.h> 37 #include <hwui/MinikinUtils.h> 38 #include <hwui/Paint.h> 39 #include <minikin/FontCollection.h> 40 #include <minikin/AndroidLineBreakerHelper.h> 41 #include <minikin/MinikinFont.h> 42 43 namespace android { 44 45 static inline minikin::MeasuredTextBuilder* toBuilder(jlong ptr) { 46 return reinterpret_cast<minikin::MeasuredTextBuilder*>(ptr); 47 } 48 49 static inline Paint* toPaint(jlong ptr) { 50 return reinterpret_cast<Paint*>(ptr); 51 } 52 53 static inline minikin::MeasuredText* toMeasuredParagraph(jlong ptr) { 54 return reinterpret_cast<minikin::MeasuredText*>(ptr); 55 } 56 57 template<typename Ptr> static inline jlong toJLong(Ptr ptr) { 58 return reinterpret_cast<jlong>(ptr); 59 } 60 61 static void releaseMeasuredParagraph(jlong measuredTextPtr) { 62 delete toMeasuredParagraph(measuredTextPtr); 63 } 64 65 // Regular JNI 66 static jlong nInitBuilder() { 67 return toJLong(new minikin::MeasuredTextBuilder()); 68 } 69 70 // Regular JNI 71 static void nAddStyleRun(JNIEnv* /* unused */, jclass /* unused */, jlong builderPtr, 72 jlong paintPtr, jint start, jint end, jboolean isRtl) { 73 Paint* paint = toPaint(paintPtr); 74 const Typeface* typeface = Typeface::resolveDefault(paint->getAndroidTypeface()); 75 minikin::MinikinPaint minikinPaint = MinikinUtils::prepareMinikinPaint(paint, typeface); 76 toBuilder(builderPtr)->addStyleRun(start, end, std::move(minikinPaint), isRtl); 77 } 78 79 // Regular JNI 80 static void nAddReplacementRun(JNIEnv* /* unused */, jclass /* unused */, jlong builderPtr, 81 jlong paintPtr, jint start, jint end, jfloat width) { 82 toBuilder(builderPtr)->addReplacementRun(start, end, width, 83 toPaint(paintPtr)->getMinikinLocaleListId()); 84 } 85 86 // Regular JNI 87 static jlong nBuildNativeMeasuredParagraph(JNIEnv* env, jclass /* unused */, jlong builderPtr, 88 jcharArray javaText, jboolean computeHyphenation, 89 jboolean computeLayout) { 90 ScopedCharArrayRO text(env, javaText); 91 const minikin::U16StringPiece textBuffer(text.get(), text.size()); 92 93 // Pass the ownership to Java. 94 return toJLong(toBuilder(builderPtr)->build(textBuffer, computeHyphenation, 95 computeLayout).release()); 96 } 97 98 // Regular JNI 99 static void nFreeBuilder(JNIEnv* env, jclass /* unused */, jlong builderPtr) { 100 delete toBuilder(builderPtr); 101 } 102 103 // CriticalNative 104 static jfloat nGetWidth(jlong ptr, jint start, jint end) { 105 minikin::MeasuredText* mt = toMeasuredParagraph(ptr); 106 float r = 0.0f; 107 for (int i = start; i < end; ++i) { 108 r += mt->widths[i]; 109 } 110 return r; 111 } 112 113 // Regular JNI 114 static void nGetBounds(JNIEnv* env, jobject, jlong ptr, jcharArray javaText, jint start, jint end, 115 jobject bounds) { 116 ScopedCharArrayRO text(env, javaText); 117 const minikin::U16StringPiece textBuffer(text.get(), text.size()); 118 const minikin::Range range(start, end); 119 120 minikin::MinikinRect rect = toMeasuredParagraph(ptr)->getBounds(textBuffer, range); 121 122 SkRect r; 123 r.fLeft = rect.mLeft; 124 r.fTop = rect.mTop; 125 r.fRight = rect.mRight; 126 r.fBottom = rect.mBottom; 127 128 SkIRect ir; 129 r.roundOut(&ir); 130 GraphicsJNI::irect_to_jrect(ir, env, bounds); 131 } 132 133 // CriticalNative 134 static jlong nGetReleaseFunc() { 135 return toJLong(&releaseMeasuredParagraph); 136 } 137 138 static jint nGetMemoryUsage(jlong ptr) { 139 return static_cast<jint>(toMeasuredParagraph(ptr)->getMemoryUsage()); 140 } 141 142 static const JNINativeMethod gMethods[] = { 143 // MeasuredParagraphBuilder native functions. 144 {"nInitBuilder", "()J", (void*) nInitBuilder}, 145 {"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun}, 146 {"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun}, 147 {"nBuildNativeMeasuredParagraph", "(J[CZZ)J", (void*) nBuildNativeMeasuredParagraph}, 148 {"nFreeBuilder", "(J)V", (void*) nFreeBuilder}, 149 150 // MeasuredParagraph native functions. 151 {"nGetWidth", "(JII)F", (void*) nGetWidth}, // Critical Natives 152 {"nGetBounds", "(J[CIILandroid/graphics/Rect;)V", (void*) nGetBounds}, // Regular JNI 153 {"nGetReleaseFunc", "()J", (void*) nGetReleaseFunc}, // Critical Natives 154 {"nGetMemoryUsage", "(J)I", (void*) nGetMemoryUsage}, // Critical Native 155 }; 156 157 int register_android_text_MeasuredParagraph(JNIEnv* env) { 158 return RegisterMethodsOrDie(env, "android/text/MeasuredParagraph", gMethods, NELEM(gMethods)); 159 } 160 161 } 162