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

Commit ebdc2df3 authored by Tyler Freeman's avatar Tyler Freeman
Browse files

feat(high contrast text): update design treatment: rounded rects

We will leave out soft light for now, as it has some rendering issues
during animations and the overscroll stretch effect.

Bug: 369901146
Flag: com.android.graphics.hwui.flags.high_contrast_text_small_text_rect
Test: atest frameworks/base/core/tests/coretests/src/android/text/LayoutTest.java
Test: atest cts/tests/tests/uirendering/src/android/uirendering/cts/testclasses/TextViewHighContrastTextTests.kt
Change-Id: I36e6828b4763478f417053d71199fee4edf69edb
parent f613f7fe
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -75,6 +75,9 @@ public abstract class Layout {
    // These should match the constants in framework/base/libs/hwui/hwui/DrawTextFunctor.h
    private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX = 4f;
    private static final float HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR = 0.2f;
    private static final float HIGH_CONTRAST_TEXT_BACKGROUND_CORNER_RADIUS_DP = 5f;
    // since we're not using soft light yet, this needs to be much lower than the spec'd 0.8
    private static final float HIGH_CONTRAST_TEXT_BACKGROUND_ALPHA_PERCENTAGE = 0.5f;

    /** @hide */
    @IntDef(prefix = { "BREAK_STRATEGY_" }, value = {
@@ -1025,11 +1028,18 @@ public abstract class Layout {

        var padding = Math.max(HIGH_CONTRAST_TEXT_BORDER_WIDTH_MIN_PX,
                mPaint.getTextSize() * HIGH_CONTRAST_TEXT_BORDER_WIDTH_FACTOR);
        var cornerRadius = mPaint.density * HIGH_CONTRAST_TEXT_BACKGROUND_CORNER_RADIUS_DP;

        // We set the alpha on the color itself instead of Paint.setAlpha(), because that function
        // actually mutates the color in... *ehem* very strange ways. Also the color might get reset
        // for various reasons, which also resets the alpha.
        var white = Color.argb(HIGH_CONTRAST_TEXT_BACKGROUND_ALPHA_PERCENTAGE, 1f, 1f, 1f);
        var black = Color.argb(HIGH_CONTRAST_TEXT_BACKGROUND_ALPHA_PERCENTAGE, 0f, 0f, 0f);

        var originalTextColor = mPaint.getColor();
        var bgPaint = mWorkPlainPaint;
        bgPaint.reset();
        bgPaint.setColor(isHighContrastTextDark(originalTextColor) ? Color.WHITE : Color.BLACK);
        bgPaint.setColor(isHighContrastTextDark(originalTextColor) ? white : black);
        bgPaint.setStyle(Paint.Style.FILL);

        int start = getLineStart(firstLine);
@@ -1082,7 +1092,12 @@ public abstract class Layout {
                    private void drawRect() {
                        if (!mLineBackground.isEmpty()) {
                            mLineBackground.inset(-padding, -padding);
                            canvas.drawRect(mLineBackground, bgPaint);
                            canvas.drawRoundRect(
                                    mLineBackground,
                                    cornerRadius,
                                    cornerRadius,
                                    bgPaint
                            );
                        }
                    }

@@ -1104,7 +1119,7 @@ public abstract class Layout {
                        if (hasColorChanged) {
                            mLastColor = textColor;

                            return isHighContrastTextDark(textColor) ? Color.WHITE : Color.BLACK;
                            return isHighContrastTextDark(textColor) ? white : black;
                        }

                        return bgPaint.getColor();
+39 −15
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import android.text.Layout.Alignment;
import android.text.style.ForegroundColorSpan;
import android.text.style.StrikethroughSpan;

import androidx.annotation.NonNull;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;

@@ -697,7 +698,7 @@ public class LayoutTest {

            if (drawCommand.path != null) {
                expect.that(drawCommand.path).isEqualTo(selectionPath);
                expect.that(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW);
                expect.that(removeAlpha(drawCommand.paint.getColor())).isEqualTo(Color.YELLOW);
                expect.that(drawCommand.paint.getBlendMode()).isNotNull();
                highlightsFound++;
            } else if (drawCommand.text != null) {
@@ -750,7 +751,7 @@ public class LayoutTest {

            if (drawCommand.path != null) {
                expect.that(drawCommand.path).isEqualTo(selectionPath);
                expect.that(drawCommand.paint.getColor()).isEqualTo(Color.YELLOW);
                expect.that(removeAlpha(drawCommand.paint.getColor())).isEqualTo(Color.YELLOW);
                expect.that(drawCommand.paint.getBlendMode()).isNotNull();
                highlightsFound++;
            } else if (drawCommand.text != null) {
@@ -802,7 +803,7 @@ public class LayoutTest {

            if (drawCommand.path != null) {
                expect.that(drawCommand.path).isEqualTo(selectionPath);
                expect.that(drawCommand.paint.getColor()).isEqualTo(Color.CYAN);
                expect.that(removeAlpha(drawCommand.paint.getColor())).isEqualTo(Color.CYAN);
                expect.that(drawCommand.paint.getBlendMode()).isNull();
                highlightsFound++;
            } else if (drawCommand.text != null) {
@@ -855,7 +856,7 @@ public class LayoutTest {

            if (drawCommand.path != null) {
                expect.that(drawCommand.path).isEqualTo(selectionPath);
                expect.that(drawCommand.paint.getColor()).isEqualTo(Color.CYAN);
                expect.that(removeAlpha(drawCommand.paint.getColor())).isEqualTo(Color.CYAN);
                expect.that(drawCommand.paint.getBlendMode()).isNull();
                highlightsFound++;
            } else if (drawCommand.text != null) {
@@ -914,7 +915,7 @@ public class LayoutTest {

            if (drawCommand.rect != null) {
                numBackgroundsFound++;
                expect.that(drawCommand.paint.getColor()).isEqualTo(Color.BLACK);
                expect.that(removeAlpha(drawCommand.paint.getColor())).isEqualTo(Color.BLACK);
                expect.that(drawCommand.rect.height()).isAtLeast(LINE_HEIGHT);
                expect.that(drawCommand.rect.width()).isGreaterThan(0);
                float expectedY = (numBackgroundsFound) * (LINE_HEIGHT + LINE_DESCENT);
@@ -997,20 +998,38 @@ public class LayoutTest {
                .filter(it -> it.rect != null)
                .toList();

        expect.that(backgroundCommands.get(0).paint.getColor()).isEqualTo(Color.BLACK);
        expect.that(backgroundCommands.get(1).paint.getColor()).isEqualTo(Color.WHITE);
        expect.that(backgroundCommands.get(2).paint.getColor()).isEqualTo(Color.WHITE);
        expect.that(backgroundCommands.get(3).paint.getColor()).isEqualTo(Color.WHITE);
        expect.that(backgroundCommands.get(4).paint.getColor()).isEqualTo(Color.WHITE);
        expect.that(backgroundCommands.get(5).paint.getColor()).isEqualTo(Color.BLACK);
        expect.that(backgroundCommands.get(6).paint.getColor()).isEqualTo(Color.BLACK);
        expect.that(backgroundCommands.get(7).paint.getColor()).isEqualTo(Color.BLACK);
        expect.that(backgroundCommands.get(8).paint.getColor()).isEqualTo(Color.BLACK);
        expect.that(backgroundCommands.get(9).paint.getColor()).isEqualTo(Color.BLACK);
        expect.that(removeAlpha(backgroundCommands.get(0).paint.getColor()))
                .isEqualTo(Color.BLACK);
        expect.that(removeAlpha(backgroundCommands.get(1).paint.getColor()))
                .isEqualTo(Color.WHITE);
        expect.that(removeAlpha(backgroundCommands.get(2).paint.getColor()))
                .isEqualTo(Color.WHITE);
        expect.that(removeAlpha(backgroundCommands.get(3).paint.getColor()))
                .isEqualTo(Color.WHITE);
        expect.that(removeAlpha(backgroundCommands.get(4).paint.getColor()))
                .isEqualTo(Color.WHITE);
        expect.that(removeAlpha(backgroundCommands.get(5).paint.getColor()))
                .isEqualTo(Color.BLACK);
        expect.that(removeAlpha(backgroundCommands.get(6).paint.getColor()))
                .isEqualTo(Color.BLACK);
        expect.that(removeAlpha(backgroundCommands.get(7).paint.getColor()))
                .isEqualTo(Color.BLACK);
        expect.that(removeAlpha(backgroundCommands.get(8).paint.getColor()))
                .isEqualTo(Color.BLACK);
        expect.that(removeAlpha(backgroundCommands.get(9).paint.getColor()))
                .isEqualTo(Color.BLACK);

        expect.that(backgroundCommands.size()).isEqualTo(backgroundRectsDrawn);
    }

    private int removeAlpha(int color) {
        return Color.rgb(
                Color.red(color),
                Color.green(color),
                Color.blue(color)
        );
    }

    private static final class MockCanvas extends Canvas {

        static class DrawCommand {
@@ -1122,6 +1141,11 @@ public class LayoutTest {
            mDrawCommands.add(new DrawCommand(rect, p));
        }

        @Override
        public void drawRoundRect(@NonNull RectF rect, float rx, float ry, @NonNull Paint paint) {
            mDrawCommands.add(new DrawCommand(rect, paint));
        }

        List<DrawCommand> getDrawCommands() {
            return mDrawCommands;
        }