Updated background for on-fixed colors in ColorSpec2026. PiperOrigin-RevId: 879233955
diff --git a/java/dynamiccolor/ColorSpec2026.java b/java/dynamiccolor/ColorSpec2026.java index 94946a5..6b626b5 100644 --- a/java/dynamiccolor/ColorSpec2026.java +++ b/java/dynamiccolor/ColorSpec2026.java
@@ -458,12 +458,28 @@ .setIsBackground(true) .setBackground(s -> highestSurface(s)) .setContrastCurve(s -> getContrastCurve(4.5)) + .setToneDeltaPair( + s -> + s.platform == DynamicScheme.Platform.PHONE + ? new ToneDeltaPair( + primaryContainer(), primary(), 5, RELATIVE_LIGHTER, FARTHER) + : null) .build(); return super.primary().toBuilder().extendSpecVersion(SpecVersion.SPEC_2026, color2026).build(); } @NonNull @Override + public DynamicColor primaryDim() { + // Remapped to primary in 2026 spec. + DynamicColor color2026 = primary().toBuilder().setName("primary_dim").build(); + return super.primaryDim().toBuilder() + .extendSpecVersion(SpecVersion.SPEC_2026, color2026) + .build(); + } + + @NonNull + @Override public DynamicColor onPrimary() { DynamicColor color2026 = new DynamicColor.Builder() @@ -495,8 +511,6 @@ }) .setIsBackground(true) .setBackground(s -> highestSurface(s)) - .setToneDeltaPair( - s -> new ToneDeltaPair(primaryContainer(), primary(), 5, RELATIVE_LIGHTER, FARTHER)) .setContrastCurve(s -> s.contrastLevel > 0 ? getContrastCurve(1.5) : null) .build(); return super.primaryContainer().toBuilder() @@ -567,7 +581,7 @@ new DynamicColor.Builder() .setName("on_primary_fixed") .setPalette(s -> s.primaryPalette) - .setBackground(s -> primaryFixedDim()) + .setBackground(s -> primaryFixed().getTone(s) > 57 ? primaryFixedDim() : primaryFixed()) .setContrastCurve(s -> getContrastCurve(7)) .build(); return super.onPrimaryFixed().toBuilder() @@ -582,7 +596,7 @@ new DynamicColor.Builder() .setName("on_primary_fixed_variant") .setPalette(s -> s.primaryPalette) - .setBackground(s -> primaryFixedDim()) + .setBackground(s -> primaryFixed().getTone(s) > 57 ? primaryFixedDim() : primaryFixed()) .setContrastCurve(s -> getContrastCurve(4.5)) .build(); return super.onPrimaryFixedVariant().toBuilder() @@ -601,6 +615,12 @@ .setIsBackground(true) .setBackground(s -> highestSurface(s)) .setContrastCurve(s -> getContrastCurve(4.5)) + .setToneDeltaPair( + s -> + s.platform == DynamicScheme.Platform.PHONE + ? new ToneDeltaPair( + secondaryContainer(), secondary(), 5, RELATIVE_LIGHTER, FARTHER) + : null) .build(); return super.secondary().toBuilder() .extendSpecVersion(SpecVersion.SPEC_2026, color2026) @@ -609,6 +629,16 @@ @NonNull @Override + public DynamicColor secondaryDim() { + // Remapped to secondary in 2025 spec. + DynamicColor color2026 = secondary().toBuilder().setName("secondary_dim").build(); + return super.secondaryDim().toBuilder() + .extendSpecVersion(SpecVersion.SPEC_2026, color2026) + .build(); + } + + @NonNull + @Override public DynamicColor onSecondary() { DynamicColor color2026 = new DynamicColor.Builder() @@ -636,10 +666,6 @@ : tMaxC(s.secondaryPalette, 61, 90)) .setIsBackground(true) .setBackground(s -> highestSurface(s)) - .setToneDeltaPair( - s -> - new ToneDeltaPair( - secondaryContainer(), secondary(), 5, RELATIVE_LIGHTER, FARTHER)) .setContrastCurve(s -> s.contrastLevel > 0 ? getContrastCurve(1.5) : null) .build(); return super.secondaryContainer().toBuilder() @@ -710,7 +736,8 @@ new DynamicColor.Builder() .setName("on_secondary_fixed") .setPalette(s -> s.secondaryPalette) - .setBackground(s -> secondaryFixedDim()) + .setBackground( + s -> secondaryFixed().getTone(s) > 57 ? secondaryFixedDim() : secondaryFixed()) .setContrastCurve(s -> getContrastCurve(7)) .build(); return super.onSecondaryFixed().toBuilder() @@ -725,7 +752,8 @@ new DynamicColor.Builder() .setName("on_secondary_fixed_variant") .setPalette(s -> s.secondaryPalette) - .setBackground(s -> secondaryFixedDim()) + .setBackground( + s -> secondaryFixed().getTone(s) > 57 ? secondaryFixedDim() : secondaryFixed()) .setContrastCurve(s -> getContrastCurve(4.5)) .build(); return super.onSecondaryFixedVariant().toBuilder() @@ -748,10 +776,25 @@ .setIsBackground(true) .setBackground(s -> highestSurface(s)) .setContrastCurve(s -> getContrastCurve(4.5)) + .setToneDeltaPair( + s -> + s.platform == DynamicScheme.Platform.PHONE + ? new ToneDeltaPair( + tertiaryContainer(), tertiary(), 5, RELATIVE_LIGHTER, FARTHER) + : null) .build(); return super.tertiary().toBuilder().extendSpecVersion(SpecVersion.SPEC_2026, color2026).build(); } + @Override + public DynamicColor tertiaryDim() { + // Remapped to tertiary in 2025 spec. + DynamicColor color2026 = tertiary().toBuilder().setName("tertiary_dim").build(); + return super.tertiaryDim().toBuilder() + .extendSpecVersion(SpecVersion.SPEC_2026, color2026) + .build(); + } + @NonNull @Override public DynamicColor onTertiary() { @@ -786,10 +829,6 @@ }) .setIsBackground(true) .setBackground(s -> highestSurface(s)) - .setToneDeltaPair( - s -> - new ToneDeltaPair( - tertiaryContainer(), tertiary(), 5, RELATIVE_LIGHTER, FARTHER)) .setContrastCurve(s -> s.contrastLevel > 0 ? getContrastCurve(1.5) : null) .build(); return super.tertiaryContainer().toBuilder() @@ -860,7 +899,8 @@ new DynamicColor.Builder() .setName("on_tertiary_fixed") .setPalette(s -> s.tertiaryPalette) - .setBackground(s -> tertiaryFixedDim()) + .setBackground( + s -> tertiaryFixed().getTone(s) > 57 ? tertiaryFixedDim() : tertiaryFixed()) .setContrastCurve(s -> getContrastCurve(7)) .build(); return super.onTertiaryFixed().toBuilder() @@ -875,7 +915,8 @@ new DynamicColor.Builder() .setName("on_tertiary_fixed_variant") .setPalette(s -> s.tertiaryPalette) - .setBackground(s -> tertiaryFixedDim()) + .setBackground( + s -> tertiaryFixed().getTone(s) > 57 ? tertiaryFixedDim() : tertiaryFixed()) .setContrastCurve(s -> getContrastCurve(4.5)) .build(); return super.onTertiaryFixedVariant().toBuilder() @@ -894,12 +935,25 @@ .setIsBackground(true) .setBackground(s -> highestSurface(s)) .setContrastCurve(s -> getContrastCurve(4.5)) + .setToneDeltaPair( + s -> + s.platform == DynamicScheme.Platform.PHONE + ? new ToneDeltaPair(errorContainer(), error(), 5, RELATIVE_LIGHTER, FARTHER) + : null) .build(); return super.error().toBuilder().extendSpecVersion(SpecVersion.SPEC_2026, color2026).build(); } @NonNull @Override + public DynamicColor errorDim() { + // Remapped to error in 2026 spec. + DynamicColor color2026 = error().toBuilder().setName("error_dim").build(); + return super.errorDim().toBuilder().extendSpecVersion(SpecVersion.SPEC_2026, color2026).build(); + } + + @NonNull + @Override public DynamicColor onError() { DynamicColor color2026 = new DynamicColor.Builder() @@ -921,8 +975,6 @@ .setTone(s -> s.isDark ? tMinC(s.errorPalette) : tMaxC(s.errorPalette)) .setIsBackground(true) .setBackground(s -> highestSurface(s)) - .setToneDeltaPair( - s -> new ToneDeltaPair(errorContainer(), error(), 5, RELATIVE_LIGHTER, FARTHER)) .setContrastCurve(s -> s.contrastLevel > 0 ? getContrastCurve(1.5) : null) .build(); return super.errorContainer().toBuilder()
diff --git a/java/scheme/SchemeCmf.java b/java/scheme/SchemeCmf.java index 1522d73..45f0b10 100644 --- a/java/scheme/SchemeCmf.java +++ b/java/scheme/SchemeCmf.java
@@ -69,7 +69,10 @@ sourceColorHctList.get(0).getHue(), sourceColorHctList.get(0).getChroma() * 0.2), Optional.of( TonalPalette.fromHueAndChroma( - 23.0, Math.max(sourceColorHctList.get(0).getChroma(), 50.0)))); + getErrorHue( + sourceColorHctList.get(0).getHue(), + tertiaryPalette(sourceColorHctList).getHue()), + Math.max(sourceColorHctList.get(0).getChroma(), 50.0)))); if (specVersion != SpecVersion.SPEC_2026) { throw new IllegalArgumentException("SchemeCmf can only be used with spec version 2026."); } @@ -87,4 +90,26 @@ secondarySourceColorHct.getHue(), secondarySourceColorHct.getChroma()); } } + + private static double getErrorHue(double primaryHue, double tertiaryHue) { + if (primaryHue <= 8) { + return tertiaryHue <= 24 ? 28 : (tertiaryHue <= 32 ? 16 : 20); + } else if (primaryHue <= 16) { + return tertiaryHue <= 24 ? 32 : (tertiaryHue <= 32 ? 20 : 24); + } else if (primaryHue <= 20) { + return tertiaryHue <= 28 ? 32 : (tertiaryHue <= 32 ? 24 : 28); + } else if (primaryHue <= 28) { + return tertiaryHue <= 24 ? 32 : 16; + } else if (primaryHue <= 32) { + return tertiaryHue <= 20 ? 24 : (tertiaryHue <= 28 ? 16 : 20); + } else if (primaryHue <= 40) { + return (tertiaryHue > 20 && tertiaryHue <= 28) ? 16 : 24; + } else if (primaryHue <= 152) { + return (tertiaryHue > 24 && tertiaryHue <= 36) ? 20 : 32; + } else if (primaryHue <= 272) { + return (tertiaryHue > 20 && tertiaryHue <= 28) ? 16 : 24; + } else { + return (tertiaryHue > 12 && tertiaryHue <= 28) ? 32 : 16; + } + } }
diff --git a/kotlin/dynamiccolor/ColorSpec2025.kt b/kotlin/dynamiccolor/ColorSpec2025.kt index 9e721c5..7837a75 100644 --- a/kotlin/dynamiccolor/ColorSpec2025.kt +++ b/kotlin/dynamiccolor/ColorSpec2025.kt
@@ -826,7 +826,7 @@ return super.secondary.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2025, color2025) } - override val secondaryDim: DynamicColor? + override val secondaryDim: DynamicColor get() { return DynamicColor( name = "secondary_dim", @@ -843,7 +843,7 @@ contrastCurve = { getContrastCurve(4.5) }, toneDeltaPair = { ToneDeltaPair( - roleA = secondaryDim!!, + roleA = secondaryDim, roleB = secondary, delta = 5.0, polarity = TonePolarity.DARKER, @@ -1005,7 +1005,7 @@ return super.tertiary.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2025, color2025) } - override val tertiaryDim: DynamicColor? + override val tertiaryDim: DynamicColor get() { return DynamicColor( name = "tertiary_dim", @@ -1022,7 +1022,7 @@ contrastCurve = { getContrastCurve(4.5) }, toneDeltaPair = { ToneDeltaPair( - roleA = tertiaryDim!!, + roleA = tertiaryDim, roleB = tertiary, delta = 5.0, polarity = TonePolarity.DARKER, @@ -1186,7 +1186,7 @@ return super.error.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2025, color2025) } - override val errorDim: DynamicColor? + override val errorDim: DynamicColor get() { return DynamicColor( name = "error_dim", @@ -1197,7 +1197,7 @@ contrastCurve = { getContrastCurve(4.5) }, toneDeltaPair = { ToneDeltaPair( - roleA = errorDim!!, + roleA = errorDim, roleB = error, delta = 5.0, polarity = TonePolarity.DARKER,
diff --git a/kotlin/dynamiccolor/ColorSpec2026.kt b/kotlin/dynamiccolor/ColorSpec2026.kt index f607ee4..0c54b2f 100644 --- a/kotlin/dynamiccolor/ColorSpec2026.kt +++ b/kotlin/dynamiccolor/ColorSpec2026.kt
@@ -284,10 +284,30 @@ isBackground = true, background = { highestSurface(it) }, contrastCurve = { getContrastCurve(4.5) }, + toneDeltaPair = { + if (it.platform == DynamicScheme.Platform.PHONE) { + ToneDeltaPair( + primaryContainer, + primary, + 5.0, + ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, + constraint = ToneDeltaPair.DeltaConstraint.FARTHER, + ) + } else { + null + } + }, ) return super.primary.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) } + override val primaryDim: DynamicColor + get() { + // Remapped to primary in 2026 spec. + val color2026 = primary.copy(name = "primary_dim") + return super.primaryDim.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) + } + override val onPrimary: DynamicColor get() { val color2026 = @@ -317,15 +337,6 @@ }, isBackground = true, background = { highestSurface(it) }, - toneDeltaPair = { - ToneDeltaPair( - primaryContainer, - primary, - 5.0, - ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, - constraint = ToneDeltaPair.DeltaConstraint.FARTHER, - ) - }, contrastCurve = { if (it.contrastLevel > 0) getContrastCurve(1.5) else null }, ) return super.primaryContainer.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) @@ -389,7 +400,7 @@ DynamicColor( name = "on_primary_fixed", palette = { it.primaryPalette }, - background = { primaryFixedDim }, + background = { if (primaryFixed.getTone(it) > 57) primaryFixedDim else primaryFixed }, contrastCurve = { getContrastCurve(7.0) }, ) return super.onPrimaryFixed.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) @@ -401,7 +412,7 @@ DynamicColor( name = "on_primary_fixed_variant", palette = { it.primaryPalette }, - background = { primaryFixedDim }, + background = { if (primaryFixed.getTone(it) > 57) primaryFixedDim else primaryFixed }, contrastCurve = { getContrastCurve(4.5) }, ) return super.onPrimaryFixedVariant.extendSpecVersion( @@ -420,10 +431,30 @@ isBackground = true, background = { highestSurface(it) }, contrastCurve = { getContrastCurve(4.5) }, + toneDeltaPair = { + if (it.platform == DynamicScheme.Platform.PHONE) { + ToneDeltaPair( + secondaryContainer, + secondary, + 5.0, + ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, + constraint = ToneDeltaPair.DeltaConstraint.FARTHER, + ) + } else { + null + } + }, ) return super.secondary.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) } + override val secondaryDim: DynamicColor + get() { + // Remapped to secondary in 2026 spec. + val color2026 = secondary.copy(name = "secondary_dim") + return super.secondaryDim.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) + } + override val onSecondary: DynamicColor get() { val color2026 = @@ -451,15 +482,6 @@ }, isBackground = true, background = { highestSurface(it) }, - toneDeltaPair = { - ToneDeltaPair( - secondaryContainer, - secondary, - 5.0, - ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, - constraint = ToneDeltaPair.DeltaConstraint.FARTHER, - ) - }, contrastCurve = { if (it.contrastLevel > 0) getContrastCurve(1.5) else null }, ) return super.secondaryContainer.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) @@ -526,7 +548,9 @@ DynamicColor( name = "on_secondary_fixed", palette = { it.secondaryPalette }, - background = { secondaryFixedDim }, + background = { + if (secondaryFixed.getTone(it) > 57) secondaryFixedDim else secondaryFixed + }, contrastCurve = { getContrastCurve(7.0) }, ) return super.onSecondaryFixed.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) @@ -538,7 +562,9 @@ DynamicColor( name = "on_secondary_fixed_variant", palette = { it.secondaryPalette }, - background = { secondaryFixedDim }, + background = { + if (secondaryFixed.getTone(it) > 57) secondaryFixedDim else secondaryFixed + }, contrastCurve = { getContrastCurve(4.5) }, ) return super.onSecondaryFixedVariant.extendSpecVersion( @@ -557,10 +583,30 @@ isBackground = true, background = { highestSurface(it) }, contrastCurve = { getContrastCurve(4.5) }, + toneDeltaPair = { + if (it.platform == DynamicScheme.Platform.PHONE) { + ToneDeltaPair( + tertiaryContainer, + tertiary, + 5.0, + ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, + constraint = ToneDeltaPair.DeltaConstraint.FARTHER, + ) + } else { + null + } + }, ) return super.tertiary.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) } + override val tertiaryDim: DynamicColor + get() { + // Remapped to tertiary in 2026 spec. + val color2026 = tertiary.copy(name = "tertiary_dim") + return super.tertiaryDim.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) + } + override val onTertiary: DynamicColor get() { val color2026 = @@ -589,15 +635,6 @@ }, isBackground = true, background = { highestSurface(it) }, - toneDeltaPair = { - ToneDeltaPair( - tertiaryContainer, - tertiary, - 5.0, - ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, - constraint = ToneDeltaPair.DeltaConstraint.FARTHER, - ) - }, contrastCurve = { if (it.contrastLevel > 0) getContrastCurve(1.5) else null }, ) return super.tertiaryContainer.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) @@ -661,7 +698,7 @@ DynamicColor( name = "on_tertiary_fixed", palette = { it.tertiaryPalette }, - background = { tertiaryFixedDim }, + background = { if (tertiaryFixed.getTone(it) > 57) tertiaryFixedDim else tertiaryFixed }, contrastCurve = { getContrastCurve(7.0) }, ) return super.onTertiaryFixed.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) @@ -673,7 +710,7 @@ DynamicColor( name = "on_tertiary_fixed_variant", palette = { it.tertiaryPalette }, - background = { tertiaryFixedDim }, + background = { if (tertiaryFixed.getTone(it) > 57) tertiaryFixedDim else tertiaryFixed }, contrastCurve = { getContrastCurve(4.5) }, ) return super.onTertiaryFixedVariant.extendSpecVersion( @@ -692,10 +729,30 @@ isBackground = true, background = { highestSurface(it) }, contrastCurve = { getContrastCurve(4.5) }, + toneDeltaPair = { + if (it.platform == DynamicScheme.Platform.PHONE) { + ToneDeltaPair( + errorContainer, + error, + 5.0, + ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, + constraint = ToneDeltaPair.DeltaConstraint.FARTHER, + ) + } else { + null + } + }, ) return super.error.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) } + override val errorDim: DynamicColor + get() { + // Remapped to error in 2026 spec. + val color2026 = error.copy(name = "error_dim") + return super.errorDim.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026) + } + override val onError: DynamicColor get() { val color2026 = @@ -717,15 +774,6 @@ tone = { if (it.isDark) tMinC(it.errorPalette) else tMaxC(it.errorPalette) }, isBackground = true, background = { highestSurface(it) }, - toneDeltaPair = { - ToneDeltaPair( - errorContainer, - error, - 5.0, - ToneDeltaPair.TonePolarity.RELATIVE_LIGHTER, - constraint = ToneDeltaPair.DeltaConstraint.FARTHER, - ) - }, contrastCurve = { if (it.contrastLevel > 0) getContrastCurve(1.5) else null }, ) return super.errorContainer.extendSpecVersion(ColorSpec.SpecVersion.SPEC_2026, color2026)
diff --git a/kotlin/scheme/SchemeCmf.kt b/kotlin/scheme/SchemeCmf.kt index 64a79bf..d5ba901 100644 --- a/kotlin/scheme/SchemeCmf.kt +++ b/kotlin/scheme/SchemeCmf.kt
@@ -58,7 +58,10 @@ sourceColorHctList.first().chroma * 0.2, ), errorPalette = - TonalPalette.fromHueAndChroma(23.0, sourceColorHctList.first().chroma.coerceAtLeast(50.0)), + TonalPalette.fromHueAndChroma( + getErrorHue(sourceColorHctList.first().hue, tertiaryPalette(sourceColorHctList).hue), + sourceColorHctList.first().chroma.coerceAtLeast(50.0), + ), ) { init { require(specVersion == ColorSpec.SpecVersion.SPEC_2026) { @@ -75,6 +78,28 @@ ) : this(listOf(sourceColorHct), isDark, contrastLevel, specVersion, platform) } +private fun getErrorHue(primaryHue: Double, tertiaryHue: Double): Double { + if (primaryHue <= 8) { + return if (tertiaryHue <= 24) 28.0 else if (tertiaryHue <= 32) 16.0 else 20.0 + } else if (primaryHue <= 16) { + return if (tertiaryHue <= 24) 32.0 else if (tertiaryHue <= 32) 20.0 else 24.0 + } else if (primaryHue <= 20) { + return if (tertiaryHue <= 28) 32.0 else if (tertiaryHue <= 32) 24.0 else 28.0 + } else if (primaryHue <= 28) { + return if (tertiaryHue <= 24) 32.0 else 16.0 + } else if (primaryHue <= 32) { + return if (tertiaryHue <= 20) 24.0 else if (tertiaryHue <= 28) 16.0 else 20.0 + } else if (primaryHue <= 40) { + return if (tertiaryHue > 20 && tertiaryHue <= 28) 16.0 else 24.0 + } else if (primaryHue <= 152) { + return if (tertiaryHue > 24 && tertiaryHue <= 36) 20.0 else 32.0 + } else if (primaryHue <= 272) { + return if (tertiaryHue > 20 && tertiaryHue <= 28) 16.0 else 24.0 + } else { + return if (tertiaryHue > 12 && tertiaryHue <= 28) 32.0 else 16.0 + } +} + private fun tertiaryPalette(sourceColorHctList: List<Hct>): TonalPalette { val sourceColorHct = sourceColorHctList.first() val secondarySourceColorHct = sourceColorHctList.getOrNull(1) ?: sourceColorHct
diff --git a/typescript/dynamiccolor/color_spec_2026.ts b/typescript/dynamiccolor/color_spec_2026.ts index 50eb845..874a431 100644 --- a/typescript/dynamiccolor/color_spec_2026.ts +++ b/typescript/dynamiccolor/color_spec_2026.ts
@@ -393,14 +393,15 @@ isBackground: true, background: (s) => this.highestSurface(s), contrastCurve: (s) => getCurve(4.5), + toneDeltaPair: (s) => s.platform === 'phone' ? + new ToneDeltaPair( + this.primaryContainer(), this.primary(), 5, 'relative_lighter', + true, 'farther') : + undefined, }); return extendSpecVersion(super.primary(), '2026', color2026); } - override primaryDim(): DynamicColor { - return super.primaryDim(); - } - override onPrimary(): DynamicColor { const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_primary', @@ -425,9 +426,6 @@ }, isBackground: true, background: (s) => this.highestSurface(s), - toneDeltaPair: (s) => new ToneDeltaPair( - this.primaryContainer(), this.primary(), 5, 'relative_lighter', true, - 'farther'), contrastCurve: (s) => s.contrastLevel > 0 ? getCurve(1.5) : undefined, }); return extendSpecVersion(super.primaryContainer(), '2026', color2026); @@ -477,7 +475,9 @@ const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_primary_fixed', palette: (s) => s.primaryPalette, - background: (s) => this.primaryFixedDim(), + background: (s) => this.primaryFixed().getTone(s) > 57 ? + this.primaryFixedDim() : + this.primaryFixed(), contrastCurve: (s) => getCurve(7), }); return extendSpecVersion(super.onPrimaryFixed(), '2026', color2026); @@ -487,7 +487,9 @@ const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_primary_fixed_variant', palette: (s) => s.primaryPalette, - background: (s) => this.primaryFixedDim(), + background: (s) => this.primaryFixed().getTone(s) > 57 ? + this.primaryFixedDim() : + this.primaryFixed(), contrastCurve: (s) => getCurve(4.5), }); return extendSpecVersion(super.onPrimaryFixedVariant(), '2026', color2026); @@ -507,14 +509,15 @@ isBackground: true, background: (s) => this.highestSurface(s), contrastCurve: (s) => getCurve(4.5), + toneDeltaPair: (s) => s.platform === 'phone' ? + new ToneDeltaPair( + this.secondaryContainer(), this.secondary(), 5, + 'relative_lighter', true, 'farther') : + undefined, }); return extendSpecVersion(super.secondary(), '2026', color2026); } - override secondaryDim(): DynamicColor { - return super.secondaryDim(); - } - override onSecondary(): DynamicColor { const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_secondary', @@ -535,9 +538,6 @@ }, isBackground: true, background: (s) => this.highestSurface(s), - toneDeltaPair: (s) => new ToneDeltaPair( - this.secondaryContainer(), this.secondary(), 5, 'relative_lighter', - true, 'farther'), contrastCurve: (s) => s.contrastLevel > 0 ? getCurve(1.5) : undefined, }); return extendSpecVersion(super.secondaryContainer(), '2026', color2026); @@ -587,7 +587,9 @@ const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_secondary_fixed', palette: (s) => s.secondaryPalette, - background: (s) => this.secondaryFixedDim(), + background: (s) => this.secondaryFixed().getTone(s) > 57 ? + this.secondaryFixedDim() : + this.secondaryFixed(), contrastCurve: (s) => getCurve(7), }); return extendSpecVersion(super.onSecondaryFixed(), '2026', color2026); @@ -597,7 +599,9 @@ const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_secondary_fixed_variant', palette: (s) => s.secondaryPalette, - background: (s) => this.secondaryFixedDim(), + background: (s) => this.secondaryFixed().getTone(s) > 57 ? + this.secondaryFixedDim() : + this.secondaryFixed(), contrastCurve: (s) => getCurve(4.5), }); return extendSpecVersion( @@ -614,14 +618,15 @@ isBackground: true, background: (s) => this.highestSurface(s), contrastCurve: (s) => getCurve(4.5), + toneDeltaPair: (s) => s.platform === 'phone' ? + new ToneDeltaPair( + this.tertiaryContainer(), this.tertiary(), 5, 'relative_lighter', + true, 'farther') : + undefined, }); return extendSpecVersion(super.tertiary(), '2026', color2026); } - override tertiaryDim(): DynamicColor { - return super.tertiaryDim(); - } - override onTertiary(): DynamicColor { const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_tertiary', @@ -645,9 +650,6 @@ }, isBackground: true, background: (s) => this.highestSurface(s), - toneDeltaPair: (s) => new ToneDeltaPair( - this.tertiaryContainer(), this.tertiary(), 5, 'relative_lighter', - true, 'farther'), contrastCurve: (s) => s.contrastLevel > 0 ? getCurve(1.5) : undefined, }); return extendSpecVersion(super.tertiaryContainer(), '2026', color2026); @@ -697,7 +699,9 @@ const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_tertiary_fixed', palette: (s) => s.tertiaryPalette, - background: (s) => this.tertiaryFixedDim(), + background: (s) => this.tertiaryFixed().getTone(s) > 57 ? + this.tertiaryFixedDim() : + this.tertiaryFixed(), contrastCurve: (s) => getCurve(7), }); return extendSpecVersion(super.onTertiaryFixed(), '2026', color2026); @@ -707,7 +711,9 @@ const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_tertiary_fixed_variant', palette: (s) => s.tertiaryPalette, - background: (s) => this.tertiaryFixedDim(), + background: (s) => this.tertiaryFixed().getTone(s) > 57 ? + this.tertiaryFixedDim() : + this.tertiaryFixed(), contrastCurve: (s) => getCurve(4.5), }); return extendSpecVersion(super.onTertiaryFixedVariant(), '2026', color2026); @@ -723,14 +729,15 @@ isBackground: true, background: (s) => this.highestSurface(s), contrastCurve: (s) => getCurve(4.5), + toneDeltaPair: (s) => s.platform === 'phone' ? + new ToneDeltaPair( + this.errorContainer(), this.error(), 5, 'relative_lighter', true, + 'farther') : + undefined, }); return extendSpecVersion(super.error(), '2026', color2026); } - override errorDim(): DynamicColor { - return super.errorDim(); - } - override onError(): DynamicColor { const color2026: DynamicColor = DynamicColor.fromPalette({ name: 'on_error', @@ -750,9 +757,6 @@ }, isBackground: true, background: (s) => this.highestSurface(s), - toneDeltaPair: (s) => new ToneDeltaPair( - this.errorContainer(), this.error(), 5, 'relative_lighter', true, - 'farther'), contrastCurve: (s) => s.contrastLevel > 0 ? getCurve(1.5) : undefined, }); return extendSpecVersion(super.errorContainer(), '2026', color2026); @@ -767,4 +771,36 @@ }); return extendSpecVersion(super.onErrorContainer(), '2026', color2026); } + + ///////////////////////////////////////////////////////////////// + // Remapped Colors // + ///////////////////////////////////////////////////////////////// + + override primaryDim(): DynamicColor { + const color2026: DynamicColor = Object.assign(this.primary().clone(), { + name: 'primary_dim', + }); + return extendSpecVersion(super.primaryDim(), '2026', color2026); + } + + override secondaryDim(): DynamicColor { + const color2026: DynamicColor = Object.assign(this.secondary().clone(), { + name: 'secondary_dim', + }); + return extendSpecVersion(super.secondaryDim(), '2026', color2026); + } + + override tertiaryDim(): DynamicColor { + const color2026: DynamicColor = Object.assign(this.tertiary().clone(), { + name: 'tertiary_dim', + }); + return extendSpecVersion(super.tertiaryDim(), '2026', color2026); + } + + override errorDim(): DynamicColor { + const color2026: DynamicColor = Object.assign(this.error().clone(), { + name: 'error_dim', + }); + return extendSpecVersion(super.errorDim(), '2026', color2026); + } } \ No newline at end of file
diff --git a/typescript/scheme/scheme_cmf.ts b/typescript/scheme/scheme_cmf.ts index ee95581..10b5ef3 100644 --- a/typescript/scheme/scheme_cmf.ts +++ b/typescript/scheme/scheme_cmf.ts
@@ -59,7 +59,8 @@ const neutralVariantPalette = TonalPalette.fromHueAndChroma( sourceColorHct.hue, sourceColorHct.chroma * 0.2); const errorPalette = TonalPalette.fromHueAndChroma( - 23.0, Math.max(sourceColorHct.chroma, 50.0)); + SchemeCmf.getErrorHue(sourceColorHct.hue, secondarySourceColorHct.hue), + Math.max(sourceColorHct.chroma, 50.0)); super({ sourceColorHcts: isArray ? sourceColorOrList : [sourceColorOrList], variant: Variant.CMF, @@ -75,4 +76,26 @@ errorPalette, }); } + + static getErrorHue(primaryHue: number, tertiaryHue: number): number { + if (primaryHue <= 8) { + return tertiaryHue <= 24 ? 28 : (tertiaryHue <= 32 ? 16 : 20); + } else if (primaryHue <= 16) { + return tertiaryHue <= 24 ? 32 : (tertiaryHue <= 32 ? 20 : 24); + } else if (primaryHue <= 20) { + return tertiaryHue <= 28 ? 32 : (tertiaryHue <= 32 ? 24 : 28); + } else if (primaryHue <= 28) { + return tertiaryHue <= 24 ? 32 : 16; + } else if (primaryHue <= 32) { + return tertiaryHue <= 20 ? 24 : (tertiaryHue <= 28 ? 16 : 20); + } else if (primaryHue <= 40) { + return (tertiaryHue > 20 && tertiaryHue <= 28) ? 16 : 24; + } else if (primaryHue <= 152) { + return (tertiaryHue > 24 && tertiaryHue <= 36) ? 20 : 32; + } else if (primaryHue <= 272) { + return (tertiaryHue > 20 && tertiaryHue <= 28) ? 16 : 24; + } else { + return (tertiaryHue > 12 && tertiaryHue <= 28) ? 32 : 16; + } + } } \ No newline at end of file