1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.google.ux.material.libmonet.dynamiccolor; 18 19 import com.google.ux.material.libmonet.hct.Hct; 20 import com.google.ux.material.libmonet.palettes.TonalPalette; 21 import com.google.ux.material.libmonet.utils.MathUtils; 22 import java.util.Optional; 23 24 /** 25 * Provides important settings for creating colors dynamically, and 6 color palettes. Requires: 1. A 26 * color. (source color) 2. A theme. (Variant) 3. Whether or not its dark mode. 4. Contrast level. 27 * (-1 to 1, currently contrast ratio 3.0 and 7.0) 28 */ 29 public class DynamicScheme { 30 public final int sourceColorArgb; 31 public final Hct sourceColorHct; 32 public final Variant variant; 33 public final boolean isDark; 34 public final double contrastLevel; 35 36 public final TonalPalette primaryPalette; 37 public final TonalPalette secondaryPalette; 38 public final TonalPalette tertiaryPalette; 39 public final TonalPalette neutralPalette; 40 public final TonalPalette neutralVariantPalette; 41 public final TonalPalette errorPalette; 42 DynamicScheme( Hct sourceColorHct, Variant variant, boolean isDark, double contrastLevel, TonalPalette primaryPalette, TonalPalette secondaryPalette, TonalPalette tertiaryPalette, TonalPalette neutralPalette, TonalPalette neutralVariantPalette)43 public DynamicScheme( 44 Hct sourceColorHct, 45 Variant variant, 46 boolean isDark, 47 double contrastLevel, 48 TonalPalette primaryPalette, 49 TonalPalette secondaryPalette, 50 TonalPalette tertiaryPalette, 51 TonalPalette neutralPalette, 52 TonalPalette neutralVariantPalette) { 53 this( 54 sourceColorHct, 55 variant, 56 isDark, 57 contrastLevel, 58 primaryPalette, 59 secondaryPalette, 60 tertiaryPalette, 61 neutralPalette, 62 neutralVariantPalette, 63 Optional.empty()); 64 } 65 DynamicScheme( Hct sourceColorHct, Variant variant, boolean isDark, double contrastLevel, TonalPalette primaryPalette, TonalPalette secondaryPalette, TonalPalette tertiaryPalette, TonalPalette neutralPalette, TonalPalette neutralVariantPalette, Optional<TonalPalette> errorPalette)66 public DynamicScheme( 67 Hct sourceColorHct, 68 Variant variant, 69 boolean isDark, 70 double contrastLevel, 71 TonalPalette primaryPalette, 72 TonalPalette secondaryPalette, 73 TonalPalette tertiaryPalette, 74 TonalPalette neutralPalette, 75 TonalPalette neutralVariantPalette, 76 Optional<TonalPalette> errorPalette) { 77 this.sourceColorArgb = sourceColorHct.toInt(); 78 this.sourceColorHct = sourceColorHct; 79 this.variant = variant; 80 this.isDark = isDark; 81 this.contrastLevel = contrastLevel; 82 83 this.primaryPalette = primaryPalette; 84 this.secondaryPalette = secondaryPalette; 85 this.tertiaryPalette = tertiaryPalette; 86 this.neutralPalette = neutralPalette; 87 this.neutralVariantPalette = neutralVariantPalette; 88 this.errorPalette = errorPalette.orElse(TonalPalette.fromHueAndChroma(25.0, 84.0)); 89 } 90 91 /** 92 * Given a set of hues and set of hue rotations, locate which hues the source color's hue is 93 * between, apply the rotation at the same index as the first hue in the range, and return the 94 * rotated hue. 95 * 96 * @param sourceColorHct The color whose hue should be rotated. 97 * @param hues A set of hues. 98 * @param rotations A set of hue rotations. 99 * @return Color's hue with a rotation applied. 100 */ getRotatedHue(Hct sourceColorHct, double[] hues, double[] rotations)101 public static double getRotatedHue(Hct sourceColorHct, double[] hues, double[] rotations) { 102 final double sourceHue = sourceColorHct.getHue(); 103 if (rotations.length == 1) { 104 return MathUtils.sanitizeDegreesDouble(sourceHue + rotations[0]); 105 } 106 final int size = hues.length; 107 for (int i = 0; i <= (size - 2); i++) { 108 final double thisHue = hues[i]; 109 final double nextHue = hues[i + 1]; 110 if (thisHue < sourceHue && sourceHue < nextHue) { 111 return MathUtils.sanitizeDegreesDouble(sourceHue + rotations[i]); 112 } 113 } 114 // If this statement executes, something is wrong, there should have been a rotation 115 // found using the arrays. 116 return sourceHue; 117 } 118 getHct(DynamicColor dynamicColor)119 public Hct getHct(DynamicColor dynamicColor) { 120 return dynamicColor.getHct(this); 121 } 122 getArgb(DynamicColor dynamicColor)123 public int getArgb(DynamicColor dynamicColor) { 124 return dynamicColor.getArgb(this); 125 } 126 getPrimaryPaletteKeyColor()127 public int getPrimaryPaletteKeyColor() { 128 return getArgb(new MaterialDynamicColors().primaryPaletteKeyColor()); 129 } 130 getSecondaryPaletteKeyColor()131 public int getSecondaryPaletteKeyColor() { 132 return getArgb(new MaterialDynamicColors().secondaryPaletteKeyColor()); 133 } 134 getTertiaryPaletteKeyColor()135 public int getTertiaryPaletteKeyColor() { 136 return getArgb(new MaterialDynamicColors().tertiaryPaletteKeyColor()); 137 } 138 getNeutralPaletteKeyColor()139 public int getNeutralPaletteKeyColor() { 140 return getArgb(new MaterialDynamicColors().neutralPaletteKeyColor()); 141 } 142 getNeutralVariantPaletteKeyColor()143 public int getNeutralVariantPaletteKeyColor() { 144 return getArgb(new MaterialDynamicColors().neutralVariantPaletteKeyColor()); 145 } 146 getBackground()147 public int getBackground() { 148 return getArgb(new MaterialDynamicColors().background()); 149 } 150 getOnBackground()151 public int getOnBackground() { 152 return getArgb(new MaterialDynamicColors().onBackground()); 153 } 154 getSurface()155 public int getSurface() { 156 return getArgb(new MaterialDynamicColors().surface()); 157 } 158 getSurfaceDim()159 public int getSurfaceDim() { 160 return getArgb(new MaterialDynamicColors().surfaceDim()); 161 } 162 getSurfaceBright()163 public int getSurfaceBright() { 164 return getArgb(new MaterialDynamicColors().surfaceBright()); 165 } 166 getSurfaceContainerLowest()167 public int getSurfaceContainerLowest() { 168 return getArgb(new MaterialDynamicColors().surfaceContainerLowest()); 169 } 170 getSurfaceContainerLow()171 public int getSurfaceContainerLow() { 172 return getArgb(new MaterialDynamicColors().surfaceContainerLow()); 173 } 174 getSurfaceContainer()175 public int getSurfaceContainer() { 176 return getArgb(new MaterialDynamicColors().surfaceContainer()); 177 } 178 getSurfaceContainerHigh()179 public int getSurfaceContainerHigh() { 180 return getArgb(new MaterialDynamicColors().surfaceContainerHigh()); 181 } 182 getSurfaceContainerHighest()183 public int getSurfaceContainerHighest() { 184 return getArgb(new MaterialDynamicColors().surfaceContainerHighest()); 185 } 186 getOnSurface()187 public int getOnSurface() { 188 return getArgb(new MaterialDynamicColors().onSurface()); 189 } 190 getSurfaceVariant()191 public int getSurfaceVariant() { 192 return getArgb(new MaterialDynamicColors().surfaceVariant()); 193 } 194 getOnSurfaceVariant()195 public int getOnSurfaceVariant() { 196 return getArgb(new MaterialDynamicColors().onSurfaceVariant()); 197 } 198 getInverseSurface()199 public int getInverseSurface() { 200 return getArgb(new MaterialDynamicColors().inverseSurface()); 201 } 202 getInverseOnSurface()203 public int getInverseOnSurface() { 204 return getArgb(new MaterialDynamicColors().inverseOnSurface()); 205 } 206 getOutline()207 public int getOutline() { 208 return getArgb(new MaterialDynamicColors().outline()); 209 } 210 getOutlineVariant()211 public int getOutlineVariant() { 212 return getArgb(new MaterialDynamicColors().outlineVariant()); 213 } 214 getShadow()215 public int getShadow() { 216 return getArgb(new MaterialDynamicColors().shadow()); 217 } 218 getScrim()219 public int getScrim() { 220 return getArgb(new MaterialDynamicColors().scrim()); 221 } 222 getSurfaceTint()223 public int getSurfaceTint() { 224 return getArgb(new MaterialDynamicColors().surfaceTint()); 225 } 226 getPrimary()227 public int getPrimary() { 228 return getArgb(new MaterialDynamicColors().primary()); 229 } 230 getOnPrimary()231 public int getOnPrimary() { 232 return getArgb(new MaterialDynamicColors().onPrimary()); 233 } 234 getPrimaryContainer()235 public int getPrimaryContainer() { 236 return getArgb(new MaterialDynamicColors().primaryContainer()); 237 } 238 getOnPrimaryContainer()239 public int getOnPrimaryContainer() { 240 return getArgb(new MaterialDynamicColors().onPrimaryContainer()); 241 } 242 getInversePrimary()243 public int getInversePrimary() { 244 return getArgb(new MaterialDynamicColors().inversePrimary()); 245 } 246 getSecondary()247 public int getSecondary() { 248 return getArgb(new MaterialDynamicColors().secondary()); 249 } 250 getOnSecondary()251 public int getOnSecondary() { 252 return getArgb(new MaterialDynamicColors().onSecondary()); 253 } 254 getSecondaryContainer()255 public int getSecondaryContainer() { 256 return getArgb(new MaterialDynamicColors().secondaryContainer()); 257 } 258 getOnSecondaryContainer()259 public int getOnSecondaryContainer() { 260 return getArgb(new MaterialDynamicColors().onSecondaryContainer()); 261 } 262 getTertiary()263 public int getTertiary() { 264 return getArgb(new MaterialDynamicColors().tertiary()); 265 } 266 getOnTertiary()267 public int getOnTertiary() { 268 return getArgb(new MaterialDynamicColors().onTertiary()); 269 } 270 getTertiaryContainer()271 public int getTertiaryContainer() { 272 return getArgb(new MaterialDynamicColors().tertiaryContainer()); 273 } 274 getOnTertiaryContainer()275 public int getOnTertiaryContainer() { 276 return getArgb(new MaterialDynamicColors().onTertiaryContainer()); 277 } 278 getError()279 public int getError() { 280 return getArgb(new MaterialDynamicColors().error()); 281 } 282 getOnError()283 public int getOnError() { 284 return getArgb(new MaterialDynamicColors().onError()); 285 } 286 getErrorContainer()287 public int getErrorContainer() { 288 return getArgb(new MaterialDynamicColors().errorContainer()); 289 } 290 getOnErrorContainer()291 public int getOnErrorContainer() { 292 return getArgb(new MaterialDynamicColors().onErrorContainer()); 293 } 294 getPrimaryFixed()295 public int getPrimaryFixed() { 296 return getArgb(new MaterialDynamicColors().primaryFixed()); 297 } 298 getPrimaryFixedDim()299 public int getPrimaryFixedDim() { 300 return getArgb(new MaterialDynamicColors().primaryFixedDim()); 301 } 302 getOnPrimaryFixed()303 public int getOnPrimaryFixed() { 304 return getArgb(new MaterialDynamicColors().onPrimaryFixed()); 305 } 306 getOnPrimaryFixedVariant()307 public int getOnPrimaryFixedVariant() { 308 return getArgb(new MaterialDynamicColors().onPrimaryFixedVariant()); 309 } 310 getSecondaryFixed()311 public int getSecondaryFixed() { 312 return getArgb(new MaterialDynamicColors().secondaryFixed()); 313 } 314 getSecondaryFixedDim()315 public int getSecondaryFixedDim() { 316 return getArgb(new MaterialDynamicColors().secondaryFixedDim()); 317 } 318 getOnSecondaryFixed()319 public int getOnSecondaryFixed() { 320 return getArgb(new MaterialDynamicColors().onSecondaryFixed()); 321 } 322 getOnSecondaryFixedVariant()323 public int getOnSecondaryFixedVariant() { 324 return getArgb(new MaterialDynamicColors().onSecondaryFixedVariant()); 325 } 326 getTertiaryFixed()327 public int getTertiaryFixed() { 328 return getArgb(new MaterialDynamicColors().tertiaryFixed()); 329 } 330 getTertiaryFixedDim()331 public int getTertiaryFixedDim() { 332 return getArgb(new MaterialDynamicColors().tertiaryFixedDim()); 333 } 334 getOnTertiaryFixed()335 public int getOnTertiaryFixed() { 336 return getArgb(new MaterialDynamicColors().onTertiaryFixed()); 337 } 338 getOnTertiaryFixedVariant()339 public int getOnTertiaryFixedVariant() { 340 return getArgb(new MaterialDynamicColors().onTertiaryFixedVariant()); 341 } 342 getControlActivated()343 public int getControlActivated() { 344 return getArgb(new MaterialDynamicColors().controlActivated()); 345 } 346 getControlNormal()347 public int getControlNormal() { 348 return getArgb(new MaterialDynamicColors().controlNormal()); 349 } 350 getControlHighlight()351 public int getControlHighlight() { 352 return getArgb(new MaterialDynamicColors().controlHighlight()); 353 } 354 getTextPrimaryInverse()355 public int getTextPrimaryInverse() { 356 return getArgb(new MaterialDynamicColors().textPrimaryInverse()); 357 } 358 getTextSecondaryAndTertiaryInverse()359 public int getTextSecondaryAndTertiaryInverse() { 360 return getArgb(new MaterialDynamicColors().textSecondaryAndTertiaryInverse()); 361 } 362 getTextPrimaryInverseDisableOnly()363 public int getTextPrimaryInverseDisableOnly() { 364 return getArgb(new MaterialDynamicColors().textPrimaryInverseDisableOnly()); 365 } 366 getTextSecondaryAndTertiaryInverseDisabled()367 public int getTextSecondaryAndTertiaryInverseDisabled() { 368 return getArgb(new MaterialDynamicColors().textSecondaryAndTertiaryInverseDisabled()); 369 } 370 getTextHintInverse()371 public int getTextHintInverse() { 372 return getArgb(new MaterialDynamicColors().textHintInverse()); 373 } 374 } 375