Merge "Color extraction implementation for gradient colors used by all apps background." into ub-launcher3-dorval-polish
This commit is contained in:
committed by
Android (Google) Code Review
commit
fd60f7274d
@@ -66,7 +66,7 @@ public class ColorExtractionService extends IntentService {
|
||||
if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
|
||||
extractedColors.updateWallpaperThemePalette(null);
|
||||
if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
|
||||
extractedColors.updateAllAppsGradientPalette(null);
|
||||
extractedColors.updateAllAppsGradientPalette(this);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -79,10 +79,9 @@ public class ColorExtractionService extends IntentService {
|
||||
}
|
||||
|
||||
if (FeatureFlags.QSB_IN_HOTSEAT || FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
|
||||
Palette wallpaperPalette = getWallpaperPalette();
|
||||
extractedColors.updateWallpaperThemePalette(wallpaperPalette);
|
||||
extractedColors.updateWallpaperThemePalette(getWallpaperPalette());
|
||||
if (FeatureFlags.LAUNCHER3_GRADIENT_ALL_APPS) {
|
||||
extractedColors.updateAllAppsGradientPalette(wallpaperPalette);
|
||||
extractedColors.updateAllAppsGradientPalette(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.launcher3.dynamicui;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.Nullable;
|
||||
@@ -25,6 +26,7 @@ import android.util.Log;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.dynamicui.colorextraction.ColorExtractor;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -161,14 +163,17 @@ public class ExtractedColors {
|
||||
? defaultColor : wallpaperPalette.getVibrantColor(defaultColor));
|
||||
}
|
||||
|
||||
public void updateAllAppsGradientPalette(@Nullable Palette wallpaperPalette) {
|
||||
// TODO b/37089857 will be modified to take the system extracted colors into account
|
||||
int idx;
|
||||
idx = ALLAPPS_GRADIENT_MAIN_INDEX;
|
||||
setColorAtIndex(idx, wallpaperPalette == null
|
||||
? DEFAULT_VALUES[idx] : wallpaperPalette.getDarkVibrantColor(DEFAULT_VALUES[idx]));
|
||||
idx = ALLAPPS_GRADIENT_SECONDARY_INDEX;
|
||||
setColorAtIndex(idx, wallpaperPalette == null
|
||||
? DEFAULT_VALUES[idx] : wallpaperPalette.getVibrantColor(DEFAULT_VALUES[idx]));
|
||||
public void updateAllAppsGradientPalette(Context context) {
|
||||
// TODO use isAtLeastO when available
|
||||
try {
|
||||
WallpaperManager.class.getDeclaredMethod("getWallpaperColors", int.class);
|
||||
ColorExtractor extractor = new ColorExtractor(context);
|
||||
ColorExtractor.GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM);
|
||||
setColorAtIndex(ALLAPPS_GRADIENT_MAIN_INDEX, colors.getMainColor());
|
||||
setColorAtIndex(ALLAPPS_GRADIENT_SECONDARY_INDEX, colors.getSecondaryColor());
|
||||
} catch (NoSuchMethodException e) {
|
||||
setColorAtIndex(ALLAPPS_GRADIENT_MAIN_INDEX, Color.WHITE);
|
||||
setColorAtIndex(ALLAPPS_GRADIENT_SECONDARY_INDEX, Color.WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
package com.android.launcher3.dynamicui.colorextraction;
|
||||
|
||||
import android.app.WallpaperManager;
|
||||
import android.content.Context;
|
||||
import android.graphics.Color;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.dynamicui.colorextraction.types.ExtractionType;
|
||||
import com.android.launcher3.dynamicui.colorextraction.types.Tonal;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
|
||||
/**
|
||||
* Class to process wallpaper colors and generate a tonal palette based on them.
|
||||
*
|
||||
* TODO remove this class if available by platform
|
||||
*/
|
||||
public class ColorExtractor {
|
||||
private static final String TAG = "ColorExtractor";
|
||||
private static final int FALLBACK_COLOR = Color.WHITE;
|
||||
|
||||
private int mMainFallbackColor = FALLBACK_COLOR;
|
||||
private int mSecondaryFallbackColor = FALLBACK_COLOR;
|
||||
private final GradientColors mSystemColors;
|
||||
private final GradientColors mLockColors;
|
||||
private final Context mContext;
|
||||
private final ExtractionType mExtractionType;
|
||||
|
||||
public ColorExtractor(Context context) {
|
||||
mContext = context;
|
||||
mSystemColors = new GradientColors();
|
||||
mLockColors = new GradientColors();
|
||||
mExtractionType = new Tonal();
|
||||
WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
|
||||
|
||||
if (wallpaperManager == null) {
|
||||
Log.w(TAG, "Can't listen to color changes!");
|
||||
} else {
|
||||
Parcelable wallpaperColorsObj;
|
||||
try {
|
||||
Method method = WallpaperManager.class
|
||||
.getDeclaredMethod("getWallpaperColors", int.class);
|
||||
|
||||
wallpaperColorsObj = (Parcelable) method.invoke(wallpaperManager,
|
||||
WallpaperManager.FLAG_SYSTEM);
|
||||
extractInto(new WallpaperColorsCompat(wallpaperColorsObj), mSystemColors);
|
||||
wallpaperColorsObj = (Parcelable) method.invoke(wallpaperManager,
|
||||
WallpaperManager.FLAG_LOCK);
|
||||
extractInto(new WallpaperColorsCompat(wallpaperColorsObj), mLockColors);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "reflection failed", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public GradientColors getColors(int which) {
|
||||
if (which == WallpaperManager.FLAG_LOCK) {
|
||||
return mLockColors;
|
||||
} else if (which == WallpaperManager.FLAG_SYSTEM) {
|
||||
return mSystemColors;
|
||||
} else {
|
||||
throw new IllegalArgumentException("which should be either FLAG_SYSTEM or FLAG_LOCK");
|
||||
}
|
||||
}
|
||||
|
||||
private void extractInto(WallpaperColorsCompat inWallpaperColors, GradientColors outGradientColors) {
|
||||
applyFallback(outGradientColors);
|
||||
if (inWallpaperColors == null) {
|
||||
return;
|
||||
}
|
||||
mExtractionType.extractInto(inWallpaperColors, outGradientColors);
|
||||
}
|
||||
|
||||
private void applyFallback(GradientColors outGradientColors) {
|
||||
outGradientColors.setMainColor(mMainFallbackColor);
|
||||
outGradientColors.setSecondaryColor(mSecondaryFallbackColor);
|
||||
}
|
||||
|
||||
public static class GradientColors {
|
||||
private int mMainColor = FALLBACK_COLOR;
|
||||
private int mSecondaryColor = FALLBACK_COLOR;
|
||||
private boolean mSupportsDarkText;
|
||||
|
||||
public void setMainColor(int mainColor) {
|
||||
mMainColor = mainColor;
|
||||
}
|
||||
|
||||
public void setSecondaryColor(int secondaryColor) {
|
||||
mSecondaryColor = secondaryColor;
|
||||
}
|
||||
|
||||
public void setSupportsDarkText(boolean supportsDarkText) {
|
||||
mSupportsDarkText = supportsDarkText;
|
||||
}
|
||||
|
||||
public void set(GradientColors other) {
|
||||
mMainColor = other.mMainColor;
|
||||
mSecondaryColor = other.mSecondaryColor;
|
||||
mSupportsDarkText = other.mSupportsDarkText;
|
||||
}
|
||||
|
||||
public int getMainColor() {
|
||||
return mMainColor;
|
||||
}
|
||||
|
||||
public int getSecondaryColor() {
|
||||
return mSecondaryColor;
|
||||
}
|
||||
|
||||
public boolean supportsDarkText() {
|
||||
return mSupportsDarkText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null || o.getClass() != getClass()) {
|
||||
return false;
|
||||
}
|
||||
GradientColors other = (GradientColors) o;
|
||||
return other.mMainColor == mMainColor &&
|
||||
other.mSecondaryColor == mSecondaryColor &&
|
||||
other.mSupportsDarkText == mSupportsDarkText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int code = mMainColor;
|
||||
code = 31 * code + mSecondaryColor;
|
||||
code = 31 * code + (mSupportsDarkText ? 0 : 1);
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
package com.android.launcher3.dynamicui.colorextraction;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A wrapper around platform implementation of WallpaperColors until the
|
||||
* updated SDK is available.
|
||||
*
|
||||
* TODO remove this class if available by platform
|
||||
*/
|
||||
public class WallpaperColorsCompat implements Parcelable {
|
||||
|
||||
private final Parcelable mObject;
|
||||
|
||||
public WallpaperColorsCompat(Parcelable object) {
|
||||
mObject = object;
|
||||
}
|
||||
|
||||
private Object invokeMethod(String methodName) {
|
||||
try {
|
||||
return mObject.getClass().getDeclaredMethod(methodName).invoke(mObject);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel parcel, int i) {
|
||||
parcel.writeParcelable(mObject, i);
|
||||
}
|
||||
|
||||
public static final Parcelable.Creator<WallpaperColorsCompat> CREATOR =
|
||||
new Parcelable.Creator<WallpaperColorsCompat>() {
|
||||
public WallpaperColorsCompat createFromParcel(Parcel source) {
|
||||
Parcelable object = source.readParcelable(null);
|
||||
return new WallpaperColorsCompat(object);
|
||||
}
|
||||
|
||||
public WallpaperColorsCompat[] newArray(int size) {
|
||||
return new WallpaperColorsCompat[size];
|
||||
}
|
||||
};
|
||||
|
||||
public List<Pair<Color, Integer>> getColors() {
|
||||
try {
|
||||
return (List<Pair<Color, Integer>>) invokeMethod("getColors");
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean supportsDarkText() {
|
||||
try {
|
||||
return (Boolean) invokeMethod("supportsDarkText");
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.android.launcher3.dynamicui.colorextraction.types;
|
||||
|
||||
import com.android.launcher3.dynamicui.colorextraction.ColorExtractor;
|
||||
import com.android.launcher3.dynamicui.colorextraction.WallpaperColorsCompat;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to allow various color extraction implementations.
|
||||
*
|
||||
* TODO remove this class if available by platform
|
||||
*/
|
||||
public interface ExtractionType {
|
||||
|
||||
/**
|
||||
* Executes color extraction by reading WallpaperColors and setting
|
||||
* main and secondary colors on GradientColors.
|
||||
*
|
||||
* @param inWallpaperColors where to read from
|
||||
* @param outGradientColors object that should receive the colors
|
||||
*/
|
||||
void extractInto(WallpaperColorsCompat inWallpaperColors,
|
||||
ColorExtractor.GradientColors outGradientColors);
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
package com.android.launcher3.dynamicui.colorextraction.types;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.graphics.ColorUtils;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import com.android.launcher3.dynamicui.colorextraction.ColorExtractor;
|
||||
import com.android.launcher3.dynamicui.colorextraction.WallpaperColorsCompat;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of tonal color extraction
|
||||
*
|
||||
* TODO remove this class if available by platform
|
||||
*/
|
||||
public class Tonal implements ExtractionType {
|
||||
private static final String TAG = "Tonal";
|
||||
|
||||
// Used for tonal palette fitting
|
||||
private static final float FIT_WEIGHT_H = 1.0f;
|
||||
private static final float FIT_WEIGHT_S = 1.0f;
|
||||
private static final float FIT_WEIGHT_L = 10.0f;
|
||||
|
||||
private static final float MIN_COLOR_OCCURRENCE = 0.1f;
|
||||
private static final float MIN_LUMINOSITY = 0.5f;
|
||||
|
||||
public void extractInto(WallpaperColorsCompat wallpaperColors,
|
||||
ColorExtractor.GradientColors gradientColors) {
|
||||
if (wallpaperColors.getColors().size() == 0) {
|
||||
return;
|
||||
}
|
||||
// Tonal is not really a sort, it takes a color from the extracted
|
||||
// palette and finds a best fit amongst a collection of pre-defined
|
||||
// palettes. The best fit is tweaked to be closer to the source color
|
||||
// and replaces the original palette
|
||||
|
||||
// First find the most representative color in the image
|
||||
populationSort(wallpaperColors);
|
||||
// Calculate total
|
||||
int total = 0;
|
||||
for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) {
|
||||
total += weightedColor.second;
|
||||
}
|
||||
|
||||
// Get bright colors that occur often enough in this image
|
||||
Pair<Color, Integer> bestColor = null;
|
||||
float[] hsl = new float[3];
|
||||
for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) {
|
||||
float colorOccurrence = weightedColor.second / (float) total;
|
||||
if (colorOccurrence < MIN_COLOR_OCCURRENCE) {
|
||||
break;
|
||||
}
|
||||
|
||||
int colorValue = weightedColor.first.toArgb();
|
||||
ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue),
|
||||
Color.blue(colorValue), hsl);
|
||||
if (hsl[2] > MIN_LUMINOSITY) {
|
||||
bestColor = weightedColor;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback to first color
|
||||
if (bestColor == null) {
|
||||
bestColor = wallpaperColors.getColors().get(0);
|
||||
}
|
||||
|
||||
int colorValue = bestColor.first.toArgb();
|
||||
ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue), Color.blue(colorValue),
|
||||
hsl);
|
||||
hsl[0] /= 360.0f; // normalize
|
||||
|
||||
// TODO, we're finding a tonal palette for a hue, not all components
|
||||
TonalPalette palette = findTonalPalette(hsl[0]);
|
||||
|
||||
// Fall back to population sort if we couldn't find a tonal palette
|
||||
if (palette == null) {
|
||||
Log.w(TAG, "Could not find a tonal palette!");
|
||||
return;
|
||||
}
|
||||
|
||||
int fitIndex = bestFit(palette, hsl[0], hsl[1], hsl[2]);
|
||||
if (fitIndex == -1) {
|
||||
Log.w(TAG, "Could not find best fit!");
|
||||
return;
|
||||
}
|
||||
float[] h = fit(palette.h, hsl[0], fitIndex,
|
||||
Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY);
|
||||
float[] s = fit(palette.s, hsl[1], fitIndex, 0.0f, 1.0f);
|
||||
float[] l = fit(palette.l, hsl[2], fitIndex, 0.0f, 1.0f);
|
||||
|
||||
|
||||
hsl[0] = fract(h[0]) * 360.0f;
|
||||
hsl[1] = s[0];
|
||||
hsl[2] = l[0];
|
||||
gradientColors.setMainColor(ColorUtils.HSLToColor(hsl));
|
||||
|
||||
hsl[0] = fract(h[1]) * 360.0f;
|
||||
hsl[1] = s[1];
|
||||
hsl[2] = l[1];
|
||||
gradientColors.setSecondaryColor(ColorUtils.HSLToColor(hsl));
|
||||
}
|
||||
|
||||
private static void populationSort(@NonNull WallpaperColorsCompat wallpaperColors) {
|
||||
wallpaperColors.getColors().sort(new Comparator<Pair<Color, Integer>>() {
|
||||
@Override
|
||||
public int compare(Pair<Color, Integer> a, Pair<Color, Integer> b) {
|
||||
return b.second - a.second;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Offsets all colors by a delta, clamping values that go beyond what's
|
||||
* supported on the color space.
|
||||
* @param data what you want to fit
|
||||
* @param v how big should be the offset
|
||||
* @param index which index to calculate the delta against
|
||||
* @param min minimum accepted value (clamp)
|
||||
* @param max maximum accepted value (clamp)
|
||||
* @return
|
||||
*/
|
||||
private static float[] fit(float[] data, float v, int index, float min, float max) {
|
||||
float[] fitData = new float[data.length];
|
||||
float delta = v - data[index];
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
fitData[i] = constrain(data[i] + delta, min, max);
|
||||
}
|
||||
|
||||
return fitData;
|
||||
}
|
||||
|
||||
// TODO no MathUtils
|
||||
private static float constrain(float x, float min, float max) {
|
||||
x = Math.min(x, max);
|
||||
x = Math.max(x, min);
|
||||
return x;
|
||||
}
|
||||
|
||||
/*function adjustSatLumForFit(val, points, fitIndex) {
|
||||
var fitValue = lerpBetweenPoints(points, fitIndex);
|
||||
var diff = val - fitValue;
|
||||
|
||||
var newPoints = [];
|
||||
for (var ii=0; ii<points.length; ii++) {
|
||||
var point = [points[ii][0], points[ii][1]];
|
||||
point[1] += diff;
|
||||
if (point[1] > 1) point[1] = 1;
|
||||
if (point[1] < 0) point[1] = 0;
|
||||
newPoints[ii] = point;
|
||||
}
|
||||
return newPoints;
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Finds the closest color in a palette, given another HSL color
|
||||
*
|
||||
* @param palette where to search
|
||||
* @param h hue
|
||||
* @param s saturation
|
||||
* @param l lightness
|
||||
* @return closest index or -1 if palette is empty.
|
||||
*/
|
||||
private static int bestFit(@NonNull TonalPalette palette, float h, float s, float l) {
|
||||
int minErrorIndex = -1;
|
||||
float minError = Float.POSITIVE_INFINITY;
|
||||
|
||||
for (int i = 0; i < palette.h.length; i++) {
|
||||
float error =
|
||||
FIT_WEIGHT_H * Math.abs(h - palette.h[i])
|
||||
+ FIT_WEIGHT_S * Math.abs(s - palette.s[i])
|
||||
+ FIT_WEIGHT_L * Math.abs(l - palette.l[i]);
|
||||
if (error < minError) {
|
||||
minError = error;
|
||||
minErrorIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return minErrorIndex;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TonalPalette findTonalPalette(float h) {
|
||||
TonalPalette best = null;
|
||||
float error = Float.POSITIVE_INFINITY;
|
||||
|
||||
for (TonalPalette candidate : TONAL_PALETTES) {
|
||||
if (h >= candidate.minHue && h <= candidate.maxHue) {
|
||||
best = candidate;
|
||||
break;
|
||||
}
|
||||
|
||||
if (candidate.maxHue > 1.0f && h >= 0.0f && h <= fract(candidate.maxHue)) {
|
||||
best = candidate;
|
||||
break;
|
||||
}
|
||||
|
||||
if (candidate.minHue < 0.0f && h >= fract(candidate.minHue) && h <= 1.0f) {
|
||||
best = candidate;
|
||||
break;
|
||||
}
|
||||
|
||||
if (h <= candidate.minHue && candidate.minHue - h < error) {
|
||||
best = candidate;
|
||||
error = candidate.minHue - h;
|
||||
} else if (h >= candidate.maxHue && h - candidate.maxHue < error) {
|
||||
best = candidate;
|
||||
error = h - candidate.maxHue;
|
||||
} else if (candidate.maxHue > 1.0f && h >= fract(candidate.maxHue)
|
||||
&& h - fract(candidate.maxHue) < error) {
|
||||
best = candidate;
|
||||
error = h - fract(candidate.maxHue);
|
||||
} else if (candidate.minHue < 0.0f && h <= fract(candidate.minHue)
|
||||
&& fract(candidate.minHue) - h < error) {
|
||||
best = candidate;
|
||||
error = fract(candidate.minHue) - h;
|
||||
}
|
||||
}
|
||||
|
||||
return best;
|
||||
}
|
||||
|
||||
private static float fract(float v) {
|
||||
return v - (float) Math.floor(v);
|
||||
}
|
||||
|
||||
static class TonalPalette {
|
||||
final float[] h;
|
||||
final float[] s;
|
||||
final float[] l;
|
||||
final float minHue;
|
||||
final float maxHue;
|
||||
|
||||
TonalPalette(float[] h, float[] s, float[] l) {
|
||||
this.h = h;
|
||||
this.s = s;
|
||||
this.l = l;
|
||||
|
||||
float minHue = Float.POSITIVE_INFINITY;
|
||||
float maxHue = Float.NEGATIVE_INFINITY;
|
||||
|
||||
for (float v : h) {
|
||||
minHue = Math.min(v, minHue);
|
||||
maxHue = Math.max(v, maxHue);
|
||||
}
|
||||
|
||||
this.minHue = minHue;
|
||||
this.maxHue = maxHue;
|
||||
}
|
||||
}
|
||||
|
||||
// Data definition of Material Design tonal palettes
|
||||
// When the sort type is set to TONAL, these palettes are used to find
|
||||
// a best fist. Each palette is defined as 10 HSL colors
|
||||
private static final TonalPalette[] TONAL_PALETTES = {
|
||||
// Orange
|
||||
new TonalPalette(
|
||||
new float[] { 0.028f, 0.042f, 0.053f, 0.061f, 0.078f, 0.1f, 0.111f, 0.111f, 0.111f, 0.111f },
|
||||
new float[] { 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f },
|
||||
new float[] { 0.5f, 0.53f, 0.54f, 0.55f, 0.535f, 0.52f, 0.5f, 0.63f, 0.75f, 0.85f }
|
||||
),
|
||||
// Yellow
|
||||
new TonalPalette(
|
||||
new float[] { 0.111f, 0.111f, 0.125f, 0.133f, 0.139f, 0.147f, 0.156f, 0.156f, 0.156f, 0.156f },
|
||||
new float[] { 1f, 0.942f, 1f, 1f, 1f, 1f, 1f, 1f, 1f, 1f },
|
||||
new float[] { 0.43f, 0.484f, 0.535f, 0.555f, 0.57f, 0.575f, 0.595f, 0.715f, 0.78f, 0.885f }
|
||||
),
|
||||
// Green
|
||||
new TonalPalette(
|
||||
new float[] { 0.325f, 0.336f, 0.353f, 0.353f, 0.356f, 0.356f, 0.356f, 0.356f, 0.356f, 0.356f },
|
||||
new float[] { 1f, 1f, 0.852f, 0.754f, 0.639f, 0.667f, 0.379f, 0.542f, 1f, 1f },
|
||||
new float[] { 0.06f, 0.1f, 0.151f, 0.194f, 0.25f, 0.312f, 0.486f, 0.651f, 0.825f, 0.885f }
|
||||
),
|
||||
// Blue
|
||||
new TonalPalette(
|
||||
new float[] { 0.631f, 0.603f, 0.592f, 0.586f, 0.572f, 0.544f, 0.519f, 0.519f, 0.519f, 0.519f },
|
||||
new float[] { 0.852f, 1f, 0.887f, 0.852f, 0.871f, 0.907f, 0.949f, 0.934f, 0.903f, 0.815f },
|
||||
new float[] { 0.34f, 0.38f, 0.482f, 0.497f, 0.536f, 0.571f, 0.608f, 0.696f, 0.794f, 0.892f }
|
||||
),
|
||||
// Purple
|
||||
new TonalPalette(
|
||||
new float[] { 0.839f, 0.831f, 0.825f, 0.819f, 0.803f, 0.803f, 0.772f, 0.772f, 0.772f, 0.772f },
|
||||
new float[] { 1f, 1f, 1f, 1f, 1f, 1f, 0.769f, 0.701f, 0.612f, 0.403f },
|
||||
new float[] { 0.125f, 0.15f, 0.2f, 0.245f, 0.31f, 0.36f, 0.567f, 0.666f, 0.743f, 0.833f }
|
||||
),
|
||||
// Red
|
||||
new TonalPalette(
|
||||
new float[] { 0.964f, 0.975f, 0.975f, 0.975f, 0.972f, 0.992f, 1.003f, 1.011f, 1.011f, 1.011f },
|
||||
new float[] { 0.869f, 0.802f, 0.739f, 0.903f, 1f, 1f, 1f, 1f, 1f, 1f },
|
||||
new float[] { 0.241f, 0.316f, 0.46f, 0.586f, 0.655f, 0.7f, 0.75f, 0.8f, 0.84f, 0.88f }
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user