File: color_transform.cc

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (368 lines) | stat: -rw-r--r-- 17,726 bytes parent folder | download | duplicates (4)
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
// 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_transform.h"

#include <utility>

#include "base/functional/bind.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/to_string.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/color/color_mixer.h"
#include "ui/color/color_provider_utils.h"

namespace ui {

ColorTransform::ColorTransform(Callback callback)
    : callback_(std::move(callback)) {}

ColorTransform::ColorTransform(SkColor color) : invariant_(true) {
  const auto generator = [](SkColor color, SkColor input_color,
                            const ColorMixer& mixer) {
    DVLOG(2) << "ColorTransform From Color:" << " Input Color:"
             << SkColorName(input_color) << " Color: " << SkColorName(color)
             << " Result Color: " << SkColorName(color);
    return color;
  };
  callback_ = base::BindRepeating(generator, color);
}

ColorTransform::ColorTransform(ColorId id) : invariant_(true) {
  const auto generator = [](ColorId id, SkColor input_color,
                            const ColorMixer& mixer) {
    SkColor result_color = mixer.GetResultColor(id);
    DVLOG(2) << "ColorTransform FromMixer:" << " Input Color:"
             << SkColorName(input_color) << " Color Id: " << ColorIdName(id)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  callback_ = base::BindRepeating(generator, id);
}

ColorTransform::ColorTransform(const ColorTransform&) = default;

ColorTransform& ColorTransform::operator=(const ColorTransform&) = default;

ColorTransform::~ColorTransform() = default;

SkColor ColorTransform::Run(SkColor input_color,
                            const ColorMixer& mixer) const {
  return callback_.Run(input_color, mixer);
}

ColorTransform AlphaBlend(ColorTransform foreground_transform,
                          ColorTransform background_transform,
                          SkAlpha alpha) {
  const auto generator = [](ColorTransform foreground_transform,
                            ColorTransform background_transform, SkAlpha alpha,
                            SkColor input_color, const ColorMixer& mixer) {
    const SkColor foreground_color =
        foreground_transform.Run(input_color, mixer);
    const SkColor background_color =
        background_transform.Run(input_color, mixer);
    const SkColor result_color =
        color_utils::AlphaBlend(foreground_color, background_color, alpha);
    DVLOG(2) << "ColorTransform AlphaBlend:" << " Input Color: "
             << SkColorName(input_color)
             << " FG Transform: " << SkColorName(foreground_color)
             << " BG Transform: " << SkColorName(background_color)
             << " Alpha: " << base::NumberToString(alpha)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(foreground_transform),
                             std::move(background_transform), alpha);
}

ColorTransform BlendForMinContrast(
    ColorTransform foreground_transform,
    ColorTransform background_transform,
    std::optional<ColorTransform> high_contrast_foreground_transform,
    float contrast_ratio) {
  const auto generator =
      [](ColorTransform foreground_transform,
         ColorTransform background_transform,
         std::optional<ColorTransform> high_contrast_foreground_transform,
         float contrast_ratio, SkColor input_color, const ColorMixer& mixer) {
        const SkColor foreground_color =
            foreground_transform.Run(input_color, mixer);
        const SkColor background_color =
            background_transform.Run(input_color, mixer);
        const std::optional<SkColor> high_contrast_foreground =
            high_contrast_foreground_transform.has_value()
                ? std::make_optional(
                      high_contrast_foreground_transform.value().Run(
                          input_color, mixer))
                : std::nullopt;
        const SkColor result_color =
            color_utils::BlendForMinContrast(foreground_color, background_color,
                                             high_contrast_foreground,
                                             contrast_ratio)
                .color;
        DVLOG(2) << "ColorTransform BlendForMinContrast:"
                 << " FG Transform Color: " << SkColorName(foreground_color)
                 << " BG Transform Color: " << SkColorName(background_color)
                 << " High Contrast Foreground: "
                 << (high_contrast_foreground.has_value()
                         ? SkColorName(high_contrast_foreground.value())
                         : "<none>")
                 << " Contrast Ratio: " << base::NumberToString(contrast_ratio)
                 << " Result Color: " << SkColorName(result_color);
        return result_color;
      };
  return base::BindRepeating(generator, std::move(foreground_transform),
                             std::move(background_transform),
                             std::move(high_contrast_foreground_transform),
                             contrast_ratio);
}

ColorTransform BlendForMinContrastWithSelf(ColorTransform transform,
                                           float contrast_ratio) {
  return BlendForMinContrast(transform, transform, std::nullopt,
                             contrast_ratio);
}

ColorTransform BlendTowardMaxContrast(ColorTransform transform, SkAlpha alpha) {
  const auto generator = [](ColorTransform transform, SkAlpha alpha,
                            SkColor input_color, const ColorMixer& mixer) {
    const SkColor transform_color = transform.Run(input_color, mixer);
    const SkColor result_color =
        color_utils::BlendTowardMaxContrast(transform_color, alpha);
    DVLOG(2) << "ColorTransform BlendTowardMaxContrast:" << " Input Color:"
             << SkColorName(input_color)
             << " Transform Color: " << SkColorName(transform_color)
             << " Alpha: " << base::NumberToString(alpha)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(transform), alpha);
}

ColorTransform ContrastInvert(ColorTransform transform) {
  const auto generator = [](ColorTransform transform, SkColor input_color,
                            const ColorMixer& mixer) {
    const SkColor foreground = transform.Run(input_color, mixer);
    const SkColor far_endpoint =
        color_utils::GetColorWithMaxContrast(foreground);
    const SkColor near_endpoint =
        color_utils::GetEndpointColorWithMinContrast(foreground);
    const float contrast_ratio =
        color_utils::GetContrastRatio(foreground, far_endpoint);
    const SkColor result_color =
        color_utils::BlendForMinContrast(foreground, near_endpoint,
                                         std::nullopt, contrast_ratio)
            .color;
    DVLOG(2) << "ColorTransform ContrastInvert:" << " Input Color: "
             << SkColorName(input_color)
             << " Foreground: " << SkColorName(foreground)
             << " Far End: " << SkColorName(far_endpoint)
             << " Near End: " << SkColorName(near_endpoint)
             << " Contrast Ratio: " << base::NumberToString(contrast_ratio)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(transform));
}

ColorTransform DeriveDefaultIconColor(ColorTransform transform) {
  const auto generator = [](ColorTransform transform, SkColor input_color,
                            const ColorMixer& mixer) {
    const SkColor transform_color = transform.Run(input_color, mixer);
    const SkColor result_color =
        color_utils::DeriveDefaultIconColor(transform_color);
    DVLOG(2) << "ColorTransform DeriveDefaultIconColor:" << " Input Color: "
             << SkColorName(input_color)
             << " Transform Color: " << SkColorName(transform_color)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(transform));
}

ColorTransform FromTransformInput() {
  const auto generator = [](SkColor input_color, const ColorMixer& mixer) {
    DVLOG(2) << "ColorTransform FromTransformInput: " << " Input/Result Color: "
             << SkColorName(input_color);
    return input_color;
  };
  return base::BindRepeating(generator);
}

ColorTransform GetColorWithMaxContrast(ColorTransform transform) {
  const auto generator = [](ColorTransform transform, SkColor input_color,
                            const ColorMixer& mixer) {
    const SkColor transform_color = transform.Run(input_color, mixer);
    const SkColor result_color =
        color_utils::GetColorWithMaxContrast(transform_color);
    DVLOG(2) << "ColorTransform GetColorWithMaxContrast:" << " Input Color: "
             << SkColorName(input_color)
             << " Transform Color: " << SkColorName(transform_color)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(transform));
}

ColorTransform GetEndpointColorWithMinContrast(ColorTransform transform) {
  const auto generator = [](ColorTransform transform, SkColor input_color,
                            const ColorMixer& mixer) {
    const SkColor transform_color = transform.Run(input_color, mixer);
    const SkColor result_color =
        color_utils::GetEndpointColorWithMinContrast(transform_color);
    DVLOG(2) << "ColorTransform GetEndPointColorWithMinContrast:"
             << " Input Color: " << SkColorName(input_color)
             << " Transform Color: " << SkColorName(transform_color)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(transform));
}

ColorTransform GetResultingPaintColor(ColorTransform foreground_transform,
                                      ColorTransform background_transform) {
  const auto generator = [](ColorTransform foreground_transform,
                            ColorTransform background_transform,
                            SkColor input_color, const ColorMixer& mixer) {
    const SkColor foreground_color =
        foreground_transform.Run(input_color, mixer);
    const SkColor background_color =
        background_transform.Run(input_color, mixer);
    const SkColor result_color =
        color_utils::GetResultingPaintColor(foreground_color, background_color);
    DVLOG(2) << "ColorTransform GetResultingPaintColor:" << " Input Color: "
             << SkColorName(input_color)
             << " FG Transform Color: " << SkColorName(foreground_color)
             << " BG Transform Color: " << SkColorName(background_color)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(foreground_transform),
                             std::move(background_transform));
}

ColorTransform SelectBasedOnDarkInput(
    ColorTransform input_transform,
    ColorTransform output_transform_for_dark_input,
    ColorTransform output_transform_for_light_input) {
  const auto generator = [](ColorTransform input_transform,
                            ColorTransform output_transform_for_dark_input,
                            ColorTransform output_transform_for_light_input,
                            SkColor input_color, const ColorMixer& mixer) {
    const SkColor color = input_transform.Run(input_color, mixer);
    const auto& output_transform = color_utils::IsDark(color)
                                       ? output_transform_for_dark_input
                                       : output_transform_for_light_input;
    const SkColor result_color = output_transform.Run(input_color, mixer);
    DVLOG(2) << "ColorTransform SelectBasedOnDarkInput:" << " Input Color: "
             << SkColorName(input_color)
             << " Input Transform: " << SkColorName(color)
             << " IsDark: " << base::ToString(color_utils::IsDark(color))
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(input_transform),
                             std::move(output_transform_for_dark_input),
                             std::move(output_transform_for_light_input));
}

ColorTransform SetAlpha(ColorTransform transform, SkAlpha alpha) {
  const auto generator = [](ColorTransform transform, SkAlpha alpha,
                            SkColor input_color, const ColorMixer& mixer) {
    const SkColor transform_color = transform.Run(input_color, mixer);
    const SkColor result_color = SkColorSetA(transform_color, alpha);
    DVLOG(2) << "ColorTransform SetAlpha:" << " Input Color: "
             << SkColorName(input_color)
             << " Transform Color: " << SkColorName(transform_color)
             << " Alpha: " << base::NumberToString(alpha)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(transform), alpha);
}

ColorTransform PickGoogleColor(ColorTransform foreground_transform,
                               ColorTransform background_transform,
                               float min_contrast,
                               float max_contrast) {
  const auto generator = [](ColorTransform foreground_transform,
                            ColorTransform background_transform,
                            float min_contrast, float max_contrast,
                            SkColor input_color, const ColorMixer& mixer) {
    const SkColor foreground_color =
        foreground_transform.Run(input_color, mixer);
    const SkColor background_color =
        background_transform.Run(input_color, mixer);
    const SkColor result_color = color_utils::PickGoogleColor(
        foreground_color, background_color, min_contrast, max_contrast);
    DVLOG(2) << "ColorTransform PickGoogleColor:" << " Input Color: "
             << SkColorName(input_color)
             << " Foreground Color: " << SkColorName(foreground_color)
             << " Background Color: " << SkColorName(background_color)
             << " Min Contrast: " << base::NumberToString(min_contrast)
             << " Max Contrast: " << base::NumberToString(max_contrast)
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(foreground_transform),
                             std::move(background_transform), min_contrast,
                             max_contrast);
}

ColorTransform PickGoogleColorTwoBackgrounds(
    ColorTransform foreground_transform,
    ColorTransform background_a_transform,
    ColorTransform background_b_transform,
    float min_contrast,
    float max_contrast_against_nearer) {
  const auto generator = [](ui::ColorTransform foreground_transform,
                            ui::ColorTransform background_a_transform,
                            ui::ColorTransform background_b_transform,
                            float min_contrast,
                            float max_contrast_against_nearer,
                            SkColor input_color, const ui::ColorMixer& mixer) {
    const SkColor foreground_color =
        foreground_transform.Run(input_color, mixer);
    const SkColor background_a_color =
        background_a_transform.Run(input_color, mixer);
    const SkColor background_b_color =
        background_b_transform.Run(input_color, mixer);
    const SkColor result_color = color_utils::PickGoogleColorTwoBackgrounds(
        foreground_color, background_a_color, background_b_color, min_contrast,
        max_contrast_against_nearer);
    DVLOG(2) << "ColorTransform PickGoogleColor:" << " Foreground Color: "
             << ui::SkColorName(foreground_color)
             << " Background Color A: " << ui::SkColorName(background_a_color)
             << " Background Color B: " << ui::SkColorName(background_b_color)
             << " Min Contrast: " << base::NumberToString(min_contrast)
             << " Max Contrast Against Nearer: "
             << base::NumberToString(max_contrast_against_nearer)
             << " Result Color: " << ui::SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(foreground_transform),
                             std::move(background_a_transform),
                             std::move(background_b_transform), min_contrast,
                             max_contrast_against_nearer);
}

ColorTransform HSLShift(ColorTransform color, color_utils::HSL hsl) {
  const auto generator = [](ColorTransform transform, color_utils::HSL hsl,
                            SkColor input_color, const ColorMixer& mixer) {
    const SkColor transform_color = transform.Run(input_color, mixer);
    const SkColor result_color = color_utils::HSLShift(transform_color, hsl);
    DVLOG(2) << "ColorTransform HSLShift:" << " Input Color: "
             << SkColorName(input_color)
             << " Transform Color: " << SkColorName(transform_color)
             << " HSL: {" << base::NumberToString(hsl.h) << ", "
             << base::NumberToString(hsl.s) << ", "
             << base::NumberToString(hsl.l) << "}"
             << " Result Color: " << SkColorName(result_color);
    return result_color;
  };
  return base::BindRepeating(generator, std::move(color), hsl);
}

}  // namespace ui