forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcolor_provider.cc
111 lines (88 loc) · 3.63 KB
/
color_provider.cc
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
111
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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/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(ColorProvider&&) = default;
ColorProvider& ColorProvider::operator=(ColorProvider&&) = default;
ColorProvider::~ColorProvider() = default;
ColorMixer& ColorProvider::AddMixer() {
DCHECK(!color_map_);
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() {
DCHECK(!color_map_);
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 {
CHECK(color_map_);
auto i = color_map_->find(id);
return i == color_map_->end() ? gfx::kPlaceholderColor : i->second;
}
void ColorProvider::GenerateColorMap() {
// This should only be called to generate the `color_map_` once.
DCHECK(!color_map_);
if (mixers_.empty())
DVLOG(2) << "ColorProvider::GenerateColorMap: No mixers defined!";
// Iterate over associated mixers and extract the ColorIds defined for this
// provider.
std::set<ColorId> color_ids;
for (const auto& mixer : mixers_) {
const auto mixer_color_ids = mixer.GetDefinedColorIds();
color_ids.insert(mixer_color_ids.begin(), mixer_color_ids.end());
}
// Iterate through all defined ColorIds and seed the `color_map` with the
// computed values. Use a std::map rather than a base::flat_map since it has
// frequent inserts and could grow very large.
std::map<ColorId, SkColor> color_map;
for (const auto& color_id : color_ids)
color_map.insert({color_id, mixers_.front().GetResultColor(color_id)});
// Construct the color_map_.
color_map_ = ColorMap(color_map.begin(), color_map.end());
// Clear away all associated mixers as these are no longer needed.
mixers_.clear();
first_postprocessing_mixer_ = mixers_.before_begin();
}
void ColorProvider::SetColorForTesting(ColorId id, SkColor color) {
if (color_map_) {
(*color_map_)[id] = color;
} else {
if (mixers_.empty())
AddMixer();
(*std::next(first_postprocessing_mixer_, 1))[id] = {color};
}
}
const ColorMixer* ColorProvider::GetLastNonPostprocessingMixer() const {
const auto it = std::next(first_postprocessing_mixer_, 1);
return (it == mixers_.cend()) ? nullptr : &(*it);
}
} // namespace ui