diff --git a/share/icons/Tango/scalable/actions/color-management.svg b/share/icons/Tango/scalable/actions/color-cms.svg
similarity index 100%
rename from share/icons/Tango/scalable/actions/color-management.svg
rename to share/icons/Tango/scalable/actions/color-cms.svg
diff --git a/share/icons/Tango/scalable/actions/color-colorproof.svg b/share/icons/Tango/scalable/actions/color-colorproof.svg
new file mode 100644
index 0000000000000000000000000000000000000000..68f016f58dce13974ca4e097b6c20df5fc9f471e
--- /dev/null
+++ b/share/icons/Tango/scalable/actions/color-colorproof.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/Tango/scalable/actions/color-gamutwarn.svg b/share/icons/Tango/scalable/actions/color-gamutwarn.svg
new file mode 100644
index 0000000000000000000000000000000000000000..de5ccabdef01a3d198a529678a550e831264ae4b
--- /dev/null
+++ b/share/icons/Tango/scalable/actions/color-gamutwarn.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/hicolor/scalable/actions/color-management.svg b/share/icons/hicolor/scalable/actions/color-cms.svg
similarity index 100%
rename from share/icons/hicolor/scalable/actions/color-management.svg
rename to share/icons/hicolor/scalable/actions/color-cms.svg
diff --git a/share/icons/hicolor/scalable/actions/color-colorproof.svg b/share/icons/hicolor/scalable/actions/color-colorproof.svg
new file mode 100644
index 0000000000000000000000000000000000000000..68f016f58dce13974ca4e097b6c20df5fc9f471e
--- /dev/null
+++ b/share/icons/hicolor/scalable/actions/color-colorproof.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/hicolor/scalable/actions/color-gamutwarn.svg b/share/icons/hicolor/scalable/actions/color-gamutwarn.svg
new file mode 100644
index 0000000000000000000000000000000000000000..de5ccabdef01a3d198a529678a550e831264ae4b
--- /dev/null
+++ b/share/icons/hicolor/scalable/actions/color-gamutwarn.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/hicolor/symbolic/actions/cms-color-ink-symbolic.svg b/share/icons/hicolor/symbolic/actions/cms-color-ink-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..6caecaa4a462cbaf6a63efab3705029e767f9a69
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/cms-color-ink-symbolic.svg
@@ -0,0 +1,23 @@
+
+
diff --git a/share/icons/hicolor/symbolic/actions/cms-color-rgb-symbolic.svg b/share/icons/hicolor/symbolic/actions/cms-color-rgb-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..db4631b7689354e3e7f650db50950ad0650acd6e
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/cms-color-rgb-symbolic.svg
@@ -0,0 +1,23 @@
+
+
diff --git a/share/icons/multicolor/symbolic/actions/color-management-symbolic.svg b/share/icons/hicolor/symbolic/actions/color-cms-symbolic.svg
similarity index 100%
rename from share/icons/multicolor/symbolic/actions/color-management-symbolic.svg
rename to share/icons/hicolor/symbolic/actions/color-cms-symbolic.svg
diff --git a/share/icons/hicolor/symbolic/actions/color-colorproof-symbolic.svg b/share/icons/hicolor/symbolic/actions/color-colorproof-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..68f016f58dce13974ca4e097b6c20df5fc9f471e
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/color-colorproof-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/hicolor/symbolic/actions/color-displayprofile-symbolic.svg b/share/icons/hicolor/symbolic/actions/color-displayprofile-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..1b2eccaf29dbc134f98b49347fb7c219e9424578
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/color-displayprofile-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/hicolor/symbolic/actions/color-gamutwarn-symbolic.svg b/share/icons/hicolor/symbolic/actions/color-gamutwarn-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..de5ccabdef01a3d198a529678a550e831264ae4b
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/color-gamutwarn-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/multicolor/symbolic/actions/cms-color-ink-symbolic.svg b/share/icons/multicolor/symbolic/actions/cms-color-ink-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..da39fe48477c9cef595bafc4b0c9a5f2ca133ad3
--- /dev/null
+++ b/share/icons/multicolor/symbolic/actions/cms-color-ink-symbolic.svg
@@ -0,0 +1,13 @@
+
+
diff --git a/share/icons/multicolor/symbolic/actions/cms-color-rgb-symbolic.svg b/share/icons/multicolor/symbolic/actions/cms-color-rgb-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..db4631b7689354e3e7f650db50950ad0650acd6e
--- /dev/null
+++ b/share/icons/multicolor/symbolic/actions/cms-color-rgb-symbolic.svg
@@ -0,0 +1,23 @@
+
+
diff --git a/share/icons/hicolor/symbolic/actions/color-management-symbolic.svg b/share/icons/multicolor/symbolic/actions/color-cms-symbolic.svg
similarity index 93%
rename from share/icons/hicolor/symbolic/actions/color-management-symbolic.svg
rename to share/icons/multicolor/symbolic/actions/color-cms-symbolic.svg
index 74ef23e2f57299372e10ffd61f88293ab5dd009d..37027abbcf2e6a00fb6b742807da404c49452a05 100644
--- a/share/icons/hicolor/symbolic/actions/color-management-symbolic.svg
+++ b/share/icons/multicolor/symbolic/actions/color-cms-symbolic.svg
@@ -14,7 +14,15 @@
width="16"
id="svg1"
version="1.1">
-
+
+
+
@@ -30,6 +38,7 @@
+
diff --git a/share/icons/multicolor/symbolic/actions/color-displayprofile-symbolic.svg b/share/icons/multicolor/symbolic/actions/color-displayprofile-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..bc44a21462e1386f607cc0e1fdae405ad0862ae2
--- /dev/null
+++ b/share/icons/multicolor/symbolic/actions/color-displayprofile-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/icons/multicolor/symbolic/actions/color-gamutwarn-symbolic.svg b/share/icons/multicolor/symbolic/actions/color-gamutwarn-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..ac7ff65c7ee2605bead9aa70f9f5e91692e2f41f
--- /dev/null
+++ b/share/icons/multicolor/symbolic/actions/color-gamutwarn-symbolic.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/share/ui/cms-popover.glade b/share/ui/cms-popover.glade
new file mode 100644
index 0000000000000000000000000000000000000000..4ad7a3ff6e2097cdae3c14fa4726430d8f68f3dc
--- /dev/null
+++ b/share/ui/cms-popover.glade
@@ -0,0 +1,436 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/share/ui/display-popup.glade b/share/ui/display-popup.glade
index 2cc7f1c6c7b81c45e00a82dc499f2b101b7ee680..523c4e73fddff1a2be97c5fa8e3b875e500de594 100644
--- a/share/ui/display-popup.glade
+++ b/share/ui/display-popup.glade
@@ -16,19 +16,6 @@
8
8
8
-
-
- True
- start
- 5
- Display mode:
-
-
- 0
- 0
- 3
-
-
@@ -123,7 +110,7 @@
0
- 8
+ 7
@@ -134,7 +121,7 @@
0
- 9
+ 8
@@ -145,7 +132,7 @@
0
- 7
+ 6
3
@@ -157,7 +144,7 @@
0
- 11
+ 9
3
@@ -171,7 +158,7 @@
0
- 12
+ 10
3
@@ -192,7 +179,7 @@
1
- 8
+ 7
@@ -212,52 +199,21 @@
1
- 9
+ 8
-
+
True
- start
+ False
5
- 5
-
-
- True
- True
- True
- Toggle between normal and color managed modes
- win.canvas-color-manage
-
-
- True
- color-management-symbolic
-
-
-
-
-
-
- True
- True
- True
- Toggle between normal and grayscale modes
- win.canvas-color-mode
-
-
- True
- grayscale-mode-symbolic
-
-
-
-
- 1
-
-
+ 5
+ Display Mode:
+ 0
0
- 6
+ 0
3
diff --git a/share/ui/document-properties.glade b/share/ui/document-properties.glade
new file mode 100644
index 0000000000000000000000000000000000000000..d0f9a5e0bd0ccbac5ab758fe97bc0970da430534
--- /dev/null
+++ b/share/ui/document-properties.glade
@@ -0,0 +1,306 @@
+
+
+
+
+
+
+
+
+
+
+
+ Standard SVG (sRGB)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Automatic
+ auto
+
+
+ Perceptual
+ perceptual
+
+
+ Saturation
+ saturation
+
+
+ Relative Colorimetric
+ relative-colorimetric
+
+
+ Relative Colorimetric with no BPC
+ relative-colorimetric-nobpc
+
+
+ Absolute Colorimetric
+ absolute-colorimetric
+
+
+
+
+ 500
+ True
+ False
+ 10
+ 10
+ 5
+ vertical
+
+
+ True
+ False
+ Color Managed Profile
+ 0
+
+
+
+
+
+ False
+ True
+ 0
+
+
+
+
+ True
+ False
+ 10
+ 10
+ Color management in Inkscape is handled by the use of Color Profiles (icc) which define how colors are transformed from the SVG standard color working space, which is always sRGB, into alternate color spaces used for printing and other output.
+
+Please see the Inkscape website cms learn page for more information:
+ True
+ 0
+
+
+ False
+ True
+ 1
+
+
+
+
+ https://inkscape.org/learn/cms
+ True
+ True
+ True
+ none
+ https://inkscape.org/learn/cms
+
+
+ False
+ True
+ 2
+
+
+
+
+ True
+ False
+ Target Color Profile
+ 0
+
+
+
+
+
+ False
+ True
+ 3
+
+
+
+
+ True
+ False
+ 10
+ 10
+ This target profile will change how Inkscape's color pickers work, settings colors with both the RGB value and the color profile's colors. Usually CMYK. It will also be used by color managed display mode for color proofing for printing.
+ True
+ 0
+
+
+ False
+ True
+ 4
+
+
+
+
+ True
+ False
+
+
+ True
+ False
+ color-profiles-store
+ 0
+ 0
+
+
+
+ 0
+
+
+
+
+ True
+ True
+ 0
+
+
+
+
+ True
+ False
+ rendering-intent-store
+ 1
+
+
+
+ 0
+
+
+
+
+ False
+ True
+ 1
+
+
+
+
+ True
+ True
+ True
+ 5
+
+
+ True
+ False
+ document-open
+
+
+
+
+ False
+ True
+ 2
+
+
+
+
+ False
+ True
+ 5
+
+
+
+
+ Convert all Existing Colors ...
+ True
+ True
+ True
+ end
+ 20
+ 20
+ 10
+ 10
+
+
+ False
+ True
+ 6
+
+
+
+
+ True
+ False
+ Other Color Profiles
+ 0
+
+
+
+
+
+ False
+ True
+ 7
+
+
+
+
+ True
+ True
+ 5
+ 5
+ 5
+ 10
+ in
+
+
+ True
+ True
+ other-profiles-store
+ False
+ 0
+ False
+ 2
+
+
+
+
+
+ Name
+
+
+
+ 0
+
+
+
+
+
+
+ Rendering Intent
+
+
+
+ 1
+
+
+
+
+
+
+
+
+ True
+ True
+ 8
+
+
+
+
diff --git a/share/ui/menus.ui b/share/ui/menus.ui
index 5822c5ef525e6531f924e905353e9cbf9a38aead..80755cba665c18fa462b2fc21e6cadadcb9be1a0 100644
--- a/share/ui/menus.ui
+++ b/share/ui/menus.ui
@@ -527,14 +527,31 @@
- -
- Gray Scale
- win.canvas-color-mode
-
- -
- Color Management
- win.canvas-color-manage
-
+
+ _Color Mode
+
+ -
+ _Gray Scale
+ win.canvas-color-mode
+
+ -
+ _Proof Colors
+ win.canvas-color-softproof
+
+
+
+ -
+ _Display Profile
+ win.canvas-color-displayprofile
+
+
+
+ -
+ _Setup
+ win.canvas-color-prefs
+
+
+
-
Page _Grid
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 1a735b364344dbfc1119b617f400c3f2c48049fe..e09a096e5b9e75ecdf6ec00fd77bcf5ee2933f1f 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -57,7 +57,6 @@ set(inkscape_SRC
perspective-line.cpp
preferences.cpp
print.cpp
- profile-manager.cpp
proj_pt.cpp
pure-transform.cpp
rdf.cpp
@@ -97,7 +96,6 @@ set(inkscape_SRC
color-rgba.h
hsluv.h
color.h
- colorspace.h
composite-undo-stack-observer.h
conditions.h
conn-avoid-ref.h
@@ -151,7 +149,6 @@ set(inkscape_SRC
preferences-skeleton.h
preferences.h
print.h
- profile-manager.h
proj_pt.h
pure-transform.h
rdf.h
@@ -307,7 +304,7 @@ list(APPEND inkscape_SRC
# these call add_inkscape_source
add_subdirectory(actions)
add_subdirectory(async)
-add_subdirectory(color)
+add_subdirectory(colors)
add_subdirectory(debug)
add_subdirectory(display)
add_subdirectory(extension)
diff --git a/src/actions/actions-canvas-mode.cpp b/src/actions/actions-canvas-mode.cpp
index 5a37abad3b4d98ad850a3c700cb21838e893b288..978efa589f2b9a0384efc9436429dac4dbd80285 100644
--- a/src/actions/actions-canvas-mode.cpp
+++ b/src/actions/actions-canvas-mode.cpp
@@ -19,7 +19,9 @@
#include "actions-helper.h"
+#include "colors/manager.h"
#include "desktop.h"
+#include "document.h"
#include "inkscape-application.h"
#include "inkscape-window.h"
@@ -27,7 +29,10 @@
#include "display/drawing.h" // Setting gray scale parameters.
#include "display/control/canvas-item-drawing.h"
+#include "ui/dialog/dialog-container.h"
+#include "ui/dialog/inkscape-preferences.h"
#include "ui/widget/canvas.h"
+#include "document-undo.h"
// TODO: Use action state rather than set variable in Canvas (via Desktop).
// TODO: Move functions from Desktop to Canvas.
@@ -199,67 +204,92 @@ canvas_color_mode_gray(InkscapeWindow *win)
* Toggle Gray scale on/off.
*/
void
-canvas_color_mode_toggle(InkscapeWindow *win)
+canvas_color_mode_toggle(bool state, InkscapeWindow *win)
{
- auto action = win->lookup_action("canvas-color-mode");
- if (!action) {
- show_output("canvas_color_mode_toggle: action missing!");
- return;
- }
-
- auto saction = Glib::RefPtr::cast_dynamic(action);
- if (!saction) {
- show_output("canvas_color_mode_toggle: action not SimpleAction!");
- return;
- }
-
- bool state = false;
- saction->get_state(state);
- state = !state;
- saction->change_state(state);
-
if (state) {
// Set gray scale parameters.
canvas_color_mode_gray(win);
}
+ auto canvas = win->get_desktop()->getCanvas();
+ canvas->set_color_mode(state ? Inkscape::ColorMode::GRAYSCALE : Inkscape::ColorMode::NORMAL);
+}
+void
+canvas_color_prefs(InkscapeWindow *win)
+{
SPDesktop* dt = win->get_desktop();
- auto canvas = dt->getCanvas();
- canvas->set_color_mode(state ? Inkscape::ColorMode::GRAYSCALE : Inkscape::ColorMode::NORMAL);
+ dt->getContainer()->get_dialog_page("Preferences", PREFS_PAGE_IO_CMS);
}
+void
+canvas_color_props(InkscapeWindow *win)
+{
+ SPDesktop* dt = win->get_desktop();
+ dt->getContainer()->get_dialog_page("DocumentProperties", 3);
+}
+
+void
+canvas_color_gamutwarn(bool state, InkscapeWindow *win)
+{
+ auto canvas = win->get_desktop()->getCanvas();
+ canvas->set_color_mode(state ? Inkscape::ColorMode::GAMUTWARN : Inkscape::ColorMode::COLORPROOF);
+}
/**
- * Toggle Color management on/off.
+ * Keep the gamut warning up to date, based on the color proof setting
*/
-void
-canvas_color_manage_toggle(InkscapeWindow *win)
+void _update_actions_canvas_mode(InkscapeWindow *win, bool is_colorproof)
{
- auto action = win->lookup_action("canvas-color-manage");
- if (!action) {
- show_output("canvas_color_manage_toggle: action missing!");
- return;
+ if (auto action = Glib::RefPtr::cast_dynamic(win->lookup_action("canvas-color-colorproof"))) {
+ action->change_state(is_colorproof);
+ auto desktop = win->get_desktop();
+ desktop->getCanvas()->set_color_mode(is_colorproof ? Inkscape::ColorMode::COLORPROOF : Inkscape::ColorMode::NORMAL);
}
-
- auto saction = Glib::RefPtr::cast_dynamic(action);
- if (!saction) {
- show_output("canvas_color_manage_toggle: action not SimpleAction!");
- return;
+ if (auto action = Glib::RefPtr::cast_dynamic(win->lookup_action("canvas-color-gamutwarn"))) {
+ bool active = false;
+ action->get_state(active);
+ if (!is_colorproof && active) {
+ canvas_color_gamutwarn(false, win);
+ action->change_state(false);
+ }
+ action->set_enabled(is_colorproof);
}
+}
- bool state = false;
- saction->get_state(state);
- state = !state;
- saction->change_state(state);
-
- // Save value as a preference
- Inkscape::Preferences *pref = Inkscape::Preferences::get();
- pref->setBool("/options/displayprofile/enable", state);
+void
+canvas_color_colorproof(bool state, InkscapeWindow *win)
+{
+ auto prefs = Inkscape::Preferences::get();
+ auto desktop = win->get_desktop();
+ auto &cm = desktop->getDocument()->getColorManager();
+
+ // Ensure we have a cmyk profile if enabling for the first time
+ if (state && !cm.defaultSpace()) {
+ auto default_uri = prefs->getString("/options/cms/uri");
+ auto default_intent = prefs->getInt("/options/cms/intent");
+ if (!default_uri.empty()) {
+ // Preferences contain a default cms profile, use that
+ //if (auto profile = cm.addProfile(default_uri)) {
+ // XXX profile->setIntent(Inkscape::Colors::RenderingIntent)(default_intent+2);
+ //cm.setDefault(profile);
+ //Inkscape::DocumentUndo::done(desktop->getDocument(), _("Auto add default color profile"), "");
+ // TODO: Convert all colors to the new profile, but ASK first!
+ // cm.convertToCMYK(profile);
+ //} else {
+ //g_warning("Couldnt set the default cms profile: '%s'", default_uri.c_str());
+ //}
+ } else {
+ // No default, so we're opening the document properties instead
+ if (auto action = Glib::RefPtr::cast_dynamic(win->lookup_action("canvas-color-colorproof"))) {
+ action->change_state(false);
+ }
+ canvas_color_props(win);
+ return;
+ }
+ }
- SPDesktop* dt = win->get_desktop();
- auto canvas = dt->getCanvas();
- canvas->set_cms_active(state);
- canvas->redraw_all();
+ // Cascade softproofing option to the gamut warning
+ _update_actions_canvas_mode(win, state);
}
std::vector> raw_data_canvas_mode =
@@ -270,45 +300,37 @@ std::vector> raw_data_canvas_mode =
{"win.canvas-display-mode(2)", N_("Display Mode: No Filters"), "Canvas Display", N_("Do not render filters (for speed)") },
{"win.canvas-display-mode(3)", N_("Display Mode: Enhance Thin Lines"), "Canvas Display", N_("Ensure all strokes are displayed on screen as at least 1 pixel wide")},
{"win.canvas-display-mode(4)", N_("Display Mode: Outline Overlay"), "Canvas Display", N_("Show objects as outlines, and the actual drawing below them with reduced opacity")},
+ {"win.canvas-display-mode(5)", N_("Display Mode: Grayscale"), "Canvas Display", N_("Show everything in a grayscale mode") },
{"win.canvas-display-mode-cycle", N_("Display Mode: Cycle"), "Canvas Display", N_("Cycle through display modes") },
{"win.canvas-display-mode-toggle", N_("Display Mode: Toggle"), "Canvas Display", N_("Toggle between normal and last non-normal mode")},
{"win.canvas-display-mode-toggle-preview", N_("Display Mode: Toggle Preview"), "Canvas Display", N_("Toggle between preview and previous mode") },
+ {"win.canvas-zoom-resize", N_("Zoom on window resize"), "Canvas Display", N_("Toggle zoom on resize mode") },
- {"win.canvas-split-mode(0)", N_("Split Mode: Normal"), "Canvas Display", N_("Do not split canvas") },
- {"win.canvas-split-mode(1)", N_("Split Mode: Split"), "Canvas Display", N_("Render part of the canvas in outline mode") },
- {"win.canvas-split-mode(2)", N_("Split Mode: X-Ray"), "Canvas Display", N_("Render a circular area in outline mode") },
+ {"win.canvas-split-mode(0)", N_("Split Mode: Normal"), "Canvas Display", N_("Do not split canvas") },
+ {"win.canvas-split-mode(1)", N_("Split Mode: Split"), "Canvas Display", N_("Render part of the canvas in outline mode") },
+ {"win.canvas-split-mode(2)", N_("Split Mode: X-Ray"), "Canvas Display", N_("Render a circular area in outline mode") },
- {"win.canvas-color-mode", N_("Color Mode"), "Canvas Display", N_("Toggle between normal and grayscale modes") },
- {"win.canvas-color-manage", N_("Color Managed Mode"), "Canvas Display", N_("Toggle between normal and color managed modes") }
+ {"win.canvas-color-displayprofile", N_("Display Profile"), "Canvas Display", N_("Toggle the display profile for this monitor") },
+ {"win.canvas-color-colorproof", N_("Proof Colors"), "Canvas Display", N_("Toggle the soft proof for CMYK output") },
+ {"win.canvas-color-gamutwarn", N_("Gamut Warning"), "Canvas Display", N_("Toogle the soft proof gamut warning") },
// clang-format on
};
void
add_actions_canvas_mode(InkscapeWindow* win)
{
- // Sync action with desktop variables. TODO: Remove!
- auto prefs = Inkscape::Preferences::get();
-
- // Initial States of Actions
- int display_mode = prefs->getIntLimited("/options/displaymode", 0, 0, static_cast(Inkscape::RenderMode::size) - 1); // Default, minimum, maximum
- bool color_manage = prefs->getBool("/options/displayprofile/enable");
-
- SPDesktop* dt = win->get_desktop();
- if (dt) {
- auto canvas = dt->getCanvas();
- canvas->set_render_mode(Inkscape::RenderMode(display_mode));
- canvas->set_cms_active(color_manage);
- } else {
- show_output("add_actions_canvas_mode: no desktop!");
- }
-
// clang-format off
- win->add_action_radio_integer ("canvas-display-mode", sigc::bind(sigc::ptr_fun(&canvas_display_mode), win), display_mode);
+ win->add_action_radio_integer ("canvas-display-mode", sigc::bind(sigc::ptr_fun(&canvas_display_mode), win), 0);
win->add_action( "canvas-display-mode-cycle", sigc::bind(sigc::ptr_fun(&canvas_display_mode_cycle), win));
win->add_action( "canvas-display-mode-toggle", sigc::bind(sigc::ptr_fun(&canvas_display_mode_toggle), win));
win->add_action_radio_integer ("canvas-split-mode", sigc::bind(sigc::ptr_fun(&canvas_split_mode), win), (int)Inkscape::SplitMode::NORMAL);
- win->add_action_bool( "canvas-color-mode", sigc::bind(sigc::ptr_fun(&canvas_color_mode_toggle), win));
- win->add_action_bool( "canvas-color-manage", sigc::bind(sigc::ptr_fun(&canvas_color_manage_toggle), win), color_manage);
+ win->add_action( "canvas-color-prefs", sigc::bind(sigc::ptr_fun(&canvas_color_prefs), win));
+ win->add_action( "canvas-color-props", sigc::bind(sigc::ptr_fun(&canvas_color_props), win));
+
+ add_action_bool( win, "canvas-zoom-resize", false, "/options/stickyzoom/value");
+ add_action_bool( win, "canvas-color-displayprofile", false, "/options/displayprofile/enable");
+ add_action_toggle(win, "canvas-color-colorproof", false, sigc::bind(sigc::ptr_fun(&canvas_color_colorproof), win));
+ add_action_toggle(win, "canvas-color-gamutwarn", false, sigc::bind(sigc::ptr_fun(&canvas_color_gamutwarn), win));
// clang-format on
auto app = InkscapeApplication::instance();
@@ -319,6 +341,22 @@ add_actions_canvas_mode(InkscapeWindow* win)
app->get_action_extra_data().add_data(raw_data_canvas_mode);
}
+// Some of our actions are enabled/disabled by the document or prefs state
+void update_actions_canvas_mode(InkscapeWindow *win, SPDocument *document)
+{
+ // This enables softproofing when loading a new document if it's CMYK
+ _update_actions_canvas_mode(win, document ? document->getColorManager().isPrintColorSpace() : false);
+}
+
+void update_actions_displayprofile(InkscapeWindow *win)
+{
+ if (auto action = Glib::RefPtr::cast_dynamic(win->lookup_action("canvas-color-displayprofile"))) {
+ auto prefs = Inkscape::Preferences::get();
+ action->set_enabled(!prefs->getString("/options/displayprofile/uri").empty());
+ }
+
+}
+
/*
Local Variables:
diff --git a/src/actions/actions-canvas-mode.h b/src/actions/actions-canvas-mode.h
index 2d171096d923b5053b7aa13f35af88f1826dccf1..85a99b20188ffe30bc470c25a7320342619c295f 100644
--- a/src/actions/actions-canvas-mode.h
+++ b/src/actions/actions-canvas-mode.h
@@ -12,8 +12,11 @@
#define INK_ACTIONS_CANVAS_MODE_H
class InkscapeWindow;
+class SPDocument;
void add_actions_canvas_mode(InkscapeWindow* win);
+void update_actions_canvas_mode(InkscapeWindow *win, SPDocument *document);
+void update_actions_displayprofile(InkscapeWindow *win);
#endif // INK_ACTIONS_CANVAS_MODE_H
diff --git a/src/actions/actions-helper.cpp b/src/actions/actions-helper.cpp
index 942f147f0ee16199df33d76f0c063aaf68f0d4d7..e0c6419159e92d05e447786432b0505bf4ced65c 100644
--- a/src/actions/actions-helper.cpp
+++ b/src/actions/actions-helper.cpp
@@ -12,11 +12,14 @@
#include "actions-helper.h"
#include
+#include
#include
#include
#include
#include "inkscape-application.h"
+#include "inkscape-window.h"
+#include "preferences.h"
#include "xml/document.h" // for Document
#include "xml/node.h" // for Node
#include "xml/repr.h" // for sp_repr_document_new, sp_repr_save...
@@ -94,6 +97,50 @@ get_document_and_selection(InkscapeApplication* app, SPDocument** document, Inks
return true;
}
+/**
+ * Add a generic toggle action with callback
+ *
+ * group - The document, window or app action group/map
+ * action_name - The name of the action to add
+ * callback - Optional callback with the boolean state
+ */
+void
+add_action_toggle(Gio::ActionMap *group, std::string const &action_name, bool inital, std::function callback)
+{
+ group->add_action_bool(action_name, [=]() {
+ auto action = group->lookup_action(action_name);
+ if (!action) {
+ show_output(action_name + ": action missing!");
+ return;
+ }
+
+ auto saction = Glib::RefPtr::cast_dynamic(action);
+ if (!saction) {
+ show_output(action_name + ": action not SimpleAction!");
+ return;
+ }
+
+ bool state = false;
+ saction->get_state(state);
+ state = !state;
+ saction->change_state(state);
+
+ if (callback)
+ callback(state);
+ }, inital);
+}
+
+void
+add_action_bool(Gio::ActionMap *group, std::string const &action_name, bool inital, std::string const &pref)
+{
+ auto prefs = Inkscape::Preferences::get();
+ inital = prefs->getBool(pref, inital);
+ // FUTURE: We may want to observe the preference and update the action state here.
+ add_action_toggle(group, action_name, inital, [prefs, pref](bool state) {
+ prefs->setBool(pref, state);
+ });
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/actions/actions-helper.h b/src/actions/actions-helper.h
index 61ed6f1fca5e229b76e0078b0dc5da29a4fcb8ae..e436211bbe6a7af919dfaec62d2f9ca0a98ec04c 100644
--- a/src/actions/actions-helper.h
+++ b/src/actions/actions-helper.h
@@ -11,11 +11,19 @@
#ifndef INK_ACTIONS_HELPER_H
#define INK_ACTIONS_HELPER_H
+#include
+#include
+#include
+
namespace Glib {
class ustring;
} // namespace Glib
+namespace Gio {
+class ActionMap;
+}
class InkscapeApplication;
+class InkscapeWindow;
class SPDocument;
namespace Inkscape {
@@ -26,6 +34,8 @@ void active_window_start_helper();
void active_window_end_helper();
void show_output(Glib::ustring const &data, bool is_cerr = true);
bool get_document_and_selection(InkscapeApplication* app, SPDocument** document, Inkscape::Selection** selection);
+void add_action_toggle(Gio::ActionMap *group, std::string const &action_name, bool inital, std::function callback = nullptr);
+void add_action_bool(Gio::ActionMap *group, std::string const &action_name, bool inital, std::string const &pref);
#endif // INK_ACTIONS_HELPER_H
diff --git a/src/actions/actions-tools.cpp b/src/actions/actions-tools.cpp
index adafe6be0c041e9eb4f7ca24d9ba16c4f19ef48b..cff020ae001196a9b4f12e567225d6a116262e6a 100644
--- a/src/actions/actions-tools.cpp
+++ b/src/actions/actions-tools.cpp
@@ -275,22 +275,7 @@ tool_preferences(Glib::ustring const &tool, InkscapeWindow *win)
show_output("tool-preferences: no desktop!");
return;
}
-
- auto prefs = Inkscape::Preferences::get();
- prefs->setInt("/dialogs/preferences/page", tool_it->second.pref);
- Inkscape::UI::Dialog::DialogContainer* container = dt->getContainer();
-
- // Create dialog if it doesn't exist (also sets page if dialog not already in opened tab).
- container->new_floating_dialog("Preferences");
-
- // Find dialog and explicitly set page (in case not set in previous line).
- auto dialog = Inkscape::UI::Dialog::DialogManager::singleton().find_floating_dialog("Preferences");
- if (dialog) {
- auto pref_dialog = dynamic_cast(dialog);
- if (pref_dialog) {
- pref_dialog->showPage(); // Switch to page indicated in preferences file (set above).
- }
- }
+ dt->getContainer()->get_dialog_page("Preferences", tool_it->second.pref);
}
/**
diff --git a/src/color.cpp b/src/color.cpp
index f516161a8a66fd023c156738f0e90c7f4912719d..8e8bb9bd992973f1157fec6037b8edcf4db04c75 100644
--- a/src/color.cpp
+++ b/src/color.cpp
@@ -16,7 +16,6 @@
#include
#include
#include
-#include
#include
#include "color.h"
@@ -25,15 +24,9 @@
#include "svg/svg-color.h"
#include "svg/css-ostringstream.h"
-#include "object/color-profile.h"
-
-#define return_if_fail(x) if (!(x)) { printf("assertion failed: " #x); return; }
-#define return_val_if_fail(x, val) if (!(x)) { printf("assertion failed: " #x); return val; }
using Inkscape::CSSOStringStream;
-static bool profileMatches(SVGICCColor const &first, SVGICCColor const &second);
-
static constexpr double PROFILE_EPSILON = 1e-8;
SPColor::SPColor(SPColor const &other)
@@ -57,7 +50,7 @@ SPColor &SPColor::operator=(SPColor const &other)
return *this;
}
- set(other.v.c[0], other.v.c[1], other.v.c[2]);
+ //set(other.v.c[0], other.v.c[1], other.v.c[2]);
copyColors(other);
return *this;
}
@@ -67,12 +60,13 @@ SPColor &SPColor::operator=(SPColor const &other)
*/
bool SPColor::operator == (SPColor const& other) const
{
- bool match =
+ bool match = false;
+ /*
(v.c[0] == other.v.c[0]) &&
(v.c[1] == other.v.c[1]) &&
(v.c[2] == other.v.c[2]);
-
- match &= profileMatches(_icc, other._icc);
+*/
+ match &= profileMatches(*this, other);
return match;
}
@@ -83,19 +77,19 @@ bool SPColor::operator == (SPColor const& other) const
*/
bool SPColor::isClose(SPColor const& other, float epsilon) const
{
- bool match = (fabs((v.c[0]) - (other.v.c[0])) < epsilon)
+ /*bool match = (fabs((v.c[0]) - (other.v.c[0])) < epsilon)
&& (fabs((v.c[1]) - (other.v.c[1])) < epsilon)
- && (fabs((v.c[2]) - (other.v.c[2])) < epsilon);
+ && (fabs((v.c[2]) - (other.v.c[2])) < epsilon);*/
- match &= profileMatches(_icc, other._icc);
+ //match &= profileMatches(*this, other);
- return match;
+ return false; //match;
}
/**
* Matches two profile colors within PROFILE_EPSILON distance.
*/
-static bool profileMatches(SVGICCColor const &first, SVGICCColor const &second)
+bool SPColor::profileMatches(SPColor const &first, SPColor const &second)
{
if (first.colorProfile != second.colorProfile || first.colors.size() != second.colors.size()) {
return false;
@@ -110,136 +104,141 @@ static bool profileMatches(SVGICCColor const &first, SVGICCColor const &second)
}
/**
- * Sets RGB values and colorspace in color.
- * \pre 0 <={r,g,b}<=1
+ * Sets the color in the specified color space, replacing any
+ * existing color space and removing any icc profile.
+ *
+ * @arg space - The new color space to use
+ * @arg colors - A vector of doubles between 0 and 1 for each channel
*/
-void SPColor::set(float r, float g, float b)
+/*void SPColor::set(Inkscape::Color::Space space, std::vector const &colors)
{
- return_if_fail(r >= 0.0);
- return_if_fail(r <= 1.0);
- return_if_fail(g >= 0.0);
- return_if_fail(g <= 1.0);
- return_if_fail(b >= 0.0);
- return_if_fail(b <= 1.0);
-
- v.c[0] = r;
- v.c[1] = g;
- v.c[2] = b;
-
- // Remove icc colors, but not the profile
- unsetColors();
-}
+ _profile.clear();
+ _space = space;
+ update(_space, colors);
+}*/
/**
- * Converts 32bit value to RGB floats and sets color.
+ * Sets the color in the specified profile color space, replacing any
+ * existing color and it's associated profile.
+ *
+ * @args profile - The new color profile to set.
+ * @args colors - A vector of doubles between 0 and 1 for each channel
*/
-void SPColor::set(guint32 value)
+/*void SPColor::set(ColorProfile *profile, std::vector const &colors)
{
- v.c[0] = (value >> 24) / 255.0F;
- v.c[1] = ((value >> 16) & 0xff) / 255.0F;
- v.c[2] = ((value >> 8) & 0xff) / 255.0F;
- // Remove icc colors, but not the profile
- unsetColors();
-}
+ if (!profile) {
+ g_error("Color profile must exist when setting a profile color.");
+ return;
+ }
+ set(profile->getColorSpace(), colors);
+ _profile = profile;
+}*/
/**
- * Returns true if this color has a color profile set.
+ * Updates the color, keeping the internal color space and icc profile and converting
+ * the given color from it's input color space if its different.
+ *
+ * If the icc profile color space is the same as the input color space, no conversion is
+ * done and it is assumed the values are *within* the profile space.
+ *
+ * @arg in_space - The color space of the input colors
+ * @arg in_colors - A vector of soubles between 0 and 1 for each input channel
+ * @arg in_profile - An optional profile which overrides in_space for conversion
*/
-bool SPColor::hasColorProfile() const
-{
- return !_icc.colorProfile.empty();
-}
+/*void SPColor::update(Color::Space in_space, std::vector const &in_colors, ColorProfile *in_profile = nullptr)
+{
+ std::vector colors;
+ if (_space == in_space) {
+ colors = in_colors;
+ } else if (_profile) {
+ if (in_profile)
+ colors = convert(in_profile, in_colors, _profile);
+ else
+ colors = convert(in_space, in_colors, _profile);
+ } else {
+ if (in_profile)
+ colors = convert(in_profile, in_colors, _space);
+ else
+ colors = convert(in_space, in_colors, _space);
+ }
+ _colors.clear();
+ for (int color : colors) {
+ if (color < 0.0 || color > 1.0) {
+ g_error("Color channel set out of bounds. 0.0<=%f<=1.0", color)
+ color = 0.0;
+ }
+ _colors.push_back(color);
+ }
+}*/
/**
- * Returns true if there is a defined color for the set profile.
+ * Converts 32bit value to RGB floats and sets color, forcing this color to be sRGB.
*/
-bool SPColor::hasColors() const
+void SPColor::set(guint32 value)
{
- return hasColorProfile() && !_icc.colors.empty() && _icc.colors[0] != -1.0;
+/* set(Inkscape::Color::Space::RGB,
+ {(value >> 24) / 255.0F,
+ ((value >> 16) & 0xff) / 255.0F,
+ ((value >> 8) & 0xff) / 255.0F});*/
}
-
-void SPColor::setColorProfile(Inkscape::ColorProfile *profile)
+void SPColor::set(float r, float g, float b)
{
- unsetColorProfile();
- if (profile) {
- _icc.colorProfile = profile->name;
- for (int i = 0; i < profile->getChannelCount(); i++) {
- _icc.colors.emplace_back(-1.0);
- }
- }
-}
-
-void SPColor::setColors(std::vector &&values)
-{
- if (values.size() != _icc.colors.size()) {
- g_error("Can't set profile-based color, wrong number of colors.");
- unsetColors();
- return;
- }
- _icc.colors = std::move(values);
+ g_warning("NOPE");
}
void SPColor::copyColors(const SPColor &other)
{
- if (!profileMatches(_icc, other._icc)) {
- _icc = other._icc; // copy
+ if (!profileMatches(*this, other)) {
+ colors = other.colors;
+ colorProfile = other.colorProfile;
}
}
void SPColor::setColor(unsigned int index, double value)
{
- if (index < 0 || index > _icc.colors.size()) {
+ if (index < 0 || index > colors.size()) {
g_warning("Can't set profile-based color, index out of range.");
}
- _icc.colors[index] = value;
+ colors[index] = value;
}
/**
* Clears the saved profile color, but retains the color profile for imediate reuse.
*/
-void SPColor::unsetColors()
-{
- for (double &color : _icc.colors) {
- color = -1.0;
- }
-}
-
-/**
- * Remove the color profile and save color, reverting to sRGB only.
- */
-void SPColor::unsetColorProfile()
+void SPColor::unset()
{
- _icc.colorProfile = "";
- _icc.colors.clear();
+// _space = Color::Space::NONE;
+// _profile.clear();
+// colors.clear();
}
/**
* Convert SPColor with integer alpha value to 32bit RGBA value.
* \pre alpha < 256
*/
-guint32 SPColor::toRGBA32( int alpha ) const
+guint32 SPColor::toRGBA32(int alpha) const
{
- return_val_if_fail (alpha <= 0xff, 0x0);
+// return_val_if_fail (alpha <= 0xff, 0x0);
if (!is_set()) {
return SP_RGBA32_U_COMPOSE(0, 0, 0, alpha);
}
- guint32 rgba = SP_RGBA32_U_COMPOSE( SP_COLOR_F_TO_U(v.c[0]),
+/* guint32 rgba = SP_RGBA32_U_COMPOSE( SP_COLOR_F_TO_U(v.c[0]),
SP_COLOR_F_TO_U(v.c[1]),
SP_COLOR_F_TO_U(v.c[2]),
- alpha );
- return rgba;
+ alpha );*/
+ return 0; //rgba;
}
/**
* Convert SPColor with float alpha value to 32bit RGBA value.
* \pre color != NULL && 0 <= alpha <= 1
*/
-guint32 SPColor::toRGBA32( double alpha ) const
+guint32 SPColor::toRGBA32(double alpha) const
{
- return_val_if_fail(alpha >= 0.0, 0x0);
- return_val_if_fail(alpha <= 1.0, 0x0);
+ //return_val_if_fail(alpha >= 0.0, 0x0);
+ //return_val_if_fail(alpha <= 1.0, 0x0);
return toRGBA32( static_cast(SP_COLOR_F_TO_U(alpha)) );
}
@@ -256,8 +255,8 @@ std::string SPColor::toString() const
if ( !css.str().empty() ) {
css << " ";
}
- css << "icc-color(" << _icc.colorProfile;
- for (double color : _icc.colors) {
+ css << "icc-color(" << colorProfile;
+ for (double color : colors) {
css << ", " << color;
}
css << ')';
@@ -276,6 +275,7 @@ bool SPColor::fromString(char const *str)
{
guint32 const rgb0 = sp_svg_read_color(str, &str, 0xff);
if (rgb0 == 0xff) {
+ unset();
return false;
}
set(rgb0);
@@ -283,9 +283,9 @@ bool SPColor::fromString(char const *str)
++str;
}
if (strneq(str, "icc-color(", 10)) {
- if (!sp_svg_read_icc_color(str, &str, &_icc)) {
+ if (!read_icc_color(str, &str)) {
g_warning("Couldn't parse icc-color format in css.");
- unsetColorProfile();
+ unset();
}
}
return true;
@@ -298,14 +298,14 @@ bool SPColor::fromString(char const *str)
void
SPColor::get_rgb_floatv(float *rgb) const
{
- return_if_fail (rgb != nullptr);
+ //return_if_fail (rgb != nullptr);
if (!is_set()) {
return;
}
- rgb[0] = v.c[0];
- rgb[1] = v.c[1];
- rgb[2] = v.c[2];
+ rgb[0] = 0; //v.c[0];
+ rgb[1] = 0; //v.c[1];
+ rgb[2] = 0; //v.c[2];
}
/**
@@ -315,15 +315,15 @@ SPColor::get_rgb_floatv(float *rgb) const
void
SPColor::get_cmyk_floatv(float *cmyk) const
{
- return_if_fail (cmyk != nullptr);
+ //return_if_fail (cmyk != nullptr);
if (!is_set()) {
return;
}
- SPColor::rgb_to_cmyk_floatv( cmyk,
+ /*SPColor::rgb_to_cmyk_floatv( cmyk,
v.c[0],
v.c[1],
- v.c[2] );
+ v.c[2] );*/
}
/* Plain mode helpers */
@@ -556,6 +556,98 @@ SPColor::hsluv_to_rgb_floatv(float *rgb, float h, float s, float l)
}
}
+/*
+ * Some discussion at http://markmail.org/message/bhfvdfptt25kgtmj
+ * Allowed ASCII first characters: ':', 'A'-'Z', '_', 'a'-'z'
+ * Allowed ASCII remaining chars add: '-', '.', '0'-'9',
+ */
+bool SPColor::read_icc_color(gchar const *str, gchar const **end_ptr)
+{
+ bool good = true;
+
+ if (end_ptr) {
+ *end_ptr = str;
+ }
+ colorProfile.clear();
+ colors.clear();
+
+ if ( !str ) {
+ // invalid input
+ good = false;
+ } else {
+ while ( g_ascii_isspace(*str) ) {
+ str++;
+ }
+
+ good = strneq( str, "icc-color(", 10 );
+
+ if ( good ) {
+ str += 10;
+ while ( g_ascii_isspace(*str) ) {
+ str++;
+ }
+
+ if ( !g_ascii_isalpha(*str)
+ && ( !(0x080 & *str) )
+ && (*str != '_')
+ && (*str != ':') ) {
+ // Name must start with a certain type of character
+ good = false;
+ } else {
+ while ( g_ascii_isdigit(*str) || g_ascii_isalpha(*str)
+ || (*str == '-') || (*str == ':') || (*str == '_') || (*str == '.') ) {
+ colorProfile += *str;
+ str++;
+ }
+ while ( g_ascii_isspace(*str) || *str == ',' ) {
+ str++;
+ }
+ }
+ }
+
+ if ( good ) {
+ while ( *str && *str != ')' ) {
+ if ( g_ascii_isdigit(*str) || *str == '.' || *str == '-' || *str == '+') {
+ gchar* endPtr = nullptr;
+ gdouble dbl = g_ascii_strtod( str, &endPtr );
+ if ( !errno ) {
+ colors.push_back( dbl );
+ str = endPtr;
+ } else {
+ good = false;
+ break;
+ }
+
+ while ( g_ascii_isspace(*str) || *str == ',' ) {
+ str++;
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ // We need to have ended on a closing parenthesis
+ if ( good ) {
+ while ( g_ascii_isspace(*str) ) {
+ str++;
+ }
+ good &= (*str == ')');
+ }
+ }
+
+ if (good) {
+ if (end_ptr) {
+ *end_ptr = str;
+ }
+ } else {
+ colorProfile.clear();
+ colors.clear();
+ }
+
+ return good;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/color.h b/src/color.h
index 9a3fa133ff10c5e52357bc9c9fa250cf491a4cc1..150e3489cb21042fd2604852af23ff311b0bca9a 100644
--- a/src/color.h
+++ b/src/color.h
@@ -15,10 +15,9 @@
* Released under GNU GPL v2+, read the file 'COPYING' for more information.
*/
+#include
#include
-#include "svg/svg-icc-color.h"
-
typedef unsigned int guint32; // uint is guaranteed to hold up to 2^32 − 1
/* Useful composition macros */
@@ -38,11 +37,9 @@ typedef unsigned int guint32; // uint is guaranteed to hold up to 2^32 − 1
#define SP_RGBA32_C_COMPOSE(c,o) SP_RGBA32_U_COMPOSE(SP_RGBA32_R_U(c),SP_RGBA32_G_U(c),SP_RGBA32_B_U(c),SP_COLOR_F_TO_U(o))
#define SP_RGBA32_LUMINANCE(v) (SP_RGBA32_R_U(v) * 0.30 + SP_RGBA32_G_U(v) * 0.59 + SP_RGBA32_B_U(v) * 0.11 + 0.5)
-struct SVGICCColor;
-
namespace Inkscape {
class ColorProfile;
-};
+}
/**
* An RGB color with optional icc-color part
@@ -61,22 +58,35 @@ public:
bool operator != ( SPColor const& other ) const { return !(*this == other); };
operator bool() const { return is_set(); }
- bool isClose( SPColor const& other, float epsilon ) const;
+ double operator[](const unsigned int index) const {
+ if (index < colors.size())
+ return colors[index];
+ return -1;
+ }
+
+ void unset();
+ // Convert this color into a different color space
+ // XXX SPColor &convertTo(Space space) const;
+
+ // Compare two colors and decide if they are close matches
+ bool isClose(SPColor const& other, float epsilon) const;
+
+ // Old API for setting RGB values
void set(float r, float g, float b);
void set(guint32 value);
- bool hasColorProfile() const;
- void unsetColorProfile();
+ //bool hasColorProfile() const;
+ //void unsetColorProfile();
void setColorProfile(Inkscape::ColorProfile *profile);
- const std::string &getColorProfile() const { return _icc.colorProfile; }
+ const std::string &getColorProfile() const { return colorProfile; }
- bool hasColors() const;
+ bool hasColors() const { return true; }
void unsetColors();
void setColors(std::vector &&values);
void setColor(unsigned int index, double value);
void copyColors(const SPColor &other);
- const std::vector &getColors() const { return _icc.colors; }
+ const std::vector &getColors() const { return colors; }
guint32 toRGBA32( int alpha ) const;
guint32 toRGBA32( double alpha ) const;
@@ -84,14 +94,10 @@ public:
std::string toString() const;
bool fromString(const char *str);
- union {
- float c[3] = { -1, 0, 0 };
- } v;
-
guint32 get_rgba32_ualpha (guint32 alpha) const;
guint32 get_rgba32_falpha (float alpha) const;
- bool is_set() const { return v.c[0] > -1; }
+ bool is_set() const { return !colors.empty(); }
void get_rgb_floatv (float *rgb) const;
void get_cmyk_floatv (float *cmyk) const;
@@ -109,8 +115,12 @@ public:
static void rgb_to_hsluv_floatv (float *hsluv, float r, float g, float b);
static void hsluv_to_rgb_floatv (float *rgb, float h, float s, float l);
+ bool read_icc_color(char const *str, char const **end_ptr = nullptr);
private:
- SVGICCColor _icc;
+ static bool profileMatches(SPColor const &first, SPColor const &second);
+
+ std::string colorProfile;
+ std::vector colors;
};
#endif // SEEN_SP_COLOR_H
diff --git a/src/color/CMakeLists.txt b/src/color/CMakeLists.txt
deleted file mode 100644
index 3cdda4a9d8334543ad8344b55c158e7cc62b2e80..0000000000000000000000000000000000000000
--- a/src/color/CMakeLists.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-or-later
-
-set(color_SRC
- cms-system.cpp
- cms-util.cpp
- cmyk-conv.cpp
- color-conv.cpp
-
- # -------
- # Headers
- color-profile-cms-fns.h
- cms-color-types.h
- cms-system.h
- cms-util.h
- cmyk-conv.h
- color-conv.h
-)
-
-add_inkscape_source("${color_SRC}")
diff --git a/src/color/cms-color-types.h b/src/color/cms-color-types.h
deleted file mode 100644
index c6b90878b2f3f22c662bea5c098e0c746c2b5752..0000000000000000000000000000000000000000
--- a/src/color/cms-color-types.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/** @file
- * TODO: insert short description here
- *//*
- * Authors: see git history
- *
- * Copyright (C) 2018 Authors
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-#ifndef SEEN_CMS_COLOR_TYPES_H
-#define SEEN_CMS_COLOR_TYPES_H
-
-/**
- * @file
- * A simple abstraction to provide opaque compatibility with either lcms or lcms2.
- */
-
-#ifdef HAVE_CONFIG_H
-# include "config.h" // only include where actually required!
-#endif
-
-#include // uint8_t, etc
-
-typedef unsigned int guint32;
-
-typedef void * cmsHPROFILE;
-typedef void * cmsHTRANSFORM;
-
-
-namespace Inkscape {
-
-/**
- * Opaque holder of a 32-bit signature type.
- */
-class FourCCSig {
-public:
- FourCCSig( FourCCSig const &other ) = default;
-
-protected:
- FourCCSig( guint32 value ) : value(value) {};
-
- guint32 value;
-};
-
-class ColorSpaceSig : public FourCCSig {
-public:
- ColorSpaceSig( ColorSpaceSig const &other ) = default;
-
-protected:
- ColorSpaceSig( guint32 value ) : FourCCSig(value) {};
-};
-
-class ColorProfileClassSig : public FourCCSig {
-public:
- ColorProfileClassSig( ColorProfileClassSig const &other ) = default;
-
-protected:
- ColorProfileClassSig( guint32 value ) : FourCCSig(value) {};
-};
-
-} // namespace Inkscape
-
-
-#endif // SEEN_CMS_COLOR_TYPES_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/color/cms-system.cpp b/src/color/cms-system.cpp
deleted file mode 100644
index 55372feb20bd9dffba8db8ce843cd864d0f025be..0000000000000000000000000000000000000000
--- a/src/color/cms-system.cpp
+++ /dev/null
@@ -1,469 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/** @file
- * A class to provide access to system/user ICC color profiles.
- *//*
- * Authors: see git history
- *
- * Copyright (C) 2018 Authors
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h" // only include where actually required!
-#endif
-
-#include "cms-system.h"
-
-#include
-
-#include
-
-#include "cms-util.h"
-#include "document.h"
-#include "preferences.h"
-
-#include "io/resource.h"
-#include "object/color-profile.h"
-
-#ifdef _WIN32
-#include
-#include
-#endif
-
-using Inkscape::ColorProfile;
-
-namespace Inkscape {
-
-/**
- * Holds information about one ICC profile.
- */
-class ProfileInfo
-{
-public:
- ProfileInfo(cmsHPROFILE prof, Glib::ustring &&path);
-
- Glib::ustring const &getName() const { return _name; }
- Glib::ustring const &getPath() const { return _path; }
- cmsColorSpaceSignature getSpace() const { return _profileSpace; }
- cmsProfileClassSignature getClass() const { return _profileClass; }
-
-private:
- Glib::ustring _path;
- Glib::ustring _name;
- cmsColorSpaceSignature _profileSpace;
- cmsProfileClassSignature _profileClass;
-};
-
-ProfileInfo::ProfileInfo(cmsHPROFILE prof, Glib::ustring &&path)
- : _path(std::move(path))
- , _name(get_color_profile_name(prof))
- , _profileSpace(cmsGetColorSpace(prof))
- , _profileClass(cmsGetDeviceClass(prof))
-{
-}
-
-CMSSystem::CMSSystem()
-{
- // Read in profiles (move to refresh()?).
- load_profiles();
-
- // Create generic sRGB profile.
- sRGB_profile = cmsCreate_sRGBProfile();
-}
-
-CMSSystem::~CMSSystem()
-{
- if (current_monitor_profile) {
- cmsCloseProfile(current_monitor_profile);
- }
-
- if (current_proof_profile) {
- cmsCloseProfile(current_proof_profile);
- }
-
- if (sRGB_profile) {
- cmsCloseProfile(sRGB_profile);
- }
-}
-
-/*
- * We track last transform created so we can delete it later.
- *
- * This is OK since we only have one transform for all montiors/canvases. If we choose to allow the
- * user to assign different profiles to different monitors or have CMS preferences that are not
- * global, we'll need to have either one transform per monitor or one transform per canvas.
- */
-
-// Search for system ICC profile files and add them to list.
-void CMSSystem::load_profiles()
-{
- system_profile_infos.clear(); // Allows us to refresh list if necessary.
-
- // Get list of all possible file directories, with flag if they are "home" directories or not.
- auto directory_paths = get_directory_paths();
-
- // Look for icc files in specified directories.
- for (auto const &directory_path : directory_paths) {
- using Inkscape::IO::Resource::get_filenames;
- for (auto &&filename : get_filenames(directory_path.first, {".icc", ".icm"})) {
- // Check if files are ICC files and extract out basic information, add to list.
- if (!is_icc_file(filename)) {
- std::cerr << "CMSSystem::load_profiles: " << filename << " is not an ICC file!" << std::endl;
- continue;
- }
-
- cmsHPROFILE profile = cmsOpenProfileFromFile(filename.c_str(), "r");
- if (!profile) {
- std::cerr << "CMSSystem::load_profiles: failed to load " << filename << std::endl;
- continue;
- }
-
- ICCProfileInfo info{profile, std::move(filename), directory_path.second};
- cmsCloseProfile(profile);
- profile = nullptr;
-
- bool same_name = false;
- for (auto const &profile_info : system_profile_infos) {
- if (profile_info.get_name() == info.get_name() ) {
- same_name = true;
- std::cerr << "CMSSystem::load_profiles: ICC profile with duplicate name: " << profile_info.get_name() << ":" << std::endl;
- std::cerr << " " << profile_info.get_path() << std::endl;
- std::cerr << " " << info.get_path() << std::endl;
- break;
- }
- }
-
- if (!same_name) {
- system_profile_infos.emplace_back(std::move(info));
- }
- }
- }
-}
-
-// Create list of all directories where ICC profiles are expected to be found.
-std::vector> CMSSystem::get_directory_paths()
-{
- std::vector> paths;
-
- // First try user's local directory.
- paths.emplace_back(Glib::build_filename(Glib::get_user_data_dir(), "color", "icc"), true);
-
- // See https://github.com/hughsie/colord/blob/fe10f76536bb27614ced04e0ff944dc6fb4625c0/lib/colord/cd-icc-store.c#L590
-
- // User store
- paths.emplace_back(Glib::build_filename(Glib::get_user_data_dir(), "icc"), true);
-
- paths.emplace_back(Glib::build_filename(Glib::get_home_dir(), ".color", "icc"), true);
-
- // System store
- paths.emplace_back("/var/lib/color/icc", false);
- paths.emplace_back("/var/lib/colord/icc", false);
-
- auto data_directories = Glib::get_system_data_dirs();
- for (auto const &data_directory : data_directories) {
- paths.emplace_back(Glib::build_filename(data_directory, "color", "icc"), false);
- }
-
-#ifdef __APPLE__
- paths.emplace_back("/System/Library/ColorSync/Profiles", false);
- paths.emplace_back("/Library/ColorSync/Profiles", false);
-
- paths.emplace_back(Glib::build_filename(Glib::get_home_dir(), "Library", "ColorSync", "Profiles"), true);
-#endif // __APPLE__
-
-#ifdef _WIN32
- wchar_t pathBuf[MAX_PATH + 1];
- pathBuf[0] = 0;
- DWORD pathSize = sizeof(pathBuf);
- g_assert(sizeof(wchar_t) == sizeof(gunichar2));
- if (GetColorDirectoryW(NULL, pathBuf, &pathSize)) {
- auto utf8Path = g_utf16_to_utf8((gunichar2*)(&pathBuf[0]), -1, NULL, NULL, NULL);
- if (!g_utf8_validate(utf8Path, -1, NULL)) {
- g_warning( "GetColorDirectoryW() resulted in invalid UTF-8" );
- } else {
- paths.emplace_back(utf8Path, false);
- }
- g_free(utf8Path);
- }
-#endif // _WIN32
-
- return paths;
-}
-
-// Get the user set monitor profile.
-cmsHPROFILE CMSSystem::get_monitor_profile()
-{
- static Glib::ustring current_monitor_uri;
- static bool use_user_monitor_profile_old = false;
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool use_user_monitor_profile = prefs->getBool("/options/displayprofile/use_user_profile", false);
-
- if (use_user_monitor_profile_old != use_user_monitor_profile) {
- use_user_monitor_profile_old = use_user_monitor_profile;
- current_monitor_profile_changed = true;
- }
-
- if (!use_user_monitor_profile) {
- if (current_monitor_profile) {
- cmsCloseProfile(current_monitor_profile);
- current_monitor_profile = nullptr;
- current_monitor_uri.clear();
- }
- return current_monitor_profile;
- }
-
- Glib::ustring new_uri = prefs->getString("/options/displayprofile/uri");
-
- if (!new_uri.empty()) {
-
- // User defined monitor profile.
- if (new_uri != current_monitor_uri) {
-
- // Monitor profile changed
- current_monitor_profile_changed = true;
- current_monitor_uri.clear();
-
- // Delete old profile
- if (current_monitor_profile) {
- cmsCloseProfile(current_monitor_profile);
- }
-
- // Open new profile
- current_monitor_profile = cmsOpenProfileFromFile(new_uri.data(), "r");
- if (current_monitor_profile) {
-
- // A display profile must be of the right type.
- cmsColorSpaceSignature space = cmsGetColorSpace(current_monitor_profile);
- cmsProfileClassSignature profClass = cmsGetDeviceClass(current_monitor_profile);
-
- if (profClass != cmsSigDisplayClass) {
- std::cerr << "CMSSystem::get_monitor_profile: Not a display (monitor) profile: " << new_uri << std::endl;
- cmsCloseProfile(current_monitor_profile);
- current_monitor_profile = nullptr;
- } else if (space != cmsSigRgbData) {
- std::cerr << "CMSSystem::get_monitor_profile: Not an RGB profile: " << new_uri << std::endl;
- cmsCloseProfile(current_monitor_profile);
- current_monitor_profile = nullptr;
- } else {
- current_monitor_uri = new_uri;
- }
- }
- }
- } else if (current_monitor_profile) {
- cmsCloseProfile(current_monitor_profile);
- current_monitor_profile = nullptr;
- current_monitor_uri.clear();
- current_monitor_profile_changed = true;
- }
-
- return current_monitor_profile;
-}
-
-// Get the user set proof profile.
-cmsHPROFILE CMSSystem::get_proof_profile()
-{
- static Glib::ustring current_proof_uri;
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- Glib::ustring new_uri = prefs->getString("/options/softproof/uri");
-
- if (!new_uri.empty()) {
-
- // User defined proof profile.
- if (new_uri != current_proof_uri) {
-
- // Proof profile changed
- current_proof_profile_changed = true;
- current_proof_uri.clear();
-
- // Delete old profile
- if (current_proof_profile) {
- cmsCloseProfile(current_proof_profile);
- }
-
- // Open new profile
- current_proof_profile = cmsOpenProfileFromFile(new_uri.data(), "r");
- if (current_proof_profile) {
-
- // We don't check validity of proof profile!
- current_proof_uri = new_uri;
- }
- }
- } else if (current_proof_profile) {
- cmsCloseProfile(current_proof_profile);
- current_proof_profile = nullptr;
- current_proof_uri.clear();
- current_proof_profile_changed = true;
- }
-
- return current_proof_profile;
-}
-
-// Get a color profile handle corresponding to "name" from the document. Also, optionally, get intent.
-cmsHPROFILE CMSSystem::get_document_profile(SPDocument *document, unsigned *intent, char const *name)
-{
- cmsHPROFILE profile_handle = nullptr;
-
- // Search through elements for one with matching name.
- ColorProfile *color_profile = nullptr;
- auto color_profiles = document->getResourceList("iccprofile");
- for (auto *object : color_profiles) {
- if (auto color_profile_test = cast(object)) {
- if (color_profile_test->name && (strcmp(color_profile_test->name, name) == 0)) {
- color_profile = color_profile_test;
- }
- }
- }
-
- // If found, set profile_handle pointer.
- if (color_profile) {
- profile_handle = color_profile->getHandle();
- }
-
- // If requested, fill "RENDERING_INTENT" value.
- if (intent) {
- *intent = color_profile ? color_profile->rendering_intent : (guint)RENDERING_INTENT_UNKNOWN;
- }
-
- return profile_handle;
-}
-
-// Returns vector of names to list in Preferences dialog: display (monitor) profiles.
-std::vector CMSSystem::get_monitor_profile_names() const
-{
- std::vector result;
-
- for (auto const &profile_info : system_profile_infos) {
- if (profile_info.get_profileclass() == cmsSigDisplayClass &&
- profile_info.get_colorspace() == cmsSigRgbData)
- {
- result.emplace_back(profile_info.get_name());
- }
- }
- std::sort(result.begin(), result.end());
-
- return result;
-}
-
-// Returns vector of names to list in Preferences dialog: proofing profiles.
-std::vector CMSSystem::get_softproof_profile_names() const
-{
- std::vector result;
-
- for (auto const &profile_info : system_profile_infos) {
- if (profile_info.get_profileclass() == cmsSigOutputClass) {
- result.emplace_back(profile_info.get_name());
- }
- }
- std::sort(result.begin(), result.end());
-
- return result;
-}
-
-// Returns location of a profile.
-std::string CMSSystem::get_path_for_profile(Glib::ustring const &name) const
-{
- std::string result;
-
- for (auto const &profile_info : system_profile_infos) {
- if (name.raw() == profile_info.get_name()) {
- result = profile_info.get_path();
- break;
- }
- }
-
- return result;
-}
-
-// Static, doesn't rely on class. Simply calls lcms' cmsDoTransform.
-// Called from Canvas and icc_color_to_sRGB in sgv-color.cpp.
-void CMSSystem::do_transform(cmsHTRANSFORM transform, unsigned char *inBuf, unsigned char *outBuf, unsigned size)
-{
- cmsDoTransform(transform, inBuf, outBuf, size);
-}
-
-// Called by Canvas to obtain transform.
-// Currently there is one transform for all monitors.
-// Transform immutably shared between CMSSystem and Canvas.
-std::shared_ptr const &CMSSystem::get_cms_transform()
-{
- bool preferences_changed = false;
-
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool warn = prefs->getBool( "/options/softproof/gamutwarn");
- int intent = prefs->getIntLimited("/options/displayprofile/intent", 0, 0, 3);
- int proofIntent = prefs->getIntLimited("/options/softproof/intent", 0, 0, 3);
- bool bpc = prefs->getBool( "/options/softproof/bpc");
- Glib::ustring colorStr = prefs->getString( "/options/softproof/gamutcolor");
- Gdk::RGBA gamutColor(colorStr.empty() ? "#808080" : colorStr);
-
- if (gamutWarn != warn ||
- lastIntent != intent ||
- lastProofIntent != proofIntent ||
- lastBPC != bpc ||
- lastGamutColor != gamutColor )
- {
- preferences_changed = true;
-
- gamutWarn = warn;
- lastIntent = intent;
- lastProofIntent = proofIntent;
- lastBPC = bpc;
- lastGamutColor = gamutColor;
- }
-
- auto monitor_profile = get_monitor_profile();
- auto proof_profile = get_proof_profile();
-
- bool need_to_update = preferences_changed || current_monitor_profile_changed || current_proof_profile_changed;
-
- if (need_to_update) {
- if (proof_profile) {
- cmsUInt32Number dwFlags = cmsFLAGS_SOFTPROOFING;
-
- if (gamutWarn) {
- dwFlags |= cmsFLAGS_GAMUTCHECK;
-
- auto gamutColor_r = gamutColor.get_red_u();
- auto gamutColor_g = gamutColor.get_green_u();
- auto gamutColor_b = gamutColor.get_blue_u();
-
- cmsUInt16Number newAlarmCodes[cmsMAXCHANNELS] = {0};
- newAlarmCodes[0] = gamutColor_r;
- newAlarmCodes[1] = gamutColor_g;
- newAlarmCodes[2] = gamutColor_b;
- newAlarmCodes[3] = ~0;
- cmsSetAlarmCodes(newAlarmCodes);
- }
-
- if (bpc) {
- dwFlags |= cmsFLAGS_BLACKPOINTCOMPENSATION;
- }
-
- current_transform = CMSTransform::create(
- cmsCreateProofingTransform(sRGB_profile, TYPE_BGRA_8, monitor_profile, TYPE_BGRA_8,
- proof_profile, intent, proofIntent, dwFlags));
-
- } else if (monitor_profile) {
- current_transform = CMSTransform::create(
- cmsCreateTransform(sRGB_profile, TYPE_BGRA_8, monitor_profile, TYPE_BGRA_8, intent, 0));
- }
- }
-
- return current_transform;
-}
-
-CMSSystem *CMSSystem::_instance = nullptr;
-
-} // namespace Inkscape
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/color/cms-system.h b/src/color/cms-system.h
deleted file mode 100644
index a040146eca851417dbb7455d10cfff8fe75e9027..0000000000000000000000000000000000000000
--- a/src/color/cms-system.h
+++ /dev/null
@@ -1,132 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/** @file
- * TODO: insert short description here
- *//*
- * Authors: see git history
- *
- * Copyright (C) 2017 Authors
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-#ifndef INKSCAPE_COLOR_CMS_SYSTEM_H
-#define INKSCAPE_COLOR_CMS_SYSTEM_H
-
-/** \file
- * Access to ICC profiles provided by system.
- * Track which profile to use for proofing.(?)
- * Track which profile to use on which monitor.
- */
-
-#include
-#include
-#include
-
-#include
-#include
-
-#include // cmsHTRANSFORM
-
-#include "cms-color-types.h" // cmsColorSpaceSignature, cmsProfileClassSignature
-#include "cms-util.h"
-
-class SPDocument;
-class ProfileInfo;
-
-namespace Inkscape {
-
-class ColorProfile;
-
-class CMSTransform
-{
-public:
- explicit CMSTransform(cmsHTRANSFORM handle) : _handle(handle) { assert(_handle); }
- CMSTransform(CMSTransform const &) = delete;
- CMSTransform &operator=(CMSTransform const &) = delete;
- ~CMSTransform() { cmsDeleteTransform(_handle); }
-
- cmsHTRANSFORM getHandle() const { return _handle; }
-
- static std::shared_ptr create(cmsHTRANSFORM handle)
- {
- return handle ? std::make_shared(handle) : nullptr;
- }
-
-private:
- cmsHTRANSFORM _handle;
-};
-
-class CMSSystem
-{
-public:
- /**
- * Access the singleton CMSSystem object.
- */
- static CMSSystem *get() {
- if (!_instance) {
- _instance = new CMSSystem();
- }
- return _instance;
- }
-
- static void unload() {
- if (_instance) {
- delete _instance;
- _instance = nullptr;
- }
- }
-
- static std::vector> get_directory_paths();
- std::vector const &get_system_profile_infos() const { return system_profile_infos; }
- std::vector get_monitor_profile_names() const;
- std::vector get_softproof_profile_names() const;
- std::string get_path_for_profile(Glib::ustring const &name) const;
- std::shared_ptr const &get_cms_transform();
- static cmsHPROFILE get_document_profile(SPDocument *document, unsigned *intent, char const *name);
-
- static void do_transform(cmsHTRANSFORM transform, unsigned char *inBuf, unsigned char *outBuf, unsigned size);
-
-private:
- CMSSystem();
- ~CMSSystem();
-
- void load_profiles(); // Should this be public (e.g., if a new ColorProfile is created).
- cmsHPROFILE get_monitor_profile(); // Get the user set monitor profile.
- cmsHPROFILE get_proof_profile(); // Get the user set proof profile.
- void clear_transform(); // Clears current_transform.
-
- static CMSSystem* _instance;
-
- // List of ICC profiles on system
- std::vector system_profile_infos;
-
- // We track last transform settings. If there is a change, we delete create new transform.
- bool gamutWarn = false;
- Gdk::RGBA lastGamutColor = Gdk::RGBA("#808080");
- bool lastBPC = false;
- int lastIntent = INTENT_PERCEPTUAL;
- int lastProofIntent = INTENT_PERCEPTUAL;
- bool current_monitor_profile_changed = true; // Force at least one update.
- bool current_proof_profile_changed = true;
-
- // Shared immutably with all canvases.
- std::shared_ptr current_transform;
-
- // So we can delete them later.
- cmsHPROFILE current_monitor_profile = nullptr;
- cmsHPROFILE current_proof_profile = nullptr;
- cmsHPROFILE sRGB_profile = nullptr; // Genric sRGB profile, find it once on inititialization.
-};
-
-} // namespace Inkscape
-
-#endif // INKSCAPE_COLOR_CMS_SYSTEM_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/color/cms-util.cpp b/src/color/cms-util.cpp
deleted file mode 100644
index 36546820b3aa366094deb53a1c86bb11552bec43..0000000000000000000000000000000000000000
--- a/src/color/cms-util.cpp
+++ /dev/null
@@ -1,123 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/** @file
- * Utilities to for working with ICC profiles. Used by CMSSystem and ColorProfile classes.
- *//*
- * Authors: see git history
- *
- * Copyright (C) 2018 Authors
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-
-#include
-#include // Debug output
-#include
-#include // File open flags
-#include // Posix read, close.
-
-#include
-#include
-
-#include "cms-util.h"
-
-namespace Inkscape {
-
-ICCProfileInfo::ICCProfileInfo(cmsHPROFILE profile, std::string &&path, bool in_home)
- : _path(std::move(path))
- , _in_home(in_home)
-{
- assert(profile);
-
- _name = get_color_profile_name(profile);
- _colorspace = cmsGetColorSpace(profile);
- _profileclass = cmsGetDeviceClass(profile);
-}
-
-bool is_icc_file(std::string const &filepath)
-{
- bool is_icc_file = false;
- GStatBuf st;
- if (g_stat(filepath.c_str(), &st) == 0 && st.st_size > 128) {
- // 0-3 == size
- // 36-39 == 'acsp' 0x61637370
- int fd = g_open(filepath.c_str(), O_RDONLY, S_IRWXU);
- if (fd != -1) {
- guchar scratch[40] = {0};
- size_t len = sizeof(scratch);
-
- ssize_t got = read(fd, scratch, len);
- if (got != -1) {
- size_t calcSize =
- (scratch[0] << 24) |
- (scratch[1] << 16) |
- (scratch[2] << 8) |
- (scratch[3]);
- if ( calcSize > 128 && calcSize <= static_cast(st.st_size) ) {
- is_icc_file =
- (scratch[36] == 'a') &&
- (scratch[37] == 'c') &&
- (scratch[38] == 's') &&
- (scratch[39] == 'p');
- }
- }
- close(fd);
-
- if (is_icc_file) {
- cmsHPROFILE profile = cmsOpenProfileFromFile(filepath.c_str(), "r");
- if (profile) {
- cmsProfileClassSignature profClass = cmsGetDeviceClass(profile);
- if (profClass == cmsSigNamedColorClass) {
- is_icc_file = false; // Ignore named color profiles for now.
- }
- cmsCloseProfile(profile);
- }
- }
- }
- }
-
- return is_icc_file;
-}
-
-std::string get_color_profile_name(cmsHPROFILE profile)
-{
- std::string name;
-
- if (profile) {
- cmsUInt32Number byteLen = cmsGetProfileInfoASCII(profile, cmsInfoDescription, "en", "US", nullptr, 0);
- if (byteLen > 0) {
- std::vector data(byteLen);
- cmsUInt32Number readLen = cmsGetProfileInfoASCII(profile, cmsInfoDescription,
- "en", "US",
- data.data(), data.size());
- if (readLen < data.size()) {
- std::cerr << "get_color_profile_name(): read less than expected!" << std::endl;
- data.resize(readLen);
- }
-
- // Remove nulls at end which will cause an invalid utf8 string.
- while (!data.empty() && data.back() == 0) {
- data.pop_back();
- }
-
- name = std::string(data.begin(), data.end());
- }
-
- if (name.empty()) {
- name = _("(Unnamed)");
- }
- }
-
- return name;
-}
-
-} // namespace Inkscape
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/color/cms-util.h b/src/color/cms-util.h
deleted file mode 100644
index e9262d9fa6842deda3b9a201cd830e06ca2fdd1f..0000000000000000000000000000000000000000
--- a/src/color/cms-util.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/** @file
- * Utilities to for working with ICC profiles. Used by CMSSystem and ColorProfile classes.
- *//*
- * Authors: see git history
- *
- * Copyright (C) 2018 Authors
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-
-#ifndef INKSCAPE_COLOR_CMS_UTIL_H
-#define INKSCAPE_COLOR_CMS_UTIL_H
-
-#include
-
-#include
-
-namespace Inkscape {
-
-// Helper class to store info
-class ICCProfileInfo
-{
-public:
- ICCProfileInfo(cmsHPROFILE profile, std::string &&path, bool in_home);
- bool operator<(ICCProfileInfo const &other) const;
- std::string const &get_path() const { return _path; }
- std::string const &get_name() const { return _name; }
- cmsColorSpaceSignature get_colorspace() const { return _colorspace; }
- cmsProfileClassSignature get_profileclass() const { return _profileclass; }
- bool in_home() const { return _in_home; }
-
-private:
- std::string _path;
- std::string _name;
- bool _in_home;
- cmsColorSpaceSignature _colorspace;
- cmsProfileClassSignature _profileclass;
-};
-
-bool is_icc_file(std::string const &filepath);
-std::string get_color_profile_name(cmsHPROFILE profile); // Read as ASCII from profile.
-
-} // namespace Inkscape
-
-#endif // INKSCAPE_COLOR_CMS_UTIL_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/color/cmyk-conv.cpp b/src/color/cmyk-conv.cpp
deleted file mode 100644
index e565bd37f9ed19d8329ab2055f024d9a8103fb12..0000000000000000000000000000000000000000
--- a/src/color/cmyk-conv.cpp
+++ /dev/null
@@ -1,93 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/**
- * CMYK to sRGB conversion routines
- *
- * Author:
- * Michael Kowalski
- *
- * Copyright (C) 2023 Michael Kowalski
- *
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-
-#include "cmyk-conv.h"
-#include
-#include
-#include
-
-namespace Inkscape {
-
-CmykConverter::CmykConverter(cmsHPROFILE profile, int intent) {
- _intent = intent;
- auto color_space = cmsGetColorSpace(profile);
- if (color_space != cmsSigCmykData && color_space != cmsSigCmyData) {
- g_warning("Select CMYK ICC profile to convert CMYK to sRGB");
- return;
- }
- //todo
- if (cmsIsIntentSupported(_profile, intent, LCMS_USED_AS_OUTPUT)) {
- }
- _profile = profile;
- _srgb = cmsCreate_sRGBProfile();
- auto fmt = color_space == cmsSigCmykData ? TYPE_CMYK_16 : TYPE_CMY_16;
- _cmy = color_space == cmsSigCmyData;
- _transform = cmsCreateTransform(profile, fmt, _srgb, TYPE_RGBA_8, intent, 0);
-}
-
-CmykConverter::~CmykConverter() {
- if (_transform) cmsDeleteTransform(_transform);
- // _srgb is virtual and probably not something that can be freed
-}
-
-// Simple CMYK to sRGB conversion using interpolation from plain cyan, magenta and yellow colors
-std::array simple_cmyk_to_rgb(float c, float m, float y, float k) {
- auto invlerp = [](float f1, float p) {
- // CSS Color module 5 allows for a wide range of CMYK values, but clamps them to 0%-100%
- p = std::clamp(p, 0.0f, 100.0f);
- f1 = (255 - f1) / 255.0f;
- return 1.0f - (f1 * p / 100.0f);
- };
-
- // interpolate cyan
- auto cr = invlerp(0x00, c);
- auto cg = invlerp(0xa4, c);
- auto cb = invlerp(0xdb, c);
- // magenta
- auto mr = invlerp(0xd7, m);
- auto mg = invlerp(0x15, m);
- auto mb = invlerp(0x7e, m);
- // and yellow
- auto yr = invlerp(0xff, y);
- auto yg = invlerp(0xf1, y);
- auto yb = invlerp(0x08, y);
- // and combine them
- auto bk = 1 - k / 100.0f;
- uint8_t r = (cr * mr * yr) * bk * 255;
- uint8_t g = (cg * mg * yg) * bk * 255;
- uint8_t b = (cb * mb * yb) * bk * 255;
- return {r, g, b};
-}
-
-std::array CmykConverter::cmyk_to_rgb(float c, float m, float y, float k) {
- if (_profile) {
- cmsUInt16Number tmp[4] = { cmsUInt16Number(c / 100.0f * 0xffff), cmsUInt16Number(m / 100.0f * 0xffff), cmsUInt16Number(y / 100.0f * 0xffff), cmsUInt16Number(k / 100.0f * 0xffff) };
-
- uint8_t post[4] = { 0, 0, 0, 0 };
- cmsDoTransform(_transform, tmp, post, 1);
-
- if (_cmy && k > 0) {
- // if profile cannot transform black, then this is only a crude approximation
- auto black = 1 - k / 100.0f;
- post[0] *= black;
- post[1] *= black;
- post[2] *= black;
- }
- return { post[0], post[1], post[2] };
- }
- else {
- // no ICC profile available
- return simple_cmyk_to_rgb(c, m, y, k);
- }
-}
-
-} // namespace
diff --git a/src/color/cmyk-conv.h b/src/color/cmyk-conv.h
deleted file mode 100644
index 524c9bddf238a12979ff7de004d65cd694f021ff..0000000000000000000000000000000000000000
--- a/src/color/cmyk-conv.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#ifndef INKSCAPE_CMYK_H
-#define INKSCAPE_CMYK_H
-
-#include
-#include
-#include "color/cms-color-types.h"
-
-namespace Inkscape {
-
-// Convert CMYK to sRGB
-class CmykConverter {
-public:
- // Conversion using ICC profile gives the best results and should always be used
- // whenever there is a profile selected/available
- CmykConverter(cmsHPROFILE profile, int intent = INTENT_PERCEPTUAL);
-
- // Simple (but not simplistic) CMYK to sRGB conversion to show approximately what
- // CMYK colors may look like on an sRGB device (without ICC profile)
- CmykConverter() {}
-
- ~CmykConverter();
-
- // if profile has been selected and can decode cmy/k, then return true
- bool profile_used() const { return _profile != nullptr; }
-
- // CMYK channels from 0 to 100 (percentage) to sRGB (channels 0..255)
- std::array cmyk_to_rgb(float c, float m, float y, float k);
-
-private:
- cmsHPROFILE _profile = nullptr;
- cmsHTRANSFORM _transform = nullptr;
- cmsHPROFILE _srgb = nullptr;
- bool _cmy = false;
- int _intent = 0;
-};
-
-} // namespace
-
-#endif
diff --git a/src/color/color-conv.cpp b/src/color/color-conv.cpp
deleted file mode 100644
index 8ce3bcbac4b2cf93fefe7cc34e21377783868348..0000000000000000000000000000000000000000
--- a/src/color/color-conv.cpp
+++ /dev/null
@@ -1,30 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-#include
-#include
-
-#include "color-conv.h"
-
-namespace Inkscape {
-namespace Util {
-
-std::string rgba_color_to_string(unsigned int rgba) {
- std::ostringstream ost;
- ost << "#" << std::setfill ('0') << std::setw(8) << std::hex << rgba;
- return ost.str();
-}
-
-std::optional string_to_rgba_color(const char* str) {
- if (!str || *str != '#') {
- return std::optional();
- }
- try {
- return static_cast(std::stoul(str + 1, nullptr, 16));
- }
- catch (...) {
- return std::optional();
- }
-}
-
-}
-}
\ No newline at end of file
diff --git a/src/color/color-conv.h b/src/color/color-conv.h
deleted file mode 100644
index 0b87704c6d2d1f1864c56caae70e9b02e9cdc584..0000000000000000000000000000000000000000
--- a/src/color/color-conv.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2022 Authors
- *
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-#ifndef INKSCAPE_UTIL_COLOR_CONV_H
-#define INKSCAPE_UTIL_COLOR_CONV_H
-
-#include
-#include
-
-namespace Inkscape {
-namespace Util {
-
-// Convert RGBA color to '#rrggbbaa' hex string
-std::string rgba_color_to_string(unsigned int rgba);
-
-// Parse hex string '#rrgbbaa' and return RGBA color
-std::optional string_to_rgba_color(const char* str);
-
-} } // namespace
-
-#endif
diff --git a/src/color/color-profile-cms-fns.h b/src/color/color-profile-cms-fns.h
deleted file mode 100644
index 06258c73e13f312c172ad3ca867dca07e9e9e746..0000000000000000000000000000000000000000
--- a/src/color/color-profile-cms-fns.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/** @file
- * TODO: insert short description here
- *//*
- * Authors: see git history
- *
- * Copyright (C) 2012 Authors
- * Released under GNU GPL v2+, read the file 'COPYING' for more information.
- */
-#ifndef SEEN_COLOR_PROFILE_CMS_FNS_H
-#define SEEN_COLOR_PROFILE_CMS_FNS_H
-
-#ifdef HAVE_CONFIG_H
-# include "config.h" // only include where actually required!
-#endif
-
-#include
-
-#include "cms-color-types.h"
-
-namespace Inkscape {
-
-// Note: these can later be adjusted to adapt for lcms2:
-
-class ColorSpaceSigWrapper : public ColorSpaceSig {
-public :
- ColorSpaceSigWrapper( cmsColorSpaceSignature sig ) : ColorSpaceSig( static_cast(sig) ) {}
- ColorSpaceSigWrapper( ColorSpaceSig const &other ) : ColorSpaceSig( other ) {}
-
- operator cmsColorSpaceSignature() const { return static_cast(value); }
-};
-
-class ColorProfileClassSigWrapper : public ColorProfileClassSig {
-public :
- ColorProfileClassSigWrapper( cmsProfileClassSignature sig ) : ColorProfileClassSig( static_cast(sig) ) {}
- ColorProfileClassSigWrapper( ColorProfileClassSig const &other ) : ColorProfileClassSig( other ) {}
-
- operator cmsProfileClassSignature() const { return static_cast(value); }
-};
-
-cmsColorSpaceSignature asICColorSpaceSig(ColorSpaceSig const & sig);
-cmsProfileClassSignature asICColorProfileClassSig(ColorProfileClassSig const & sig);
-
-} // namespace Inkscape
-
-
-#endif // !SEEN_COLOR_PROFILE_CMS_FNS_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/colors/CMakeLists.txt b/src/colors/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..3265f5a7f038b3cbf19eebf86533683315d24775
--- /dev/null
+++ b/src/colors/CMakeLists.txt
@@ -0,0 +1,66 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+set(colors_SRC
+ cms/profile.cpp
+ cms/system.cpp
+ cms/transform.cpp
+ color.cpp
+ dragndrop.cpp
+ manager.cpp
+ parser.cpp
+ printer.cpp
+ spaces/base.cpp
+ spaces/cms.cpp
+ spaces/cmyk.cpp
+ spaces/components.cpp
+ spaces/hsl.cpp
+ spaces/hsluv.cpp
+ spaces/hsv.cpp
+ spaces/lab.cpp
+ spaces/lch.cpp
+ spaces/linear-rgb.cpp
+ spaces/luv.cpp
+ spaces/okhsl.cpp
+ spaces/oklab.cpp
+ spaces/oklch.cpp
+ spaces/named.cpp
+ spaces/rgb.cpp
+ spaces/xyz.cpp
+ tracker.cpp
+ utils.cpp
+ xml-color.cpp
+
+ # -------
+ # Headers
+ cms/profile.h
+ cms/system.h
+ cms/transform.h
+ color.h
+ dragndrop.h
+ manager.h
+ parser.h
+ printer.h
+ spaces/base.h
+ spaces/cms.h
+ spaces/cmyk.h
+ spaces/components.h
+ spaces/enum.h
+ spaces/hsl.h
+ spaces/hsluv.h
+ spaces/hsv.h
+ spaces/lab.h
+ spaces/lch.h
+ spaces/linear-rgb.h
+ spaces/luv.h
+ spaces/okhsl.h
+ spaces/oklab.h
+ spaces/oklch.h
+ spaces/named.h
+ spaces/rgb.h
+ spaces/xyz.h
+ tracker.h
+ utils.h
+ xml-color.h
+)
+
+add_inkscape_source("${colors_SRC}")
diff --git a/src/colors/cms/profile.cpp b/src/colors/cms/profile.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..618cf76789d12add7e3c3f878f52459a185e955e
--- /dev/null
+++ b/src/colors/cms/profile.cpp
@@ -0,0 +1,281 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/** @file
+ * A C++ wrapper for lcms2 profiles
+ *//*
+ * Authors: see git history
+ *
+ * Copyright (C) 2018 Authors
+ * Released under GNU GPL v2+, read the file 'COPYING' for more information.
+ */
+
+#include "profile.h"
+
+#include
+#include
+#include
+#include
+#include