diff --git a/api/current.txt b/api/current.txt index b017f9d2f5b94..c2b557637bfc2 100644 --- a/api/current.txt +++ b/api/current.txt @@ -39434,6 +39434,7 @@ package android.text { method public android.text.StaticLayout.Builder setHyphenationFrequency(int); method public android.text.StaticLayout.Builder setIncludePad(boolean); method public android.text.StaticLayout.Builder setIndents(int[], int[]); + method public android.text.StaticLayout.Builder setJustify(boolean); method public android.text.StaticLayout.Builder setLineSpacing(float, float); method public android.text.StaticLayout.Builder setMaxLines(int); method public android.text.StaticLayout.Builder setText(java.lang.CharSequence); @@ -48958,6 +48959,7 @@ package android.widget { method public boolean getIncludeFontPadding(); method public android.os.Bundle getInputExtras(boolean); method public int getInputType(); + method public boolean getJustify(); method public final android.text.method.KeyListener getKeyListener(); method public final android.text.Layout getLayout(); method public float getLetterSpacing(); @@ -49066,6 +49068,7 @@ package android.widget { method public void setIncludeFontPadding(boolean); method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public void setInputType(int); + method public void setJustify(boolean); method public void setKeyListener(android.text.method.KeyListener); method public void setLetterSpacing(float); method public void setLineSpacing(float, float); diff --git a/api/system-current.txt b/api/system-current.txt index a5534deebd93e..b193c57633e72 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -42644,6 +42644,7 @@ package android.text { method public android.text.StaticLayout.Builder setHyphenationFrequency(int); method public android.text.StaticLayout.Builder setIncludePad(boolean); method public android.text.StaticLayout.Builder setIndents(int[], int[]); + method public android.text.StaticLayout.Builder setJustify(boolean); method public android.text.StaticLayout.Builder setLineSpacing(float, float); method public android.text.StaticLayout.Builder setMaxLines(int); method public android.text.StaticLayout.Builder setText(java.lang.CharSequence); @@ -52528,6 +52529,7 @@ package android.widget { method public boolean getIncludeFontPadding(); method public android.os.Bundle getInputExtras(boolean); method public int getInputType(); + method public boolean getJustify(); method public final android.text.method.KeyListener getKeyListener(); method public final android.text.Layout getLayout(); method public float getLetterSpacing(); @@ -52636,6 +52638,7 @@ package android.widget { method public void setIncludeFontPadding(boolean); method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public void setInputType(int); + method public void setJustify(boolean); method public void setKeyListener(android.text.method.KeyListener); method public void setLetterSpacing(float); method public void setLineSpacing(float, float); diff --git a/api/test-current.txt b/api/test-current.txt index 5db134a289646..754aa659a5f05 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -39554,6 +39554,7 @@ package android.text { method public android.text.StaticLayout.Builder setHyphenationFrequency(int); method public android.text.StaticLayout.Builder setIncludePad(boolean); method public android.text.StaticLayout.Builder setIndents(int[], int[]); + method public android.text.StaticLayout.Builder setJustify(boolean); method public android.text.StaticLayout.Builder setLineSpacing(float, float); method public android.text.StaticLayout.Builder setMaxLines(int); method public android.text.StaticLayout.Builder setText(java.lang.CharSequence); @@ -49260,6 +49261,7 @@ package android.widget { method public boolean getIncludeFontPadding(); method public android.os.Bundle getInputExtras(boolean); method public int getInputType(); + method public boolean getJustify(); method public final android.text.method.KeyListener getKeyListener(); method public final android.text.Layout getLayout(); method public float getLetterSpacing(); @@ -49368,6 +49370,7 @@ package android.widget { method public void setIncludeFontPadding(boolean); method public void setInputExtras(int) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException; method public void setInputType(int); + method public void setJustify(boolean); method public void setKeyListener(android.text.method.KeyListener); method public void setLetterSpacing(float); method public void setLineSpacing(float, float); diff --git a/core/java/android/text/DynamicLayout.java b/core/java/android/text/DynamicLayout.java index 9ac89960ab95d..1e9deebd8dcfe 100644 --- a/core/java/android/text/DynamicLayout.java +++ b/core/java/android/text/DynamicLayout.java @@ -85,7 +85,7 @@ public class DynamicLayout extends Layout this(base, display, paint, width, align, TextDirectionHeuristics.FIRSTSTRONG_LTR, spacingmult, spacingadd, includepad, StaticLayout.BREAK_STRATEGY_SIMPLE, StaticLayout.HYPHENATION_FREQUENCY_NONE, - ellipsize, ellipsizedWidth); + false /* justify */, ellipsize, ellipsizedWidth); } /** @@ -102,7 +102,8 @@ public class DynamicLayout extends Layout int width, Alignment align, TextDirectionHeuristic textDir, float spacingmult, float spacingadd, boolean includepad, int breakStrategy, int hyphenationFrequency, - TextUtils.TruncateAt ellipsize, int ellipsizedWidth) { + boolean justify, TextUtils.TruncateAt ellipsize, + int ellipsizedWidth) { super((ellipsize == null) ? display : (display instanceof Spanned) @@ -127,6 +128,7 @@ public class DynamicLayout extends Layout mIncludePad = includepad; mBreakStrategy = breakStrategy; + mJustify = justify; mHyphenationFrequency = hyphenationFrequency; /* @@ -300,7 +302,8 @@ public class DynamicLayout extends Layout .setEllipsizedWidth(mEllipsizedWidth) .setEllipsize(mEllipsizeAt) .setBreakStrategy(mBreakStrategy) - .setHyphenationFrequency(mHyphenationFrequency); + .setHyphenationFrequency(mHyphenationFrequency) + .setJustify(mJustify); reflowed.generate(b, false, true); int n = reflowed.getLineCount(); // If the new layout has a blank line at the end, but it is not @@ -808,6 +811,7 @@ public class DynamicLayout extends Layout private TextUtils.TruncateAt mEllipsizeAt; private int mBreakStrategy; private int mHyphenationFrequency; + private boolean mJustify; private PackedIntVector mInts; private PackedObjectVector mObjects; diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java index 3cb81b0a250fa..2fc12d30ffd89 100644 --- a/core/java/android/text/Layout.java +++ b/core/java/android/text/Layout.java @@ -218,6 +218,11 @@ public abstract class Layout { mTextDir = textDir; } + /** @hide */ + protected void setJustify(boolean justify) { + mJustify = justify; + } + /** * Replace constructor properties of this Layout with new ones. Be careful. */ @@ -266,6 +271,99 @@ public abstract class Layout { drawText(canvas, firstLine, lastLine); } + private boolean isJustificationRequired(int lineNum) { + if (!mJustify) return false; + final int lineEnd = getLineEnd(lineNum); + return lineEnd < mText.length() && mText.charAt(lineEnd - 1) != '\n'; + } + + private float getJustifyWidth(int lineNum) { + Alignment paraAlign = mAlignment; + TabStops tabStops = null; + boolean tabStopsIsInitialized = false; + + int left = 0; + int right = mWidth; + + final int dir = getParagraphDirection(lineNum); + + ParagraphStyle[] spans = NO_PARA_SPANS; + if (mSpannedText) { + Spanned sp = (Spanned) mText; + final int start = getLineStart(lineNum); + + final boolean isFirstParaLine = (start == 0 || mText.charAt(start - 1) == '\n'); + + if (isFirstParaLine) { + final int spanEnd = sp.nextSpanTransition(start, mText.length(), + ParagraphStyle.class); + spans = getParagraphSpans(sp, start, spanEnd, ParagraphStyle.class); + + for (int n = spans.length - 1; n >= 0; n--) { + if (spans[n] instanceof AlignmentSpan) { + paraAlign = ((AlignmentSpan) spans[n]).getAlignment(); + break; + } + } + } + + final int length = spans.length; + boolean useFirstLineMargin = isFirstParaLine; + for (int n = 0; n < length; n++) { + if (spans[n] instanceof LeadingMarginSpan2) { + int count = ((LeadingMarginSpan2) spans[n]).getLeadingMarginLineCount(); + int startLine = getLineForOffset(sp.getSpanStart(spans[n])); + if (lineNum < startLine + count) { + useFirstLineMargin = true; + break; + } + } + } + for (int n = 0; n < length; n++) { + if (spans[n] instanceof LeadingMarginSpan) { + LeadingMarginSpan margin = (LeadingMarginSpan) spans[n]; + if (dir == DIR_RIGHT_TO_LEFT) { + right -= margin.getLeadingMargin(useFirstLineMargin); + } else { + left += margin.getLeadingMargin(useFirstLineMargin); + } + } + } + } + + if (getLineContainsTab(lineNum)) { + tabStops = new TabStops(TAB_INCREMENT, spans); + } + + final Alignment align; + if (paraAlign == Alignment.ALIGN_LEFT) { + align = (dir == DIR_LEFT_TO_RIGHT) ? Alignment.ALIGN_NORMAL : Alignment.ALIGN_OPPOSITE; + } else if (paraAlign == Alignment.ALIGN_RIGHT) { + align = (dir == DIR_LEFT_TO_RIGHT) ? Alignment.ALIGN_OPPOSITE : Alignment.ALIGN_NORMAL; + } else { + align = paraAlign; + } + + final int indentWidth; + if (align == Alignment.ALIGN_NORMAL) { + if (dir == DIR_LEFT_TO_RIGHT) { + indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT); + } else { + indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT); + } + } else if (align == Alignment.ALIGN_OPPOSITE) { + if (dir == DIR_LEFT_TO_RIGHT) { + indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT); + } else { + indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT); + } + } else { // Alignment.ALIGN_CENTER + indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER); + } + + return right - left - indentWidth; + } + /** * @hide */ @@ -274,7 +372,7 @@ public abstract class Layout { int previousLineEnd = getLineStart(firstLine); ParagraphStyle[] spans = NO_PARA_SPANS; int spanEnd = 0; - TextPaint paint = mPaint; + final TextPaint paint = mPaint; CharSequence buf = mText; Alignment paraAlign = mAlignment; @@ -288,6 +386,7 @@ public abstract class Layout { for (int lineNum = firstLine; lineNum <= lastLine; lineNum++) { int start = previousLineEnd; previousLineEnd = getLineStart(lineNum + 1); + final boolean justify = isJustificationRequired(lineNum); int end = getLineVisibleEnd(lineNum, start, previousLineEnd); int ltop = previousLineBottom; @@ -386,34 +485,42 @@ public abstract class Layout { } int x; + final int indentWidth; if (align == Alignment.ALIGN_NORMAL) { if (dir == DIR_LEFT_TO_RIGHT) { - x = left + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT); + indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT); + x = left + indentWidth; } else { - x = right + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT); + indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT); + x = right - indentWidth; } } else { int max = (int)getLineExtent(lineNum, tabStops, false); if (align == Alignment.ALIGN_OPPOSITE) { if (dir == DIR_LEFT_TO_RIGHT) { - x = right - max + getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT); + indentWidth = -getIndentAdjust(lineNum, Alignment.ALIGN_RIGHT); + x = right - max - indentWidth; } else { - x = left - max + getIndentAdjust(lineNum, Alignment.ALIGN_LEFT); + indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_LEFT); + x = left - max + indentWidth; } } else { // Alignment.ALIGN_CENTER + indentWidth = getIndentAdjust(lineNum, Alignment.ALIGN_CENTER); max = max & ~1; - x = ((right + left - max) >> 1) + - getIndentAdjust(lineNum, Alignment.ALIGN_CENTER); + x = ((right + left - max) >> 1) + indentWidth; } } paint.setHyphenEdit(getHyphen(lineNum)); Directions directions = getLineDirections(lineNum); - if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTab) { + if (directions == DIRS_ALL_LEFT_TO_RIGHT && !mSpannedText && !hasTab && !justify) { // XXX: assumes there's nothing additional to be done canvas.drawText(buf, start, end, x, lbaseline, paint); } else { tl.set(paint, buf, start, end, dir, directions, hasTab, tabStops); + if (justify) { + tl.justify(right - left - indentWidth); + } tl.draw(canvas, x, ltop, lbaseline, lbottom); } paint.setHyphenEdit(0); @@ -1094,6 +1201,9 @@ public abstract class Layout { TextLine tl = TextLine.obtain(); mPaint.setHyphenEdit(getHyphen(line)); tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops); + if (isJustificationRequired(line)) { + tl.justify(getJustifyWidth(line)); + } float width = tl.metrics(null); mPaint.setHyphenEdit(0); TextLine.recycle(tl); @@ -1118,6 +1228,9 @@ public abstract class Layout { TextLine tl = TextLine.obtain(); mPaint.setHyphenEdit(getHyphen(line)); tl.set(mPaint, mText, start, end, dir, directions, hasTabs, tabStops); + if (isJustificationRequired(line)) { + tl.justify(getJustifyWidth(line)); + } float width = tl.metrics(null); mPaint.setHyphenEdit(0); TextLine.recycle(tl); @@ -1303,10 +1416,7 @@ public abstract class Layout { return end - 1; } - // Note: keep this in sync with Minikin LineBreaker::isLineEndSpace() - if (!(ch == ' ' || ch == '\t' || ch == 0x1680 || - (0x2000 <= ch && ch <= 0x200A && ch != 0x2007) || - ch == 0x205F || ch == 0x3000)) { + if (!TextLine.isLineEndSpace(ch)) { break; } @@ -2086,6 +2196,7 @@ public abstract class Layout { private boolean mSpannedText; private TextDirectionHeuristic mTextDir; private SpanSet mLineBackgroundSpans; + private boolean mJustify; public static final int DIR_LEFT_TO_RIGHT = 1; public static final int DIR_RIGHT_TO_LEFT = -1; diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 081be3afd6d32..cb5b073318d8a 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -94,6 +94,7 @@ public class StaticLayout extends Layout { b.mMaxLines = Integer.MAX_VALUE; b.mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; b.mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE; + b.mJustify = false; b.mMeasuredText = MeasuredText.obtain(); return b; @@ -319,6 +320,17 @@ public class StaticLayout extends Layout { return this; } + /** + * Enables or disables paragraph justification. The default value is disabled (false). + * + * @param justify true for enabling and false for disabling paragraph justification. + * @return this builder, useful for chaining. + */ + public Builder setJustify(boolean justify) { + mJustify = justify; + return this; + } + /** * Measurement and break iteration is done in native code. The protocol for using * the native code is as follows. @@ -404,6 +416,7 @@ public class StaticLayout extends Layout { int mHyphenationFrequency; int[] mLeftIndents; int[] mRightIndents; + boolean mJustify; Paint.FontMetricsInt mFontMetricsInt = new Paint.FontMetricsInt(); @@ -557,6 +570,7 @@ public class StaticLayout extends Layout { mLeftIndents = b.mLeftIndents; mRightIndents = b.mRightIndents; + setJustify(b.mJustify); generate(b, b.mIncludePad, b.mIncludePad); } @@ -676,7 +690,8 @@ public class StaticLayout extends Layout { nSetupParagraph(b.mNativePtr, chs, paraEnd - paraStart, firstWidth, firstWidthLineCount, restWidth, - variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency); + variableTabStops, TAB_INCREMENT, b.mBreakStrategy, b.mHyphenationFrequency, + b.mJustify); if (mLeftIndents != null || mRightIndents != null) { // TODO(raph) performance: it would be better to do this once per layout rather // than once per paragraph, but that would require a change to the native @@ -1284,7 +1299,8 @@ public class StaticLayout extends Layout { // Set up paragraph text and settings; done as one big method to minimize jni crossings private static native void nSetupParagraph(long nativePtr, char[] text, int length, float firstWidth, int firstWidthLineCount, float restWidth, - int[] variableTabStops, int defaultTabStop, int breakStrategy, int hyphenationFrequency); + int[] variableTabStops, int defaultTabStop, int breakStrategy, int hyphenationFrequency, + boolean isJustified); private static native float nAddStyleRun(long nativePtr, long nativePaint, long nativeTypeface, int start, int end, boolean isRtl); diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index c4118605b44c4..fcff9a2e5fcac 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -54,6 +54,10 @@ class TextLine { private char[] mChars; private boolean mCharsValid; private Spanned mSpanned; + + // Additional width of whitespace for justification. This value is per whitespace, thus + // the line width will increase by mAddedWidth x (number of stretchable whitespaces). + private float mAddedWidth; private final TextPaint mWorkPaint = new TextPaint(); private final SpanSet mMetricAffectingSpanSpanSet = new SpanSet(MetricAffectingSpan.class); @@ -177,6 +181,25 @@ class TextLine { } } mTabs = tabStops; + mAddedWidth = 0; + } + + /** + * Justify the line to the given width. + */ + void justify(float justifyWidth) { + int end = mLen; + while (end > 0 && isLineEndSpace(mText.charAt(mStart + end - 1))) { + end--; + } + final int spaces = countStretchableSpaces(0, end); + if (spaces == 0) { + // There are no stretchable spaces, so we can't help the justification by adding any + // width. + return; + } + final float width = Math.abs(measure(end, false, null)); + mAddedWidth = (justifyWidth - width) / spaces; } /** @@ -595,6 +618,7 @@ class TextLine { TextPaint wp = mWorkPaint; wp.set(mPaint); + wp.setWordSpacing(mAddedWidth); int spanStart = runStart; int spanLimit; @@ -695,6 +719,7 @@ class TextLine { Canvas c, float x, int top, int y, int bottom, FontMetricsInt fmi, boolean needWidth, int offset) { + wp.setWordSpacing(mAddedWidth); // Get metrics first (even for empty strings or "0" width runs) if (fmi != null) { expandMetricsFromPaint(fmi, wp); @@ -981,5 +1006,34 @@ class TextLine { return TabStops.nextDefaultStop(h, TAB_INCREMENT); } + private boolean isStretchableWhitespace(int ch) { + // TODO: Support other stretchable whitespace. (Bug: 34013491) + return ch == 0x0020 || ch == 0x00A0; + } + + private int nextStretchableSpace(int start, int end) { + for (int i = start; i < end; i++) { + final char c = mCharsValid ? mChars[i] : mText.charAt(i + mStart); + if (isStretchableWhitespace(c)) return i; + } + return end; + } + + /* Return the number of spaces in the text line, for the purpose of justification */ + private int countStretchableSpaces(int start, int end) { + int count = 0; + for (int i = start; i < end; i = nextStretchableSpace(i + 1, end)) { + count++; + } + return count; + } + + // Note: keep this in sync with Minikin LineBreaker::isLineEndSpace() + public static boolean isLineEndSpace(char ch) { + return ch == ' ' || ch == '\t' || ch == 0x1680 + || (0x2000 <= ch && ch <= 0x200A && ch != 0x2007) + || ch == 0x205F || ch == 0x3000; + } + private static final int TAB_INCREMENT = 20; } diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java index 1961bf6b7e151..70034e4b7fcc3 100644 --- a/core/java/android/widget/TextView.java +++ b/core/java/android/widget/TextView.java @@ -596,6 +596,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener private int mBreakStrategy; private int mHyphenationFrequency; + private boolean mJustify; private int mMaximum = Integer.MAX_VALUE; private int mMaxMode = LINES; @@ -769,6 +770,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener String fontFeatureSettings = null; mBreakStrategy = Layout.BREAK_STRATEGY_SIMPLE; mHyphenationFrequency = Layout.HYPHENATION_FREQUENCY_NONE; + mJustify = false; final Resources.Theme theme = context.getTheme(); @@ -3297,6 +3299,29 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener return mHyphenationFrequency; } + /** + * Enables or disables full justification. The default value is false. + * + * @see #getJustify() + */ + public void setJustify(boolean justify) { + mJustify = justify; + if (mLayout != null) { + nullLayouts(); + requestLayout(); + invalidate(); + } + } + + /** + * @return true if currently paragraph justification is enabled. + * + * @see #setJustify(boolean) + */ + public boolean getJustify() { + return mJustify; + } + /** * Sets font feature settings. The format is the same as the CSS * font-feature-settings attribute: @@ -7170,6 +7195,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setIncludePad(mIncludePad) .setBreakStrategy(mBreakStrategy) .setHyphenationFrequency(mHyphenationFrequency) + .setJustify(mJustify) .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE); if (shouldEllipsize) { builder.setEllipsize(mEllipsize) @@ -7211,7 +7237,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener if (mText instanceof Spannable) { result = new DynamicLayout(mText, mTransformed, mTextPaint, wantWidth, alignment, mTextDir, mSpacingMult, mSpacingAdd, mIncludePad, - mBreakStrategy, mHyphenationFrequency, + mBreakStrategy, mHyphenationFrequency, mJustify, getKeyListener() == null ? effectiveEllipsize : null, ellipsisWidth); } else { if (boring == UNKNOWN_BORING) { @@ -7261,6 +7287,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener .setIncludePad(mIncludePad) .setBreakStrategy(mBreakStrategy) .setHyphenationFrequency(mHyphenationFrequency) + .setJustify(mJustify) .setMaxLines(mMaxMode == LINES ? mMaximum : Integer.MAX_VALUE); if (shouldEllipsize) { builder.setEllipsize(effectiveEllipsize) diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp index 02fa8720d5d2a..c05ef26fd5ac2 100644 --- a/core/jni/android_text_StaticLayout.cpp +++ b/core/jni/android_text_StaticLayout.cpp @@ -54,7 +54,8 @@ static JLineBreaksID gLineBreaks_fieldID; // hyphenFrequency) static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray text, jint length, jfloat firstWidth, jint firstWidthLineLimit, jfloat restWidth, - jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency) { + jintArray variableTabStops, jint defaultTabStop, jint strategy, jint hyphenFrequency, + jboolean isJustified) { minikin::LineBreaker* b = reinterpret_cast(nativePtr); b->resize(length); env->GetCharArrayRegion(text, 0, length, b->buffer()); @@ -68,6 +69,7 @@ static void nSetupParagraph(JNIEnv* env, jclass, jlong nativePtr, jcharArray tex } b->setStrategy(static_cast(strategy)); b->setHyphenationFrequency(static_cast(hyphenFrequency)); + b->setJustified(isJustified); } static void recycleCopy(JNIEnv* env, jobject recycle, jintArray recycleBreaks, @@ -190,7 +192,7 @@ static const JNINativeMethod gMethods[] = { {"nFinishBuilder", "(J)V", (void*) nFinishBuilder}, {"nLoadHyphenator", "(Ljava/nio/ByteBuffer;I)J", (void*) nLoadHyphenator}, {"nSetLocale", "(JLjava/lang/String;J)V", (void*) nSetLocale}, - {"nSetupParagraph", "(J[CIFIF[IIII)V", (void*) nSetupParagraph}, + {"nSetupParagraph", "(J[CIFIF[IIIIZ)V", (void*) nSetupParagraph}, {"nSetIndents", "(J[I)V", (void*) nSetIndents}, {"nAddStyleRun", "(JJJIIZ)F", (void*) nAddStyleRun}, {"nAddMeasuredRun", "(JII[F)V", (void*) nAddMeasuredRun},