Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
utils.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * Copyright (C) 2023 AUTHORS
4 *
5 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
6 */
7
8#include <algorithm>
9#include <cmath>
10#include <glibmm/regex.h>
11#include <glibmm/stringutils.h>
12#include <iomanip>
13#include <sstream>
14
15#include "colors/color.h"
16#include "colors/spaces/base.h"
17#include "colors/spaces/named.h"
18#include "spaces/enum.h"
19
20namespace Inkscape::Colors {
21
32uint32_t hex_to_rgba(std::string const &value)
33{
34 if (value.empty())
35 return 0x0;
36
37 std::istringstream ss(value);
38 if (value.size() != 9 || ss.get() != '#') {
39 throw ColorError("Baddly formatted color, it must be in #RRGGBBAA format");
40 }
41 unsigned int hex;
42 ss >> std::hex >> hex;
43 return hex;
44}
45
54std::vector<double> rgba_to_values(uint32_t rgba, bool opacity)
55{
56 std::vector<double> values(3 + opacity);
57 values[0] = SP_RGBA32_R_F(rgba);
58 values[1] = SP_RGBA32_G_F(rgba);
59 values[2] = SP_RGBA32_B_F(rgba);
60 if (opacity) {
61 values[3] = SP_RGBA32_A_F(rgba);
62 }
63 return values;
64}
65
70std::string rgba_to_hex(uint32_t value, bool alpha)
71{
72 std::ostringstream oo;
73 oo.imbue(std::locale("C"));
74 oo << "#" << std::setfill('0') << std::setw(alpha ? 8 : 6) << std::hex << (alpha ? value : value >> 8);
75 return oo.str();
76}
77
81std::string color_to_id(std::optional<Color> const &color)
82{
83 if (!color)
84 return "none";
85
86 auto name = color->getName();
87 if (!name.empty() && name[0] != '#')
88 return desc_to_id(name);
89
90 std::ostringstream oo;
91
92 // Special case cssname
93 if (auto cns = std::dynamic_pointer_cast<Space::NamedColor>(color->getSpace())) {
94 auto name = cns->getNameFor(color->toRGBA());
95 if (!name.empty()) {
96 oo << "css-" << color->toString();
97 return oo.str();
98 }
99 }
100
101 oo << color->getSpace()->getName() << "-" << std::hex << std::setfill('0');
102 for (double const &value : color->getValues()) {
103 unsigned int diget = value * 0xff;
104 oo << std::setw(2) << diget;
105 }
106
107 auto ret = oo.str();
108 std::transform(ret.begin(), ret.end(), ret.begin(), ::tolower);
109 return ret;
110}
111
115std::string desc_to_id(std::string const &desc)
116{
117 auto name = Glib::ustring(desc);
118 // Convert description to ascii, strip out symbols, remove duplicate dashes and prefixes
119 static auto const reg1 = Glib::Regex::create("[^[:alnum:]]");
120 name = reg1->replace(name, 0, "-", static_cast<Glib::Regex::MatchFlags>(0));
121 static auto const reg2 = Glib::Regex::create("-{2,}");
122 name = reg2->replace(name, 0, "-", static_cast<Glib::Regex::MatchFlags>(0));
123 static auto const reg3 = Glib::Regex::create("(^-|-$)");
124 name = reg3->replace(name, 0, "", static_cast<Glib::Regex::MatchFlags>(0));
125 // Move important numbers from the start where they are invalid xml, to the end.
126 static auto const reg4 = Glib::Regex::create("^(\\d+)(-?)([^\\d]*)");
127 name = reg4->replace(name, 0, "\\3\\2\\1", static_cast<Glib::Regex::MatchFlags>(0));
128 return name.lowercase();
129}
130
134Color make_contrasted_color(Color const &orig, double amount)
135{
136 if (auto color = orig.converted(Space::Type::HSL)) {
137 auto lightness = (*color)[2];
138 color->set(2, lightness + ((lightness < 0.08 ? 0.08 : -0.08) * amount));
139 color->convert(orig.getSpace());
140 return *color;
141 }
142 return orig;
143}
144
149{
150 // color of the image strip to HSL, so we can manipulate its lightness
151 auto color = *orig.converted(Colors::Space::Type::HSLUV);
152
153 if (dark) {
154 // limit saturation to improve contrast with some artwork
155 color.set(1, std::min(color[1], 0.8));
156 // make a darker shade and limit to remove extremes
157 color.set(2, std::min(color[2] * 0.7, 0.3));
158 } else {
159 // make a lighter shade and limit to remove extemes
160 color.set(2, std::max(color[2] + (1.0 - color[2]) * 0.5, 0.8));
161 }
162
163 return *color.converted(Colors::Space::Type::RGB);
164}
165
166double perceptual_lightness(double l)
167{
168 return l <= 0.885645168 ? l * 0.09032962963 : std::cbrt(l) * 0.249914424 - 0.16;
169}
170
174double get_perceptual_lightness(Color const &color)
175{
176 return perceptual_lightness((*color.converted(Space::Type::HSLUV))[2] * 100);
177}
178
179std::pair<double, double> get_contrasting_color(double l)
180{
181 double constexpr l_threshold = 0.85;
182 if (l > l_threshold) { // Draw dark over light.
183 auto t = (l - l_threshold) / (1.0 - l_threshold);
184 return {0.0, 0.4 - 0.1 * t};
185 } else { // Draw light over dark.
186 auto t = (l_threshold - l) / l_threshold;
187 return {1.0, 0.6 + 0.1 * t};
188 }
189}
190
191}; // namespace Inkscape::Colors
192
193/*
194 Local Variables:
195 mode:c++
196 c-file-style:"stroustrup"
197 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
198 indent-tabs-mode:nil
199 fill-column:99
200 End:
201*/
202// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
bool set(unsigned int index, double value)
Set a specific channel in the color.
Definition color.cpp:350
std::optional< Color > converted(Color const &other) const
Return a copy of this color converted to the same format as the other color.
Definition color.cpp:189
constexpr double SP_RGBA32_G_F(uint32_t v)
Definition utils.h:47
constexpr double SP_RGBA32_R_F(uint32_t v)
Definition utils.h:43
constexpr double SP_RGBA32_A_F(uint32_t v)
Definition utils.h:55
constexpr double SP_RGBA32_B_F(uint32_t v)
Definition utils.h:51
Geom::Point orig
A set of useful color modifying functions which do not fit as generic methods on the color class itse...
Definition profile.cpp:24
std::vector< double > rgba_to_values(uint32_t rgba, bool opacity)
Convert a 32bit unsigned int into a set of 3 or 4 double values for rgba.
Definition utils.cpp:54
std::pair< double, double > get_contrasting_color(double l)
Definition utils.cpp:179
uint32_t hex_to_rgba(std::string const &value)
Parse a color directly without any CSS or CMS support.
Definition utils.cpp:32
double perceptual_lightness(double l)
Definition utils.cpp:166
double get_perceptual_lightness(Color const &color)
Return a value for how the light the color appears to be using HSLUV.
Definition utils.cpp:174
Color make_contrasted_color(Color const &orig, double amount)
Make a darker or lighter version of the color, useful for making checkerboards.
Definition utils.cpp:134
double lightness(Color color)
std::string color_to_id(std::optional< Color > const &color)
Create a somewhat unique id for the given color used for palette identification.
Definition utils.cpp:81
Color make_theme_color(Color const &orig, bool dark)
Make a themed dark or light color based on a previous shade, returns RGB color.
Definition utils.cpp:148
std::string desc_to_id(std::string const &desc)
Transform a color name or description into an id used for palette identification.
Definition utils.cpp:115
std::string rgba_to_hex(uint32_t value, bool alpha)
Output the RGBA value as a #RRGGBB hex color, if alpha is true then the output will be #RRGGBBAA inst...
Definition utils.cpp:70
Glib::ustring name
Definition toolbars.cpp:55