Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6423d01b authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Implement fast hyphenation algorithm"

parents 8266e332 0f761404
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -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();
+7 −1
Original line number Diff line number Diff line
@@ -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
  }
+24 −3
Original line number Diff line number Diff line
@@ -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);
+3 −3
Original line number Diff line number Diff line
@@ -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);
+24 −3
Original line number Diff line number Diff line
@@ -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()]);
    }
Loading