Merge "Implement fast hyphenation algorithm"
This commit is contained in:
committed by
Android (Google) Code Review
commit
6423d01b01
@@ -137,6 +137,21 @@ public class StaticLayoutPerfTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreate_RandomText_NoStyled_Balanced_Hyphenation_Fast() {
|
||||
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
while (state.keepRunning()) {
|
||||
state.pauseTiming();
|
||||
final CharSequence text = mTextUtil.nextRandomParagraph(WORD_LENGTH, NO_STYLE_TEXT);
|
||||
state.resumeTiming();
|
||||
|
||||
StaticLayout.Builder.obtain(text, 0, text.length(), PAINT, TEXT_WIDTH)
|
||||
.setHyphenationFrequency(Layout.HYPHENATION_FREQUENCY_NORMAL_FAST)
|
||||
.setBreakStrategy(Layout.BREAK_STRATEGY_BALANCED)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreate_RandomText_Styled_Greedy_NoHyphenation() {
|
||||
final BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
|
||||
|
||||
@@ -17273,8 +17273,12 @@ package android.graphics.text {
|
||||
method @NonNull public android.graphics.text.MeasuredText.Builder appendReplacementRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, @FloatRange(from=0) @Px float);
|
||||
method @NonNull public android.graphics.text.MeasuredText.Builder appendStyleRun(@NonNull android.graphics.Paint, @IntRange(from=0) int, boolean);
|
||||
method @NonNull public android.graphics.text.MeasuredText build();
|
||||
method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
|
||||
method @Deprecated @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(boolean);
|
||||
method @NonNull public android.graphics.text.MeasuredText.Builder setComputeHyphenation(int);
|
||||
method @NonNull public android.graphics.text.MeasuredText.Builder setComputeLayout(boolean);
|
||||
field public static final int HYPHENATION_MODE_FAST = 2; // 0x2
|
||||
field public static final int HYPHENATION_MODE_NONE = 0; // 0x0
|
||||
field public static final int HYPHENATION_MODE_NORMAL = 1; // 0x1
|
||||
}
|
||||
|
||||
public final class PositionedGlyphs {
|
||||
@@ -44523,8 +44527,10 @@ package android.text {
|
||||
field public static final int DIR_LEFT_TO_RIGHT = 1; // 0x1
|
||||
field public static final int DIR_RIGHT_TO_LEFT = -1; // 0xffffffff
|
||||
field public static final int HYPHENATION_FREQUENCY_FULL = 2; // 0x2
|
||||
field public static final int HYPHENATION_FREQUENCY_FULL_FAST = 4; // 0x4
|
||||
field public static final int HYPHENATION_FREQUENCY_NONE = 0; // 0x0
|
||||
field public static final int HYPHENATION_FREQUENCY_NORMAL = 1; // 0x1
|
||||
field public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3; // 0x3
|
||||
field public static final int JUSTIFICATION_MODE_INTER_WORD = 1; // 0x1
|
||||
field public static final int JUSTIFICATION_MODE_NONE = 0; // 0x0
|
||||
}
|
||||
|
||||
@@ -82,7 +82,9 @@ public abstract class Layout {
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "HYPHENATION_FREQUENCY_" }, value = {
|
||||
HYPHENATION_FREQUENCY_NORMAL,
|
||||
HYPHENATION_FREQUENCY_NORMAL_FAST,
|
||||
HYPHENATION_FREQUENCY_FULL,
|
||||
HYPHENATION_FREQUENCY_FULL_FAST,
|
||||
HYPHENATION_FREQUENCY_NONE
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@@ -95,21 +97,40 @@ public abstract class Layout {
|
||||
* layout and there is otherwise no valid break. Soft hyphens are ignored and will not be used
|
||||
* as suggestions for potential line breaks.
|
||||
*/
|
||||
public static final int HYPHENATION_FREQUENCY_NONE = LineBreaker.HYPHENATION_FREQUENCY_NONE;
|
||||
public static final int HYPHENATION_FREQUENCY_NONE = 0;
|
||||
|
||||
/**
|
||||
* Value for hyphenation frequency indicating a light amount of automatic hyphenation, which
|
||||
* is a conservative default. Useful for informal cases, such as short sentences or chat
|
||||
* messages.
|
||||
*/
|
||||
public static final int HYPHENATION_FREQUENCY_NORMAL = LineBreaker.HYPHENATION_FREQUENCY_NORMAL;
|
||||
public static final int HYPHENATION_FREQUENCY_NORMAL = 1;
|
||||
|
||||
/**
|
||||
* Value for hyphenation frequency indicating the full amount of automatic hyphenation, typical
|
||||
* in typography. Useful for running text and where it's important to put the maximum amount of
|
||||
* text in a screen with limited space.
|
||||
*/
|
||||
public static final int HYPHENATION_FREQUENCY_FULL = LineBreaker.HYPHENATION_FREQUENCY_FULL;
|
||||
public static final int HYPHENATION_FREQUENCY_FULL = 2;
|
||||
|
||||
/**
|
||||
* Value for hyphenation frequency indicating a light amount of automatic hyphenation with
|
||||
* using faster algorithm.
|
||||
*
|
||||
* This option is useful for informal cases, such as short sentences or chat messages. To make
|
||||
* text rendering faster with hyphenation, this algorithm ignores some hyphen character related
|
||||
* typographic features, e.g. kerning.
|
||||
*/
|
||||
public static final int HYPHENATION_FREQUENCY_NORMAL_FAST = 3;
|
||||
/**
|
||||
* Value for hyphenation frequency indicating the full amount of automatic hyphenation with
|
||||
* using faster algorithm.
|
||||
*
|
||||
* This option is useful for running text and where it's important to put the maximum amount of
|
||||
* text in a screen with limited space. To make text rendering faster with hyphenation, this
|
||||
* algorithm ignores some hyphen character related typographic features, e.g. kerning.
|
||||
*/
|
||||
public static final int HYPHENATION_FREQUENCY_FULL_FAST = 4;
|
||||
|
||||
private static final ParagraphStyle[] NO_PARA_SPANS =
|
||||
ArrayUtils.emptyArray(ParagraphStyle.class);
|
||||
|
||||
@@ -377,7 +377,7 @@ public class MeasuredParagraph {
|
||||
* @param start the inclusive start offset of the target region in the text
|
||||
* @param end the exclusive end offset of the target region in the text
|
||||
* @param textDir the text direction
|
||||
* @param computeHyphenation true if need to compute hyphenation, otherwise false
|
||||
* @param hyphenationMode a hyphenation mode
|
||||
* @param computeLayout true if need to compute full layout, otherwise false.
|
||||
* @param hint pass if you already have measured paragraph.
|
||||
* @param recycle pass existing MeasuredParagraph if you want to recycle it.
|
||||
@@ -390,7 +390,7 @@ public class MeasuredParagraph {
|
||||
@IntRange(from = 0) int start,
|
||||
@IntRange(from = 0) int end,
|
||||
@NonNull TextDirectionHeuristic textDir,
|
||||
boolean computeHyphenation,
|
||||
int hyphenationMode,
|
||||
boolean computeLayout,
|
||||
@Nullable MeasuredParagraph hint,
|
||||
@Nullable MeasuredParagraph recycle) {
|
||||
@@ -399,7 +399,7 @@ public class MeasuredParagraph {
|
||||
final MeasuredText.Builder builder;
|
||||
if (hint == null) {
|
||||
builder = new MeasuredText.Builder(mt.mCopiedBuffer)
|
||||
.setComputeHyphenation(computeHyphenation)
|
||||
.setComputeHyphenation(hyphenationMode)
|
||||
.setComputeLayout(computeLayout);
|
||||
} else {
|
||||
builder = new MeasuredText.Builder(hint.mMeasuredText);
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.text.MeasuredText;
|
||||
import android.text.style.MetricAffectingSpan;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
@@ -395,17 +396,30 @@ public class PrecomputedText implements Spannable {
|
||||
return new PrecomputedText(text, 0, text.length(), params, paraInfo);
|
||||
}
|
||||
|
||||
private static boolean isFastHyphenation(int frequency) {
|
||||
return frequency == Layout.HYPHENATION_FREQUENCY_FULL_FAST
|
||||
|| frequency == Layout.HYPHENATION_FREQUENCY_NORMAL_FAST;
|
||||
}
|
||||
|
||||
private static ParagraphInfo[] createMeasuredParagraphsFromPrecomputedText(
|
||||
@NonNull PrecomputedText pct, @NonNull Params params, boolean computeLayout) {
|
||||
final boolean needHyphenation = params.getBreakStrategy() != Layout.BREAK_STRATEGY_SIMPLE
|
||||
&& params.getHyphenationFrequency() != Layout.HYPHENATION_FREQUENCY_NONE;
|
||||
final int hyphenationMode;
|
||||
if (needHyphenation) {
|
||||
hyphenationMode = isFastHyphenation(params.getHyphenationFrequency())
|
||||
? MeasuredText.Builder.HYPHENATION_MODE_FAST :
|
||||
MeasuredText.Builder.HYPHENATION_MODE_NORMAL;
|
||||
} else {
|
||||
hyphenationMode = MeasuredText.Builder.HYPHENATION_MODE_NONE;
|
||||
}
|
||||
ArrayList<ParagraphInfo> result = new ArrayList<>();
|
||||
for (int i = 0; i < pct.getParagraphCount(); ++i) {
|
||||
final int paraStart = pct.getParagraphStart(i);
|
||||
final int paraEnd = pct.getParagraphEnd(i);
|
||||
result.add(new ParagraphInfo(paraEnd, MeasuredParagraph.buildForStaticLayout(
|
||||
params.getTextPaint(), pct, paraStart, paraEnd, params.getTextDirection(),
|
||||
needHyphenation, computeLayout, pct.getMeasuredParagraph(i),
|
||||
hyphenationMode, computeLayout, pct.getMeasuredParagraph(i),
|
||||
null /* no recycle */)));
|
||||
}
|
||||
return result.toArray(new ParagraphInfo[result.size()]);
|
||||
@@ -421,6 +435,14 @@ public class PrecomputedText implements Spannable {
|
||||
Preconditions.checkNotNull(params);
|
||||
final boolean needHyphenation = params.getBreakStrategy() != Layout.BREAK_STRATEGY_SIMPLE
|
||||
&& params.getHyphenationFrequency() != Layout.HYPHENATION_FREQUENCY_NONE;
|
||||
final int hyphenationMode;
|
||||
if (needHyphenation) {
|
||||
hyphenationMode = isFastHyphenation(params.getHyphenationFrequency())
|
||||
? MeasuredText.Builder.HYPHENATION_MODE_FAST :
|
||||
MeasuredText.Builder.HYPHENATION_MODE_NORMAL;
|
||||
} else {
|
||||
hyphenationMode = MeasuredText.Builder.HYPHENATION_MODE_NONE;
|
||||
}
|
||||
|
||||
int paraEnd = 0;
|
||||
for (int paraStart = start; paraStart < end; paraStart = paraEnd) {
|
||||
@@ -435,8 +457,7 @@ public class PrecomputedText implements Spannable {
|
||||
|
||||
result.add(new ParagraphInfo(paraEnd, MeasuredParagraph.buildForStaticLayout(
|
||||
params.getTextPaint(), text, paraStart, paraEnd, params.getTextDirection(),
|
||||
needHyphenation, computeLayout, null /* no hint */,
|
||||
null /* no recycle */)));
|
||||
hyphenationMode, computeLayout, null /* no hint */, null /* no recycle */)));
|
||||
}
|
||||
return result.toArray(new ParagraphInfo[result.size()]);
|
||||
}
|
||||
|
||||
@@ -591,6 +591,20 @@ public class StaticLayout extends Layout {
|
||||
generate(b, b.mIncludePad, b.mIncludePad);
|
||||
}
|
||||
|
||||
private static int getBaseHyphenationFrequency(int frequency) {
|
||||
switch (frequency) {
|
||||
case Layout.HYPHENATION_FREQUENCY_FULL:
|
||||
case Layout.HYPHENATION_FREQUENCY_FULL_FAST:
|
||||
return LineBreaker.HYPHENATION_FREQUENCY_FULL;
|
||||
case Layout.HYPHENATION_FREQUENCY_NORMAL:
|
||||
case Layout.HYPHENATION_FREQUENCY_NORMAL_FAST:
|
||||
return LineBreaker.HYPHENATION_FREQUENCY_NORMAL;
|
||||
case Layout.HYPHENATION_FREQUENCY_NONE:
|
||||
default:
|
||||
return LineBreaker.HYPHENATION_FREQUENCY_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/* package */ void generate(Builder b, boolean includepad, boolean trackpad) {
|
||||
final CharSequence source = b.mText;
|
||||
final int bufStart = b.mStart;
|
||||
@@ -641,7 +655,7 @@ public class StaticLayout extends Layout {
|
||||
|
||||
final LineBreaker lineBreaker = new LineBreaker.Builder()
|
||||
.setBreakStrategy(b.mBreakStrategy)
|
||||
.setHyphenationFrequency(b.mHyphenationFrequency)
|
||||
.setHyphenationFrequency(getBaseHyphenationFrequency(b.mHyphenationFrequency))
|
||||
// TODO: Support more justification mode, e.g. letter spacing, stretching.
|
||||
.setJustificationMode(b.mJustificationMode)
|
||||
.setIndents(indents)
|
||||
|
||||
@@ -5383,6 +5383,16 @@
|
||||
<!-- Standard amount of hyphenation, useful for running text and for
|
||||
screens with limited space for text. -->
|
||||
<enum name="full" value="2" />
|
||||
|
||||
<!-- Same to hyphenationFrequency="normal" but using faster algorithm for measuring
|
||||
hyphenation break points. To make text rendering faster with hyphenation, this algorithm
|
||||
ignores some hyphen character related typographic features, e.g. kerning. -->
|
||||
<enum name="normalFast" value="3" />
|
||||
|
||||
<!-- Same to hyphenationFrequency="full" but using faster algorithm for measuring
|
||||
hyphenation break points. To make text rendering faster with hyphenation, this algorithm
|
||||
ignores some hyphen character related typographic features, e.g. kerning. -->
|
||||
<enum name="fullFast" value="4" />
|
||||
</attr>
|
||||
<!-- Specify the type of auto-size. Note that this feature is not supported by EditText,
|
||||
works only for TextView. -->
|
||||
|
||||
@@ -23,6 +23,7 @@ import static org.junit.Assert.assertNull;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Typeface;
|
||||
import android.graphics.text.MeasuredText;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -135,7 +136,8 @@ public class MeasuredParagraphTest {
|
||||
MeasuredParagraph mt = null;
|
||||
|
||||
mt = MeasuredParagraph.buildForStaticLayout(
|
||||
PAINT, "XXX", 0, 3, LTR, false, false, null /* no hint */, null);
|
||||
PAINT, "XXX", 0, 3, LTR, MeasuredText.Builder.HYPHENATION_MODE_NONE, false,
|
||||
null /* no hint */, null);
|
||||
assertNotNull(mt);
|
||||
assertNotNull(mt.getChars());
|
||||
assertEquals("XXX", charsToString(mt.getChars()));
|
||||
@@ -150,7 +152,8 @@ public class MeasuredParagraphTest {
|
||||
|
||||
// Recycle it
|
||||
MeasuredParagraph mt2 = MeasuredParagraph.buildForStaticLayout(
|
||||
PAINT, "_VVV_", 1, 4, RTL, false, false, null /* no hint */, mt);
|
||||
PAINT, "_VVV_", 1, 4, RTL, MeasuredText.Builder.HYPHENATION_MODE_NONE, false,
|
||||
null /* no hint */, mt);
|
||||
assertEquals(mt2, mt);
|
||||
assertNotNull(mt2.getChars());
|
||||
assertEquals("VVV", charsToString(mt.getChars()));
|
||||
|
||||
@@ -17,12 +17,14 @@
|
||||
package android.graphics.text;
|
||||
|
||||
import android.annotation.FloatRange;
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.IntRange;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.Px;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.util.Preconditions;
|
||||
|
||||
@@ -30,6 +32,9 @@ import dalvik.annotation.optimization.CriticalNative;
|
||||
|
||||
import libcore.util.NativeAllocationRegistry;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Result of text shaping of the single paragraph string.
|
||||
*
|
||||
@@ -49,6 +54,8 @@ import libcore.util.NativeAllocationRegistry;
|
||||
* </p>
|
||||
*/
|
||||
public class MeasuredText {
|
||||
private static final String TAG = "MeasuredText";
|
||||
|
||||
private long mNativePtr;
|
||||
private boolean mComputeHyphenation;
|
||||
private boolean mComputeLayout;
|
||||
@@ -179,6 +186,7 @@ public class MeasuredText {
|
||||
private final @NonNull char[] mText;
|
||||
private boolean mComputeHyphenation = false;
|
||||
private boolean mComputeLayout = true;
|
||||
private boolean mFastHyphenation = false;
|
||||
private int mCurrentOffset = 0;
|
||||
private @Nullable MeasuredText mHintMt = null;
|
||||
|
||||
@@ -275,10 +283,78 @@ public class MeasuredText {
|
||||
* Even if you pass false to this method, you can still enable automatic hyphenation of
|
||||
* LineBreaker but line break computation becomes slower.
|
||||
*
|
||||
* @deprecated use setComputeHyphenation(int) instead.
|
||||
*
|
||||
* @param computeHyphenation true if you want to use automatic hyphenations.
|
||||
*/
|
||||
public @NonNull Builder setComputeHyphenation(boolean computeHyphenation) {
|
||||
mComputeHyphenation = computeHyphenation;
|
||||
setComputeHyphenation(
|
||||
computeHyphenation ? HYPHENATION_MODE_NORMAL : HYPHENATION_MODE_NONE);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "HYPHENATION_MODE_" }, value = {
|
||||
HYPHENATION_MODE_NONE,
|
||||
HYPHENATION_MODE_NORMAL,
|
||||
HYPHENATION_MODE_FAST
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface HyphenationMode {}
|
||||
|
||||
/**
|
||||
* A value for hyphenation calculation mode.
|
||||
*
|
||||
* This value indicates that no hyphenation points are calculated.
|
||||
*/
|
||||
public static final int HYPHENATION_MODE_NONE = 0;
|
||||
|
||||
/**
|
||||
* A value for hyphenation calculation mode.
|
||||
*
|
||||
* This value indicates that hyphenation points are calculated.
|
||||
*/
|
||||
public static final int HYPHENATION_MODE_NORMAL = 1;
|
||||
|
||||
/**
|
||||
* A value for hyphenation calculation mode.
|
||||
*
|
||||
* This value indicates that hyphenation points are calculated with faster algorithm. This
|
||||
* algorithm measures text width with ignoring the context of hyphen character shaping, e.g.
|
||||
* kerning.
|
||||
*/
|
||||
public static final int HYPHENATION_MODE_FAST = 2;
|
||||
|
||||
/**
|
||||
* By passing true to this method, the build method will calculate hyphenation break
|
||||
* points faster with ignoring some typographic features, e.g. kerning.
|
||||
*
|
||||
* {@link #HYPHENATION_MODE_NONE} is by default.
|
||||
*
|
||||
* @see #setComputeHyphenation(boolean)
|
||||
*
|
||||
* @param mode a hyphenation mode.
|
||||
*/
|
||||
public @NonNull Builder setComputeHyphenation(@HyphenationMode int mode) {
|
||||
switch (mode) {
|
||||
case HYPHENATION_MODE_NONE:
|
||||
mComputeHyphenation = false;
|
||||
mFastHyphenation = false;
|
||||
break;
|
||||
case HYPHENATION_MODE_NORMAL:
|
||||
mComputeHyphenation = true;
|
||||
mFastHyphenation = false;
|
||||
break;
|
||||
case HYPHENATION_MODE_FAST:
|
||||
mComputeHyphenation = true;
|
||||
mFastHyphenation = true;
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unknown hyphenation mode: " + mode);
|
||||
mComputeHyphenation = false;
|
||||
mFastHyphenation = false;
|
||||
break;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -319,7 +395,7 @@ public class MeasuredText {
|
||||
try {
|
||||
long hintPtr = (mHintMt == null) ? 0 : mHintMt.getNativePtr();
|
||||
long ptr = nBuildMeasuredText(mNativePtr, hintPtr, mText, mComputeHyphenation,
|
||||
mComputeLayout);
|
||||
mComputeLayout, mFastHyphenation);
|
||||
final MeasuredText res = new MeasuredText(ptr, mText, mComputeHyphenation,
|
||||
mComputeLayout);
|
||||
sRegistry.registerNativeAllocation(res, ptr);
|
||||
@@ -378,7 +454,8 @@ public class MeasuredText {
|
||||
long hintMtPtr,
|
||||
@NonNull char[] text,
|
||||
boolean computeHyphenation,
|
||||
boolean computeLayout);
|
||||
boolean computeLayout,
|
||||
boolean fastHyphenationMode);
|
||||
|
||||
private static native void nFreeBuilder(/* Non Zero */ long nativeBuilderPtr);
|
||||
}
|
||||
|
||||
@@ -80,15 +80,17 @@ static void nAddReplacementRun(JNIEnv* /* unused */, jclass /* unused */, jlong
|
||||
}
|
||||
|
||||
// Regular JNI
|
||||
static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr,
|
||||
jlong hintPtr, jcharArray javaText, jboolean computeHyphenation,
|
||||
jboolean computeLayout) {
|
||||
static jlong nBuildMeasuredText(JNIEnv* env, jclass /* unused */, jlong builderPtr, jlong hintPtr,
|
||||
jcharArray javaText, jboolean computeHyphenation,
|
||||
jboolean computeLayout, jboolean fastHyphenationMode) {
|
||||
ScopedCharArrayRO text(env, javaText);
|
||||
const minikin::U16StringPiece textBuffer(text.get(), text.size());
|
||||
|
||||
// Pass the ownership to Java.
|
||||
return toJLong(toBuilder(builderPtr)->build(textBuffer, computeHyphenation, computeLayout,
|
||||
toMeasuredParagraph(hintPtr)).release());
|
||||
return toJLong(toBuilder(builderPtr)
|
||||
->build(textBuffer, computeHyphenation, computeLayout,
|
||||
fastHyphenationMode, toMeasuredParagraph(hintPtr))
|
||||
.release());
|
||||
}
|
||||
|
||||
// Regular JNI
|
||||
@@ -140,12 +142,12 @@ static jint nGetMemoryUsage(CRITICAL_JNI_PARAMS_COMMA jlong ptr) {
|
||||
}
|
||||
|
||||
static const JNINativeMethod gMTBuilderMethods[] = {
|
||||
// MeasuredParagraphBuilder native functions.
|
||||
{"nInitBuilder", "()J", (void*) nInitBuilder},
|
||||
{"nAddStyleRun", "(JJIIZ)V", (void*) nAddStyleRun},
|
||||
{"nAddReplacementRun", "(JJIIF)V", (void*) nAddReplacementRun},
|
||||
{"nBuildMeasuredText", "(JJ[CZZ)J", (void*) nBuildMeasuredText},
|
||||
{"nFreeBuilder", "(J)V", (void*) nFreeBuilder},
|
||||
// MeasuredParagraphBuilder native functions.
|
||||
{"nInitBuilder", "()J", (void*)nInitBuilder},
|
||||
{"nAddStyleRun", "(JJIIZ)V", (void*)nAddStyleRun},
|
||||
{"nAddReplacementRun", "(JJIIF)V", (void*)nAddReplacementRun},
|
||||
{"nBuildMeasuredText", "(JJ[CZZZ)J", (void*)nBuildMeasuredText},
|
||||
{"nFreeBuilder", "(J)V", (void*)nFreeBuilder},
|
||||
};
|
||||
|
||||
static const JNINativeMethod gMTMethods[] = {
|
||||
|
||||
Reference in New Issue
Block a user