Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
color-wheel-factory.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2//
3
4#include <chrono>
6
7#include "color-plate.h"
8#include "ink-color-wheel.h"
9#include "oklab-color-wheel.h"
10
11namespace Inkscape::UI::Widget {
12
13using namespace Colors::Space;
14
15constexpr bool TEST_TIMING = false;
16
17class FastColorWheel : public ColorPlate, public ColorWheel {
18public:
19 FastColorWheel(Type source, Type plate, int fixed_channel, int var_channel1, int var_channel2, bool disc) {
20 _source = source;
21 _plate = plate;
22 _fixed_channel = fixed_channel;
23 _var_channel1 = var_channel1;
24 _var_channel2 = var_channel2;
25 set_disc(disc);
26 }
27
28 void set_color(const Colors::Color& color) override {
29 auto copy = color.converted(_plate);
30 auto dest = copy.value_or(Colors::Color{_plate, {0,0,0}});
31 set_base_color(dest, _fixed_channel, _var_channel1, _var_channel2);
32 // move color indicator to correct spot on the disc
34 }
35 Widget& get_widget() override { return *this; }
36 sigc::connection connect_color_changed(sigc::slot<void(const Colors::Color&)> cb) override {
37 return signal_color_changed().connect([this, cb](auto& c) {
38 auto color = c.converted(_source);
39 if (color) cb(*color); else g_warning("Color conversion from type %d to type %d failed.", int(_plate), int(_source));
40 });
41 }
42 void redraw(const Cairo::RefPtr<Cairo::Context>& ctx) override { draw_plate(ctx); }
43
44private:
45 Type _source;
46 Type _plate;
47 int _fixed_channel;
48 int _var_channel1;
49 int _var_channel2;
50};
51
52static std::pair<ColorWheel*, bool> create_color_wheel_helper(Type type, bool create_widget) {
53 bool can_create = true;
54 ColorWheel* wheel = nullptr;
55
56 switch (type) {
57 case Type::HSL:
58 if (create_widget) wheel = new ColorWheelHSL();
59 break;
60
61 case Type::HSLUV:
62 if (create_widget) wheel = new ColorWheelHSLuv();
63 break;
64
65 case Type::OKHSL:
66 if (create_widget) {
67 auto luminocity = 2; // if luma changes, color wheel needs to be rebuilt
68 auto hue = 0; // vary hue with angle (while painting the disc)
69 auto sat = 1; // vary saturation with distance from the center of the disc (while painting the disc)
70 wheel = new FastColorWheel(Type::OKHSL, Type::OKHSL, luminocity, hue, sat, true);
71 }
72 break;
73
74 case Type::HSV:
75 if (create_widget) wheel = new ColorWheelHSL();
76 // if (create_widget) {
77 // wheel = new FastColorWheel(Type::HSV, Type::HSV);
78 // }
79 break;
80
81 case Type::RGB:
82 if (create_widget) {
83 // create rectangular HSV plate for RGB picker
84 auto hue = 0; // hue is fixed in a rectangular plate
85 auto sat = 1; // vary saturation
86 auto val = 2; // vary value
87 wheel = new FastColorWheel(Type::RGB, Type::HSV, hue, sat, val, false);
88 }
89 break;
90
91 default:
92 can_create = false;
93 break;
94 }
95
96 // Speed test - use this test to evaluate how quickly we can rebuild a color wheel of given Space::Type
97 if (TEST_TIMING && create_widget) {
98 // test
99 ColorWheel* w1 = new FastColorWheel(Type::OKHSL, Type::OKHSL, 0, 1, 2, true);
100 ColorWheel* w2 = new OKWheel();
101
102 auto s = Cairo::ImageSurface::create(Cairo::Surface::Format::ARGB32, 1024, 1024);
103 auto ctx = Cairo::Context::create(s);
104 for (auto w : {w1, w2}) {
105 w->get_widget().size_allocate(Gtk::Allocation(0,0,500,500), 0);
106 // w->get_widget().set_size_request(500, 500);
107 auto old_time = std::chrono::high_resolution_clock::now();
108 Colors::Color color(Type::OKHSL, {0.5, 0.5, 0.5});
109 for (int i = 0; i < 100; ++i) {
110 color.set(0, i / 100.0);
111 w->set_color(color);
112 w->redraw(ctx);
113 }
114 auto current_time = std::chrono::high_resolution_clock::now();
115 auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(current_time - old_time);
116 g_message("render time for test wheel: %d ms", static_cast<int>(elapsed.count()));
117 }
118
119 delete w1;
120 delete w2;
121 }
122
123 return std::make_pair(wheel, can_create);
124}
125
127 auto [wheel, _] = create_color_wheel_helper(type, true);
128 if (wheel) {
129 wheel->get_widget().set_manage();
130 }
131 return wheel;
132}
133
135 auto [_, ok] = create_color_wheel_helper(type, false);
136 return ok;
137}
138
139} // Inkscape
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
void draw_plate(const Cairo::RefPtr< Cairo::Context > &ctx)
void move_indicator_to(const Colors::Color &color)
sigc::signal< void(const Colors::Color &)> & signal_color_changed()
void set_base_color(Colors::Color color, int fixed_channel, int var_channel1, int var_channel2)
The color wheel used in the OKHSL picker.
const double w
Definition conic-4.cpp:19
double c[8][4]
Custom widgets.
Definition desktop.h:126
bool can_create_color_wheel(Type type)
static std::pair< ColorWheel *, bool > create_color_wheel_helper(Type type, bool create_widget)
ColorWheel * create_managed_color_wheel(Type type)
W & get_widget(const Glib::RefPtr< Gtk::Builder > &builder, const char *id)
void redraw()