From 6c9956e7f2db06ee9649529f222b2ef9b5a08034 Mon Sep 17 00:00:00 2001 From: Seigo Nonaka Date: Thu, 29 Jun 2023 17:45:00 +0900 Subject: Add NoHyphenationSpan and no hyphenation config into LineBreakConfig NoHyphenationSpan is a specialized class of LineBreakConfigSpan that disables hyphenation. Bug: 283193586 Test: atest LineBreakTest Change-Id: Ie77d345d83d871a5049ff713211a9dab116656b7 --- .../android/graphics/text/LineBreakConfig.java | 136 ++++++++++++++++++++- .../java/android/graphics/text/MeasuredText.java | 5 +- 2 files changed, 135 insertions(+), 6 deletions(-) (limited to 'graphics/java') diff --git a/graphics/java/android/graphics/text/LineBreakConfig.java b/graphics/java/android/graphics/text/LineBreakConfig.java index 7b204f244bd8..13540e0df789 100644 --- a/graphics/java/android/graphics/text/LineBreakConfig.java +++ b/graphics/java/android/graphics/text/LineBreakConfig.java @@ -16,6 +16,9 @@ package android.graphics.text; +import static com.android.text.flags.Flags.FLAG_NO_BREAK_NO_HYPHENATION_SPAN; + +import android.annotation.FlaggedApi; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; @@ -33,6 +36,56 @@ import java.util.Objects; */ public final class LineBreakConfig { + /** + * No hyphenation preference is specified. + * + * This is a special value of hyphenation preference indicating no hyphenation preference is + * specified. When overriding a {@link LineBreakConfig} with another {@link LineBreakConfig} + * with {@link Builder#merge(LineBreakConfig)} function, the hyphenation preference of + * overridden config will be kept if the hyphenation preference of overriding config is + * {@link #HYPHENATION_UNSPECIFIED}. + * + *
+     *     val override = LineBreakConfig.Builder()
+     *          .setLineBreakWordStyle(LineBreakConfig.LINE_BREAK_WORD_STYLE_PHRASE)
+     *          .build();  // UNSPECIFIED if no setHyphenation is called.
+     *     val config = LineBreakConfig.Builder()
+     *          .setHyphenation(LineBreakConfig.HYPHENATION_DISABLED)
+     *          .merge(override)
+     *          .build()
+     *     // Here, config has HYPHENATION_DISABLED for line break config and
+     *     // LINE_BREAK_WORD_STYLE_PHRASE for line break word style.
+     * 
+ * + * This value is resolved to {@link #HYPHENATION_ENABLED} if this value is used for text + * layout/rendering. + */ + @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) + public static final int HYPHENATION_UNSPECIFIED = -1; + + /** + * The hyphenation is disabled. + */ + @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) + public static final int HYPHENATION_DISABLED = 0; + + /** + * The hyphenation is enabled. + * + * Note: Even if the hyphenation is enabled with a line break strategy + * {@link LineBreaker#BREAK_STRATEGY_SIMPLE}, the hyphenation will not be performed unless a + * single word cannot meet width constraints. + */ + @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) + public static final int HYPHENATION_ENABLED = 1; + + /** @hide */ + @IntDef(prefix = { "HYPHENATION_" }, value = { + HYPHENATION_UNSPECIFIED, HYPHENATION_ENABLED, HYPHENATION_DISABLED, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface Hyphenation {} + /** * No line break style is specified. * @@ -147,6 +200,8 @@ public final class LineBreakConfig { private @LineBreakWordStyle int mLineBreakWordStyle = LineBreakConfig.LINE_BREAK_WORD_STYLE_UNSPECIFIED; + private @Hyphenation int mHyphenation = LineBreakConfig.HYPHENATION_UNSPECIFIED; + /** * Builder constructor. */ @@ -188,6 +243,9 @@ public final class LineBreakConfig { if (config.mLineBreakWordStyle != LINE_BREAK_WORD_STYLE_UNSPECIFIED) { mLineBreakWordStyle = config.mLineBreakWordStyle; } + if (config.mHyphenation != HYPHENATION_UNSPECIFIED) { + mHyphenation = config.mHyphenation; + } return this; } @@ -201,9 +259,11 @@ public final class LineBreakConfig { if (config == null) { mLineBreakStyle = LINE_BREAK_STYLE_UNSPECIFIED; mLineBreakWordStyle = LINE_BREAK_WORD_STYLE_UNSPECIFIED; + mHyphenation = HYPHENATION_UNSPECIFIED; } else { mLineBreakStyle = config.mLineBreakStyle; mLineBreakWordStyle = config.mLineBreakWordStyle; + mHyphenation = config.mHyphenation; } return this; } @@ -215,6 +275,11 @@ public final class LineBreakConfig { * {@link #LINE_BREAK_STYLE_UNSPECIFIED}, the line break style is reset to * {@link #LINE_BREAK_STYLE_UNSPECIFIED}. * + * @see + * Unicode Line Break Style Identifier + * @see + * CSS Line Break Property + * * @param lineBreakStyle The new line-break style. * @return This {@code Builder}. */ @@ -230,6 +295,11 @@ public final class LineBreakConfig { * with {@link #LINE_BREAK_WORD_STYLE_UNSPECIFIED}, the line break style is reset to * {@link #LINE_BREAK_WORD_STYLE_UNSPECIFIED}. * + * @see + * Unicode Line Break Word Identifier + * @see + * CSS Word Break Property + * * @param lineBreakWordStyle The new line-break word style. * @return This {@code Builder}. */ @@ -238,6 +308,27 @@ public final class LineBreakConfig { return this; } + /** + * Sets the hyphenation preference + * + * Note: Even if the {@link LineBreakConfig#HYPHENATION_ENABLED} is specified, the + * hyphenation will not be performed if the {@link android.widget.TextView} or underlying + * {@link android.text.StaticLayout}, {@link LineBreaker} are configured with + * {@link LineBreaker#HYPHENATION_FREQUENCY_NONE}. + * + * Note: Even if the hyphenation is enabled with a line break strategy + * {@link LineBreaker#BREAK_STRATEGY_SIMPLE}, the hyphenation will not be performed unless a + * single word cannot meet width constraints. + * + * @param hyphenation The hyphenation preference. + * @return This {@code Builder}. + */ + @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) + public @NonNull Builder setHyphenation(@Hyphenation int hyphenation) { + mHyphenation = hyphenation; + return this; + } + /** * Builds a {@link LineBreakConfig} instance. * @@ -247,7 +338,7 @@ public final class LineBreakConfig { * @return The {@code LineBreakConfig} instance. */ public @NonNull LineBreakConfig build() { - return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle); + return new LineBreakConfig(mLineBreakStyle, mLineBreakWordStyle, mHyphenation); } } @@ -275,6 +366,7 @@ public final class LineBreakConfig { private final @LineBreakStyle int mLineBreakStyle; private final @LineBreakWordStyle int mLineBreakWordStyle; + private final @Hyphenation int mHyphenation; /** * Constructor with line-break parameters. @@ -283,9 +375,11 @@ public final class LineBreakConfig { * {@code LineBreakConfig} instance. */ private LineBreakConfig(@LineBreakStyle int lineBreakStyle, - @LineBreakWordStyle int lineBreakWordStyle) { + @LineBreakWordStyle int lineBreakWordStyle, + @Hyphenation int hyphenation) { mLineBreakStyle = lineBreakStyle; mLineBreakWordStyle = lineBreakWordStyle; + mHyphenation = hyphenation; } /** @@ -339,6 +433,34 @@ public final class LineBreakConfig { ? LINE_BREAK_WORD_STYLE_NONE : config.mLineBreakWordStyle; } + /** + * Returns a hyphenation preference. + * + * @return A hyphenation preference. + */ + @FlaggedApi(FLAG_NO_BREAK_NO_HYPHENATION_SPAN) + public @Hyphenation int getHyphenation() { + return mHyphenation; + } + + /** + * Returns a hyphenation preference. + * + * This method never returns {@link #HYPHENATION_UNSPECIFIED}. + * + * @return A hyphenation preference. + * @hide + */ + public static @Hyphenation int getResolvedHyphenation( + @Nullable LineBreakConfig config) { + if (config == null) { + return HYPHENATION_ENABLED; + } + return config.mHyphenation == HYPHENATION_UNSPECIFIED + ? HYPHENATION_ENABLED : config.mHyphenation; + } + + /** * Generates a new {@link LineBreakConfig} instance merged with given {@code config}. * @@ -366,7 +488,9 @@ public final class LineBreakConfig { config.mLineBreakStyle == LINE_BREAK_STYLE_UNSPECIFIED ? mLineBreakStyle : config.mLineBreakStyle, config.mLineBreakWordStyle == LINE_BREAK_WORD_STYLE_UNSPECIFIED - ? mLineBreakWordStyle : config.mLineBreakWordStyle); + ? mLineBreakWordStyle : config.mLineBreakWordStyle, + config.mHyphenation == HYPHENATION_UNSPECIFIED + ? mHyphenation : config.mHyphenation); } @Override @@ -376,12 +500,13 @@ public final class LineBreakConfig { if (!(o instanceof LineBreakConfig)) return false; LineBreakConfig that = (LineBreakConfig) o; return (mLineBreakStyle == that.mLineBreakStyle) - && (mLineBreakWordStyle == that.mLineBreakWordStyle); + && (mLineBreakWordStyle == that.mLineBreakWordStyle) + && (mHyphenation == that.mHyphenation); } @Override public int hashCode() { - return Objects.hash(mLineBreakStyle, mLineBreakWordStyle); + return Objects.hash(mLineBreakStyle, mLineBreakWordStyle, mHyphenation); } @Override @@ -389,6 +514,7 @@ public final class LineBreakConfig { return "LineBreakConfig{" + "mLineBreakStyle=" + mLineBreakStyle + ", mLineBreakWordStyle=" + mLineBreakWordStyle + + ", mHyphenation= " + mHyphenation + '}'; } } diff --git a/graphics/java/android/graphics/text/MeasuredText.java b/graphics/java/android/graphics/text/MeasuredText.java index 8317985303ad..2d33e8d24ece 100644 --- a/graphics/java/android/graphics/text/MeasuredText.java +++ b/graphics/java/android/graphics/text/MeasuredText.java @@ -301,7 +301,9 @@ public class MeasuredText { Preconditions.checkArgument(end <= mText.length, "Style exceeds the text length"); int lbStyle = LineBreakConfig.getResolvedLineBreakStyle(lineBreakConfig); int lbWordStyle = LineBreakConfig.getResolvedLineBreakWordStyle(lineBreakConfig); - nAddStyleRun(mNativePtr, paint.getNativeInstance(), lbStyle, lbWordStyle, + boolean hyphenation = LineBreakConfig.getResolvedHyphenation(lineBreakConfig) + == LineBreakConfig.HYPHENATION_ENABLED; + nAddStyleRun(mNativePtr, paint.getNativeInstance(), lbStyle, lbWordStyle, hyphenation, mCurrentOffset, end, isRtl); mCurrentOffset = end; @@ -510,6 +512,7 @@ public class MeasuredText { /* Non Zero */ long paintPtr, int lineBreakStyle, int lineBreakWordStyle, + boolean hyphenation, @IntRange(from = 0) int start, @IntRange(from = 0) int end, boolean isRtl); -- cgit v1.2.3-59-g8ed1b