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

Commit 7a597bb5 authored by Lucas Dupin's avatar Lucas Dupin
Browse files

Add luma capabilities to ColorStateList

It's now possible to define an lStar attribute.
This attribute will modify the base color in a way that its chroma will
be conserved, but perceptive luminance will change.

Fixes: 183609373
Test: atest ColorStateListTest
Change-Id: I341a0a532bd9c030e8f52185bacda0db55486216
parent d99447b6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -866,6 +866,7 @@ package android {
    field public static final int keycode = 16842949; // 0x10100c5
    field public static final int killAfterRestore = 16843420; // 0x101029c
    field public static final int knownCerts = 16844330; // 0x101062a
    field public static final int lStar = 16844359; // 0x1010647
    field public static final int label = 16842753; // 0x1010001
    field public static final int labelFor = 16843718; // 0x10103c6
    field @Deprecated public static final int labelTextSize = 16843317; // 0x1010235
@@ -13158,6 +13159,7 @@ package android.content.res {
    method public boolean isStateful();
    method @NonNull public static android.content.res.ColorStateList valueOf(@ColorInt int);
    method @NonNull public android.content.res.ColorStateList withAlpha(int);
    method @NonNull public android.content.res.ColorStateList withLStar(float);
    method public void writeToParcel(android.os.Parcel, int);
    field @NonNull public static final android.os.Parcelable.Creator<android.content.res.ColorStateList> CREATOR;
  }
+50 −5
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.util.StateSet;
import android.util.Xml;

import com.android.internal.R;
import com.android.internal.graphics.ColorUtils;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.GrowingArrayUtils;

@@ -112,6 +113,18 @@ import java.util.Arrays;
 *         android:color="?android:attr/colorAccent"
 *         android:alpha="0.5" /&gt;
 * </pre>
 * <p>
 * Starting with API 31, items may optionally define an {@link android.R.attr#lStar android:lStar}
 * attribute to modify the base color's perceptual luminance. This attribute takes a either
 * floating-point value between 0 and 100 or a theme attribute that resolves as such. The item's
 * overall color is calculated by converting the base color to an accessibility friendly color space
 * and setting its L* to the value specified on the {@code lStar} attribute. For
 * example, the following item represents the theme's accent color at 50% perpectual luminosity:
 * <pre>
 * &lt;item android:state_enabled="false"
 *         android:color="?android:attr/colorAccent"
 *         android:lStar="50" /&gt;
 * </pre>
 *
 * <a name="DeveloperGuide"></a>
 * <h3>Developer guide</h3>
@@ -122,6 +135,7 @@ import java.util.Arrays;
 *
 * @attr ref android.R.styleable#ColorStateListItem_alpha
 * @attr ref android.R.styleable#ColorStateListItem_color
 * @attr ref android.R.styleable#ColorStateListItem_lStar
 */
public class ColorStateList extends ComplexColor implements Parcelable {
    private static final String TAG = "ColorStateList";
@@ -300,6 +314,24 @@ public class ColorStateList extends ComplexColor implements Parcelable {
        return new ColorStateList(mStateSpecs, colors);
    }

    /**
     * Creates a new ColorStateList that has the same states and colors as this
     * one but where each color has the specified perceived luminosity value (0-100).
     *
     * @param lStar Target perceptual luminance (0-100).
     * @return A new color state list.
     */
    @NonNull
    public ColorStateList withLStar(float lStar) {
        final int[] colors = new int[mColors.length];
        final int len = colors.length;
        for (int i = 0; i < len; i++) {
            colors[i] = modulateColor(mColors[i], 1.0f /* alphaMod */, lStar);
        }

        return new ColorStateList(mStateSpecs, colors);
    }

    /**
     * Fill in this object based on the contents of an XML "selector" element.
     */
@@ -332,6 +364,7 @@ public class ColorStateList extends ComplexColor implements Parcelable {
            final int[] themeAttrs = a.extractThemeAttrs();
            final int baseColor = a.getColor(R.styleable.ColorStateListItem_color, Color.MAGENTA);
            final float alphaMod = a.getFloat(R.styleable.ColorStateListItem_alpha, 1.0f);
            final float lStar = a.getFloat(R.styleable.ColorStateListItem_lStar, -1.0f);

            changingConfigurations |= a.getChangingConfigurations();

@@ -346,6 +379,7 @@ public class ColorStateList extends ComplexColor implements Parcelable {
                switch (stateResId) {
                    case R.attr.color:
                    case R.attr.alpha:
                    case R.attr.lStar:
                        // Recognized attribute, ignore.
                        break;
                    default:
@@ -355,10 +389,11 @@ public class ColorStateList extends ComplexColor implements Parcelable {
            }
            stateSpec = StateSet.trimStateSet(stateSpec, j);

            // Apply alpha modulation. If we couldn't resolve the color or
            // Apply alpha and luma modulation. If we couldn't resolve the color or
            // alpha yet, the default values leave us enough information to
            // modulate again during applyTheme().
            final int color = modulateColorAlpha(baseColor, alphaMod);
            final int color = modulateColor(baseColor, alphaMod, lStar);

            if (listSize == 0 || stateSpec.length == 0) {
                defaultColor = color;
            }
@@ -455,7 +490,9 @@ public class ColorStateList extends ComplexColor implements Parcelable {
                        R.styleable.ColorStateListItem_color, mColors[i]);
                final float alphaMod = a.getFloat(
                        R.styleable.ColorStateListItem_alpha, defaultAlphaMod);
                mColors[i] = modulateColorAlpha(baseColor, alphaMod);
                final float lStar = a.getFloat(
                        R.styleable.ColorStateListItem_lStar, -1.0f);
                mColors[i] = modulateColor(baseColor, alphaMod, lStar);

                // Account for any configuration changes.
                mChangingConfigurations |= a.getChangingConfigurations();
@@ -505,13 +542,21 @@ public class ColorStateList extends ComplexColor implements Parcelable {
        return super.getChangingConfigurations() | mChangingConfigurations;
    }

    private int modulateColorAlpha(int baseColor, float alphaMod) {
        if (alphaMod == 1.0f) {
    private int modulateColor(int baseColor, float alphaMod, float lStar) {
        final boolean validLStar = lStar >= 0.0f && lStar <= 100.0f;
        if (alphaMod == 1.0f && !validLStar) {
            return baseColor;
        }

        final int baseAlpha = Color.alpha(baseColor);
        final int alpha = MathUtils.constrain((int) (baseAlpha * alphaMod + 0.5f), 0, 255);

        if (validLStar) {
            final double[] labColor = new double[3];
            ColorUtils.colorToLAB(baseColor, labColor);
            baseColor = ColorUtils.LABToColor(lStar, labColor[1], labColor[2]);
        }

        return (baseColor & 0xFFFFFF) | (alpha << 24);
    }

+4 −0
Original line number Diff line number Diff line
@@ -6070,6 +6070,8 @@
        <attr name="color" />
        <!-- Alpha multiplier applied to the base color. -->
        <attr name="alpha" />
        <!-- Perceptual luminance applied to the base color. From 0 to 100. -->
        <attr name="lStar" format="float" />
    </declare-styleable>
    <!-- Drawable used to render according to the animation scale. Esp. when it is 0 due to battery
@@ -9535,4 +9537,6 @@
    <attr name="iconfactoryIconSize" format="dimension"/>
    <attr name="iconfactoryBadgeSize" format="dimension"/>
    <!-- Perceptual luminance of a color, in accessibility friendly color space. From 0 to 100. -->
    <attr name="lStar" format="float"/>
</resources>
+1 −0
Original line number Diff line number Diff line
@@ -3095,6 +3095,7 @@
    <public name="requestOptimizedExternalStorageAccess" />
    <!-- @hide @SystemApi -->
    <public name="playHomeTransitionSound" />
    <public name="lStar" />
  </public-group>

  <public-group type="drawable" first-id="0x010800b5">