From c5e3abae719154a0d3772c2dca8a1b333d3ffcc5 Mon Sep 17 00:00:00 2001 From: Andy Scherzinger Date: Sun, 22 Jun 2025 18:41:19 +0200 Subject: [PATCH] fix: Update material color implementation to 13th June 2025 Signed-off-by: Andy Scherzinger --- .../main/java/dynamiccolor/ColorSpec2025.java | 39 +++++++++++++++++-- .../main/java/dynamiccolor/DynamicScheme.java | 6 ++- .../src/main/java/palettes/TonalPalette.java | 19 ++++++++- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/material-color-utilities/src/main/java/dynamiccolor/ColorSpec2025.java b/material-color-utilities/src/main/java/dynamiccolor/ColorSpec2025.java index 328c32d5..52f048bb 100644 --- a/material-color-utilities/src/main/java/dynamiccolor/ColorSpec2025.java +++ b/material-color-utilities/src/main/java/dynamiccolor/ColorSpec2025.java @@ -1210,10 +1210,21 @@ public DynamicColor primaryFixed() { .setPalette((s) -> s.primaryPalette) .setTone( (s) -> { - DynamicScheme tempS = DynamicScheme.from(s, /* isDark= */ false); + DynamicScheme tempS = + DynamicScheme.from(s, /* isDark= */ false, /* contrastLevel= */ 0.0); return primaryContainer().getTone(tempS); }) .setIsBackground(true) + .setBackground( + (s) -> { + if (s.platform == PHONE) { + return s.isDark ? surfaceBright() : surfaceDim(); + } else { + return null; + } + }) + .setContrastCurve( + (s) -> s.platform == PHONE && s.contrastLevel > 0 ? getContrastCurve(1.5) : null) .build(); return super.primaryFixed().toBuilder() .extendSpecVersion(SpecVersion.SPEC_2025, color2025) @@ -1280,10 +1291,21 @@ public DynamicColor secondaryFixed() { .setPalette((s) -> s.secondaryPalette) .setTone( (s) -> { - DynamicScheme tempS = DynamicScheme.from(s, /* isDark= */ false); + DynamicScheme tempS = + DynamicScheme.from(s, /* isDark= */ false, /* contrastLevel= */ 0.0); return secondaryContainer().getTone(tempS); }) .setIsBackground(true) + .setBackground( + (s) -> { + if (s.platform == PHONE) { + return s.isDark ? surfaceBright() : surfaceDim(); + } else { + return null; + } + }) + .setContrastCurve( + (s) -> s.platform == PHONE && s.contrastLevel > 0 ? getContrastCurve(1.5) : null) .build(); return super.secondaryFixed().toBuilder() .extendSpecVersion(SpecVersion.SPEC_2025, color2025) @@ -1350,10 +1372,21 @@ public DynamicColor tertiaryFixed() { .setPalette((s) -> s.tertiaryPalette) .setTone( (s) -> { - DynamicScheme tempS = DynamicScheme.from(s, /* isDark= */ false); + DynamicScheme tempS = + DynamicScheme.from(s, /* isDark= */ false, /* contrastLevel= */ 0.0); return tertiaryContainer().getTone(tempS); }) .setIsBackground(true) + .setBackground( + (s) -> { + if (s.platform == PHONE) { + return s.isDark ? surfaceBright() : surfaceDim(); + } else { + return null; + } + }) + .setContrastCurve( + (s) -> s.platform == PHONE && s.contrastLevel > 0 ? getContrastCurve(1.5) : null) .build(); return super.tertiaryFixed().toBuilder() .extendSpecVersion(SpecVersion.SPEC_2025, color2025) diff --git a/material-color-utilities/src/main/java/dynamiccolor/DynamicScheme.java b/material-color-utilities/src/main/java/dynamiccolor/DynamicScheme.java index c683d1ea..db43e126 100644 --- a/material-color-utilities/src/main/java/dynamiccolor/DynamicScheme.java +++ b/material-color-utilities/src/main/java/dynamiccolor/DynamicScheme.java @@ -152,11 +152,15 @@ public DynamicScheme( } public static DynamicScheme from(DynamicScheme other, boolean isDark) { + return from(other, isDark, other.contrastLevel); + } + + public static DynamicScheme from(DynamicScheme other, boolean isDark, double contrastLevel) { return new DynamicScheme( other.sourceColorHct, other.variant, isDark, - other.contrastLevel, + contrastLevel, other.platform, other.specVersion, other.primaryPalette, diff --git a/material-color-utilities/src/main/java/palettes/TonalPalette.java b/material-color-utilities/src/main/java/palettes/TonalPalette.java index e4163c6b..804bc94b 100644 --- a/material-color-utilities/src/main/java/palettes/TonalPalette.java +++ b/material-color-utilities/src/main/java/palettes/TonalPalette.java @@ -79,7 +79,11 @@ private TonalPalette(double hue, double chroma, Hct keyColor) { public int tone(int tone) { Integer color = cache.get(tone); if (color == null) { - color = Hct.from(this.hue, this.chroma, tone).toInt(); + if (tone == 99 && Hct.isYellow(this.hue)) { + color = averageArgb(this.tone(98), this.tone(100)); + } else { + color = Hct.from(this.hue, this.chroma, tone).toInt(); + } cache.put(tone, color); } return color; @@ -105,6 +109,19 @@ public Hct getKeyColor() { return this.keyColor; } + private int averageArgb(int argb1, int argb2) { + int red1 = (argb1 >>> 16) & 0xff; + int green1 = (argb1 >>> 8) & 0xff; + int blue1 = argb1 & 0xff; + int red2 = (argb2 >>> 16) & 0xff; + int green2 = (argb2 >>> 8) & 0xff; + int blue2 = argb2 & 0xff; + int red = Math.round((red1 + red2) / 2f); + int green = Math.round((green1 + green2) / 2f); + int blue = Math.round((blue1 + blue2) / 2f); + return (255 << 24 | (red & 255) << 16 | (green & 255) << 8 | (blue & 255)) >>> 0; + } + /** Key color is a color that represents the hue and chroma of a tonal palette. */ private static final class KeyColor { private final double hue;