Home | History | Annotate | Download | only in util
      1 /*
      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 
     17 package com.android.contacts.util;
     18 
     19 import android.app.Activity;
     20 import android.content.res.Resources;
     21 import android.content.res.TypedArray;
     22 import android.os.Parcel;
     23 import android.os.Parcelable;
     24 import android.os.Trace;
     25 import android.support.v4.content.ContextCompat;
     26 
     27 import com.android.contacts.R;
     28 import com.android.contacts.activities.PeopleActivity;
     29 
     30 public class MaterialColorMapUtils {
     31     private final TypedArray sPrimaryColors;
     32     private final TypedArray sSecondaryColors;
     33 
     34     public MaterialColorMapUtils(Resources resources) {
     35         sPrimaryColors = resources.obtainTypedArray(
     36                 com.android.contacts.R.array.letter_tile_colors);
     37         sSecondaryColors = resources.obtainTypedArray(
     38                 com.android.contacts.R.array.letter_tile_colors_dark);
     39     }
     40 
     41     public static class MaterialPalette implements Parcelable {
     42         public MaterialPalette(int primaryColor, int secondaryColor) {
     43             mPrimaryColor = primaryColor;
     44             mSecondaryColor = secondaryColor;
     45         }
     46         public final int mPrimaryColor;
     47         public final int mSecondaryColor;
     48 
     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         }
     78 
     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         };
    106     }
    107 
    108     /**
    109      * Return primary and secondary colors from the Material color palette that are similar to
    110      * {@param color}.
    111      */
    112     public MaterialPalette calculatePrimaryAndSecondaryColor(int color) {
    113         Trace.beginSection("calculatePrimaryAndSecondaryColor");
    114 
    115         final float colorHue = hue(color);
    116         float minimumDistance = Float.MAX_VALUE;
    117         int indexBestMatch = 0;
    118         for (int i = 0; i < sPrimaryColors.length(); i++) {
    119             final int primaryColor = sPrimaryColors.getColor(i, 0);
    120             final float comparedHue = hue(primaryColor);
    121             // 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();
    132         return new MaterialPalette(sPrimaryColors.getColor(indexBestMatch, 0),
    133                 sSecondaryColors.getColor(indexBestMatch, 0));
    134     }
    135 
    136     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);
    142     }
    143 
    144     /**
    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     }
    183 
    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 PeopleActivity
    189                 && ((PeopleActivity) 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 PeopleActivity
    200                 && ((PeopleActivity) activity).isGroupView();
    201         return isGroupView
    202                 ? ContextCompat.getColor(activity, R.color.group_primary_color)
    203                 : ContextCompat.getColor(activity, R.color.primary_color);
    204     }
    205 }
    206