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

Commit c9fd978d authored by Gilles Debunne's avatar Gilles Debunne
Browse files

Bug 5281947: add to dictionnary option promoted in suggestions.

When several SuggestionSpans are available at a given position, their
content are merged, in creation time order.

As a result, the IME's suggestions are picked before the spell check, and
no add to dictionnary option is created.

This CL modifies the comparator to make easy correction spans appear first
(Voice IME), then misspelled words and then regular suggestions.

Also avoids the creation of a new comparator and length hash map on every display.

Change-Id: I1f9f031a6fdcbbc09f248a192b83051092765f8e
parent 51322732
Loading
Loading
Loading
Loading
+4 −7
Original line number Diff line number Diff line
@@ -723,7 +723,7 @@ class TextLine {
        float ret = 0;

        int contextLen = contextEnd - contextStart;
        if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineCount != 0 || runIsRtl))) {
        if (needWidth || (c != null && (wp.bgColor != 0 || wp.underlineColor != 0 || runIsRtl))) {
            int flags = runIsRtl ? Paint.DIRECTION_RTL : Paint.DIRECTION_LTR;
            if (mCharsValid) {
                ret = wp.getTextRunAdvances(mChars, start, runLen,
@@ -753,7 +753,7 @@ class TextLine {
                wp.setColor(previousColor);
            }

            if (wp.underlineCount != 0) {
            if (wp.underlineColor != 0) {
                // kStdUnderline_Offset = 1/9, defined in SkTextFormatParams.h
                float underlineTop = y + wp.baselineShift + (1.0f / 9.0f) * wp.getTextSize();

@@ -764,11 +764,8 @@ class TextLine {
                wp.setStyle(Paint.Style.FILL);
                wp.setAntiAlias(true);

                for (int i = 0; i < wp.underlineCount; i++) {
                    wp.setColor(wp.underlineColors[i]);
                    c.drawRect(x, underlineTop, x + ret, underlineTop + wp.underlineThicknesses[i],
                            wp);
                }
                wp.setColor(wp.underlineColor);
                c.drawRect(x, underlineTop, x + ret, underlineTop + wp.underlineThickness, wp);

                wp.setStyle(previousStyle);
                wp.setColor(previousColor);
+6 −45
Original line number Diff line number Diff line
@@ -24,8 +24,6 @@ import android.graphics.Paint;
 */
public class TextPaint extends Paint {

    private static final int DEFAULT_UNDERLINE_SIZE = 3;

    // Special value 0 means no background paint
    public int bgColor;
    public int baselineShift;
@@ -36,17 +34,12 @@ public class TextPaint extends Paint {
     * Special value 0 means no custom underline
     * @hide
     */
    public int[] underlineColors;
    public int underlineColor = 0;
    /**
     * Defined as a multiplier of the default underline thickness. Use 1.0f for default thickness.
     * @hide
     */
    public float[] underlineThicknesses;
    /**
     * The number of underlines currently stored in the array. If 0, no underline is drawn.
     * @hide
     */
    public int underlineCount;
    public float underlineThickness;

    public TextPaint() {
        super();
@@ -72,16 +65,8 @@ public class TextPaint extends Paint {
        linkColor = tp.linkColor;
        drawableState = tp.drawableState;
        density = tp.density;

        if (tp.underlineColors != null) {
            if (underlineColors == null || underlineColors.length < tp.underlineCount) {
                underlineColors = new int[tp.underlineCount];
                underlineThicknesses = new float[tp.underlineCount];
            }
            System.arraycopy(tp.underlineColors, 0, underlineColors, 0, tp.underlineCount);
            System.arraycopy(tp.underlineThicknesses, 0, underlineThicknesses, 0, tp.underlineCount);
        }
        underlineCount = tp.underlineCount;
        underlineColor = tp.underlineColor;
        underlineThickness = tp.underlineThickness;
    }

    /**
@@ -91,31 +76,7 @@ public class TextPaint extends Paint {
     * @hide
     */
    public void setUnderlineText(int color, float thickness) {
        if (color == 0) {
            // No underline
            return;
        }

        if (underlineCount == 0) {
            underlineColors = new int[DEFAULT_UNDERLINE_SIZE];
            underlineThicknesses = new float[DEFAULT_UNDERLINE_SIZE];
            underlineColors[underlineCount] = color;
            underlineThicknesses[underlineCount] = thickness;
            underlineCount++;
        } else {
            if (underlineCount == underlineColors.length) {
                int[] newColors = new int[underlineColors.length + DEFAULT_UNDERLINE_SIZE];
                float[] newThickness = new float[underlineThicknesses.length
                        + DEFAULT_UNDERLINE_SIZE];
                System.arraycopy(underlineColors, 0, newColors, 0, underlineColors.length);
                System.arraycopy(
                        underlineThicknesses, 0, newThickness, 0, underlineThicknesses.length);
                underlineColors = newColors;
                underlineThicknesses = newThickness;
            }
            underlineColors[underlineCount] = color;
            underlineThicknesses[underlineCount] = thickness;
            underlineCount++;
        }
        underlineColor = color;
        underlineThickness = thickness;
    }
}
+21 −7
Original line number Diff line number Diff line
@@ -108,7 +108,8 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
    /**
     * @param context Context for the application
     * @param locale locale Locale of the suggestions
     * @param suggestions Suggestions for the string under the span
     * @param suggestions Suggestions for the string under the span. Only the first up to
     * {@link SuggestionSpan#SUGGESTIONS_MAX_SIZE} will be considered.
     * @param flags Additional flags indicating how this span is handled in TextView
     * @param notificationTargetClass if not null, this class will get notified when the user
     * selects one of the suggestions.
@@ -258,10 +259,16 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {

    @Override
    public void updateDrawState(TextPaint tp) {
        if ((mFlags & FLAG_MISSPELLED) != 0) {
            tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
        } else if ((mFlags & FLAG_EASY_CORRECT) != 0) {
        final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0;
        final boolean easy = (mFlags & FLAG_EASY_CORRECT) != 0;
        if (easy) {
            if (!misspelled) {
                tp.setUnderlineText(mEasyCorrectUnderlineColor, mEasyCorrectUnderlineThickness);
            } else if (tp.underlineColor == 0) {
                // Spans are rendered in an arbitrary order. Since misspelled is less prioritary
                // than just easy, do not apply misspelled if an easy (or a mispelled) has been set
                tp.setUnderlineText(mMisspelledUnderlineColor, mMisspelledUnderlineThickness);
            }
        }
    }

@@ -272,8 +279,15 @@ public class SuggestionSpan extends CharacterStyle implements ParcelableSpan {
     */
    public int getUnderlineColor() {
        // The order here should match what is used in updateDrawState
        if ((mFlags & FLAG_MISSPELLED) != 0) return mMisspelledUnderlineColor;
        if ((mFlags & FLAG_EASY_CORRECT) != 0) return mEasyCorrectUnderlineColor;
        final boolean misspelled = (mFlags & FLAG_MISSPELLED) != 0;
        final boolean easy = (mFlags & FLAG_EASY_CORRECT) != 0;
        if (easy) {
            if (!misspelled) {
                return mEasyCorrectUnderlineColor;
            } else {
                return mMisspelledUnderlineColor;
            }
        }
        return 0;
    }
}
+30 −13
Original line number Diff line number Diff line
@@ -9547,6 +9547,9 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        private int mNumberOfSuggestions;
        private boolean mCursorWasVisibleBeforeSuggestions;
        private SuggestionAdapter mSuggestionsAdapter;
        private final Comparator<SuggestionSpan> mSuggestionSpanComparator;
        private final HashMap<SuggestionSpan, Integer> mSpansLengths;


        private class CustomPopupWindow extends PopupWindow {
            public CustomPopupWindow(Context context, int defStyle) {
@@ -9572,6 +9575,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener

        public SuggestionsPopupWindow() {
            mCursorWasVisibleBeforeSuggestions = mCursorVisible;
            mSuggestionSpanComparator = new SuggestionSpanComparator();
            mSpansLengths = new HashMap<SuggestionSpan, Integer>();
        }

        @Override
@@ -9650,6 +9655,26 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            }
        }

        private class SuggestionSpanComparator implements Comparator<SuggestionSpan> {
            public int compare(SuggestionSpan span1, SuggestionSpan span2) {
                final int flag1 = span1.getFlags();
                final int flag2 = span2.getFlags();
                if (flag1 != flag2) {
                    // The order here should match what is used in updateDrawState
                    final boolean easy1 = (flag1 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
                    final boolean easy2 = (flag2 & SuggestionSpan.FLAG_EASY_CORRECT) != 0;
                    final boolean misspelled1 = (flag1 & SuggestionSpan.FLAG_MISSPELLED) != 0;
                    final boolean misspelled2 = (flag2 & SuggestionSpan.FLAG_MISSPELLED) != 0;
                    if (easy1 && !misspelled1) return -1;
                    if (easy2 && !misspelled2) return 1;
                    if (misspelled1) return -1;
                    if (misspelled2) return 1;
                }

                return mSpansLengths.get(span1).intValue() - mSpansLengths.get(span2).intValue();
            }
        }

        /**
         * Returns the suggestion spans that cover the current cursor position. The suggestion
         * spans are sorted according to the length of text that they are attached to.
@@ -9659,24 +9684,16 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
            Spannable spannable = (Spannable) TextView.this.mText;
            SuggestionSpan[] suggestionSpans = spannable.getSpans(pos, pos, SuggestionSpan.class);

            // Cache the span length for performance reason.
            final HashMap<SuggestionSpan, Integer> spansLengths =
                    new HashMap<SuggestionSpan, Integer>();

            mSpansLengths.clear();
            for (SuggestionSpan suggestionSpan : suggestionSpans) {
                int start = spannable.getSpanStart(suggestionSpan);
                int end = spannable.getSpanEnd(suggestionSpan);
                spansLengths.put(suggestionSpan, Integer.valueOf(end - start));
            }

            // The suggestions are sorted according to the lenght of the text that they cover
            // (shorter first)
            Arrays.sort(suggestionSpans, new Comparator<SuggestionSpan>() {
                public int compare(SuggestionSpan span1, SuggestionSpan span2) {
                    return spansLengths.get(span1).intValue() - spansLengths.get(span2).intValue();
                mSpansLengths.put(suggestionSpan, Integer.valueOf(end - start));
            }
            });

            // The suggestions are sorted according to their types (easy correction first, then
            // misspelled) and to the length of the text that they cover (shorter first).
            Arrays.sort(suggestionSpans, mSuggestionSpanComparator);
            return suggestionSpans;
        }