Home | History | Annotate | Download | only in jni
      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