blob: 37d9f667880c6d4b8749b479e42e4bf71154f9d3 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/color/color_provider.h"
#include <map>
#include <set>
#include <utility>
#include "base/functional/bind.h"
#include "base/logging.h"
#include "ui/color/color_mixer.h"
#include "ui/color/color_provider_utils.h"
#include "ui/color/color_recipe.h"
#include "ui/gfx/color_palette.h"
namespace ui {
ColorProvider::ColorProvider() = default;
ColorProvider::~ColorProvider() = default;
ColorMixer& ColorProvider::AddMixer() {
color_map_.clear();
mixers_.emplace_after(
first_postprocessing_mixer_,
base::BindRepeating([](const ColorMixer* mixer) { return mixer; },
GetLastNonPostprocessingMixer()),
base::BindRepeating(&ColorProvider::GetLastNonPostprocessingMixer,
base::Unretained(this)));
return *std::next(first_postprocessing_mixer_, 1);
}
ColorMixer& ColorProvider::AddPostprocessingMixer() {
color_map_.clear();
if (first_postprocessing_mixer_ == mixers_.before_begin()) {
// The first postprocessing mixer points to the last regular mixer.
auto previous_mixer_getter = base::BindRepeating(
&ColorProvider::GetLastNonPostprocessingMixer, base::Unretained(this));
mixers_.emplace_front(previous_mixer_getter, previous_mixer_getter);
first_postprocessing_mixer_ = mixers_.begin();
} else {
// Other postprocessing mixers point to the next postprocessing mixer.
auto previous_mixer_getter =
base::BindRepeating([](const ColorMixer* mixer) { return mixer; },
base::Unretained(&mixers_.front()));
mixers_.emplace_front(previous_mixer_getter, previous_mixer_getter);
}
return mixers_.front();
}
SkColor ColorProvider::GetColor(ColorId id) const {
auto i = color_map_.find(id);
if (i == color_map_.end()) {
if (mixers_.empty()) {
DVLOG(2) << "ColorProvider::GetColor: No mixers defined!";
return gfx::kPlaceholderColor;
}
DVLOG(2) << "ColorProvider::GetColor: Computing color for ColorId: "
<< ColorIdName(id);
const SkColor color = mixers_.front().GetResultColor(id);
if (color == gfx::kPlaceholderColor) {
return gfx::kPlaceholderColor;
}
i = color_map_.insert({id, color}).first;
}
DVLOG(2) << "ColorProvider::GetColor: ColorId: " << ColorIdName(id)
<< " Value: " << SkColorName(i->second);
return i->second;
}
void ColorProvider::SetColorForTesting(ColorId id, SkColor color) {
color_map_[id] = color;
}
void ColorProvider::GenerateColorMapForTesting() {
for (const auto& mixer : mixers_) {
const auto mixer_color_ids = mixer.GetDefinedColorIds();
for (const auto color_id : mixer_color_ids) {
GetColor(color_id);
}
}
}
const ColorMixer* ColorProvider::GetLastNonPostprocessingMixer() const {
const auto it = std::next(first_postprocessing_mixer_, 1);
return (it == mixers_.cend()) ? nullptr : &(*it);
}
} // namespace ui