blob: b54ec0ef0a7c79e6b5ff9050ee1907eafa226b49 [file] [log] [blame]
Brian Attwell845b0202014-07-10 18:15:31 -07001/*
2 * Copyright (C) 2014 The Android Open Source Project
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
Gary Mai69c182a2016-12-05 13:07:03 -080017package com.android.contacts.util;
Brian Attwell845b0202014-07-10 18:15:31 -070018
Wenyi Wang92d7e512016-10-03 14:57:19 -070019import android.app.Activity;
Brian Attwell5ca1b1d2014-07-15 13:46:25 -070020import android.content.res.Resources;
21import android.content.res.TypedArray;
Yorke Leeebf16fa2014-11-26 15:21:43 -080022import android.os.Parcel;
23import android.os.Parcelable;
Brian Attwell845b0202014-07-10 18:15:31 -070024import android.os.Trace;
Wenyi Wang92d7e512016-10-03 14:57:19 -070025import android.support.v4.content.ContextCompat;
Brian Attwell845b0202014-07-10 18:15:31 -070026
Gary Mai0a49afa2016-12-05 15:53:58 -080027import com.android.contacts.ContactsDrawerActivity;
28import com.android.contacts.R;
29
Brian Attwell845b0202014-07-10 18:15:31 -070030public class MaterialColorMapUtils {
Brian Attwell5ca1b1d2014-07-15 13:46:25 -070031 private final TypedArray sPrimaryColors;
32 private final TypedArray sSecondaryColors;
Brian Attwell845b0202014-07-10 18:15:31 -070033
Brian Attwell5ca1b1d2014-07-15 13:46:25 -070034 public MaterialColorMapUtils(Resources resources) {
35 sPrimaryColors = resources.obtainTypedArray(
Arthur Wang3f6a2442016-12-05 14:51:59 -080036 com.android.contacts.R.array.letter_tile_colors);
Brian Attwell5ca1b1d2014-07-15 13:46:25 -070037 sSecondaryColors = resources.obtainTypedArray(
Arthur Wang3f6a2442016-12-05 14:51:59 -080038 com.android.contacts.R.array.letter_tile_colors_dark);
Brian Attwell5ca1b1d2014-07-15 13:46:25 -070039 }
Brian Attwell845b0202014-07-10 18:15:31 -070040
Yorke Leeebf16fa2014-11-26 15:21:43 -080041 public static class MaterialPalette implements Parcelable {
Brian Attwell845b0202014-07-10 18:15:31 -070042 public MaterialPalette(int primaryColor, int secondaryColor) {
43 mPrimaryColor = primaryColor;
44 mSecondaryColor = secondaryColor;
45 }
46 public final int mPrimaryColor;
47 public final int mSecondaryColor;
Nancy Chen5e29d6e2014-10-27 08:41:11 -070048
49 @Override
50 public boolean equals(Object obj) {
51 if (this == obj) {
52 return true;
53 }
54 if (obj == null) {
55 return false;
56 }
57 if (getClass() != obj.getClass()) {
58 return false;
59 }
60 MaterialPalette other = (MaterialPalette) obj;
61 if (mPrimaryColor != other.mPrimaryColor) {
62 return false;
63 }
64 if (mSecondaryColor != other.mSecondaryColor) {
65 return false;
66 }
67 return true;
68 }
69
70 @Override
71 public int hashCode() {
72 final int prime = 31;
73 int result = 1;
74 result = prime * result + mPrimaryColor;
75 result = prime * result + mSecondaryColor;
76 return result;
77 }
Yorke Leeebf16fa2014-11-26 15:21:43 -080078
79 @Override
80 public int describeContents() {
81 return 0;
82 }
83
84 @Override
85 public void writeToParcel(Parcel dest, int flags) {
86 dest.writeInt(mPrimaryColor);
87 dest.writeInt(mSecondaryColor);
88 }
89
90 private MaterialPalette(Parcel in) {
91 mPrimaryColor = in.readInt();
92 mSecondaryColor = in.readInt();
93 }
94
95 public static final Creator<MaterialPalette> CREATOR = new Creator<MaterialPalette>() {
96 @Override
97 public MaterialPalette createFromParcel(Parcel in) {
98 return new MaterialPalette(in);
99 }
100
101 @Override
102 public MaterialPalette[] newArray(int size) {
103 return new MaterialPalette[size];
104 }
105 };
Brian Attwell845b0202014-07-10 18:15:31 -0700106 }
107
108 /**
Brian Attwell5ca1b1d2014-07-15 13:46:25 -0700109 * Return primary and secondary colors from the Material color palette that are similar to
110 * {@param color}.
Brian Attwell845b0202014-07-10 18:15:31 -0700111 */
Brian Attwell5ca1b1d2014-07-15 13:46:25 -0700112 public MaterialPalette calculatePrimaryAndSecondaryColor(int color) {
Brian Attwell845b0202014-07-10 18:15:31 -0700113 Trace.beginSection("calculatePrimaryAndSecondaryColor");
114
Yorke Lee059319e2014-07-15 12:24:19 -0700115 final float colorHue = hue(color);
Brian Attwell845b0202014-07-10 18:15:31 -0700116 float minimumDistance = Float.MAX_VALUE;
117 int indexBestMatch = 0;
Brian Attwell5ca1b1d2014-07-15 13:46:25 -0700118 for (int i = 0; i < sPrimaryColors.length(); i++) {
119 final int primaryColor = sPrimaryColors.getColor(i, 0);
120 final float comparedHue = hue(primaryColor);
Brian Attwell845b0202014-07-10 18:15:31 -0700121 // No need to be perceptually accurate when calculating color distances since
122 // we are only mapping to 15 colors. Being slightly inaccurate isn't going to change
123 // the mapping very often.
124 final float distance = Math.abs(comparedHue - colorHue);
125 if (distance < minimumDistance) {
126 minimumDistance = distance;
127 indexBestMatch = i;
128 }
129 }
130
131 Trace.endSection();
Brian Attwell5ca1b1d2014-07-15 13:46:25 -0700132 return new MaterialPalette(sPrimaryColors.getColor(indexBestMatch, 0),
133 sSecondaryColors.getColor(indexBestMatch, 0));
Brian Attwell845b0202014-07-10 18:15:31 -0700134 }
135
Brian Attwell5ca1b1d2014-07-15 13:46:25 -0700136 public static MaterialPalette getDefaultPrimaryAndSecondaryColors(Resources resources) {
137 final int primaryColor = resources.getColor(
138 R.color.quickcontact_default_photo_tint_color);
139 final int secondaryColor = resources.getColor(
140 R.color.quickcontact_default_photo_tint_color_dark);
141 return new MaterialPalette(primaryColor, secondaryColor);
Brian Attwell845b0202014-07-10 18:15:31 -0700142 }
143
Yorke Lee059319e2014-07-15 12:24:19 -0700144 /**
145 * Returns the hue component of a color int.
146 *
147 * @return A value between 0.0f and 1.0f
148 */
149 public static float hue(int color) {
150 int r = (color >> 16) & 0xFF;
151 int g = (color >> 8) & 0xFF;
152 int b = color & 0xFF;
153
154 int V = Math.max(b, Math.max(r, g));
155 int temp = Math.min(b, Math.min(r, g));
156
157 float H;
158
159 if (V == temp) {
160 H = 0;
161 } else {
162 final float vtemp = V - temp;
163 final float cr = (V - r) / vtemp;
164 final float cg = (V - g) / vtemp;
165 final float cb = (V - b) / vtemp;
166
167 if (r == V) {
168 H = cb - cg;
169 } else if (g == V) {
170 H = 2 + cr - cb;
171 } else {
172 H = 4 + cg - cr;
173 }
174
175 H /= 6.f;
176 if (H < 0) {
177 H++;
178 }
179 }
180
181 return H;
182 }
Wenyi Wang92d7e512016-10-03 14:57:19 -0700183
184 /**
185 * Returns status bar color for group view and non-group views.
186 */
187 public static int getStatusBarColor(Activity activity) {
188 final boolean isGroupView = activity instanceof ContactsDrawerActivity
189 && ((ContactsDrawerActivity) activity).isGroupView();
190 return isGroupView
191 ? ContextCompat.getColor(activity, R.color.group_primary_color_dark)
192 : ContextCompat.getColor(activity, R.color.primary_color_dark);
193 }
194
195 /**
196 * Returns toolbar color for group view and non-group views.
197 */
198 public static int getToolBarColor(Activity activity) {
199 final boolean isGroupView = activity instanceof ContactsDrawerActivity
200 && ((ContactsDrawerActivity) activity).isGroupView();
201 return isGroupView
202 ? ContextCompat.getColor(activity, R.color.group_primary_color)
203 : ContextCompat.getColor(activity, R.color.primary_color);
204 }
Brian Attwell845b0202014-07-10 18:15:31 -0700205}