1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110

ash / style / sparkle_colors.cc [blame]

// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/style/sparkle_colors.h"

#include "ash/style/harmonized_colors.h"
#include "third_party/material_color_utilities/src/cpp/cam/hct.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/chromeos/styles/cros_tokens_color_mappings.h"
#include "ui/color/color_id.h"
#include "ui/color/color_recipe.h"

namespace ash {

namespace {

// Mappings of tones to ColorId as they comprise the tonal palette.
// https://m3.material.io/styles/color/the-color-system/key-colors-tones
constexpr std::array<std::pair<int, ui::ColorId>, 13> kAnalogIds{
    {{0, cros_tokens::kCrosRefSparkleAnalog0},
     {10, cros_tokens::kCrosRefSparkleAnalog10},
     {20, cros_tokens::kCrosRefSparkleAnalog20},
     {30, cros_tokens::kCrosRefSparkleAnalog30},
     {40, cros_tokens::kCrosRefSparkleAnalog40},
     {50, cros_tokens::kCrosRefSparkleAnalog50},
     {60, cros_tokens::kCrosRefSparkleAnalog60},
     {70, cros_tokens::kCrosRefSparkleAnalog70},
     {80, cros_tokens::kCrosRefSparkleAnalog80},
     {90, cros_tokens::kCrosRefSparkleAnalog90},
     {95, cros_tokens::kCrosRefSparkleAnalog95},
     {99, cros_tokens::kCrosRefSparkleAnalog99},
     {100, cros_tokens::kCrosRefSparkleAnalog100}}};

constexpr std::array<std::pair<int, ui::ColorId>, 13> kMutedIds{
    {{0, cros_tokens::kCrosRefSparkleMuted0},
     {10, cros_tokens::kCrosRefSparkleMuted10},
     {20, cros_tokens::kCrosRefSparkleMuted20},
     {30, cros_tokens::kCrosRefSparkleMuted30},
     {40, cros_tokens::kCrosRefSparkleMuted40},
     {50, cros_tokens::kCrosRefSparkleMuted50},
     {60, cros_tokens::kCrosRefSparkleMuted60},
     {70, cros_tokens::kCrosRefSparkleMuted70},
     {80, cros_tokens::kCrosRefSparkleMuted80},
     {90, cros_tokens::kCrosRefSparkleMuted90},
     {95, cros_tokens::kCrosRefSparkleMuted95},
     {99, cros_tokens::kCrosRefSparkleMuted99},
     {100, cros_tokens::kCrosRefSparkleMuted100}}};

constexpr std::array<std::pair<int, ui::ColorId>, 13> kComplementIds{
    {{0, cros_tokens::kCrosRefSparkleComplement0},
     {10, cros_tokens::kCrosRefSparkleComplement10},
     {20, cros_tokens::kCrosRefSparkleComplement20},
     {30, cros_tokens::kCrosRefSparkleComplement30},
     {40, cros_tokens::kCrosRefSparkleComplement40},
     {50, cros_tokens::kCrosRefSparkleComplement50},
     {60, cros_tokens::kCrosRefSparkleComplement60},
     {70, cros_tokens::kCrosRefSparkleComplement70},
     {80, cros_tokens::kCrosRefSparkleComplement80},
     {90, cros_tokens::kCrosRefSparkleComplement90},
     {95, cros_tokens::kCrosRefSparkleComplement95},
     {99, cros_tokens::kCrosRefSparkleComplement99},
     {100, cros_tokens::kCrosRefSparkleComplement100}}};

struct HueChroma {
  int hue;
  int chroma;
};

// For the ColorId in `data`, generate the appropriate tone values combined with
// hue and chroma from `hc` and add the mappings to `mixer`.
void InsertIntoMixer(ui::ColorMixer& mixer,
                     const HueChroma& hc,
                     const std::array<std::pair<int, ui::ColorId>, 13>& data) {
  for (const auto& [tone, color_id] : data) {
    material_color_utilities::Hct hct(hc.hue, hc.chroma, tone);

    // `Hct::ToInt()` is in Argb which matches the representation of SkColor
    // (ARGB).
    mixer[color_id] = {hct.ToInt()};
  }
}

}  // namespace

void AddSparkleColors(ui::ColorMixer& mixer, const ui::ColorProviderKey& key) {
  int angle = 217;  // Default to blue
  if (key.user_color) {
    angle = HueAngle(*key.user_color);
  }

  HueChroma analog;
  HueChroma muted;
  HueChroma complement;
  if (angle > 49 && angle < 121) {
    analog = {.hue = 283, .chroma = 60};
    muted = {.hue = 273, .chroma = 35};
    complement = {.hue = 170, .chroma = 30};
  } else {
    analog = {.hue = 303, .chroma = 60};
    muted = {.hue = 293, .chroma = 35};
    complement = {.hue = 150, .chroma = 30};
  }

  InsertIntoMixer(mixer, analog, kAnalogIds);
  InsertIntoMixer(mixer, muted, kMutedIds);
  InsertIntoMixer(mixer, complement, kComplementIds);
}

}  // namespace ash