diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java index 3d0c6622d8afd..24d746e0dfe2f 100644 --- a/core/java/android/text/StaticLayout.java +++ b/core/java/android/text/StaticLayout.java @@ -376,9 +376,13 @@ public class StaticLayout extends Layout { * Set paragraph justification mode. The default value is * {@link Layout#JUSTIFICATION_MODE_NONE}. If the last line is too short for justification, * the last line will be displayed with the alignment set by {@link #setAlignment}. + * When Justification mode is JUSTIFICATION_MODE_INTER_WORD, wordSpacing on the given + * {@link Paint} will be ignored. This behavior also affects Spans which change the + * wordSpacing. * * @param justificationMode justification mode for the paragraph. * @return this builder, useful for chaining. + * @see Paint#setWordSpacing(float) */ @NonNull public Builder setJustificationMode(@JustificationMode int justificationMode) { diff --git a/core/java/android/text/TextLine.java b/core/java/android/text/TextLine.java index 6eb433abf16c8..949328fd3a990 100644 --- a/core/java/android/text/TextLine.java +++ b/core/java/android/text/TextLine.java @@ -75,8 +75,9 @@ public class TextLine { private int mEllipsisEnd; // 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; + // the line width will increase by mAddedWidthForJustify x (number of stretchable whitespaces). + private float mAddedWidthForJustify; + private boolean mIsJustifying; private final TextPaint mWorkPaint = new TextPaint(); private final TextPaint mActivePaint = new TextPaint(); @@ -229,7 +230,8 @@ public class TextLine { } } mTabs = tabStops; - mAddedWidth = 0; + mAddedWidthForJustify = 0; + mIsJustifying = false; mEllipsisStart = ellipsisStart != ellipsisEnd ? ellipsisStart : 0; mEllipsisEnd = ellipsisStart != ellipsisEnd ? ellipsisEnd : 0; @@ -255,7 +257,8 @@ public class TextLine { return; } final float width = Math.abs(measure(end, false, null)); - mAddedWidth = (justifyWidth - width) / spaces; + mAddedWidthForJustify = (justifyWidth - width) / spaces; + mIsJustifying = true; } /** @@ -713,7 +716,9 @@ public class TextLine { TextPaint wp = mWorkPaint; wp.set(mPaint); - wp.setWordSpacing(mAddedWidth); + if (mIsJustifying) { + wp.setWordSpacing(mAddedWidthForJustify); + } int spanStart = runStart; int spanLimit; @@ -849,7 +854,9 @@ public class TextLine { FontMetricsInt fmi, boolean needWidth, int offset, @Nullable ArrayList decorations) { - wp.setWordSpacing(mAddedWidth); + if (mIsJustifying) { + wp.setWordSpacing(mAddedWidthForJustify); + } // Get metrics first (even for empty strings or "0" width runs) if (fmi != null) { expandMetricsFromPaint(fmi, wp); diff --git a/core/tests/coretests/src/android/text/TextLineTest.java b/core/tests/coretests/src/android/text/TextLineTest.java index 61f976a7308d3..2fe882c8f9f8e 100644 --- a/core/tests/coretests/src/android/text/TextLineTest.java +++ b/core/tests/coretests/src/android/text/TextLineTest.java @@ -253,6 +253,18 @@ public class TextLineTest { new float[]{0.0f, -10.0f, -10.0f, -100.0f, -110.0f, -110.0f}); } + @Test + public void testMeasure_wordSpacing() { + final TextPaint paint = new TextPaint(); + paint.setTypeface(TYPEFACE); + paint.setTextSize(10.0f); // make 1em = 10px + paint.setWordSpacing(10.0f); + + TextLine tl = getTextLine("I I", paint); + assertMeasurements(tl, 3, false, + new float[]{0.0f, 10.0f, 120.0f, 130.0f}); + } + @Test public void testHandleRun_ellipsizedReplacementSpan_isSkipped() { final Spannable text = new SpannableStringBuilder("This is a... text");