The Battle for Wesnoth 1.21.0-dev
 
Loading...
Searching...
No Matches
color_range.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2003 - 2025
3 by David White <dave@whitevine.net>
4 Part of the Battle for Wesnoth Project https://www.wesnoth.org/
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY.
12
13 See the COPYING file for more details.
14*/
15
16/**
17 * @file
18 * Generate ranges of colors, and color palettes.
19 * Used e.g. to color HP, XP.
20 */
21
22#include "color_range.hpp"
23
24#include "utils/span.hpp"
25
26#include <array>
27#include <cassert>
28#include <sstream>
29
30namespace
31{
32std::vector<color_t> recolor_palette(const color_range& new_range, utils::span<const color_t> old_rgb)
33{
34 std::vector<color_t> clist;
35 clist.reserve(old_rgb.size());
36
37 const color_t mid_c = new_range.mid();
38 const color_t max_c = new_range.max();
39 const color_t min_c = new_range.min();
40
41 // Map first color in vector to exact new color
42 const uint8_t reference_avg = old_rgb.empty()
43 ? 255u
44 : (old_rgb[0].r + old_rgb[0].g + old_rgb[0].b) / 3;
45
46 for(const color_t& old_c : old_rgb) {
47 const uint8_t old_avg = (old_c.r + old_c.g + old_c.b) / 3;
48
49 if(reference_avg && old_avg <= reference_avg) {
50 float old_ratio = static_cast<float>(old_avg) / reference_avg;
51
52 clist.emplace_back(
53 std::min(255u, static_cast<uint32_t>(old_ratio * mid_c.r + (1 - old_ratio) * min_c.r)),
54 std::min(255u, static_cast<uint32_t>(old_ratio * mid_c.g + (1 - old_ratio) * min_c.g)),
55 std::min(255u, static_cast<uint32_t>(old_ratio * mid_c.b + (1 - old_ratio) * min_c.b))
56 );
57 } else if(reference_avg != 255) {
58 float old_ratio = (255.0f - static_cast<float>(old_avg)) / (255.0f - reference_avg);
59
60 clist.emplace_back(
61 std::min(255u, static_cast<uint32_t>(old_ratio * mid_c.r + (1 - old_ratio) * max_c.r)),
62 std::min(255u, static_cast<uint32_t>(old_ratio * mid_c.g + (1 - old_ratio) * max_c.g)),
63 std::min(255u, static_cast<uint32_t>(old_ratio * mid_c.b + (1 - old_ratio) * max_c.b))
64 );
65 }
66 }
67
68 return clist;
69}
70
71constexpr auto base_palette = []() {
72 // Two entries per color, except on the first iteration.
73 std::array<color_t, (255 * 2) - 1> res;
74 std::size_t index = 0;
75
76 // Use blue to make master set of possible colors
77 for(uint8_t i = 255u; i != 0; --i) {
78 res[index++] = {0, 0, i};
79
80 // Avoid duplicate entry on the first pass when j == 0
81 if(uint8_t j = 255u - i; j != 0) {
82 res[index++] = {j, j, 255};
83 }
84 }
85
86 return res;
87}();
88
89} // namespace
90
91color_mapping generate_color_mapping(const color_range& new_range, const std::vector<color_t>& old_rgb)
92{
93 std::vector new_rgb = recolor_palette(new_range, old_rgb);
94 assert(new_rgb.size() == old_rgb.size());
95
96 color_mapping res;
97 for(std::size_t i = 0; i < new_rgb.size(); ++i) {
98 res[old_rgb[i]] = new_rgb[i];
99 }
100
101 return res;
102}
103
104std::vector<color_t> generate_reference_palette(const color_range& cr)
105{
106 return recolor_palette(cr, base_palette);
107}
108
109std::string color_range::debug() const
110{
111 std::ostringstream o;
112
113 o << '{' << mid_.to_hex_string()
114 << ',' << max_.to_hex_string()
115 << ',' << min_.to_hex_string()
116 << ',' << rep_.to_hex_string()
117 << ',' << font_color_.to_hex_string()
118 << '}';
119
120 return o.str();
121}
constexpr bool empty() const noexcept
Definition span.hpp:363
constexpr size_type size() const noexcept
Definition span.hpp:355
Representing the "team color" information, this C++ class contains a subset of WML's [color_range] ta...
color_t max() const
Maximum color shade.
color_t font_color_
color_t mid() const
Average color shade.
color_t min() const
Minimum color shade.
std::string debug() const
Return a string describing the color range for debug output.
color_mapping generate_color_mapping(const color_range &new_range, const std::vector< color_t > &old_rgb)
Converts a source palette using the specified color_range object.
std::vector< color_t > generate_reference_palette(const color_range &cr)
Creates a reference color palette from a color range.
std::unordered_map< color_t, color_t > color_mapping
std::size_t index(std::string_view str, const std::size_t index)
Codepoint index corresponding to the nth character in a UTF-8 string.
Definition unicode.cpp:70
The basic class for representing 8-bit RGB or RGBA colour values.
Definition color.hpp:51
std::string to_hex_string() const
Returns the stored color in rrggbb hex format.
Definition color.cpp:88
#define i