Compare commits
175 Commits
css-render
...
color-mana
Author | SHA1 | Date | |
---|---|---|---|
|
8b3957f20f | ||
|
12e67c644c | ||
|
f94bdbeedb | ||
|
8dc4faac96 | ||
|
6aeb0ef751 | ||
|
f622f21c0f | ||
|
74ad081dd8 | ||
|
b3aff6570d | ||
|
fcffe94259 | ||
|
37e12d1fa1 | ||
|
e083ff1fed | ||
|
6d2f311942 | ||
|
5765b0d795 | ||
|
8eec8f8234 | ||
|
7d62a85825 | ||
|
e444cdae9d | ||
|
fd17c4a425 | ||
|
c3cc3cdacc | ||
|
0402a350e7 | ||
|
74460f148b | ||
|
89609ec412 | ||
|
598874dc7b | ||
|
ea6b5b4425 | ||
|
b415e74dbd | ||
|
8d9532d204 | ||
|
0764cfe566 | ||
|
1f1e41bdaa | ||
|
c690079ee5 | ||
|
c59b7bde2a | ||
|
74f5bcdd4a | ||
|
a7c2c7c041 | ||
|
537f8ec69b | ||
|
134ec9343d | ||
|
79c214e75d | ||
|
f271049263 | ||
|
fb5d69fc02 | ||
|
b27eaa344b | ||
|
d245674c1f | ||
|
4c7526ad99 | ||
|
d83643d6fc | ||
|
e979595280 | ||
|
6b76c13bcc | ||
|
5ab831215e | ||
|
1e404f6625 | ||
|
2dc85d7e5f | ||
|
5f706c73fd | ||
|
208e5a9931 | ||
|
421e8dcbc8 | ||
|
2bc12a8b27 | ||
|
bfca93eafc | ||
|
bd2ac3e897 | ||
|
1e1c8d1a6d | ||
|
7b4f08eea6 | ||
|
baefbc5259 | ||
|
81da727a9c | ||
|
13e3242e7d | ||
|
afb02f2d54 | ||
|
c53772908c | ||
|
83523d88f6 | ||
|
b5e4bf7a70 | ||
|
1c1d52cc59 | ||
|
6b600a2bd8 | ||
|
e3100bde3b | ||
|
5395e839a3 | ||
|
9cbe82d7fe | ||
|
8ed427dab9 | ||
|
47fe542e62 | ||
|
67e3afe42e | ||
|
b2e72700e8 | ||
|
ae1e2a13d1 | ||
|
76a80d8f45 | ||
|
153b8399f7 | ||
|
da41271dd5 | ||
|
5610af1b77 | ||
|
8da70fec91 | ||
|
f9cd30a859 | ||
|
763d620a23 | ||
|
500a3a6dee | ||
|
57073e1057 | ||
|
6bbfd2f62a | ||
|
6c69a96cd7 | ||
|
fa247d5a84 | ||
|
0320c4ac14 | ||
|
36993ac707 | ||
|
2f93eb4a28 | ||
|
5a2982ac31 | ||
|
441b704afd | ||
|
abf6ebd7fe | ||
|
34fb08af6e | ||
|
0b9dfdd41f | ||
|
701e0812e4 | ||
|
4918a46172 | ||
|
ef5e3fae64 | ||
|
9fcf55571e | ||
|
260898ecf6 | ||
|
66c9132abe | ||
|
c5abdfb72b | ||
|
4fe37847ba | ||
|
c99a0b0518 | ||
|
31f3edec5c | ||
|
dee372c08e | ||
|
8c0a4e5a6e | ||
|
7195514fb5 | ||
|
420bd5bc16 | ||
|
f024ee1adf | ||
|
18c2c71cd5 | ||
|
2d1bfc84b9 | ||
|
8edfa759fb | ||
|
2d1e978599 | ||
|
d71fc41152 | ||
|
d141cb7b72 | ||
|
7010067884 | ||
|
0ec29c4176 | ||
|
42c6e0249f | ||
|
54eb85f814 | ||
|
18b3b4feed | ||
|
0045ac839b | ||
|
a9da807de3 | ||
|
366639b7e4 | ||
|
7d2e2171be | ||
|
e3ceda15ac | ||
|
7291a21a85 | ||
|
888afe3e46 | ||
|
171bfde133 | ||
|
82d1fdb714 | ||
|
82b19daa7e | ||
|
dc1ff3c2e3 | ||
|
6602ac5eae | ||
|
5dab5bf0e9 | ||
|
721be8fe9f | ||
|
58fe590eae | ||
|
c18a7ff5cf | ||
|
24fc38b287 | ||
|
aa03c50f05 | ||
|
03e971b2e3 | ||
|
a595133b77 | ||
|
e50f4ecccf | ||
|
67913e4af0 | ||
|
b3d1795327 | ||
|
6edcc8f256 | ||
|
d5e5f47666 | ||
|
0524c40640 | ||
|
b5fd894f77 | ||
|
d8492121aa | ||
|
4a0bf603d7 | ||
|
02fa89df9e | ||
|
5b6dde9a73 | ||
|
e9d8ebdfc9 | ||
|
366efc3d61 | ||
|
3b890fd3c1 | ||
|
5de373a14b | ||
|
24cb9d2437 | ||
|
83aa176466 | ||
|
0e94e5ecda | ||
|
130485a583 | ||
|
f34c10abb5 | ||
|
48b00f0ac1 | ||
|
743329a3af | ||
|
f5783f1637 | ||
|
67f61a8d39 | ||
|
f7df663dea | ||
|
c99278aa58 | ||
|
1765e1b7c2 | ||
|
bf1a434d5c | ||
|
9256b5b552 | ||
|
577e4afb3c | ||
|
2a05c04db7 | ||
|
a6ffd6b3b2 | ||
|
24eba7c4c1 | ||
|
80de844922 | ||
|
a2223c0884 | ||
|
5ffa2b757c | ||
|
b660fa27d3 | ||
|
77f0e5e1ba | ||
|
32a4f805b8 |
@@ -35,7 +35,11 @@ pacman --noconfirm -S --needed \
|
||||
mingw-w64-$MSYS2_ARCH-python-gobject \
|
||||
mingw-w64-$MSYS2_ARCH-shaderc \
|
||||
mingw-w64-$MSYS2_ARCH-vulkan \
|
||||
mingw-w64-$MSYS2_ARCH-vulkan-headers
|
||||
mingw-w64-$MSYS2_ARCH-vulkan-headers \
|
||||
mingw-w64-$MSYS2_ARCH-libpng \
|
||||
mingw-w64-$MSYS2_ARCH-libjpeg-turbo \
|
||||
mingw-w64-$MSYS2_ARCH-libtiff \
|
||||
mingw-w64-$MSYS2_ARCH-lcms2
|
||||
|
||||
mkdir -p _ccache
|
||||
export CCACHE_BASEDIR="$(pwd)"
|
||||
|
34
NEWS
@@ -1,6 +1,40 @@
|
||||
Overview of Changes in 4.15.2, xx-xx-xxxx
|
||||
=========================================
|
||||
|
||||
* GtkFileChooserWidget:
|
||||
- Plug some memory leaks
|
||||
- Make Ctrl-Shift-N create a new folder
|
||||
|
||||
* CSS:
|
||||
- Support color(), oklab(), etc (https://www.w3.org/TR/css-color-4/)
|
||||
- Support color-mix() (https://www.w3.org/TR/css-color-5/)
|
||||
- Support relative colors (https://www.w3.org/TR/css-color-5/)
|
||||
|
||||
* Accessibility:
|
||||
- Avoid markup when reading labels
|
||||
|
||||
* GSK:
|
||||
- Subset fonts when serializing node trees
|
||||
|
||||
* Wayland:
|
||||
- Use xdg-dialog protocol for attached dialogs
|
||||
|
||||
* Windows:
|
||||
- Build with UNICODE
|
||||
|
||||
* Debugging:
|
||||
- Add GTK_DEBUG=css for warning about deprecated css syntax
|
||||
|
||||
* Tools:
|
||||
- nodeparser: Add an extract command for data urls
|
||||
|
||||
* Deprecations:
|
||||
- CSS Color functions shade(), lighter(), darker(), alpha(), mix()
|
||||
|
||||
* Translation updates:
|
||||
Hebrew
|
||||
|
||||
|
||||
Overview of Changes in 4.15.1, 21-05-2024
|
||||
=========================================
|
||||
|
||||
|
After Width: | Height: | Size: 24 KiB |
BIN
demos/gtk-demo/ICC-Rendering-Intent-Test.jpg
Normal file
After Width: | Height: | Size: 290 KiB |
BIN
demos/gtk-demo/ICC-Rendering-Intent-Test.png
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
demos/gtk-demo/ICC-Rendering-Intent-Test.tif
Normal file
86
demos/gtk-demo/colorspaces.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/* Color Spaces
|
||||
*
|
||||
* Demonstrates support for color spaces.
|
||||
*
|
||||
* The test images used here are taken from http://displaycal.net/icc-color-management-test/
|
||||
* and are licensed under the Creative Commons BY-SA 4.0 International License
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static GtkWidget *jpeg;
|
||||
static GtkWidget *png;
|
||||
static GtkWidget *tiff;
|
||||
static GtkWidget *noprofile;
|
||||
static GtkWidget *test1;
|
||||
static GtkWidget *test2;
|
||||
|
||||
static void
|
||||
on_changed (GtkCheckButton *button,
|
||||
gpointer user_data)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
const char *extension = NULL;
|
||||
char *path;
|
||||
|
||||
if (!gtk_check_button_get_active (GTK_CHECK_BUTTON (button)))
|
||||
return;
|
||||
|
||||
if (gtk_check_button_get_active (GTK_CHECK_BUTTON (jpeg)))
|
||||
extension = ".jpg";
|
||||
else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (png)))
|
||||
extension = ".png";
|
||||
else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (tiff)))
|
||||
extension = ".tif";
|
||||
else if (gtk_check_button_get_active (GTK_CHECK_BUTTON (noprofile)))
|
||||
extension = "-expected-result-no-cm.png";
|
||||
|
||||
path = g_strconcat ("/colorspaces/sRGB_Gray", extension, NULL);
|
||||
texture = gdk_texture_new_from_resource (path);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (test1), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
|
||||
path = g_strconcat ("/colorspaces/ICC-Rendering-Intent-Test", extension, NULL);
|
||||
texture = gdk_texture_new_from_resource (path);
|
||||
gtk_picture_set_paintable (GTK_PICTURE (test2), GDK_PAINTABLE (texture));
|
||||
g_object_unref (texture);
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
do_colorspaces (GtkWidget *do_widget)
|
||||
{
|
||||
static GtkWidget *window;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
GtkBuilder *builder;
|
||||
GtkBuilderScope *scope;
|
||||
|
||||
scope = gtk_builder_cscope_new ();
|
||||
gtk_builder_cscope_add_callback_symbol (GTK_BUILDER_CSCOPE (scope),
|
||||
"on_changed", G_CALLBACK (on_changed));
|
||||
|
||||
builder = gtk_builder_new ();
|
||||
gtk_builder_set_scope (builder, scope);
|
||||
gtk_builder_add_from_resource (builder, "/colorspaces/colorspaces.ui", NULL);
|
||||
window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
|
||||
jpeg = GTK_WIDGET (gtk_builder_get_object (builder, "jpeg"));
|
||||
png = GTK_WIDGET (gtk_builder_get_object (builder, "png"));
|
||||
tiff = GTK_WIDGET (gtk_builder_get_object (builder, "tiff"));
|
||||
noprofile = GTK_WIDGET (gtk_builder_get_object (builder, "noprofile"));
|
||||
test1 = GTK_WIDGET (gtk_builder_get_object (builder, "test1"));
|
||||
test2 = GTK_WIDGET (gtk_builder_get_object (builder, "test2"));
|
||||
gtk_window_set_display (GTK_WINDOW (window),
|
||||
gtk_widget_get_display (do_widget));
|
||||
g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
|
||||
g_object_unref (builder);
|
||||
g_object_unref (scope);
|
||||
}
|
||||
|
||||
if (!gtk_widget_get_visible (window))
|
||||
gtk_window_present (GTK_WINDOW (window));
|
||||
else
|
||||
gtk_window_destroy (GTK_WINDOW (window));
|
||||
|
||||
return window;
|
||||
}
|
94
demos/gtk-demo/colorspaces.ui
Normal file
@@ -0,0 +1,94 @@
|
||||
<interface>
|
||||
<object class="GtkWindow" id="window">
|
||||
<property name="default-width">660</property>
|
||||
<property name="default-height">660</property>
|
||||
<property name="resizable">false</property>
|
||||
<property name="title">Color Profiles</property>
|
||||
<child>
|
||||
<object class="GtkScrolledWindow">
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">10</property>
|
||||
<property name="margin-top">10</property>
|
||||
<property name="margin-bottom">10</property>
|
||||
<property name="margin-start">10</property>
|
||||
<property name="margin-end">10</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<property name="spacing">10</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">File format:</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="jpeg">
|
||||
<property name="label">JPEG</property>
|
||||
<property name="active">1</property>
|
||||
<signal name="notify::active" handler="on_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="png">
|
||||
<property name="label">PNG</property>
|
||||
<property name="group">jpeg</property>
|
||||
<signal name="notify::active" handler="on_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="tiff">
|
||||
<property name="label">TIFF</property>
|
||||
<property name="group">png</property>
|
||||
<signal name="notify::active" handler="on_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="noprofile">
|
||||
<property name="label">No profile</property>
|
||||
<property name="group">tiff</property>
|
||||
<signal name="notify::active" handler="on_changed"/>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Test 1: Matrix-based profile</property>
|
||||
<style>
|
||||
<class name="title-3"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture" id="test1">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="can-shrink">1</property>
|
||||
<property name="keep-aspect-ratio">1</property>
|
||||
<property name="file">resource:///colorprofiles/sRGB_Gray.jpg</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">Test 2: Lookup table-based profile</property>
|
||||
<style>
|
||||
<class name="title-3"/>
|
||||
</style>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture" id="test2">
|
||||
<property name="hexpand">1</property>
|
||||
<property name="vexpand">1</property>
|
||||
<property name="can-shrink">1</property>
|
||||
<property name="keep-aspect-ratio">1</property>
|
||||
<property name="file">resource:///colorprofiles/ICC-Rendering-Intent-Test.jpg</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
@@ -19,6 +19,17 @@
|
||||
<file>demoimage.c</file>
|
||||
<file>demoimage.h</file>
|
||||
</gresource>
|
||||
<gresource prefix="/colorspaces">
|
||||
<file>colorspaces.ui</file>
|
||||
<file>sRGB_Gray.jpg</file>
|
||||
<file>sRGB_Gray.png</file>
|
||||
<file>sRGB_Gray.tif</file>
|
||||
<file>sRGB_Gray-expected-result-no-cm.png</file>
|
||||
<file>ICC-Rendering-Intent-Test.png</file>
|
||||
<file>ICC-Rendering-Intent-Test.jpg</file>
|
||||
<file>ICC-Rendering-Intent-Test.tif</file>
|
||||
<file>ICC-Rendering-Intent-Test-expected-result-no-cm.png</file>
|
||||
</gresource>
|
||||
<gresource prefix="/constraints_builder">
|
||||
<file>constraints_builder.ui</file>
|
||||
</gresource>
|
||||
@@ -265,6 +276,7 @@
|
||||
<file>assistant.c</file>
|
||||
<file>builder.c</file>
|
||||
<file>clipboard.c</file>
|
||||
<file>colorspaces.c</file>
|
||||
<file>combobox.c</file>
|
||||
<file>constraints.c</file>
|
||||
<file>constraints_interactive.c</file>
|
||||
|
@@ -5,6 +5,7 @@ demos = files([
|
||||
'assistant.c',
|
||||
'builder.c',
|
||||
'clipboard.c',
|
||||
'colorspaces.c',
|
||||
'combobox.c',
|
||||
'constraints.c',
|
||||
'constraints_interactive.c',
|
||||
|
BIN
demos/gtk-demo/sRGB_Gray-expected-result-no-cm.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
demos/gtk-demo/sRGB_Gray.jpg
Normal file
After Width: | Height: | Size: 36 KiB |
BIN
demos/gtk-demo/sRGB_Gray.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
demos/gtk-demo/sRGB_Gray.tif
Normal file
@@ -117,16 +117,27 @@ should be aware that the allowed values are meant to be used on 3D transformatio
|
||||
so their naming might appear awkward. However, it is always possible to use the
|
||||
matrix3d() production to specify all 16 values individually.
|
||||
|
||||
### color-state
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| ----------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| color-state | `<ident>|<url>` | srgb | always |
|
||||
|
||||
Creates a node like `gsk_color_state_node_new()` with the given properties.
|
||||
|
||||
### conic-gradient
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| center | `<point>` | 25, 25 | always |
|
||||
| rotation | `<number>` | 0 | always |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
| property | syntax | default | printed |
|
||||
| ----------------- | ----------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| center | `<point>` | 25, 25 | always |
|
||||
| rotation | `<number>` | 0 | always |
|
||||
| color-state | `<ident>`|`<url>` | srgb | non-default |
|
||||
| hue-interpolation | `<ident>` | shorter | non-default |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
|
||||
Creates a node like `gsk_conic_gradient_node_new()` with the given properties.
|
||||
Creates a node like `gsk_conic_gradient_node_new_in()` with the given properties.
|
||||
|
||||
### cross-fade
|
||||
|
||||
@@ -192,14 +203,16 @@ Creates a node like `gsk_inset_shadow_node_new()` with the given properties.
|
||||
|
||||
### linear-gradient
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| start | `<point>` | 0 0 | always |
|
||||
| end | `<point>` | 0 50 | always |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
| property | syntax | default | printed |
|
||||
| ----------------- | ----------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| start | `<point>` | 0 0 | always |
|
||||
| end | `<point>` | 0 50 | always |
|
||||
| color-state | `<ident>`|`<url>` | srgb | non-default |
|
||||
| hue-interpolation | `<ident>` | shorter | non-default |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
|
||||
Creates a node like `gsk_linear_gradient_node_new()` with the given properties.
|
||||
Creates a node like `gsk_linear_gradient_node_new_in()` with the given properties.
|
||||
|
||||
### mask
|
||||
|
||||
@@ -235,15 +248,17 @@ Creates a node like `gsk_outset_shadow_node_new()` with the given properties.
|
||||
|
||||
### radial-gradient
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| center | `<point>` | 25 25 | always |
|
||||
| hradius | `<number>` | 25 | always |
|
||||
| vradius | `<number>` | 25 | always |
|
||||
| start | `<number>` | 0 | always |
|
||||
| end | `<number>` | 1 | always |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
| property | syntax | default | printed |
|
||||
| ----------------- | ----------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| center | `<point>` | 25 25 | always |
|
||||
| hradius | `<number>` | 25 | always |
|
||||
| vradius | `<number>` | 25 | always |
|
||||
| start | `<number>` | 0 | always |
|
||||
| end | `<number>` | 1 | always |
|
||||
| color-state | `<ident>`|`<url>` | srgb | non-default |
|
||||
| hue-interpolation | `<ident>` | shorter | non-default |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
|
||||
Creates a node like `gsk_radial_gradient_node_new()` with the given properties.
|
||||
|
||||
@@ -259,29 +274,33 @@ Creates a node like `gsk_repeat_node_new()` with the given properties.
|
||||
|
||||
### repeating-linear-gradient
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| start | `<point>` | 0 0 | always |
|
||||
| end | `<point>` | 0 50 | always |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
| property | syntax | default | printed |
|
||||
| ----------------- | ----------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| start | `<point>` | 0 0 | always |
|
||||
| end | `<point>` | 0 50 | always |
|
||||
| color-state | `<ident>`|`<url>` | srgb | non-default |
|
||||
| hue-interpolation | `<ident>` | shorter | non-default |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
|
||||
Creates a node like `gsk_repeating_linear_gradient_node_new()` with the given
|
||||
Creates a node like `gsk_repeating_linear_gradient_node_new_in()` with the given
|
||||
properties.
|
||||
|
||||
### repeating radial-gradient
|
||||
|
||||
| property | syntax | default | printed |
|
||||
| -------- | ---------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| center | `<point>` | 25 25 | always |
|
||||
| hradius | `<number>` | 25 | always |
|
||||
| vradius | `<number>` | 25 | always |
|
||||
| start | `<number>` | 0 | always |
|
||||
| end | `<number>` | 1 | always |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
| property | syntax | default | printed |
|
||||
| ----------------- | ----------------- | ---------------------- | ----------- |
|
||||
| bounds | `<rect>` | 50 | always |
|
||||
| center | `<point>` | 25 25 | always |
|
||||
| hradius | `<number>` | 25 | always |
|
||||
| vradius | `<number>` | 25 | always |
|
||||
| start | `<number>` | 0 | always |
|
||||
| end | `<number>` | 1 | always |
|
||||
| color-state | `<ident>`|`<url>` | srgb | non-default |
|
||||
| hue-interpolation | `<ident>` | shorter | non-default |
|
||||
| stops | `<color-stop>` | 0 #AF0, 1 #F0C | always |
|
||||
|
||||
Creates a node like `gsk_repeating_radial_gradient_node_new()` with the given
|
||||
Creates a node like `gsk_repeating_radial_gradient_node_new_in()` with the given
|
||||
properties.
|
||||
|
||||
### rounded-clip
|
||||
|
BIN
demos/widget-factory/linear-gradient-color.png
Normal file
After Width: | Height: | Size: 213 B |
BIN
demos/widget-factory/linear-gradient-monochrome.png
Normal file
After Width: | Height: | Size: 220 B |
BIN
demos/widget-factory/srgb-gradient-color.png
Normal file
After Width: | Height: | Size: 154 B |
BIN
demos/widget-factory/srgb-gradient-monochrome.png
Normal file
After Width: | Height: | Size: 164 B |
@@ -6,3 +6,10 @@
|
||||
.toolbar {
|
||||
-gtk-icon-style: symbolic;
|
||||
}
|
||||
|
||||
.gtk-gradient-color {
|
||||
background: linear-gradient(to right, lime, red);
|
||||
}
|
||||
.gtk-gradient-monochrome {
|
||||
background: linear-gradient(to right, black, white);
|
||||
}
|
||||
|
@@ -117,5 +117,9 @@
|
||||
<file>portland-rose.jpg</file>
|
||||
<file>nyc.jpg</file>
|
||||
<file>beach.jpg</file>
|
||||
<file>linear-gradient-color.png</file>
|
||||
<file>linear-gradient-monochrome.png</file>
|
||||
<file>srgb-gradient-color.png</file>
|
||||
<file>srgb-gradient-monochrome.png</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@@ -1344,13 +1344,173 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<child>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box8">
|
||||
<property name="orientation">1</property>
|
||||
<object class="GtkGrid">
|
||||
<property name="hexpand">0</property>
|
||||
<property name="row-spacing">6</property>
|
||||
<property name="column-spacing">6</property>
|
||||
<property name="margin-start">6</property>
|
||||
<property name="margin-end">6</property>
|
||||
<property name="margin-top">6</property>
|
||||
<property name="margin-bottom">6</property>
|
||||
<property name="row-homogeneous">1</property>
|
||||
<property name="valign">start</property>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">color</property>
|
||||
<style>
|
||||
<class name="caption-heading"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">0</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">sRGB</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/srgb-gradient-color.png</property>
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="keep-aspect-ratio">0</property>
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">GTK</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture">
|
||||
<property name="width-request">128</property>
|
||||
<property name="keep-aspect-ratio">0</property>
|
||||
<style>
|
||||
<class name="gtk-gradient-color"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">linear</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/linear-gradient-color.png</property>
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="keep-aspect-ratio">0</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label" translatable="yes">monochrome</property>
|
||||
<style>
|
||||
<class name="caption-heading"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">4</property>
|
||||
<property name="column-span">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">sRGB</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/srgb-gradient-monochrome.png</property>
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="keep-aspect-ratio">0</property>
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">5</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">GTK</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture">
|
||||
<property name="width-request">128</property>
|
||||
<property name="keep-aspect-ratio">0</property>
|
||||
<style>
|
||||
<class name="gtk-gradient-monochrome"/>
|
||||
</style>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">6</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">linear</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">7</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkPicture">
|
||||
<property name="file">resource:///org/gtk/WidgetFactory4/linear-gradient-monochrome.png</property>
|
||||
<property name="can-shrink">0</property>
|
||||
<property name="keep-aspect-ratio">0</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">7</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
<object class="GtkLabel" id="label8">
|
||||
<property name="label" translatable="1">page 1</property>
|
||||
<property name="label" translatable="1">Gradients</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
@@ -93,11 +93,12 @@ Colors can be expressed in numerous ways in CSS (see the
|
||||
many (but not all) of these.
|
||||
|
||||
You can use rgb(), rgba(), hsl() with both the legacy or the modern CSS
|
||||
syntax, and calc() can be used as well in color expressions.
|
||||
syntax, and calc() can be used as well in color expressions. hwb(), oklab(),
|
||||
oklch(), color(), color-mix() and relative colors are supported as well.
|
||||
|
||||
### Non-CSS Colors
|
||||
|
||||
GTK extends the CSS syntax with several additional ways to specify colors.
|
||||
GTK extends the CSS syntax with several additional ways to specify colors.
|
||||
|
||||
These extensions are deprecated and should be replaced by the equivalent
|
||||
standard CSS notions.
|
||||
|
@@ -99,16 +99,15 @@ reaches the requested phase. However, in practice most things
|
||||
happen at higher levels:
|
||||
|
||||
- If you are doing an animation, you can use
|
||||
gtk_widget_add_tick_callback() which will cause a regular
|
||||
[method@Gtk.Widget.add_tick_callback] which will cause a regular
|
||||
beating of the clock with a callback in the Update phase
|
||||
until you stop the tick.
|
||||
- If some state changes that causes the size of your widget to
|
||||
change you call gtk_widget_queue_resize() which will request
|
||||
change you call [method@Gtk.Widget.queue_resize] which will request
|
||||
a Layout phase and mark your widget as needing relayout.
|
||||
- If some state changes so you need to redraw some area of
|
||||
your widget you use the normal gtk_widget_queue_draw()
|
||||
set of functions. These will request a Paint phase and
|
||||
mark the region as needing redraw.
|
||||
- If some state changes so you need to redraw your widget you
|
||||
use [method@Gtk.Widget.queue_draw] to request a Paint phase for
|
||||
your widget.
|
||||
|
||||
There are also a lot of implicit triggers of these from the
|
||||
CSS layer (which does animations, resizes and repaints as needed).
|
||||
|
@@ -18,6 +18,7 @@ SYNOPSIS
|
||||
|
|
||||
| **gtk4-rendernode-tool** benchmark [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** compare [OPTIONS...] <FILE1> <FILE2>
|
||||
| **gtk4-rendernode-tool** extract [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** info [OPTIONS...] <FILE>
|
||||
| **gtk4-rendernode-tool** render [OPTIONS...] <FILE> [<FILE>]
|
||||
| **gtk4-rendernode-tool** show [OPTIONS...] <FILE>
|
||||
@@ -99,3 +100,15 @@ exit code is 1. If the images are identical, it is 0.
|
||||
``--quiet``
|
||||
|
||||
Don't write results to stdout.
|
||||
|
||||
|
||||
Extract
|
||||
^^^^^^^
|
||||
|
||||
The ``extract`` command saves all the data urls found in a node file to a given
|
||||
directory. The file names for the extracted files are derived from the mimetype
|
||||
of the url.
|
||||
|
||||
``--dir=DIRECTORY``
|
||||
|
||||
Save extracted files in ``DIRECTORY`` (defaults to the current directory).
|
||||
|
@@ -77,6 +77,7 @@ content_files = [
|
||||
"section-tree-widget.md",
|
||||
"migrating-2to4.md",
|
||||
"migrating-3to4.md",
|
||||
"migrating-4to5.md",
|
||||
"broadway.md",
|
||||
"osx.md",
|
||||
"wayland.md",
|
||||
|
@@ -14,6 +14,7 @@ expand_content_md_files = [
|
||||
'running.md',
|
||||
'migrating-2to4.md',
|
||||
'migrating-3to4.md',
|
||||
'migrating-4to5.md',
|
||||
'actions.md',
|
||||
'input-handling.md',
|
||||
'drawing-model.md',
|
||||
|
@@ -58,7 +58,7 @@ use a GtkLabel.
|
||||
If you have a need for custom drawing that fits into the current
|
||||
(dark or light) theme, e.g. for rendering a graph, you can still
|
||||
get the current style foreground color, using
|
||||
[method@Gtk.Widget.get_style_color].
|
||||
[method@Gtk.Widget.get_color].
|
||||
|
||||
## Local stylesheets are going away
|
||||
|
||||
@@ -73,6 +73,103 @@ GTK 5 will no longer provide this functionality. The recommendations
|
||||
is to use a global stylesheet (i.e. gtk_style_context_add_provider_for_display())
|
||||
and rely on style classes to make your CSS apply only where desired.
|
||||
|
||||
## Non-standard CSS extensions are going away
|
||||
|
||||
GTK's CSS machinery has a some non-standard extensions around colors:
|
||||
named colors with \@define-color and color functions: lighter(), darker(),
|
||||
shade(), alpha(), mix().
|
||||
|
||||
GTK now implements equivalent functionality from the CSS specs.
|
||||
|
||||
### \@define-color is going away
|
||||
|
||||
\@define-color should be replaced by custom properties in the :root scope.
|
||||
|
||||
Instead of
|
||||
|
||||
```
|
||||
@define-color fg_color #2e3436
|
||||
|
||||
...
|
||||
|
||||
box {
|
||||
color: @fg_color;
|
||||
}
|
||||
```
|
||||
|
||||
use
|
||||
|
||||
```
|
||||
:root {
|
||||
--fg-color: #2e3436;
|
||||
}
|
||||
|
||||
...
|
||||
|
||||
box {
|
||||
color: var(--fg-color);
|
||||
}
|
||||
```
|
||||
|
||||
For more information about custom CSS properties and variables, see the
|
||||
[CSS Custom Properties for Cascading Variables](https://www.w3.org/TR/css-variables-1/)
|
||||
spec.
|
||||
|
||||
### Color expressions are going away
|
||||
|
||||
The color functions can all be replaced by combinations of calc() and color-mix().
|
||||
|
||||
ligher(c) and darker(c) are just shade(c, 1.3) or shade(c, 0.7), respectively, and
|
||||
thus can be handled the same way as shade in the examples below.
|
||||
|
||||
Replace
|
||||
|
||||
```
|
||||
a {
|
||||
color: mix(red, green, 0.8);
|
||||
}
|
||||
|
||||
b {
|
||||
color: alpha(green, 0.6);
|
||||
}
|
||||
|
||||
c {
|
||||
color: shade(red, 1.3);
|
||||
}
|
||||
|
||||
d {
|
||||
color: shade(red, 0.7);
|
||||
}
|
||||
```
|
||||
|
||||
with
|
||||
|
||||
```
|
||||
a {
|
||||
color: color-mix(in srgb, red, green 80%);
|
||||
}
|
||||
|
||||
b {
|
||||
color: rgb(from green, r g b / calc(alpha * 0.6));
|
||||
}
|
||||
|
||||
c {
|
||||
color: hsl(from red, h calc(s * 1.3) calc(l * 1.3));
|
||||
}
|
||||
|
||||
d {
|
||||
color: hsl(from red, h calc(s * 0.7) calc(l * 0.7));
|
||||
}
|
||||
```
|
||||
|
||||
Variations of these replacements are possible.
|
||||
|
||||
Note that GTK has historically computed mix() and shade() values in the SRGB and HSL
|
||||
colorspaces, but using OKLAB instead might yield slightly better results.
|
||||
|
||||
For more information about color-mix(), see the
|
||||
[CSS Color](https://drafts.csswg.org/css-color-5) spec.
|
||||
|
||||
## Chooser interfaces are going away
|
||||
|
||||
The GtkColorChooser, GtkFontChooser, GtkFileChooser and GtkAppChooser
|
||||
|
@@ -46,9 +46,10 @@ gdk_broadway_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
width = gdk_surface_get_width (surface);
|
||||
height = gdk_surface_get_height (surface);
|
||||
scale = gdk_surface_get_scale_factor (surface);
|
||||
self->paint_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
width * scale, height * scale);
|
||||
cairo_surface_set_device_scale (self->paint_surface, scale, scale);
|
||||
|
||||
self->paint_surface = gdk_surface_create_similar_surface (surface,
|
||||
CAIRO_CONTENT_COLOR_ALPHA,
|
||||
width * scale, height *scale);
|
||||
|
||||
repaint_region = cairo_region_create_rectangle (&(cairo_rectangle_int_t) { 0, 0, width, height });
|
||||
cairo_region_union (region, repaint_region);
|
||||
|
@@ -19,7 +19,7 @@
|
||||
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||
* files for a list of changes. These files are distributed with
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
@@ -138,6 +138,7 @@ static const GdkDebugKey gdk_debug_keys[] = {
|
||||
{ "high-depth", GDK_DEBUG_HIGH_DEPTH, "Use high bit depth rendering if possible" },
|
||||
{ "no-vsync", GDK_DEBUG_NO_VSYNC, "Repaint instantly (uses 100% CPU with animations)" },
|
||||
{ "dmabuf-disable", GDK_DEBUG_DMABUF_DISABLE, "Disable dmabuf support" },
|
||||
{ "srgb", GDK_DEBUG_SRGB, "Force sRRGB rendering and turn off color profiles" },
|
||||
};
|
||||
|
||||
|
||||
|
@@ -30,6 +30,8 @@
|
||||
#include <gdk/gdkcairo.h>
|
||||
#include <gdk/gdkcairocontext.h>
|
||||
#include <gdk/gdkclipboard.h>
|
||||
#include <gdk/gdkcolor.h>
|
||||
#include <gdk/gdkcolorstate.h>
|
||||
#include <gdk/gdkconfig.h>
|
||||
#include <gdk/gdkcontentdeserializer.h>
|
||||
#include <gdk/gdkcontentformats.h>
|
||||
|
140
gdk/gdkcairo.c
@@ -20,7 +20,11 @@
|
||||
#include "gdkcairo.h"
|
||||
|
||||
#include "gdkrgba.h"
|
||||
#include "gdkcolor.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkcolorprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -35,14 +39,47 @@ void
|
||||
gdk_cairo_set_source_rgba (cairo_t *cr,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
GdkColor color;
|
||||
const float *components;
|
||||
|
||||
g_return_if_fail (cr != NULL);
|
||||
g_return_if_fail (rgba != NULL);
|
||||
|
||||
gdk_color_convert_rgba (&color, gdk_cairo_get_color_state (cr), rgba);
|
||||
components = gdk_color_get_components (&color);
|
||||
cairo_set_source_rgba (cr,
|
||||
rgba->red,
|
||||
rgba->green,
|
||||
rgba->blue,
|
||||
rgba->alpha);
|
||||
components[0],
|
||||
components[1],
|
||||
components[2],
|
||||
components[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cairo_set_source_color:
|
||||
* @cr: a cairo contet
|
||||
* @rgba: a `GdkColor`
|
||||
*
|
||||
* Sets the specified `GdkColor` as the source color of @cr.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_cairo_set_source_color (cairo_t *cr,
|
||||
const GdkColor *color)
|
||||
{
|
||||
GdkColor c;
|
||||
const float *components;
|
||||
|
||||
g_return_if_fail (cr != NULL);
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
gdk_color_convert (&c, gdk_cairo_get_color_state (cr), color);
|
||||
components = gdk_color_get_components (&c);
|
||||
cairo_set_source_rgba (cr,
|
||||
components[0],
|
||||
components[1],
|
||||
components[2],
|
||||
components[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -303,3 +340,98 @@ gdk_cairo_region_create_from_surface (cairo_surface_t *surface)
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
static cairo_user_data_key_t color_state_key;
|
||||
|
||||
/**
|
||||
* gdk_cairo_surface_set_color_state:
|
||||
* @surface: a surface
|
||||
* @color_state: the color state to attach to the surface
|
||||
*
|
||||
* Attaches a `GdkColorState` to the Cairo surface.
|
||||
*
|
||||
* This is just auxiliary data for use by GTK, no Cairo functions
|
||||
* do interact with this information.
|
||||
*
|
||||
* Note that all Cairo compositing operations are assumed to happen
|
||||
* in a linear RGB color state, so if you want to use the surface
|
||||
* as a target for rendering in a color managed way, you should use
|
||||
* such a color state.
|
||||
*
|
||||
* The default color state is assumed to be sRGB, which is not
|
||||
* linear.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_cairo_surface_set_color_state (cairo_surface_t *surface,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_return_if_fail (surface != NULL);
|
||||
g_return_if_fail (color_state != NULL);
|
||||
|
||||
cairo_surface_set_user_data (surface,
|
||||
&color_state_key,
|
||||
gdk_color_state_ref (color_state),
|
||||
(cairo_destroy_func_t) gdk_color_state_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cairo_surface_get_color_state:
|
||||
* @surface: a surface
|
||||
*
|
||||
* Gets the color state GTK assumes for the surface.
|
||||
*
|
||||
* See [method@Gdk.CairoSurface.set_color_state] for details.
|
||||
*
|
||||
* Returns: (transfer none): the color state
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_cairo_surface_get_color_state (cairo_surface_t *surface)
|
||||
{
|
||||
GdkColorState *color_state;
|
||||
|
||||
g_return_val_if_fail (surface != NULL, gdk_color_state_get_srgb ());
|
||||
|
||||
color_state = cairo_surface_get_user_data (surface, &color_state_key);
|
||||
if (color_state == NULL)
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
return color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_cairo_get_color_state:
|
||||
* @cr: a cairo context
|
||||
*
|
||||
* Gets the color state GTK assumes for the cairo context.
|
||||
*
|
||||
* Returns: (transfer none): the color state
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_cairo_get_color_state (cairo_t *cr)
|
||||
{
|
||||
GdkColorState *color_state;
|
||||
cairo_surface_t *surface;
|
||||
|
||||
g_return_val_if_fail (cr != NULL, gdk_color_state_get_srgb ());
|
||||
|
||||
surface = cairo_get_group_target (cr);
|
||||
color_state = cairo_surface_get_user_data (surface, &color_state_key);
|
||||
if (color_state != NULL)
|
||||
return color_state;
|
||||
|
||||
/* theoretically, we should walk the whole group stack, but I don't
|
||||
* think Cairo lets us do that
|
||||
*/
|
||||
surface = cairo_get_target (cr);
|
||||
color_state = cairo_surface_get_user_data (surface, &color_state_key);
|
||||
if (color_state != NULL)
|
||||
return color_state;
|
||||
|
||||
return gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
@@ -30,6 +30,11 @@ G_BEGIN_DECLS
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_cairo_set_source_rgba (cairo_t *cr,
|
||||
const GdkRGBA *rgba);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_cairo_set_source_color (cairo_t *cr,
|
||||
const GdkColor *color);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_cairo_set_source_pixbuf (cairo_t *cr,
|
||||
const GdkPixbuf *pixbuf,
|
||||
@@ -44,9 +49,15 @@ void gdk_cairo_region (cairo_t *cr,
|
||||
const cairo_region_t *region);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
cairo_region_t *
|
||||
gdk_cairo_region_create_from_surface
|
||||
(cairo_surface_t *surface);
|
||||
cairo_region_t * gdk_cairo_region_create_from_surface (cairo_surface_t *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_cairo_surface_set_color_state (cairo_surface_t *surface,
|
||||
GdkColorState *color_state);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_cairo_surface_get_color_state (cairo_surface_t *surface);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_cairo_get_color_state (cairo_t *cr);
|
||||
|
||||
GDK_DEPRECATED_IN_4_6_FOR(gdk_gl_texture_new)
|
||||
void gdk_cairo_draw_from_gl (cairo_t *cr,
|
||||
|
507
gdk/gdkcolor.c
Normal file
@@ -0,0 +1,507 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* Copyright (C) 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkcolorprivate.h"
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkrgbaprivate.h"
|
||||
|
||||
#include <lcms2.h>
|
||||
|
||||
/**
|
||||
* GdkColor:
|
||||
* @color_state: the color state to interpret the values in
|
||||
* @values: the 3 coordinates that define the color, followed
|
||||
* by the alpha value
|
||||
*
|
||||
* A `GdkColor` represents a color.
|
||||
*
|
||||
* The color state defines the meaning and range of the values.
|
||||
* E.g., the srgb color state has r, g, b components representing
|
||||
* red, green and blue with a range of [0,1], while the oklch color
|
||||
* state has l, c, h components representing luminosity, chromaticity
|
||||
* and hue, with l ranging from 0 to 1 and c from 0 to about 0.4, while
|
||||
* h is interpreted as angle in degrees.
|
||||
*
|
||||
* value[3] is always the alpha value with a range of [0,1].
|
||||
*
|
||||
* Note that `GdkColor` is mainly intended for on-stack use, and does
|
||||
* not take a reference to the @color_state, unless you use gdk_color_copy().
|
||||
*/
|
||||
|
||||
/* {{{ Boxed type */
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkColor, gdk_color,
|
||||
gdk_color_copy, gdk_color_free)
|
||||
|
||||
/**
|
||||
* gdk_color_copy:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Makes a copy of a `GdkColor`.
|
||||
*
|
||||
* The result must be freed through [method@Gdk.Color.free].
|
||||
*
|
||||
* Returns: A newly allocated `GdkColor`, with the same contents as @self
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColor *
|
||||
gdk_color_copy (const GdkColor *self)
|
||||
{
|
||||
GdkColor *copy = g_new0 (GdkColor, 1);
|
||||
g_set_object (©->color_state, self->color_state);
|
||||
memcpy (copy->values, self->values, sizeof (float) * 4);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_free:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Frees a `Gdkcolor`.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_color_free (GdkColor *self)
|
||||
{
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
void
|
||||
(gdk_color_init) (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const float components[4])
|
||||
{
|
||||
_gdk_color_init (self, color_state, components);
|
||||
}
|
||||
|
||||
void
|
||||
(gdk_color_init_from_rgba) (GdkColor *self,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
_gdk_color_init_from_rgba (self, rgba);
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_get_color_state) (const GdkColor *self)
|
||||
{
|
||||
return _gdk_color_get_color_state (self);
|
||||
}
|
||||
|
||||
const float *
|
||||
(gdk_color_get_components) (const GdkColor *self)
|
||||
{
|
||||
return _gdk_color_get_components (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
(gdk_color_equal) (const GdkColor *self,
|
||||
const GdkColor *other)
|
||||
{
|
||||
return _gdk_color_equal (self, other);
|
||||
}
|
||||
|
||||
gboolean
|
||||
(gdk_color_is_black) (const GdkColor *self)
|
||||
{
|
||||
return _gdk_color_is_black (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
(gdk_color_is_clear) (const GdkColor *self)
|
||||
{
|
||||
return _gdk_color_is_clear (self);
|
||||
}
|
||||
|
||||
gboolean
|
||||
(gdk_color_is_opaque) (const GdkColor *self)
|
||||
{
|
||||
return _gdk_color_is_opaque (self);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/**
|
||||
* gdk_color_convert:
|
||||
* @self: the `GdkColor` to store the result in
|
||||
* @color_state: the target color start
|
||||
* @other: the `GdkColor` to convert
|
||||
*
|
||||
* Converts a given `GdkColor` to another color state.
|
||||
*
|
||||
* After the conversion, @self will represent the same
|
||||
* color as @other in @color_state, to the degree possible.
|
||||
*
|
||||
* Different color states have different gamuts of colors
|
||||
* they can represent, and converting a color to a color
|
||||
* state with a smaller gamut may yield an 'out of gamut'
|
||||
* result.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
(gdk_color_convert) (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *other)
|
||||
{
|
||||
GdkColorStateTransform tf;
|
||||
|
||||
self->color_state = color_state;
|
||||
|
||||
gdk_color_state_transform_init (&tf, other->color_state, color_state, TRUE);
|
||||
gdk_color_state_transform (&tf, other->values, self->values, 1);
|
||||
gdk_color_state_transform_finish (&tf);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_convert_rgba:
|
||||
* @self: the `GdkColor` to store the result in
|
||||
* @color_state: the target color state
|
||||
* @rgba: the `GdkRGBA` to convert
|
||||
*
|
||||
* Converts a given `GdkRGBA` to the target @color_state.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_color_convert_rgba (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
GdkColor tmp = { (GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_SRGB),
|
||||
{ rgba->red, rgba->green, rgba->blue, rgba->alpha } };
|
||||
|
||||
gdk_color_convert (self, color_state, &tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_mix:
|
||||
* @self: the `GdkColor` to store the result in
|
||||
* @color_start: the target color state
|
||||
* @src1: the first color
|
||||
* @src2: the second color
|
||||
* @progress: the relative amount of @src2, from 0 to 1
|
||||
*
|
||||
* Mix two colors.
|
||||
*
|
||||
* This operation first converts @src1 and @src2 to the
|
||||
* target @color_state, and then interpolates between them
|
||||
* with a position given by @progress.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_color_mix (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *src1,
|
||||
const GdkColor *src2,
|
||||
double progress)
|
||||
{
|
||||
if (src1->color_state != color_state)
|
||||
{
|
||||
GdkColor tmp;
|
||||
gdk_color_convert (&tmp, color_state, src1);
|
||||
gdk_color_mix (self, color_state, &tmp, src2, progress);
|
||||
}
|
||||
else if (src2->color_state != color_state)
|
||||
{
|
||||
GdkColor tmp;
|
||||
gdk_color_convert (&tmp, color_state, src2);
|
||||
gdk_color_mix (self, color_state, src1, &tmp, progress);
|
||||
}
|
||||
else
|
||||
{
|
||||
gsize i;
|
||||
const float *s1, *s2;
|
||||
float *d;
|
||||
|
||||
self->color_state = color_state;
|
||||
self->values[3] = src1->values[3] * (1.0 - progress) + src2->values[3] * progress;
|
||||
|
||||
d = (float *) gdk_color_get_components (self);
|
||||
s1 = gdk_color_get_components (src1);
|
||||
s2 = gdk_color_get_components (src2);
|
||||
|
||||
if (self->values[3] == 0)
|
||||
{
|
||||
for (i = 0; i < 3; i++)
|
||||
d[i] = s1[i] * (1.0 - progress) + s2[i] * progress;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0; i < 3; i++)
|
||||
d[i] = (s1[i] * src1->values[3] * (1.0 - progress) + s2[i] * src2->values[3] * progress) / self->values[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*< private >
|
||||
* gdk_color_parser_parse:
|
||||
* @parser: the parser
|
||||
* @color: location to store the parsed color
|
||||
*
|
||||
* Parses a string representation of colors that
|
||||
* is inspired by CSS.
|
||||
*
|
||||
* Returns: `TRUE` if parsing succeeded
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
gboolean
|
||||
gdk_color_parser_parse (GtkCssParser *parser,
|
||||
GdkColor *color)
|
||||
{
|
||||
const GtkCssToken *token;
|
||||
GdkRGBA rgba;
|
||||
|
||||
if (gtk_css_parser_has_function (parser, "color"))
|
||||
{
|
||||
GdkColorState *color_state;
|
||||
float values[4];
|
||||
const char *coords;
|
||||
|
||||
gtk_css_parser_start_block (parser);
|
||||
|
||||
if (gtk_css_parser_try_ident (parser, "srgb"))
|
||||
{
|
||||
coords = "rgb";
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
else if (gtk_css_parser_try_ident (parser, "srgb-linear"))
|
||||
{
|
||||
coords = "rgb";
|
||||
color_state = gdk_color_state_get_srgb_linear ();
|
||||
}
|
||||
else if (gtk_css_parser_try_ident (parser, "oklab"))
|
||||
{
|
||||
coords = "lab";
|
||||
color_state = gdk_color_state_get_oklab ();
|
||||
}
|
||||
else if (gtk_css_parser_try_ident (parser, "oklch"))
|
||||
{
|
||||
coords = "lch";
|
||||
color_state = gdk_color_state_get_oklch ();
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Expected a valid color state");
|
||||
gtk_css_parser_end_block (parser);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
token = gtk_css_parser_get_token (parser);
|
||||
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE))
|
||||
{
|
||||
float v = token->number.number;
|
||||
|
||||
switch (coords[i])
|
||||
{
|
||||
case 'l':
|
||||
values[i] = CLAMP (v / 100.0, 0, 1);
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
values[i] = v * 0.4 / 100.0;
|
||||
break;
|
||||
case 'c':
|
||||
values[i] = MAX (0, v * 0.4 / 100.0);
|
||||
break;
|
||||
case 'h':
|
||||
gtk_css_parser_error_syntax (parser, "Can't use percentage for hue");
|
||||
gtk_css_parser_end_block (parser);
|
||||
return FALSE;
|
||||
default:
|
||||
values[i] = CLAMP (v / 100.0, 0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_css_parser_consume_token (parser);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_NUMBER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_NUMBER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
float v = token->number.number;
|
||||
|
||||
switch (coords[i])
|
||||
{
|
||||
case 'l':
|
||||
values[i] = CLAMP (v, 0, 1);
|
||||
break;
|
||||
case 'a':
|
||||
case 'b':
|
||||
case 'h':
|
||||
values[i] = v;
|
||||
break;
|
||||
case 'c':
|
||||
values[i] = MAX (0, v);
|
||||
break;
|
||||
default:
|
||||
values[i] = CLAMP (v, 0, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
gtk_css_parser_consume_token (parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Expected a number or percentage");
|
||||
gtk_css_parser_end_block (parser);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
token = gtk_css_parser_get_token (parser);
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
values[3] = 1;
|
||||
}
|
||||
else if (gtk_css_token_is_delim (token, '/'))
|
||||
{
|
||||
gtk_css_parser_consume_token (parser);
|
||||
|
||||
token = gtk_css_parser_get_token (parser);
|
||||
|
||||
if (gtk_css_token_is (token, GTK_CSS_TOKEN_PERCENTAGE))
|
||||
{
|
||||
values[3] = CLAMP (token->number.number / 100.0, 0, 1);
|
||||
gtk_css_parser_consume_token (parser);
|
||||
}
|
||||
else if (gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_NUMBER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_NUMBER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNED_INTEGER) ||
|
||||
gtk_css_token_is (token, GTK_CSS_TOKEN_SIGNLESS_INTEGER))
|
||||
{
|
||||
values[3] = CLAMP (token->number.number, 0, 1);
|
||||
gtk_css_parser_consume_token (parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Expected a number or percentage");
|
||||
gtk_css_parser_end_block (parser);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
token = gtk_css_parser_get_token (parser);
|
||||
if (!gtk_css_token_is (token, GTK_CSS_TOKEN_EOF))
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Garbage at the end of the value");
|
||||
gtk_css_parser_end_block (parser);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_css_parser_consume_token (parser);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_css_parser_error_syntax (parser, "Expected '/'");
|
||||
gtk_css_parser_end_block (parser);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gtk_css_parser_end_block (parser);
|
||||
|
||||
gdk_color_init (color, color_state, values);
|
||||
return TRUE;
|
||||
}
|
||||
else if (gdk_rgba_parser_parse (parser, &rgba))
|
||||
{
|
||||
gdk_color_init_from_rgba (color, &rgba);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_print:
|
||||
* @self: a `GdkColor`
|
||||
* @string: the string to print on
|
||||
*
|
||||
* Appends a representation of @self to @string.
|
||||
*
|
||||
* The representation is inspired by CSS3 colors,
|
||||
* but not 100% identical, and looks like this:
|
||||
*
|
||||
* color(NAME V1 V2 V3 / ALPHA)
|
||||
*
|
||||
* where `NAME` is the name of the color state,
|
||||
* `V1`, `V2`, `V3` and `ALPHA` are the components
|
||||
* of the color. Alpha may be omitted if it is 1.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_color_print (const GdkColor *self,
|
||||
GString *string)
|
||||
{
|
||||
char buffer[48];
|
||||
|
||||
g_string_append (string, "color(");
|
||||
g_string_append (string, gdk_color_state_get_name (self->color_state));
|
||||
g_string_append_c (string, ' ');
|
||||
g_ascii_dtostr (buffer, sizeof (buffer), self->values[0]);
|
||||
g_string_append (string, buffer);
|
||||
g_string_append_c (string, ' ');
|
||||
g_ascii_dtostr (buffer, sizeof (buffer), self->values[1]);
|
||||
g_string_append (string, buffer);
|
||||
g_string_append_c (string, ' ');
|
||||
g_ascii_dtostr (buffer, sizeof (buffer), self->values[2]);
|
||||
g_string_append (string, buffer);
|
||||
if (self->values[3] < 0.999)
|
||||
{
|
||||
g_string_append (string, " / ");
|
||||
g_ascii_dtostr (buffer, sizeof (buffer), self->values[3]);
|
||||
g_string_append (string, buffer);
|
||||
}
|
||||
g_string_append_c (string, ')');
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_to_string:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Returns a string representation @self.
|
||||
*
|
||||
* See [method@Gdk.Color.print] for details about
|
||||
* the format.
|
||||
*
|
||||
* Returns: (transfer full): a newly allocated string
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
char *
|
||||
gdk_color_to_string (const GdkColor *self)
|
||||
{
|
||||
GString *string = g_string_new ("");
|
||||
gdk_color_print (self, string);
|
||||
return g_string_free (string, FALSE);
|
||||
}
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
106
gdk/gdkcolor.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* Copyright (C) 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkcolorstate.h>
|
||||
#include <gdk/gdkrgba.h>
|
||||
|
||||
|
||||
/* The interpretation of the first 3 components depends on the color state.
|
||||
* values[3] is always alpha.
|
||||
*/
|
||||
struct _GdkColor
|
||||
{
|
||||
GdkColorState *color_state;
|
||||
float values[4];
|
||||
};
|
||||
|
||||
G_STATIC_ASSERT (sizeof (GdkColor) % sizeof (gpointer) == 0);
|
||||
|
||||
#define GDK_TYPE_COLOR (gdk_color_get_type ())
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_COLOR_INIT(cs, c1, c2, c3, c4) \
|
||||
(GdkColor) { (cs), { (c1), (c2), (c3), (c4) } }
|
||||
|
||||
#define GDK_COLOR_INIT_SRGB(c1, c2, c3, c4) \
|
||||
GDK_COLOR_INIT (GDK_COLOR_STATE_SRGB, (c1), (c2), (c3), (c4) )
|
||||
|
||||
#define GDK_COLOR_INIT_RGBA(r) \
|
||||
GDK_COLOR_INIT_SRGB ((r)->red, (r)->green, (r)->blue, (r)->alpha)
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GType gdk_color_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColor * gdk_color_copy (const GdkColor *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_free (GdkColor *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_init (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const float components[4]);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_init_from_rgba (GdkColor *self,
|
||||
const GdkRGBA *rgba);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_convert (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *other);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_convert_rgba (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkRGBA *rgba);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_mix (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *src1,
|
||||
const GdkColor *src2,
|
||||
double progress);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_print (const GdkColor *self,
|
||||
GString *string);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
char * gdk_color_to_string (const GdkColor *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_get_color_state (const GdkColor *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
const float * gdk_color_get_components (const GdkColor *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_equal (const GdkColor *color1,
|
||||
const GdkColor *color2);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_is_black (const GdkColor *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_is_clear (const GdkColor *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_is_opaque (const GdkColor *self);
|
||||
|
||||
#include "gdkcolorimpl.h"
|
||||
|
||||
G_END_DECLS
|
122
gdk/gdkcolorimpl.h
Normal file
@@ -0,0 +1,122 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
*
|
||||
* Copyright (C) 2021 Benjamin Otte
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define gdk_color_init(self, cs, comp) _gdk_color_init ((self), (cs), (comp))
|
||||
static inline void
|
||||
_gdk_color_init (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const float components[4])
|
||||
{
|
||||
self->color_state = color_state;
|
||||
self->values[0] = components[0];
|
||||
self->values[1] = components[1];
|
||||
self->values[2] = components[2];
|
||||
self->values[3] = components[3];
|
||||
}
|
||||
|
||||
#define gdk_color_init_from_rgb(self, rgba) _gdk_color_init_from_rgba (self, rgba)
|
||||
static inline void
|
||||
_gdk_color_init_from_rgba (GdkColor *self,
|
||||
const GdkRGBA *rgba)
|
||||
{
|
||||
self->color_state = GDK_COLOR_STATE_SRGB;
|
||||
self->values[0] = rgba->red;
|
||||
self->values[1] = rgba->green;
|
||||
self->values[2] = rgba->blue;
|
||||
self->values[3] = rgba->alpha;
|
||||
}
|
||||
|
||||
#define gdk_color_get_color_state(self) _gdk_color_get_color_state (self)
|
||||
static inline GdkColorState *
|
||||
_gdk_color_get_color_state (const GdkColor *self)
|
||||
{
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
#define gdk_color_get_components(self) _gdk_color_get_components (self)
|
||||
static inline const float *
|
||||
_gdk_color_get_components (const GdkColor *self)
|
||||
{
|
||||
return self->values;
|
||||
}
|
||||
|
||||
#define gdk_color_equal(self, other) _gdk_color_equal (self, other)
|
||||
static inline gboolean
|
||||
_gdk_color_equal (const GdkColor *self,
|
||||
const GdkColor *other)
|
||||
{
|
||||
return self->values[0] == other->values[0] &&
|
||||
self->values[1] == other->values[1] &&
|
||||
self->values[2] == other->values[2] &&
|
||||
self->values[3] == other->values[3] &&
|
||||
gdk_color_state_equal (self->color_state, other->color_state);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
all_zero (const GdkColor *c)
|
||||
{
|
||||
return c->values[0] == 0 && c->values[1] == 0 && c->values[2] == 0;
|
||||
}
|
||||
|
||||
#define gdk_color_is_black(self) _gdk_color_is_black (self)
|
||||
static inline gboolean
|
||||
_gdk_color_is_black (const GdkColor *self)
|
||||
{
|
||||
if (gdk_color_state_equal (self->color_state, GDK_COLOR_STATE_SRGB))
|
||||
return all_zero (self);
|
||||
else
|
||||
{
|
||||
GdkColor c;
|
||||
gboolean res;
|
||||
|
||||
gdk_color_convert (&c, GDK_COLOR_STATE_SRGB, self);
|
||||
res = all_zero (&c);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
#define gdk_color_is_clear(self) _gdk_color_is_clear (self)
|
||||
static inline gboolean
|
||||
_gdk_color_is_clear (const GdkColor *self)
|
||||
{
|
||||
return self->values[3] < ((float) 0x00ff / (float) 0xffff);
|
||||
}
|
||||
|
||||
#define gdk_color_is_opaque(self) _gdk_color_is_opaque (self)
|
||||
static inline gboolean
|
||||
_gdk_color_is_opaque (const GdkColor *self)
|
||||
{
|
||||
return self->values[3] > ((float)0xff00 / (float)0xffff);
|
||||
}
|
||||
|
||||
#define gdk_color_convert(self, cs, other) _gdk_color_convert (self, cs, other)
|
||||
static inline void
|
||||
_gdk_color_convert (GdkColor *self,
|
||||
GdkColorState *color_state,
|
||||
const GdkColor *other)
|
||||
{
|
||||
if (gdk_color_state_equal (color_state, other->color_state))
|
||||
{
|
||||
gdk_color_init (self, color_state, other->values);
|
||||
return;
|
||||
}
|
||||
|
||||
(gdk_color_convert) (self, color_state, other);
|
||||
}
|
27
gdk/gdkcolorprivate.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* GDK - The GIMP Drawing Kit
|
||||
* Copyright (C) 2024, Red Hat, Inc
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gdkcolor.h"
|
||||
|
||||
#include "gtk/css/gtkcssparserprivate.h"
|
||||
|
||||
|
||||
gboolean gdk_color_parser_parse (GtkCssParser *parser,
|
||||
GdkColor *color);
|
||||
|
950
gdk/gdkcolorstate.c
Normal file
@@ -0,0 +1,950 @@
|
||||
/* gdkcolorstate.c
|
||||
*
|
||||
* Copyright 2024 Matthias Clasen
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gtk/gtkcolorutilsprivate.h"
|
||||
|
||||
/**
|
||||
* GdkColorState:
|
||||
*
|
||||
* A `GdkColorState` object provides the information to interpret
|
||||
* colors and pixels in a variety of ways.
|
||||
*
|
||||
* They are also known as
|
||||
* [*color spaces*](https://en.wikipedia.org/wiki/Color_space).
|
||||
*
|
||||
* Crucially, GTK knows how to convert colors from one color
|
||||
* state to another.
|
||||
*
|
||||
* `GdkColorState objects are immutable and therefore threadsafe.
|
||||
*
|
||||
* Since 4.16
|
||||
*/
|
||||
|
||||
static GdkColorStateClass * get_class (GdkColorState *self);
|
||||
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkColorState, gdk_color_state,
|
||||
gdk_color_state_ref, gdk_color_state_unref);
|
||||
|
||||
/* {{{ Public API */
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_ref) (GdkColorState *self)
|
||||
{
|
||||
return _gdk_color_state_ref (self);
|
||||
}
|
||||
|
||||
void
|
||||
(gdk_color_state_unref) (GdkColorState *self)
|
||||
{
|
||||
_gdk_color_state_unref (self);
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_srgb) (void)
|
||||
{
|
||||
return _gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_srgb_linear) (void)
|
||||
{
|
||||
return _gdk_color_state_get_srgb_linear ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_hsl) (void)
|
||||
{
|
||||
return _gdk_color_state_get_hsl ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_hwb) (void)
|
||||
{
|
||||
return _gdk_color_state_get_hwb ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_oklab) (void)
|
||||
{
|
||||
return _gdk_color_state_get_oklab ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_oklch) (void)
|
||||
{
|
||||
return _gdk_color_state_get_oklch ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_display_p3) (void)
|
||||
{
|
||||
return _gdk_color_state_get_display_p3 ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_xyz) (void)
|
||||
{
|
||||
return _gdk_color_state_get_xyz ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_rec2020) (void)
|
||||
{
|
||||
return _gdk_color_state_get_rec2020 ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_rec2100_pq) (void)
|
||||
{
|
||||
return _gdk_color_state_get_rec2100_pq ();
|
||||
}
|
||||
|
||||
GdkColorState *
|
||||
(gdk_color_state_get_rec2100_linear) (void)
|
||||
{
|
||||
return _gdk_color_state_get_rec2100_linear ();
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_equal:
|
||||
* @self: a `GdkColorState`
|
||||
* @other: another `GdkColorStatee`
|
||||
*
|
||||
* Compares two `GdkColorStates` for equality.
|
||||
*
|
||||
* Note that this function is not guaranteed to be perfect and two objects
|
||||
* describing the same color state may compare not equal. However, different
|
||||
* color states will never compare equal.
|
||||
*
|
||||
* Returns: %TRUE if the two color states compare equal
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
gboolean
|
||||
(gdk_color_state_equal) (GdkColorState *self,
|
||||
GdkColorState *other)
|
||||
{
|
||||
return _gdk_color_state_equal (self, other);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_is_linear:
|
||||
* @self: a `GdkColorState`
|
||||
*
|
||||
* Returns whether the color state is linear.
|
||||
*
|
||||
* Returns: `TRUE` if the color state is linear
|
||||
* Since: 4.16
|
||||
*/
|
||||
gboolean
|
||||
gdk_color_state_is_linear (GdkColorState *self)
|
||||
{
|
||||
return get_class (self)->is_linear (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_save_to_icc_profile:
|
||||
* @self: a `GdkColorState`
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Saves the color state to an
|
||||
* [ICC profile](https://en.wikipedia.org/wiki/ICC_profile).
|
||||
*
|
||||
* Some color states cannot be represented as ICC profiles.
|
||||
* In that case, @error will be set and %NULL will be returned.
|
||||
*
|
||||
* Returns: (nullable): A new `GBytes` containing the ICC profile
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GBytes *
|
||||
gdk_color_state_save_to_icc_profile (GdkColorState *self,
|
||||
GError **error)
|
||||
{
|
||||
return get_class (self)->save_to_icc_profile (self, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_state_save_to_cicp_data:
|
||||
* @self: a `GdkColorState`
|
||||
* @color_primaries: return location for color primaries
|
||||
* @transfer_characteristics: return location for transfer characteristics
|
||||
* @matrix_coefficients: return location for matrix_coefficients
|
||||
* @full_range: return location for the full range flag
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Saves the color state as
|
||||
* [CICP](https://en.wikipedia.org/wiki/Coding-independent_code_points)
|
||||
* data.
|
||||
*
|
||||
* Some color states cannot be represented as CICP data.
|
||||
* In that case, @error will be set and `FALSE` will be returned.
|
||||
*
|
||||
* Returns: (nullable): `TRUE` if the out arguments were set
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
gboolean
|
||||
gdk_color_state_save_to_cicp_data (GdkColorState *self,
|
||||
int *color_primaries,
|
||||
int *transfer_characteristics,
|
||||
int *matrix_coefficients,
|
||||
gboolean *full_range,
|
||||
GError **error)
|
||||
{
|
||||
return get_class (self)->save_to_cicp_data (self,
|
||||
color_primaries,
|
||||
transfer_characteristics,
|
||||
matrix_coefficients,
|
||||
full_range,
|
||||
error);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ ICC implementation */
|
||||
|
||||
#define GDK_LCMS_COLOR_STATE(c) ((GdkLcmsColorState *)(c))
|
||||
|
||||
typedef struct {
|
||||
GdkColorState state;
|
||||
|
||||
cmsHPROFILE lcms_profile;
|
||||
} GdkLcmsColorState;
|
||||
|
||||
/* {{{ Helpers */
|
||||
|
||||
static cmsHPROFILE
|
||||
gdk_lcms_color_state_get_lcms_profile (GdkColorState *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_LCMS_COLOR_STATE (self), NULL);
|
||||
|
||||
return GDK_LCMS_COLOR_STATE (self)->lcms_profile;
|
||||
}
|
||||
|
||||
static cmsHPROFILE
|
||||
gdk_lcms_get_srgb_profile (void)
|
||||
{
|
||||
return cmsCreate_sRGBProfile ();
|
||||
}
|
||||
|
||||
static cmsHPROFILE
|
||||
gdk_lcms_get_srgb_linear_profile (void)
|
||||
{
|
||||
cmsToneCurve *curve;
|
||||
cmsHPROFILE profile;
|
||||
|
||||
curve = cmsBuildGamma (NULL, 1.0);
|
||||
profile = cmsCreateRGBProfile (&(cmsCIExyY) {
|
||||
0.3127, 0.3290, 1.0
|
||||
},
|
||||
&(cmsCIExyYTRIPLE) {
|
||||
{ 0.6400, 0.3300, 1.0 },
|
||||
{ 0.3000, 0.6000, 1.0 },
|
||||
{ 0.1500, 0.0600, 1.0 }
|
||||
},
|
||||
(cmsToneCurve*[3]) { curve, curve, curve });
|
||||
cmsFreeToneCurve (curve);
|
||||
|
||||
return profile;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_lcms_save_profile (cmsHPROFILE profile,
|
||||
GError **error)
|
||||
{
|
||||
cmsUInt32Number size;
|
||||
guchar *data;
|
||||
|
||||
size = 0;
|
||||
if (!cmsSaveProfileToMem (profile, NULL, &size))
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Could not prepare ICC profile"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
data = g_malloc (size);
|
||||
if (!cmsSaveProfileToMem (profile, data, &size))
|
||||
{
|
||||
g_free (data);
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to save ICC profile"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return g_bytes_new_take (data, size);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ GdkColorState vfuncs */
|
||||
|
||||
static void
|
||||
gdk_lcms_color_state_free (GdkColorState *state)
|
||||
{
|
||||
GdkLcmsColorState *self = (GdkLcmsColorState *) state;
|
||||
|
||||
cmsCloseProfile (self->lcms_profile);
|
||||
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_lcms_color_state_equal (GdkColorState *state1,
|
||||
GdkColorState *state2)
|
||||
{
|
||||
GBytes *icc1, *icc2;
|
||||
gboolean res;
|
||||
|
||||
icc1 = gdk_color_state_save_to_icc_profile (state1, NULL);
|
||||
icc2 = gdk_color_state_save_to_icc_profile (state2, NULL);
|
||||
|
||||
res = g_bytes_equal (icc1, icc2);
|
||||
|
||||
g_bytes_unref (icc1);
|
||||
g_bytes_unref (icc2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_lcms_color_state_is_linear (GdkColorState *state)
|
||||
{
|
||||
return FALSE; /* FIXME */
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_lcms_color_state_save_to_icc_profile (GdkColorState *state,
|
||||
GError **error)
|
||||
{
|
||||
GdkLcmsColorState *self = GDK_LCMS_COLOR_STATE (state);
|
||||
|
||||
return gdk_lcms_save_profile (self->lcms_profile, error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_lcms_color_state_save_to_cicp_data (GdkColorState *self,
|
||||
int *color_primaries,
|
||||
int *transfer_characteristics,
|
||||
int *matrix_coefficients,
|
||||
gboolean *full_range,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("This color state does not support CICP data"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static const char *
|
||||
gdk_lcms_color_state_get_name (GdkColorState *self)
|
||||
{
|
||||
static char buffer[48];
|
||||
|
||||
g_snprintf (buffer, sizeof (buffer), "lcms color state %p", self);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static guint
|
||||
gdk_lcms_color_state_get_min_depth (GdkColorState *self)
|
||||
{
|
||||
return GDK_MEMORY_U16; /* ? */
|
||||
}
|
||||
|
||||
static int
|
||||
gdk_lcms_color_state_get_hue_coord (GdkColorState *self)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static GdkColorStateClass LCMS_COLOR_STATE_CLASS =
|
||||
{
|
||||
GDK_TYPE_LCMS_COLOR_STATE,
|
||||
gdk_lcms_color_state_free,
|
||||
gdk_lcms_color_state_equal,
|
||||
gdk_lcms_color_state_is_linear,
|
||||
gdk_lcms_color_state_save_to_icc_profile,
|
||||
gdk_lcms_color_state_save_to_cicp_data,
|
||||
gdk_lcms_color_state_get_name,
|
||||
gdk_lcms_color_state_get_min_depth,
|
||||
gdk_lcms_color_state_get_hue_coord,
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Private API */
|
||||
|
||||
GdkColorState *
|
||||
gdk_color_state_new_from_lcms_profile (cmsHPROFILE lcms_profile)
|
||||
{
|
||||
GdkLcmsColorState *self;
|
||||
|
||||
self= g_new0 (GdkLcmsColorState, 1);
|
||||
|
||||
self->state.klass = &LCMS_COLOR_STATE_CLASS;
|
||||
self->state.ref_count = 1;
|
||||
|
||||
self->lcms_profile = lcms_profile;
|
||||
|
||||
return (GdkColorState *) self;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
/**
|
||||
* gdk_color_state_new_from_icc_profile:
|
||||
* @icc_profile: The ICC profiles given as a `GBytes`
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new color state for the given ICC profile data.
|
||||
*
|
||||
* if the profile is not valid, %NULL is returned and an error
|
||||
* is raised.
|
||||
*
|
||||
* Returns: a new `GdkColorState` or %NULL on error
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_color_state_new_from_icc_profile (GBytes *icc_profile,
|
||||
GError **error)
|
||||
{
|
||||
cmsHPROFILE lcms_profile;
|
||||
const guchar *data;
|
||||
gsize size;
|
||||
|
||||
g_return_val_if_fail (icc_profile != NULL, NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
data = g_bytes_get_data (icc_profile, &size);
|
||||
|
||||
lcms_profile = cmsOpenProfileFromMem (data, size);
|
||||
if (lcms_profile == NULL)
|
||||
{
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Failed to load ICC profile"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return gdk_color_state_new_from_lcms_profile (lcms_profile);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* }}} */
|
||||
/* {{{ Named implementation */
|
||||
|
||||
static gboolean
|
||||
gdk_named_color_state_is_linear (GdkColorState *self)
|
||||
{
|
||||
switch (GDK_NAMED_COLOR_STATE_ID (self))
|
||||
{
|
||||
case GDK_COLOR_STATE_ID_SRGB_LINEAR:
|
||||
case GDK_COLOR_STATE_ID_OKLAB:
|
||||
case GDK_COLOR_STATE_ID_OKLCH:
|
||||
case GDK_COLOR_STATE_ID_XYZ:
|
||||
case GDK_COLOR_STATE_ID_REC2100_LINEAR:
|
||||
return TRUE;
|
||||
|
||||
case GDK_COLOR_STATE_ID_SRGB:
|
||||
case GDK_COLOR_STATE_ID_HSL:
|
||||
case GDK_COLOR_STATE_ID_HWB:
|
||||
case GDK_COLOR_STATE_ID_DISPLAY_P3:
|
||||
case GDK_COLOR_STATE_ID_REC2020:
|
||||
case GDK_COLOR_STATE_ID_REC2100_PQ:
|
||||
return FALSE;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_named_color_state_save_to_icc_profile (GdkColorState *self,
|
||||
GError **error)
|
||||
{
|
||||
cmsHPROFILE profile;
|
||||
|
||||
switch (GDK_NAMED_COLOR_STATE_ID (self))
|
||||
{
|
||||
case GDK_COLOR_STATE_ID_SRGB:
|
||||
profile = gdk_lcms_get_srgb_profile ();
|
||||
break;
|
||||
|
||||
case GDK_COLOR_STATE_ID_SRGB_LINEAR:
|
||||
profile = gdk_lcms_get_srgb_linear_profile ();
|
||||
break;
|
||||
|
||||
case GDK_COLOR_STATE_ID_OKLAB:
|
||||
case GDK_COLOR_STATE_ID_OKLCH:
|
||||
case GDK_COLOR_STATE_ID_HSL:
|
||||
case GDK_COLOR_STATE_ID_HWB:
|
||||
case GDK_COLOR_STATE_ID_DISPLAY_P3:
|
||||
case GDK_COLOR_STATE_ID_XYZ:
|
||||
case GDK_COLOR_STATE_ID_REC2020:
|
||||
case GDK_COLOR_STATE_ID_REC2100_PQ:
|
||||
case GDK_COLOR_STATE_ID_REC2100_LINEAR:
|
||||
profile = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (profile)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_lcms_save_profile (profile, error);
|
||||
cmsCloseProfile (profile);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_set_error (error,
|
||||
G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
_("ICC profile not supported for this color state"));
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_named_color_state_save_to_cicp_data (GdkColorState *self,
|
||||
int *color_primaries,
|
||||
int *transfer_characteristics,
|
||||
int *matrix_coefficients,
|
||||
gboolean *full_range,
|
||||
GError **error)
|
||||
{
|
||||
switch (GDK_NAMED_COLOR_STATE_ID (self))
|
||||
{
|
||||
case GDK_COLOR_STATE_ID_SRGB:
|
||||
*color_primaries = 0;
|
||||
*transfer_characteristics = 13;
|
||||
*matrix_coefficients = 0;
|
||||
*full_range = TRUE;
|
||||
return TRUE;
|
||||
|
||||
case GDK_COLOR_STATE_ID_SRGB_LINEAR:
|
||||
*color_primaries = 0;
|
||||
*transfer_characteristics = 8;
|
||||
*matrix_coefficients = 0;
|
||||
*full_range = TRUE;
|
||||
return TRUE;
|
||||
|
||||
case GDK_COLOR_STATE_ID_REC2100_PQ:
|
||||
*color_primaries = 9;
|
||||
*transfer_characteristics = 16;
|
||||
*matrix_coefficients = 0;
|
||||
*full_range = TRUE;
|
||||
return TRUE;
|
||||
|
||||
case GDK_COLOR_STATE_ID_REC2100_LINEAR:
|
||||
*color_primaries = 9;
|
||||
*transfer_characteristics = 8;
|
||||
*matrix_coefficients = 0;
|
||||
*full_range = TRUE;
|
||||
return TRUE;
|
||||
|
||||
case GDK_COLOR_STATE_ID_DISPLAY_P3:
|
||||
*color_primaries = 12;
|
||||
*transfer_characteristics = 13;
|
||||
*matrix_coefficients = 0;
|
||||
*full_range = TRUE;
|
||||
return TRUE;
|
||||
|
||||
case GDK_COLOR_STATE_ID_HSL:
|
||||
case GDK_COLOR_STATE_ID_HWB:
|
||||
case GDK_COLOR_STATE_ID_OKLAB:
|
||||
case GDK_COLOR_STATE_ID_OKLCH:
|
||||
case GDK_COLOR_STATE_ID_XYZ:
|
||||
case GDK_COLOR_STATE_ID_REC2020:
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("This color state does not support CICP data"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
const char *
|
||||
gdk_color_state_get_name_from_id (GdkColorStateId id)
|
||||
{
|
||||
const char *names[] = {
|
||||
"srgb", "srgb-linear", "hsl", "hwb",
|
||||
"oklab", "oklch", "display-p3", "xyz",
|
||||
"rec2020", "rec2100-pq", "rec2100-linear",
|
||||
};
|
||||
|
||||
return names[(id - 1) >> 1];
|
||||
}
|
||||
|
||||
static const char *
|
||||
gdk_named_color_state_get_name (GdkColorState *self)
|
||||
{
|
||||
return gdk_color_state_get_name_from_id (GDK_NAMED_COLOR_STATE_ID (self));
|
||||
}
|
||||
|
||||
static guint
|
||||
gdk_named_color_state_get_min_depth (GdkColorState *self)
|
||||
{
|
||||
switch (GDK_NAMED_COLOR_STATE_ID (self))
|
||||
{
|
||||
case GDK_COLOR_STATE_ID_OKLAB:
|
||||
case GDK_COLOR_STATE_ID_OKLCH:
|
||||
case GDK_COLOR_STATE_ID_HSL:
|
||||
case GDK_COLOR_STATE_ID_HWB:
|
||||
case GDK_COLOR_STATE_ID_DISPLAY_P3:
|
||||
case GDK_COLOR_STATE_ID_XYZ:
|
||||
case GDK_COLOR_STATE_ID_REC2020:
|
||||
case GDK_COLOR_STATE_ID_REC2100_PQ:
|
||||
case GDK_COLOR_STATE_ID_REC2100_LINEAR:
|
||||
case GDK_COLOR_STATE_ID_SRGB_LINEAR:
|
||||
return GDK_MEMORY_FLOAT16;
|
||||
|
||||
case GDK_COLOR_STATE_ID_SRGB:
|
||||
return GDK_MEMORY_U8;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
gdk_named_color_state_get_hue_coord (GdkColorState *in)
|
||||
{
|
||||
switch (GDK_NAMED_COLOR_STATE_ID (in))
|
||||
{
|
||||
case GDK_COLOR_STATE_ID_SRGB:
|
||||
case GDK_COLOR_STATE_ID_SRGB_LINEAR:
|
||||
case GDK_COLOR_STATE_ID_OKLAB:
|
||||
case GDK_COLOR_STATE_ID_DISPLAY_P3:
|
||||
case GDK_COLOR_STATE_ID_XYZ:
|
||||
case GDK_COLOR_STATE_ID_REC2020:
|
||||
case GDK_COLOR_STATE_ID_REC2100_PQ:
|
||||
case GDK_COLOR_STATE_ID_REC2100_LINEAR:
|
||||
return -1;
|
||||
|
||||
case GDK_COLOR_STATE_ID_HSL:
|
||||
case GDK_COLOR_STATE_ID_HWB:
|
||||
return 0;
|
||||
|
||||
case GDK_COLOR_STATE_ID_OKLCH:
|
||||
return 2;
|
||||
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
}
|
||||
|
||||
static GdkColorStateClass NAMED_COLOR_STATE_CLASS =
|
||||
{
|
||||
GDK_TYPE_NAMED_COLOR_STATE,
|
||||
NULL,
|
||||
NULL,
|
||||
gdk_named_color_state_is_linear,
|
||||
gdk_named_color_state_save_to_icc_profile,
|
||||
gdk_named_color_state_save_to_cicp_data,
|
||||
gdk_named_color_state_get_name,
|
||||
gdk_named_color_state_get_min_depth,
|
||||
gdk_named_color_state_get_hue_coord,
|
||||
};
|
||||
|
||||
/* }}} */
|
||||
/* {{{ CICP support */
|
||||
|
||||
GdkColorState *
|
||||
gdk_color_state_new_from_cicp_data (int color_primaries,
|
||||
int transfer_characteristics,
|
||||
int matrix_coefficients,
|
||||
gboolean full_range)
|
||||
{
|
||||
/* FIXME We don't support these */
|
||||
if (!full_range || matrix_coefficients != 0)
|
||||
return NULL;
|
||||
|
||||
/* Look for cases we can handle */
|
||||
if (color_primaries == 0 && transfer_characteristics == 13)
|
||||
return gdk_color_state_get_srgb ();
|
||||
else if (color_primaries == 0 && transfer_characteristics == 8)
|
||||
return gdk_color_state_get_srgb_linear ();
|
||||
else if (color_primaries == 9 && transfer_characteristics == 16)
|
||||
return gdk_color_state_get_rec2100_pq ();
|
||||
else if (color_primaries == 9 && transfer_characteristics == 8)
|
||||
return gdk_color_state_get_rec2100_linear ();
|
||||
else if (color_primaries == 12 && transfer_characteristics == 13)
|
||||
return gdk_color_state_get_display_p3 ();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Private API */
|
||||
|
||||
static GdkColorStateClass *
|
||||
get_class (GdkColorState *self)
|
||||
{
|
||||
if (GDK_IS_NAMED_COLOR_STATE (self))
|
||||
return &NAMED_COLOR_STATE_CLASS;
|
||||
|
||||
return self->klass;
|
||||
}
|
||||
|
||||
GdkMemoryDepth
|
||||
gdk_color_state_get_min_depth (GdkColorState *self)
|
||||
{
|
||||
return (GdkMemoryDepth) get_class (self)->get_min_depth (self);
|
||||
}
|
||||
|
||||
const char *
|
||||
gdk_color_state_get_name (GdkColorState *self)
|
||||
{
|
||||
return get_class (self)->get_name (self);
|
||||
}
|
||||
|
||||
int
|
||||
gdk_color_state_get_hue_coord (GdkColorState *self)
|
||||
{
|
||||
return get_class (self)->get_hue_coord (self);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Conversion */
|
||||
|
||||
#define two_step(name, func1, func2) \
|
||||
static void \
|
||||
name (float r, float g, float b, \
|
||||
float *x, float *y, float *z) \
|
||||
{ \
|
||||
func1 (r, g, b, x, y, z); \
|
||||
func2 (*x, *y, *z, x, y, z); \
|
||||
}
|
||||
|
||||
/* A full complement of xyz <> anything step functions */
|
||||
two_step (srgb_to_xyz, gtk_rgb_to_linear_srgb, gtk_linear_srgb_to_xyz)
|
||||
two_step (xyz_to_srgb, gtk_xyz_to_linear_srgb, gtk_linear_srgb_to_rgb)
|
||||
two_step (hsl_to_xyz, gtk_hsl_to_rgb, srgb_to_xyz)
|
||||
two_step (xyz_to_hsl, xyz_to_srgb, gtk_rgb_to_hsl)
|
||||
two_step (hwb_to_xyz, gtk_hwb_to_rgb, srgb_to_xyz)
|
||||
two_step (xyz_to_hwb, xyz_to_srgb, gtk_rgb_to_hwb)
|
||||
two_step (oklab_to_xyz, gtk_oklab_to_linear_srgb, gtk_linear_srgb_to_xyz)
|
||||
two_step (xyz_to_oklab, gtk_xyz_to_linear_srgb, gtk_linear_srgb_to_oklab)
|
||||
two_step (oklch_to_xyz, gtk_oklch_to_oklab, oklab_to_xyz)
|
||||
two_step (xyz_to_oklch, xyz_to_oklab, gtk_oklab_to_oklch)
|
||||
two_step (p3_to_xyz, gtk_p3_to_rgb, srgb_to_xyz)
|
||||
two_step (xyz_to_p3, xyz_to_srgb, gtk_rgb_to_p3)
|
||||
two_step (rec2100_linear_to_xyz, gtk_rec2100_linear_to_rec2020_linear, gtk_rec2020_linear_to_xyz)
|
||||
two_step (xyz_to_rec2100_linear, gtk_xyz_to_rec2020_linear, gtk_rec2020_linear_to_rec2100_linear)
|
||||
two_step (rec2100_pq_to_xyz, gtk_rec2100_pq_to_rec2100_linear, rec2100_linear_to_xyz)
|
||||
two_step (xyz_to_rec2100_pq, xyz_to_rec2100_linear, gtk_rec2100_linear_to_rec2100_pq)
|
||||
|
||||
|
||||
static struct {
|
||||
GdkColorStateId n1;
|
||||
GdkColorStateId n2;
|
||||
StepFunc func;
|
||||
} functions[] = {
|
||||
{ GDK_COLOR_STATE_ID_SRGB, GDK_COLOR_STATE_ID_SRGB_LINEAR, gtk_rgb_to_linear_srgb },
|
||||
{ GDK_COLOR_STATE_ID_SRGB, GDK_COLOR_STATE_ID_HSL, gtk_rgb_to_hsl },
|
||||
{ GDK_COLOR_STATE_ID_SRGB, GDK_COLOR_STATE_ID_HWB, gtk_rgb_to_hwb },
|
||||
{ GDK_COLOR_STATE_ID_SRGB, GDK_COLOR_STATE_ID_OKLAB, gtk_rgb_to_oklab },
|
||||
{ GDK_COLOR_STATE_ID_SRGB, GDK_COLOR_STATE_ID_DISPLAY_P3, gtk_rgb_to_p3 },
|
||||
{ GDK_COLOR_STATE_ID_SRGB, GDK_COLOR_STATE_ID_XYZ, srgb_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_SRGB_LINEAR, GDK_COLOR_STATE_ID_SRGB, gtk_linear_srgb_to_rgb },
|
||||
{ GDK_COLOR_STATE_ID_SRGB_LINEAR, GDK_COLOR_STATE_ID_OKLAB, gtk_linear_srgb_to_oklab },
|
||||
{ GDK_COLOR_STATE_ID_SRGB_LINEAR, GDK_COLOR_STATE_ID_XYZ, gtk_linear_srgb_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_HSL, GDK_COLOR_STATE_ID_SRGB, gtk_hsl_to_rgb },
|
||||
{ GDK_COLOR_STATE_ID_HSL, GDK_COLOR_STATE_ID_XYZ, hsl_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_HWB, GDK_COLOR_STATE_ID_SRGB, gtk_hwb_to_rgb },
|
||||
{ GDK_COLOR_STATE_ID_HWB, GDK_COLOR_STATE_ID_XYZ, hwb_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_OKLAB, GDK_COLOR_STATE_ID_SRGB, gtk_oklab_to_rgb },
|
||||
{ GDK_COLOR_STATE_ID_OKLAB, GDK_COLOR_STATE_ID_SRGB_LINEAR, gtk_oklab_to_linear_srgb },
|
||||
{ GDK_COLOR_STATE_ID_OKLAB, GDK_COLOR_STATE_ID_OKLCH, gtk_oklab_to_oklch },
|
||||
{ GDK_COLOR_STATE_ID_OKLAB, GDK_COLOR_STATE_ID_XYZ, oklab_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_OKLCH, GDK_COLOR_STATE_ID_OKLAB, gtk_oklch_to_oklab },
|
||||
{ GDK_COLOR_STATE_ID_OKLCH, GDK_COLOR_STATE_ID_XYZ, oklch_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_DISPLAY_P3, GDK_COLOR_STATE_ID_SRGB, gtk_p3_to_rgb },
|
||||
{ GDK_COLOR_STATE_ID_DISPLAY_P3, GDK_COLOR_STATE_ID_XYZ, p3_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_SRGB, xyz_to_srgb },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_SRGB_LINEAR, gtk_xyz_to_linear_srgb },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_HSL, xyz_to_hsl },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_HWB, xyz_to_hwb },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_OKLAB, xyz_to_oklab },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_OKLCH, xyz_to_oklch },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_DISPLAY_P3, xyz_to_p3 },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_REC2020, gtk_xyz_to_rec2020 },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_REC2100_PQ, xyz_to_rec2100_pq },
|
||||
{ GDK_COLOR_STATE_ID_XYZ, GDK_COLOR_STATE_ID_REC2100_LINEAR, xyz_to_rec2100_linear },
|
||||
{ GDK_COLOR_STATE_ID_REC2020, GDK_COLOR_STATE_ID_XYZ, gtk_rec2020_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_REC2100_PQ, GDK_COLOR_STATE_ID_XYZ, rec2100_pq_to_xyz },
|
||||
{ GDK_COLOR_STATE_ID_REC2100_PQ, GDK_COLOR_STATE_ID_REC2100_LINEAR, gtk_rec2100_pq_to_rec2100_linear },
|
||||
{ GDK_COLOR_STATE_ID_REC2100_LINEAR, GDK_COLOR_STATE_ID_REC2100_PQ, gtk_rec2100_linear_to_rec2100_pq },
|
||||
{ GDK_COLOR_STATE_ID_REC2100_LINEAR, GDK_COLOR_STATE_ID_XYZ, rec2100_linear_to_xyz },
|
||||
};
|
||||
|
||||
static StepFunc
|
||||
find_function (GdkColorStateId n1, GdkColorStateId n2)
|
||||
{
|
||||
for (int k = 0; k < G_N_ELEMENTS (functions); k++)
|
||||
{
|
||||
if (functions[k].n1 == n1 && functions[k].n2 == n2)
|
||||
return functions[k].func;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_color_state_transform_init (GdkColorStateTransform *tf,
|
||||
GdkColorState *from,
|
||||
GdkColorState *to,
|
||||
gboolean copy_alpha)
|
||||
{
|
||||
memset (tf, 0, sizeof (GdkColorStateTransform));
|
||||
|
||||
if (GDK_IS_NAMED_COLOR_STATE (from) &&
|
||||
GDK_IS_NAMED_COLOR_STATE (to))
|
||||
{
|
||||
tf->step1 = find_function (GDK_NAMED_COLOR_STATE_ID (from),
|
||||
GDK_NAMED_COLOR_STATE_ID (to));
|
||||
if (tf->step1 == NULL && from != to)
|
||||
{
|
||||
tf->step1 = find_function (GDK_NAMED_COLOR_STATE_ID (from),
|
||||
GDK_COLOR_STATE_ID_XYZ);
|
||||
tf->step2 = find_function (GDK_COLOR_STATE_ID_XYZ,
|
||||
GDK_NAMED_COLOR_STATE_ID (to));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cmsHPROFILE profile1, profile2;
|
||||
|
||||
if (GDK_IS_LCMS_COLOR_STATE (from))
|
||||
profile1 = gdk_lcms_color_state_get_lcms_profile (from);
|
||||
else
|
||||
profile1 = NULL;
|
||||
|
||||
if (GDK_IS_LCMS_COLOR_STATE (to))
|
||||
profile2 = gdk_lcms_color_state_get_lcms_profile (to);
|
||||
else
|
||||
profile2 = NULL;
|
||||
|
||||
if (profile1 && profile2)
|
||||
{
|
||||
tf->transform = cmsCreateTransform (profile1,
|
||||
TYPE_RGBA_FLT,
|
||||
profile2,
|
||||
TYPE_RGBA_FLT,
|
||||
INTENT_PERCEPTUAL,
|
||||
copy_alpha ? cmsFLAGS_COPY_ALPHA : 0);
|
||||
}
|
||||
else if (GDK_IS_NAMED_COLOR_STATE (from) && profile2)
|
||||
{
|
||||
tf->step1 = find_function (GDK_NAMED_COLOR_STATE_ID (from),
|
||||
GDK_COLOR_STATE_ID_XYZ);
|
||||
|
||||
profile1 = cmsCreateXYZProfile ();
|
||||
tf->transform = cmsCreateTransform (profile1,
|
||||
TYPE_RGBA_FLT,
|
||||
profile2,
|
||||
TYPE_RGBA_FLT,
|
||||
INTENT_PERCEPTUAL,
|
||||
copy_alpha ? cmsFLAGS_COPY_ALPHA : 0);
|
||||
|
||||
tf->cms_first = FALSE;
|
||||
}
|
||||
else if (profile1 && GDK_IS_NAMED_COLOR_STATE (to))
|
||||
{
|
||||
profile2 = cmsCreateXYZProfile ();
|
||||
tf->transform = cmsCreateTransform (profile1,
|
||||
TYPE_RGBA_FLT,
|
||||
profile2,
|
||||
TYPE_RGBA_FLT,
|
||||
INTENT_PERCEPTUAL,
|
||||
copy_alpha ? cmsFLAGS_COPY_ALPHA : 0);
|
||||
|
||||
tf->step1 = find_function (GDK_COLOR_STATE_ID_XYZ,
|
||||
GDK_NAMED_COLOR_STATE_ID (to));
|
||||
|
||||
tf->cms_first = TRUE;
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
g_clear_pointer (&profile1, cmsCloseProfile);
|
||||
g_clear_pointer (&profile2, cmsCloseProfile);
|
||||
}
|
||||
|
||||
tf->copy_alpha = copy_alpha;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_color_state_transform_finish (GdkColorStateTransform *tf)
|
||||
{
|
||||
if (tf->transform)
|
||||
cmsDeleteTransform (tf->transform);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_color_state_transform (GdkColorStateTransform *tf,
|
||||
const float *src,
|
||||
float *dst,
|
||||
int width)
|
||||
{
|
||||
if (tf->copy_alpha)
|
||||
memcpy (dst, src, sizeof (float) * 4 * width);
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < width * 4; i += 4)
|
||||
{
|
||||
dst[i] = src[i];
|
||||
dst[i + 1] = src[i + 1];
|
||||
dst[i + 2] = src[i + 2];
|
||||
}
|
||||
}
|
||||
|
||||
if (tf->cms_first && tf->transform)
|
||||
cmsDoTransform (tf->transform, dst, dst, width);
|
||||
|
||||
if (tf->step1 && tf->step2)
|
||||
{
|
||||
for (int i = 0; i < width * 4; i += 4)
|
||||
{
|
||||
tf->step1 (dst[i], dst[i+1], dst[i+2], &dst[i], &dst[i+1], &dst[i+2]);
|
||||
tf->step2 (dst[i], dst[i+1], dst[i+2], &dst[i], &dst[i+1], &dst[i+2]);
|
||||
}
|
||||
}
|
||||
else if (tf->step1)
|
||||
{
|
||||
for (int i = 0; i < width * 4; i += 4)
|
||||
tf->step1 (dst[i], dst[i+1], dst[i+2], &dst[i], &dst[i+1], &dst[i+2]);
|
||||
}
|
||||
|
||||
if (!tf->cms_first && tf->transform)
|
||||
cmsDoTransform (tf->transform, dst, dst, width);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
|
||||
/* vim:set foldmethod=marker expandtab: */
|
104
gdk/gdkcolorstate.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/* gdkcolorstate.h
|
||||
*
|
||||
* Copyright 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_COLOR_STATE (gdk_color_state_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GType gdk_color_state_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_ref (GdkColorState *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_color_state_unref (GdkColorState *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_srgb (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_srgb_linear (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_hsl (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_hwb (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_oklab (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_oklch (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_display_p3 (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_xyz (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_rec2020 (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_rec2100_pq (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_get_rec2100_linear (void);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_state_is_linear (GdkColorState *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_new_from_icc_profile (GBytes *icc_profile,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_color_state_new_from_cicp_data (int color_primaries,
|
||||
int transfer_characteristics,
|
||||
int matrix_coefficients,
|
||||
gboolean full_range);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GBytes * gdk_color_state_save_to_icc_profile (GdkColorState *self,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
gboolean gdk_color_state_save_to_cicp_data (GdkColorState *self,
|
||||
int *color_primaries,
|
||||
int *transfer_characteristic,
|
||||
int *matrix_coefficients,
|
||||
gboolean *full_range,
|
||||
GError **error);
|
||||
|
||||
#include "gdkcolorstateimpl.h"
|
||||
|
||||
G_END_DECLS
|
204
gdk/gdkcolorstateimpl.h
Normal file
@@ -0,0 +1,204 @@
|
||||
/* gdkcolorstateimpl.h
|
||||
*
|
||||
* Copyright 2024 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
typedef enum
|
||||
{
|
||||
GDK_COLOR_STATE_ID_SRGB = 1,
|
||||
GDK_COLOR_STATE_ID_SRGB_LINEAR = 3,
|
||||
GDK_COLOR_STATE_ID_HSL = 5,
|
||||
GDK_COLOR_STATE_ID_HWB = 7,
|
||||
GDK_COLOR_STATE_ID_OKLAB = 9,
|
||||
GDK_COLOR_STATE_ID_OKLCH = 11,
|
||||
GDK_COLOR_STATE_ID_DISPLAY_P3 = 13,
|
||||
GDK_COLOR_STATE_ID_XYZ = 15,
|
||||
GDK_COLOR_STATE_ID_REC2020 = 17,
|
||||
GDK_COLOR_STATE_ID_REC2100_PQ = 19,
|
||||
GDK_COLOR_STATE_ID_REC2100_LINEAR = 21,
|
||||
} GdkColorStateId;
|
||||
|
||||
enum
|
||||
{
|
||||
GDK_TYPE_NAMED_COLOR_STATE,
|
||||
GDK_TYPE_LCMS_COLOR_STATE,
|
||||
};
|
||||
|
||||
typedef struct _GdkColorStateClass GdkColorStateClass;
|
||||
|
||||
struct _GdkColorState
|
||||
{
|
||||
GdkColorStateClass *klass;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
struct _GdkColorStateClass
|
||||
{
|
||||
int type;
|
||||
|
||||
void (* free) (GdkColorState *self);
|
||||
gboolean (* equal) (GdkColorState *self,
|
||||
GdkColorState *other);
|
||||
gboolean (* is_linear) (GdkColorState *self);
|
||||
GBytes * (* save_to_icc_profile) (GdkColorState *self,
|
||||
GError **error);
|
||||
gboolean (* save_to_cicp_data) (GdkColorState *self,
|
||||
int *color_primaries,
|
||||
int *transfer_characteristics,
|
||||
int *matrix_coefficients,
|
||||
gboolean *full_range,
|
||||
GError **error);
|
||||
const char * (* get_name) (GdkColorState *self);
|
||||
guint (* get_min_depth) (GdkColorState *self);
|
||||
int (* get_hue_coord) (GdkColorState *self);
|
||||
};
|
||||
|
||||
#define GDK_NAMED_COLOR_STATE_ID(c) ((GdkColorStateId) (GPOINTER_TO_INT (c)))
|
||||
#define GDK_IS_NAMED_COLOR_STATE(c) ((GPOINTER_TO_INT(c)) & 1)
|
||||
#define GDK_IS_LCMS_COLOR_STATE(c) ((c)->klass->type == GDK_TYPE_LCMS_COLOR_STATE)
|
||||
|
||||
#define gdk_color_state_ref(self) _gdk_color_state_ref (self)
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_ref (GdkColorState *self)
|
||||
{
|
||||
if (GDK_IS_NAMED_COLOR_STATE (self))
|
||||
return self;
|
||||
|
||||
self->ref_count++;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
#define gdk_color_state_unref(self) _gdk_color_state_unref (self)
|
||||
static inline void
|
||||
_gdk_color_state_unref (GdkColorState *self)
|
||||
{
|
||||
if (GDK_IS_NAMED_COLOR_STATE (self))
|
||||
return;
|
||||
|
||||
self->ref_count--;
|
||||
|
||||
if (self->ref_count == 0)
|
||||
self->klass->free (self);
|
||||
}
|
||||
|
||||
#define GDK_COLOR_STATE_SRGB ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_SRGB))
|
||||
#define GDK_COLOR_STATE_SRGB_LINEAR ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_SRGB_LINEAR))
|
||||
#define GDK_COLOR_STATE_HSL ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_HSL))
|
||||
#define GDK_COLOR_STATE_HWB ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_HWB))
|
||||
#define GDK_COLOR_STATE_OKLAB ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_OKLAB))
|
||||
#define GDK_COLOR_STATE_OKLCH ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_OKLCH))
|
||||
#define GDK_COLOR_STATE_DISPLAY_P3 ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_DISPLAY_P3))
|
||||
#define GDK_COLOR_STATE_XYZ ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_XYZ))
|
||||
#define GDK_COLOR_STATE_REC2020 ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_REC2020))
|
||||
#define GDK_COLOR_STATE_REC2100_PQ ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_REC2100_PQ))
|
||||
#define GDK_COLOR_STATE_REC2100_LINEAR ((GdkColorState *) GINT_TO_POINTER (GDK_COLOR_STATE_ID_REC2100_LINEAR))
|
||||
|
||||
#define gdk_color_state_get_srgb() _gdk_color_state_get_srgb ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_srgb (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_SRGB;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_srgb_linear() _gdk_color_state_get_srgb_linear ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_srgb_linear (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_SRGB_LINEAR;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_hsl() _gdk_color_state_get_hsl ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_hsl (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_HSL;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_hwb() _gdk_color_state_get_hwb ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_hwb (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_HWB;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_oklab() _gdk_color_state_get_oklab ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_oklab (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_OKLAB;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_oklch() _gdk_color_state_get_oklch ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_oklch (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_OKLCH;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_display_p3() _gdk_color_state_get_display_p3 ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_display_p3 (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_DISPLAY_P3;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_xyz() _gdk_color_state_get_xyz ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_xyz (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_XYZ;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_rec2020() _gdk_color_state_get_rec2020 ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_rec2020 (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_REC2020;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_rec2100_pq() _gdk_color_state_get_rec2100_pq ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_rec2100_pq (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_REC2100_PQ;
|
||||
}
|
||||
|
||||
#define gdk_color_state_get_rec2100_linear() _gdk_color_state_get_rec2100_linear ()
|
||||
static inline GdkColorState *
|
||||
_gdk_color_state_get_rec2100_linear (void)
|
||||
{
|
||||
return GDK_COLOR_STATE_REC2100_LINEAR;
|
||||
}
|
||||
|
||||
#define gdk_color_state_equal(a,b) _gdk_color_state_equal ((a), (b))
|
||||
static inline gboolean
|
||||
_gdk_color_state_equal (GdkColorState *self,
|
||||
GdkColorState *other)
|
||||
{
|
||||
if (self == other)
|
||||
return TRUE;
|
||||
|
||||
if (GDK_IS_NAMED_COLOR_STATE (self) || GDK_IS_NAMED_COLOR_STATE (other))
|
||||
return FALSE;
|
||||
|
||||
if (self->klass != other->klass)
|
||||
return FALSE;
|
||||
|
||||
return self->klass->equal (self, other);
|
||||
}
|
39
gdk/gdkcolorstateprivate.h
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include <lcms2.h>
|
||||
|
||||
const char * gdk_color_state_get_name (GdkColorState *color_state);
|
||||
GdkMemoryDepth gdk_color_state_get_min_depth (GdkColorState *color_state);
|
||||
int gdk_color_state_get_hue_coord (GdkColorState *color_state);
|
||||
|
||||
typedef void (* StepFunc) (float s0, float s1, float s2,
|
||||
float *d0, float *d1, float *d2);
|
||||
|
||||
typedef struct _GdkColorStateTransform GdkColorStateTransform;
|
||||
|
||||
struct _GdkColorStateTransform
|
||||
{
|
||||
gpointer transform;
|
||||
StepFunc step1;
|
||||
StepFunc step2;
|
||||
gboolean cms_first;
|
||||
gboolean copy_alpha;
|
||||
};
|
||||
|
||||
void gdk_color_state_transform_init (GdkColorStateTransform *tf,
|
||||
GdkColorState *from,
|
||||
GdkColorState *to,
|
||||
gboolean copy_alpha);
|
||||
|
||||
void gdk_color_state_transform_finish (GdkColorStateTransform *tf);
|
||||
|
||||
void gdk_color_state_transform (GdkColorStateTransform *tf,
|
||||
const float *src,
|
||||
float *dst,
|
||||
int width);
|
||||
|
||||
GdkColorState *gdk_color_state_new_from_lcms_profile (cmsHPROFILE profile);
|
||||
|
||||
const char *gdk_color_state_get_name_from_id (GdkColorStateId id);
|
@@ -40,6 +40,7 @@ typedef enum {
|
||||
GDK_DEBUG_OFFLOAD = 1 << 12,
|
||||
|
||||
/* flags below are influencing behavior */
|
||||
GDK_DEBUG_SRGB = 1 << 13,
|
||||
GDK_DEBUG_PORTALS = 1 << 14,
|
||||
GDK_DEBUG_NO_PORTALS = 1 << 15,
|
||||
GDK_DEBUG_GL_DISABLE = 1 << 16,
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "gdkdmabuffourccprivate.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
|
||||
#ifdef HAVE_DMABUF
|
||||
#include <sys/mman.h>
|
||||
@@ -2062,12 +2063,15 @@ out:
|
||||
void
|
||||
gdk_dmabuf_download_mmap (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryFormat src_format = gdk_texture_get_format (texture);
|
||||
GdkColorState *src_color_state = gdk_texture_get_color_state (texture);
|
||||
|
||||
if (format == src_format)
|
||||
if (format == src_format &&
|
||||
gdk_color_state_equal (color_state, src_color_state))
|
||||
gdk_dmabuf_do_download_mmap (texture, data, stride);
|
||||
else
|
||||
{
|
||||
@@ -2083,8 +2087,10 @@ gdk_dmabuf_download_mmap (GdkTexture *texture,
|
||||
|
||||
gdk_dmabuf_do_download_mmap (texture, src_data, src_stride);
|
||||
|
||||
gdk_memory_convert (data, stride, format,
|
||||
src_data, src_stride, src_format,
|
||||
gdk_memory_convert (data, stride,
|
||||
format, color_state,
|
||||
src_data, src_stride,
|
||||
src_format, src_color_state,
|
||||
width, height);
|
||||
|
||||
g_free (src_data);
|
||||
|
@@ -35,6 +35,7 @@ void
|
||||
gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
|
||||
GdkDmabufTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -43,6 +44,6 @@ gdk_dmabuf_downloader_download (GdkDmabufDownloader *self,
|
||||
g_return_if_fail (GDK_IS_DMABUF_DOWNLOADER (self));
|
||||
|
||||
iface = GDK_DMABUF_DOWNLOADER_GET_IFACE (self);
|
||||
iface->download (self, texture, format, data, stride);
|
||||
iface->download (self, texture, format, color_state, data, stride);
|
||||
}
|
||||
|
||||
|
@@ -20,6 +20,7 @@ struct _GdkDmabufDownloaderInterface
|
||||
void (* download) (GdkDmabufDownloader *downloader,
|
||||
GdkDmabufTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
};
|
||||
@@ -31,6 +32,7 @@ gboolean gdk_dmabuf_downloader_supports (GdkDmabufDownlo
|
||||
void gdk_dmabuf_downloader_download (GdkDmabufDownloader *downloader,
|
||||
GdkDmabufTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
|
||||
|
@@ -27,6 +27,7 @@ struct _GdkDmabuf
|
||||
GdkDmabufFormats * gdk_dmabuf_get_mmap_formats (void) G_GNUC_CONST;
|
||||
void gdk_dmabuf_download_mmap (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
|
||||
|
@@ -96,6 +96,7 @@ struct _Download
|
||||
{
|
||||
GdkDmabufTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
volatile int spinlock;
|
||||
@@ -109,6 +110,7 @@ gdk_dmabuf_texture_invoke_callback (gpointer data)
|
||||
gdk_dmabuf_downloader_download (download->texture->downloader,
|
||||
download->texture,
|
||||
download->format,
|
||||
download->color_state,
|
||||
download->data,
|
||||
download->stride);
|
||||
|
||||
@@ -120,16 +122,17 @@ gdk_dmabuf_texture_invoke_callback (gpointer data)
|
||||
static void
|
||||
gdk_dmabuf_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GdkDmabufTexture *self = GDK_DMABUF_TEXTURE (texture);
|
||||
Download download = { self, format, data, stride, 0 };
|
||||
Download download = { self, format, color_state, data, stride, 0 };
|
||||
|
||||
if (self->downloader == NULL)
|
||||
{
|
||||
#ifdef HAVE_DMABUF
|
||||
gdk_dmabuf_download_mmap (texture, format, data, stride);
|
||||
gdk_dmabuf_download_mmap (texture, format, color_state, data, stride);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
@@ -200,6 +203,7 @@ gdk_dmabuf_texture_new_from_builder (GdkDmabufTextureBuilder *builder,
|
||||
self = g_object_new (GDK_TYPE_DMABUF_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
"color-state", gdk_dmabuf_texture_builder_get_color_state (builder),
|
||||
NULL);
|
||||
|
||||
g_set_object (&self->display, display);
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "gdkdebugprivate.h"
|
||||
#include "gdkdisplay.h"
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkdmabuftexturebuilderprivate.h"
|
||||
|
||||
@@ -41,6 +42,8 @@ struct _GdkDmabufTextureBuilder
|
||||
|
||||
GdkDmabuf dmabuf;
|
||||
|
||||
GdkColorState *color_state;
|
||||
|
||||
GdkTexture *update_texture;
|
||||
cairo_region_t *update_region;
|
||||
};
|
||||
@@ -124,6 +127,7 @@ enum
|
||||
PROP_MODIFIER,
|
||||
PROP_PREMULTIPLIED,
|
||||
PROP_N_PLANES,
|
||||
PROP_COLOR_STATE,
|
||||
PROP_UPDATE_REGION,
|
||||
PROP_UPDATE_TEXTURE,
|
||||
|
||||
@@ -141,6 +145,7 @@ gdk_dmabuf_texture_builder_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&self->update_texture);
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_dmabuf_texture_builder_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -183,6 +188,10 @@ gdk_dmabuf_texture_builder_get_property (GObject *object,
|
||||
g_value_set_uint (value, self->dmabuf.n_planes);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_boxed (value, self->color_state);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
g_value_set_boxed (value, self->update_region);
|
||||
break;
|
||||
@@ -235,6 +244,10 @@ gdk_dmabuf_texture_builder_set_property (GObject *object,
|
||||
gdk_dmabuf_texture_builder_set_n_planes (self, g_value_get_uint (value));
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
gdk_dmabuf_texture_builder_set_color_state (self, g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
gdk_dmabuf_texture_builder_set_update_region (self, g_value_get_boxed (value));
|
||||
break;
|
||||
@@ -347,6 +360,18 @@ gdk_dmabuf_texture_builder_class_init (GdkDmabufTextureBuilderClass *klass)
|
||||
1, GDK_DMABUF_MAX_PLANES, 1,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:color-state: (attributes org.gtk.Property.get=gdk_dmabuf_texture_builder_get_color_state org.gtk.Property.set=gdk_dmabuf_texture_builder_set_color_state)
|
||||
*
|
||||
* The color state of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkDmabufTextureBuilder:update-region: (attributes org.gtk.Property.get=gdk_dmabuf_texture_builder_get_update_region org.gtk.Property.set=gdk_dmabuf_texture_builder_set_update_region)
|
||||
*
|
||||
@@ -383,6 +408,8 @@ gdk_dmabuf_texture_builder_init (GdkDmabufTextureBuilder *self)
|
||||
|
||||
for (int i = 0; i < GDK_DMABUF_MAX_PLANES; i++)
|
||||
self->dmabuf.planes[i].fd = -1;
|
||||
|
||||
self->color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -843,6 +870,48 @@ gdk_dmabuf_texture_builder_set_offset (GdkDmabufTextureBuilder *self,
|
||||
self->dmabuf.planes[plane].offset = offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_color_state: (attributes org.gtk.Method.get_property=color-state)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
*
|
||||
* Gets the color state previously set via gdk_dmabuf_texture_builder_set_color_state().
|
||||
*
|
||||
* Returns: the color state
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_dmabuf_texture_builder_get_color_state (GdkDmabufTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_set_color_state: (attributes org.gtk.Method.set_property=color-state)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
* @color_state: a `GdkColorState`
|
||||
*
|
||||
* Sets the color state for the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_dmabuf_texture_builder_set_color_state (GdkDmabufTextureBuilder *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_DMABUF_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (color_state != NULL);
|
||||
|
||||
if (self->color_state != color_state)
|
||||
{
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_STATE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_dmabuf_texture_builder_get_update_texture: (attributes org.gtk.Method.get_property=update-texture)
|
||||
* @self: a `GdkDmabufTextureBuilder`
|
||||
|
@@ -100,6 +100,12 @@ void gdk_dmabuf_texture_builder_set_offset (GdkDmabufT
|
||||
unsigned int plane,
|
||||
unsigned int offset);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_dmabuf_texture_builder_get_color_state (GdkDmabufTextureBuilder *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_dmabuf_texture_builder_set_color_state (GdkDmabufTextureBuilder *self,
|
||||
GdkColorState *color_state);
|
||||
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
GdkTexture * gdk_dmabuf_texture_builder_get_update_texture (GdkDmabufTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_14
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "gdkglcontextprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
@@ -136,6 +137,7 @@ typedef struct _Download Download;
|
||||
struct _Download
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
};
|
||||
@@ -185,13 +187,15 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
{
|
||||
GdkTexture *texture = GDK_TEXTURE (self);
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
gsize expected_stride;
|
||||
Download *download = download_;
|
||||
GLint gl_internal_format;
|
||||
GLenum gl_format, gl_type;
|
||||
GLint gl_swizzle[4];
|
||||
|
||||
format = gdk_texture_get_format (texture),
|
||||
format = gdk_texture_get_format (texture);
|
||||
color_state = gdk_texture_get_color_state (texture);
|
||||
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
|
||||
|
||||
if (!gdk_gl_context_get_use_es (context) &&
|
||||
@@ -225,9 +229,11 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
gdk_memory_convert (download->data,
|
||||
download->stride,
|
||||
download->format,
|
||||
download->color_state,
|
||||
pixels,
|
||||
stride,
|
||||
format,
|
||||
color_state,
|
||||
texture->width,
|
||||
texture->height);
|
||||
|
||||
@@ -377,9 +383,11 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
gdk_memory_convert (download->data,
|
||||
download->stride,
|
||||
download->format,
|
||||
download->color_state,
|
||||
pixels,
|
||||
stride,
|
||||
actual_format,
|
||||
color_state,
|
||||
texture->width,
|
||||
texture->height);
|
||||
|
||||
@@ -393,6 +401,7 @@ gdk_gl_texture_do_download (GdkGLTexture *self,
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -401,11 +410,12 @@ gdk_gl_texture_download (GdkTexture *texture,
|
||||
|
||||
if (self->saved)
|
||||
{
|
||||
gdk_texture_do_download (self->saved, format, data, stride);
|
||||
gdk_texture_do_download (self->saved, format, color_state, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
download.format = format;
|
||||
download.color_state = color_state;
|
||||
download.data = data;
|
||||
download.stride = stride;
|
||||
|
||||
@@ -471,8 +481,7 @@ gdk_gl_texture_release (GdkGLTexture *self)
|
||||
g_return_if_fail (self->saved == NULL);
|
||||
|
||||
texture = GDK_TEXTURE (self);
|
||||
self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture)));
|
||||
self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture));
|
||||
|
||||
drop_gl_resources (self);
|
||||
}
|
||||
@@ -488,6 +497,7 @@ gdk_gl_texture_new_from_builder (GdkGLTextureBuilder *builder,
|
||||
self = g_object_new (GDK_TYPE_GL_TEXTURE,
|
||||
"width", gdk_gl_texture_builder_get_width (builder),
|
||||
"height", gdk_gl_texture_builder_get_height (builder),
|
||||
"color-state", gdk_gl_texture_builder_get_color_state (builder),
|
||||
NULL);
|
||||
|
||||
self->context = g_object_ref (gdk_gl_texture_builder_get_context (builder));
|
||||
|
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "gdkenumtypes.h"
|
||||
#include "gdkglcontext.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include <cairo-gobject.h>
|
||||
@@ -38,6 +39,7 @@ struct _GdkGLTextureBuilder
|
||||
GdkMemoryFormat format;
|
||||
gboolean has_mipmap;
|
||||
gpointer sync;
|
||||
GdkColorState *color_state;
|
||||
|
||||
GdkTexture *update_texture;
|
||||
cairo_region_t *update_region;
|
||||
@@ -75,6 +77,7 @@ enum
|
||||
PROP_HEIGHT,
|
||||
PROP_ID,
|
||||
PROP_SYNC,
|
||||
PROP_COLOR_STATE,
|
||||
PROP_UPDATE_REGION,
|
||||
PROP_UPDATE_TEXTURE,
|
||||
PROP_WIDTH,
|
||||
@@ -95,6 +98,7 @@ gdk_gl_texture_builder_dispose (GObject *object)
|
||||
|
||||
g_clear_object (&self->update_texture);
|
||||
g_clear_pointer (&self->update_region, cairo_region_destroy);
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_gl_texture_builder_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -133,6 +137,10 @@ gdk_gl_texture_builder_get_property (GObject *object,
|
||||
g_value_set_pointer (value, self->sync);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_object (value, self->color_state);
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
g_value_set_boxed (value, self->update_region);
|
||||
break;
|
||||
@@ -185,6 +193,10 @@ gdk_gl_texture_builder_set_property (GObject *object,
|
||||
gdk_gl_texture_builder_set_sync (self, g_value_get_pointer (value));
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
gdk_gl_texture_builder_set_color_state (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_UPDATE_REGION:
|
||||
gdk_gl_texture_builder_set_update_region (self, g_value_get_boxed (value));
|
||||
break;
|
||||
@@ -286,6 +298,18 @@ gdk_gl_texture_builder_class_init (GdkGLTextureBuilderClass *klass)
|
||||
g_param_spec_pointer ("sync", NULL, NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkGLTextureBuilder:color-state: (attributes org.gtk.Property.get=gdk_gl_texture_builder_get_color_state org.gtk.Property.set=gdk_gl_texture_builder_set_color_state)
|
||||
*
|
||||
* The color state of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkGLTextureBuilder:update-region: (attributes org.gtk.Property.get=gdk_gl_texture_builder_get_update_region org.gtk.Property.set=gdk_gl_texture_builder_set_update_region)
|
||||
*
|
||||
@@ -329,6 +353,7 @@ static void
|
||||
gdk_gl_texture_builder_init (GdkGLTextureBuilder *self)
|
||||
{
|
||||
self->format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED;
|
||||
self->color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -616,6 +641,48 @@ gdk_gl_texture_builder_set_sync (GdkGLTextureBuilder *self,
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SYNC]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_texture_builder_get_color_state: (attributes org.gtk.Method.get_property=color-state)
|
||||
* @self: a `GdkGLTextureBuilder`
|
||||
*
|
||||
* Gets the color state previously set via gdk_gl_texture_builder_set_color_state().
|
||||
*
|
||||
* Returns: the color state
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_gl_texture_builder_get_color_state (GdkGLTextureBuilder *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self), NULL);
|
||||
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_texture_builder_set_color_state: (attributes org.gtk.Method.set_property=color-state)
|
||||
* @self: a `GdkGLTextureBuilder`
|
||||
* @color_state: a `GdkColorState`
|
||||
*
|
||||
* Sets the color state for the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_gl_texture_builder_set_color_state (GdkGLTextureBuilder *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_GL_TEXTURE_BUILDER (self));
|
||||
g_return_if_fail (color_state != NULL);
|
||||
|
||||
if (self->color_state != color_state)
|
||||
{
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_STATE]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_gl_texture_builder_get_format: (attributes org.gtk.Method.get_property=format)
|
||||
* @self: a `GdkGLTextureBuilder`
|
||||
|
@@ -76,6 +76,12 @@ GDK_AVAILABLE_IN_4_12
|
||||
void gdk_gl_texture_builder_set_sync (GdkGLTextureBuilder *self,
|
||||
gpointer sync);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_gl_texture_builder_get_color_state (GdkGLTextureBuilder *self);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_gl_texture_builder_set_color_state (GdkGLTextureBuilder *self,
|
||||
GdkColorState *color_state);
|
||||
|
||||
GDK_AVAILABLE_IN_4_12
|
||||
GdkTexture * gdk_gl_texture_builder_get_update_texture (GdkGLTextureBuilder *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_12
|
||||
|
@@ -23,8 +23,9 @@
|
||||
|
||||
#include "gdkdmabuffourccprivate.h"
|
||||
#include "gdkglcontextprivate.h"
|
||||
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gsk/gl/fp16private.h"
|
||||
#include "gtk/gtkcolorutilsprivate.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
|
||||
@@ -327,6 +328,7 @@ ADD_ALPHA_FUNC(r8g8b8_to_a8b8g8r8, 0, 1, 2, 3, 2, 1, 0)
|
||||
|
||||
struct _GdkMemoryFormatDescription
|
||||
{
|
||||
const char *name;
|
||||
GdkMemoryAlpha alpha;
|
||||
GdkMemoryFormat premultiplied;
|
||||
GdkMemoryFormat straight;
|
||||
@@ -366,6 +368,7 @@ struct _GdkMemoryFormatDescription
|
||||
|
||||
static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
[GDK_MEMORY_B8G8R8A8_PREMULTIPLIED] = {
|
||||
.name = "*BGRA8",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_B8G8R8A8,
|
||||
@@ -394,6 +397,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = b8g8r8a8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8R8G8B8_PREMULTIPLIED] = {
|
||||
.name = "*ARGB8",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_A8R8G8B8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_A8R8G8B8,
|
||||
@@ -422,6 +426,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = a8r8g8b8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8A8_PREMULTIPLIED] = {
|
||||
.name = "*RGBA8",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R8G8B8A8,
|
||||
@@ -449,6 +454,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r8g8b8a8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8B8G8R8_PREMULTIPLIED] = {
|
||||
.name = "*ABGR8",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_A8B8G8R8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_A8B8G8R8,
|
||||
@@ -477,6 +483,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = a8b8g8r8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_B8G8R8A8] = {
|
||||
.name = "BGRA8",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_B8G8R8A8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_B8G8R8A8,
|
||||
@@ -505,6 +512,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = b8g8r8a8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8R8G8B8] = {
|
||||
.name = "ARGB8",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_A8R8G8B8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_A8R8G8B8,
|
||||
@@ -533,6 +541,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = a8r8g8b8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8A8] = {
|
||||
.name = "RGBA8",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R8G8B8A8,
|
||||
@@ -560,6 +569,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r8g8b8a8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8B8G8R8] = {
|
||||
.name = "ABGR8",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_A8B8G8R8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_A8B8G8R8,
|
||||
@@ -588,6 +598,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = a8b8g8r8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_B8G8R8X8] = {
|
||||
.name = "BGRX8",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_B8G8R8X8,
|
||||
.straight = GDK_MEMORY_B8G8R8X8,
|
||||
@@ -617,6 +628,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = b8g8r8x8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_X8R8G8B8] = {
|
||||
.name = "XRGB8",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_X8R8G8B8,
|
||||
.straight = GDK_MEMORY_X8R8G8B8,
|
||||
@@ -646,6 +658,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = x8r8g8b8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8X8] = {
|
||||
.name = "RGBX8",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_R8G8B8X8,
|
||||
.straight = GDK_MEMORY_R8G8B8X8,
|
||||
@@ -674,6 +687,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r8g8b8x8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_X8B8G8R8] = {
|
||||
.name = "XBGR8",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_X8B8G8R8,
|
||||
.straight = GDK_MEMORY_X8B8G8R8,
|
||||
@@ -703,6 +717,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = x8b8g8r8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R8G8B8] = {
|
||||
.name = "RGB8",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_R8G8B8,
|
||||
.straight = GDK_MEMORY_R8G8B8,
|
||||
@@ -731,6 +746,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r8g8b8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_B8G8R8] = {
|
||||
.name = "BGR8",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_B8G8R8,
|
||||
.straight = GDK_MEMORY_B8G8R8,
|
||||
@@ -760,6 +776,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = b8g8r8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16] = {
|
||||
.name = "RGB16",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_R16G16B16,
|
||||
.straight = GDK_MEMORY_R16G16B16,
|
||||
@@ -791,6 +808,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r16g16b16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16A16_PREMULTIPLIED] = {
|
||||
.name = "*RGBA16",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R16G16B16A16,
|
||||
@@ -821,6 +839,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r16g16b16a16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16A16] = {
|
||||
.name = "RGBA16",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_R16G16B16A16_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R16G16B16A16,
|
||||
@@ -851,6 +870,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r16g16b16a16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16_FLOAT] = {
|
||||
.name = "RGBA16f",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_R16G16B16_FLOAT,
|
||||
.straight = GDK_MEMORY_R16G16B16_FLOAT,
|
||||
@@ -881,6 +901,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r16g16b16_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED] = {
|
||||
.name = "*RGBA16f",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R16G16B16A16_FLOAT,
|
||||
@@ -910,6 +931,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r16g16b16a16_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R16G16B16A16_FLOAT] = {
|
||||
.name = "RGBA16f",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_R16G16B16A16_FLOAT_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R16G16B16A16_FLOAT,
|
||||
@@ -939,6 +961,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r16g16b16a16_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R32G32B32_FLOAT] = {
|
||||
.name = "RGB32f",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_R32G32B32_FLOAT,
|
||||
.straight = GDK_MEMORY_R32G32B32_FLOAT,
|
||||
@@ -969,6 +992,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r32g32b32_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED] = {
|
||||
.name = "*RGBA32f",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R32G32B32A32_FLOAT,
|
||||
@@ -998,6 +1022,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r32g32b32a32_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_R32G32B32A32_FLOAT] = {
|
||||
.name = "RGBA32f",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_R32G32B32A32_FLOAT,
|
||||
@@ -1027,6 +1052,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = r32g32b32a32_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_G8A8_PREMULTIPLIED] = {
|
||||
.name = "*GA8",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_G8A8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_G8A8,
|
||||
@@ -1055,6 +1081,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = g8a8_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_G8A8] = {
|
||||
.name = "GA8",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_G8A8_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_G8A8,
|
||||
@@ -1083,6 +1110,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = g8a8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_G8] = {
|
||||
.name = "G8",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_G8,
|
||||
.straight = GDK_MEMORY_G8,
|
||||
@@ -1111,6 +1139,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = g8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_G16A16_PREMULTIPLIED] = {
|
||||
.name = "*GA16",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_G16A16_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_G16A16,
|
||||
@@ -1142,6 +1171,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = g16a16_premultiplied_from_float,
|
||||
},
|
||||
[GDK_MEMORY_G16A16] = {
|
||||
.name = "GA16",
|
||||
.alpha = GDK_MEMORY_ALPHA_STRAIGHT,
|
||||
.premultiplied = GDK_MEMORY_G16A16_PREMULTIPLIED,
|
||||
.straight = GDK_MEMORY_G16A16,
|
||||
@@ -1173,6 +1203,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = g16a16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_G16] = {
|
||||
.name = "G16",
|
||||
.alpha = GDK_MEMORY_ALPHA_OPAQUE,
|
||||
.premultiplied = GDK_MEMORY_G16,
|
||||
.straight = GDK_MEMORY_G16,
|
||||
@@ -1204,6 +1235,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = g16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A8] = {
|
||||
.name = "A8",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_A8,
|
||||
.straight = GDK_MEMORY_A8,
|
||||
@@ -1232,6 +1264,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = a8_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A16] = {
|
||||
.name = "A16",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_A16,
|
||||
.straight = GDK_MEMORY_A16,
|
||||
@@ -1263,6 +1296,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = a16_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A16_FLOAT] = {
|
||||
.name = "A16f",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_A16_FLOAT,
|
||||
.straight = GDK_MEMORY_A16_FLOAT,
|
||||
@@ -1293,6 +1327,7 @@ static const GdkMemoryFormatDescription memory_formats[] = {
|
||||
.from_float = a16_float_from_float,
|
||||
},
|
||||
[GDK_MEMORY_A32_FLOAT] = {
|
||||
.name = "A32f",
|
||||
.alpha = GDK_MEMORY_ALPHA_PREMULTIPLIED,
|
||||
.premultiplied = GDK_MEMORY_A32_FLOAT,
|
||||
.straight = GDK_MEMORY_A32_FLOAT,
|
||||
@@ -1661,6 +1696,12 @@ gdk_memory_format_get_dmabuf_fourcc (GdkMemoryFormat format)
|
||||
#endif
|
||||
}
|
||||
|
||||
const char *
|
||||
gdk_memory_format_get_name (GdkMemoryFormat format)
|
||||
{
|
||||
return memory_formats[format].name;
|
||||
}
|
||||
|
||||
static void
|
||||
premultiply (float *rgba,
|
||||
gsize n)
|
||||
@@ -1694,14 +1735,18 @@ void
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
GdkColorState *dest_color_state,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
GdkColorState *src_color_state,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format];
|
||||
const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
|
||||
GdkColorStateTransform transform;
|
||||
gboolean has_transform;
|
||||
float *tmp;
|
||||
gsize y;
|
||||
void (*func) (guchar *, const guchar *, gsize) = NULL;
|
||||
@@ -1709,7 +1754,8 @@ gdk_memory_convert (guchar *dest_data,
|
||||
g_assert (dest_format < GDK_MEMORY_N_FORMATS);
|
||||
g_assert (src_format < GDK_MEMORY_N_FORMATS);
|
||||
|
||||
if (src_format == dest_format)
|
||||
if (gdk_color_state_equal (src_color_state, dest_color_state) &&
|
||||
src_format == dest_format)
|
||||
{
|
||||
gsize bytes_per_row = src_desc->bytes_per_pixel * width;
|
||||
|
||||
@@ -1729,7 +1775,9 @@ gdk_memory_convert (guchar *dest_data,
|
||||
return;
|
||||
}
|
||||
|
||||
if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
|
||||
if (!gdk_color_state_equal (src_color_state, dest_color_state))
|
||||
func = NULL;
|
||||
else if (src_format == GDK_MEMORY_R8G8B8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
|
||||
func = r8g8b8a8_to_r8g8b8a8_premultiplied;
|
||||
else if (src_format == GDK_MEMORY_B8G8R8A8 && dest_format == GDK_MEMORY_R8G8B8A8_PREMULTIPLIED)
|
||||
func = r8g8b8a8_to_b8g8r8a8_premultiplied;
|
||||
@@ -1777,19 +1825,43 @@ gdk_memory_convert (guchar *dest_data,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!gdk_color_state_equal (src_color_state, dest_color_state))
|
||||
{
|
||||
gdk_color_state_transform_init (&transform, src_color_state, dest_color_state, TRUE);
|
||||
has_transform = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
has_transform = FALSE;
|
||||
}
|
||||
|
||||
tmp = g_new (float, width * 4);
|
||||
|
||||
for (y = 0; y < height; y++)
|
||||
{
|
||||
src_desc->to_float (tmp, src_data, width);
|
||||
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
unpremultiply (tmp, width);
|
||||
else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
premultiply (tmp, width);
|
||||
if (has_transform)
|
||||
{
|
||||
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED)
|
||||
unpremultiply (tmp, width);
|
||||
gdk_color_state_transform (&transform, tmp, tmp, width);
|
||||
if (dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
premultiply (tmp, width);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED && dest_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
unpremultiply (tmp, width);
|
||||
else if (src_desc->alpha == GDK_MEMORY_ALPHA_STRAIGHT && dest_desc->alpha != GDK_MEMORY_ALPHA_STRAIGHT)
|
||||
premultiply (tmp, width);
|
||||
}
|
||||
dest_desc->from_float (dest_data, tmp, width);
|
||||
src_data += src_stride;
|
||||
dest_data += dest_stride;
|
||||
}
|
||||
|
||||
if (has_transform)
|
||||
gdk_color_state_transform_finish (&transform);
|
||||
|
||||
g_free (tmp);
|
||||
}
|
||||
|
@@ -75,14 +75,16 @@ VkFormat gdk_memory_format_vk_rgba_format (GdkMemoryFormat
|
||||
VkComponentMapping *out_swizzle);
|
||||
#endif
|
||||
guint32 gdk_memory_format_get_dmabuf_fourcc (GdkMemoryFormat format);
|
||||
|
||||
const char * gdk_memory_format_get_name (GdkMemoryFormat format);
|
||||
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
GdkColorState *dest_color_state,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
GdkColorState *src_color_state,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
/**
|
||||
@@ -58,6 +59,7 @@ gdk_memory_texture_dispose (GObject *object)
|
||||
static void
|
||||
gdk_memory_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -65,9 +67,11 @@ gdk_memory_texture_download (GdkTexture *texture,
|
||||
|
||||
gdk_memory_convert (data, stride,
|
||||
format,
|
||||
color_state,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
texture->format,
|
||||
texture->color_state,
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
@@ -131,7 +135,7 @@ gdk_memory_sanitize (GBytes *bytes,
|
||||
* @bytes: the `GBytes` containing the pixel data
|
||||
* @stride: rowstride for the data
|
||||
*
|
||||
* Creates a new texture for a blob of image data.
|
||||
* Creates a new texture for a blob of sRGB image data.
|
||||
*
|
||||
* The `GBytes` must contain @stride × @height pixels
|
||||
* in the given format.
|
||||
@@ -144,11 +148,43 @@ gdk_memory_texture_new (int width,
|
||||
GdkMemoryFormat format,
|
||||
GBytes *bytes,
|
||||
gsize stride)
|
||||
{
|
||||
return gdk_memory_texture_new_with_color_state (width, height, format,
|
||||
gdk_color_state_get_srgb (),
|
||||
bytes, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_new_with_color_state:
|
||||
* @width: the width of the texture
|
||||
* @height: the height of the texture
|
||||
* @format: the format of the data
|
||||
* @color_state: a `GdkColorSpace`
|
||||
* @bytes: the `GBytes` containing the pixel data
|
||||
* @stride: rowstride for the data
|
||||
*
|
||||
* Creates a new texture for a blob of image data with a given color state.
|
||||
*
|
||||
* The `GBytes` must contain @stride x @height pixels
|
||||
* in the given format.
|
||||
*
|
||||
* Returns: A newly-created `GdkTexture`
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_memory_texture_new_with_color_state (int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
GBytes *bytes,
|
||||
gsize stride)
|
||||
{
|
||||
GdkMemoryTexture *self;
|
||||
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
g_return_val_if_fail (color_state != NULL, NULL);
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
/* needs to be this complex to support subtexture of the bottom right part */
|
||||
@@ -159,6 +195,7 @@ gdk_memory_texture_new (int width,
|
||||
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
"color-state", color_state,
|
||||
NULL);
|
||||
|
||||
GDK_TEXTURE (self)->format = format;
|
||||
@@ -191,19 +228,19 @@ gdk_memory_texture_new_subtexture (GdkMemoryTexture *source,
|
||||
size = source->stride * (height - 1) + width * bpp;
|
||||
bytes = g_bytes_new_from_bytes (source->bytes, offset, size);
|
||||
|
||||
result = gdk_memory_texture_new (width,
|
||||
height,
|
||||
texture->format,
|
||||
bytes,
|
||||
source->stride);
|
||||
result = gdk_memory_texture_new_with_color_state (width,
|
||||
height,
|
||||
texture->format,
|
||||
texture->color_state,
|
||||
bytes,
|
||||
source->stride);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
GdkMemoryTexture *
|
||||
gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
GdkMemoryFormat format)
|
||||
gdk_memory_texture_from_texture (GdkTexture *texture)
|
||||
{
|
||||
GdkTexture *result;
|
||||
GBytes *bytes;
|
||||
@@ -213,23 +250,19 @@ gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
if (GDK_IS_MEMORY_TEXTURE (texture))
|
||||
{
|
||||
GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (texture);
|
||||
return g_object_ref (GDK_MEMORY_TEXTURE (texture));
|
||||
|
||||
if (gdk_texture_get_format (texture) == format)
|
||||
return g_object_ref (memtex);
|
||||
}
|
||||
|
||||
stride = texture->width * gdk_memory_format_bytes_per_pixel (format);
|
||||
stride = texture->width * gdk_memory_format_bytes_per_pixel (texture->format);
|
||||
data = g_malloc_n (stride, texture->height);
|
||||
|
||||
gdk_texture_do_download (texture, format, data, stride);
|
||||
gdk_texture_do_download (texture, texture->format, texture->color_state, data, stride);
|
||||
bytes = g_bytes_new_take (data, stride * texture->height);
|
||||
result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
bytes,
|
||||
stride);
|
||||
result = gdk_memory_texture_new_with_color_state (texture->width,
|
||||
texture->height,
|
||||
texture->format,
|
||||
texture->color_state,
|
||||
bytes,
|
||||
stride);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return GDK_MEMORY_TEXTURE (result);
|
||||
|
@@ -68,6 +68,14 @@ GdkTexture * gdk_memory_texture_new (int
|
||||
GBytes *bytes,
|
||||
gsize stride);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkTexture * gdk_memory_texture_new_with_color_state (int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
GBytes *bytes,
|
||||
gsize stride);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@@ -28,8 +28,7 @@ G_BEGIN_DECLS
|
||||
#define GDK_MEMORY_GDK_PIXBUF_OPAQUE GDK_MEMORY_R8G8B8
|
||||
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
|
||||
|
||||
GdkMemoryTexture * gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
GdkMemoryFormat format);
|
||||
GdkMemoryTexture * gdk_memory_texture_from_texture (GdkTexture *texture);
|
||||
GdkTexture * gdk_memory_texture_new_subtexture (GdkMemoryTexture *texture,
|
||||
int x,
|
||||
int y,
|
||||
|
@@ -30,6 +30,8 @@
|
||||
#include "gdksurface.h"
|
||||
|
||||
#include "gdkprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkcairo.h"
|
||||
#include "gdkcontentprovider.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
@@ -44,6 +46,7 @@
|
||||
#include "gdktoplevelprivate.h"
|
||||
#include "gdkvulkancontext.h"
|
||||
#include "gdksubsurfaceprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
@@ -89,6 +92,7 @@ enum {
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_COLOR_STATE,
|
||||
PROP_CURSOR,
|
||||
PROP_DISPLAY,
|
||||
PROP_FRAME_CLOCK,
|
||||
@@ -484,6 +488,18 @@ gdk_surface_init (GdkSurface *surface)
|
||||
|
||||
surface->alpha = 255;
|
||||
|
||||
if (g_getenv ("GDK_DISPLAY_COLORSTATE"))
|
||||
{
|
||||
const char *env = g_getenv ("GDK_DISPLAY_COLORSTATE");
|
||||
if (strcmp (env, "srgb") == 0)
|
||||
surface->color_state = gdk_color_state_get_srgb ();
|
||||
else if (strcmp (env, "srgb-linear") == 0)
|
||||
surface->color_state = gdk_color_state_get_srgb_linear ();
|
||||
}
|
||||
|
||||
if (surface->color_state == NULL)
|
||||
surface->color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
surface->device_cursor = g_hash_table_new_full (NULL, NULL,
|
||||
NULL, g_object_unref);
|
||||
|
||||
@@ -528,6 +544,25 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
klass->get_scale = gdk_surface_real_get_scale;
|
||||
klass->create_subsurface = gdk_surface_real_create_subsurface;
|
||||
|
||||
/**
|
||||
* GdkSurface:color-state: (attributes org.gtk.Property.get=gdk_surface_get_color_state)
|
||||
*
|
||||
* The preferred color state for rendering to the surface
|
||||
*
|
||||
* This color state is negotiated between GTK and the compositor.
|
||||
*
|
||||
* The color state may change as the surface gets moved around - for example
|
||||
* to different monitors or when the compositor gets reconfigured. As long as
|
||||
* the surface isn't shown, the color space may not represent the actual color
|
||||
* state that is going to be used.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
|
||||
|
||||
/**
|
||||
* GdkSurface:cursor: (attributes org.gtk.Property.get=gdk_surface_get_cursor org.gtk.Property.set=gdk_surface_set_cursor)
|
||||
*
|
||||
@@ -786,6 +821,10 @@ gdk_surface_set_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLOR_STATE:
|
||||
gdk_surface_set_color_state (surface, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_CURSOR:
|
||||
gdk_surface_set_cursor (surface, g_value_get_object (value));
|
||||
break;
|
||||
@@ -819,6 +858,10 @@ gdk_surface_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_object (value, gdk_surface_get_color_state (surface));
|
||||
break;
|
||||
|
||||
case PROP_CURSOR:
|
||||
g_value_set_object (value, gdk_surface_get_cursor (surface));
|
||||
break;
|
||||
@@ -2330,6 +2373,7 @@ gdk_surface_create_similar_surface (GdkSurface *surface,
|
||||
content == CAIRO_CONTENT_ALPHA ? CAIRO_FORMAT_A8 : CAIRO_FORMAT_ARGB32,
|
||||
width * scale, height * scale);
|
||||
cairo_surface_set_device_scale (similar_surface, scale, scale);
|
||||
gdk_cairo_surface_set_color_state (similar_surface, gdk_surface_get_color_state (surface));
|
||||
|
||||
return similar_surface;
|
||||
}
|
||||
@@ -3076,3 +3120,37 @@ gdk_surface_get_subsurface (GdkSurface *surface,
|
||||
{
|
||||
return g_ptr_array_index (surface->subsurfaces, idx);
|
||||
}
|
||||
|
||||
void
|
||||
gdk_surface_set_color_state (GdkSurface *surface,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
/* This way we support unsetting, too */
|
||||
if (G_UNLIKELY (gdk_display_get_debug_flags (surface->display) & GDK_DEBUG_SRGB))
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
if (gdk_color_state_equal (surface->color_state, color_state))
|
||||
return;
|
||||
|
||||
g_set_object (&surface->color_state, color_state);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_COLOR_STATE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_get_color_state:
|
||||
* @self: a `GdkSurface`
|
||||
*
|
||||
* Returns the preferred color state for rendering to the given @surface.
|
||||
*
|
||||
* Returns: (transfer none): The color state of @surface
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_surface_get_color_state (GdkSurface *surface)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (surface), gdk_color_state_get_srgb ());
|
||||
|
||||
return surface->color_state;
|
||||
}
|
||||
|
@@ -139,6 +139,9 @@ GdkVulkanContext *
|
||||
gdk_surface_create_vulkan_context(GdkSurface *surface,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState *gdk_surface_get_color_state (GdkSurface *surface);
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GdkSurface, g_object_unref)
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -105,6 +105,8 @@ struct _GdkSurface
|
||||
*/
|
||||
GdkSubsurface *subsurfaces_above;
|
||||
GdkSubsurface *subsurfaces_below;
|
||||
|
||||
GdkColorState *color_state;
|
||||
};
|
||||
|
||||
struct _GdkSurfaceClass
|
||||
@@ -355,4 +357,7 @@ gsize gdk_surface_get_n_subsurfaces (GdkSurface *surface);
|
||||
GdkSubsurface * gdk_surface_get_subsurface (GdkSurface *surface,
|
||||
gsize idx);
|
||||
|
||||
void gdk_surface_set_color_state (GdkSurface *surface,
|
||||
GdkColorState *color_state);
|
||||
|
||||
G_END_DECLS
|
||||
|
122
gdk/gdktexture.c
@@ -44,6 +44,8 @@
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkpaintable.h"
|
||||
#include "gdksnapshot.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkcairo.h"
|
||||
|
||||
#include <graphene.h>
|
||||
#include "loaders/gdkpngprivate.h"
|
||||
@@ -69,6 +71,7 @@ enum {
|
||||
PROP_0,
|
||||
PROP_WIDTH,
|
||||
PROP_HEIGHT,
|
||||
PROP_COLOR_STATE,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@@ -258,6 +261,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
|
||||
static void
|
||||
gdk_texture_default_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -282,6 +286,12 @@ gdk_texture_set_property (GObject *gobject,
|
||||
self->height = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
if (self->color_state)
|
||||
gdk_color_state_unref (self->color_state);
|
||||
self->color_state = gdk_color_state_ref (g_value_get_boxed (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@@ -306,6 +316,10 @@ gdk_texture_get_property (GObject *gobject,
|
||||
g_value_set_int (value, self->height);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_STATE:
|
||||
g_value_set_boxed (value, self->color_state);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@@ -344,6 +358,8 @@ gdk_texture_dispose (GObject *object)
|
||||
|
||||
gdk_texture_clear_render_data (self);
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_texture_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@@ -388,12 +404,28 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkTexture:color-state: (attributes org.gtk.Property.get=gdk_texture_get_color_state)
|
||||
*
|
||||
* The color state of the texture.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
properties[PROP_COLOR_STATE] =
|
||||
g_param_spec_boxed ("color-state", NULL, NULL,
|
||||
GDK_TYPE_COLOR_STATE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
g_object_class_install_properties (gobject_class, N_PROPS, properties);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_texture_init (GdkTexture *self)
|
||||
{
|
||||
self->color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -424,17 +456,42 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
|
||||
(GDestroyNotify) cairo_surface_destroy,
|
||||
cairo_surface_reference (surface));
|
||||
|
||||
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
GDK_MEMORY_DEFAULT,
|
||||
bytes,
|
||||
cairo_image_surface_get_stride (surface));
|
||||
texture = gdk_memory_texture_new_with_color_state (cairo_image_surface_get_width (surface),
|
||||
cairo_image_surface_get_height (surface),
|
||||
GDK_MEMORY_DEFAULT,
|
||||
gdk_cairo_surface_get_color_state (surface),
|
||||
bytes,
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
static GdkColorState *
|
||||
gdk_color_state_from_pixbuf (GdkPixbuf *pixbuf)
|
||||
{
|
||||
const char *icc_profile_base64;
|
||||
GdkColorState *color_state = NULL;
|
||||
|
||||
icc_profile_base64 = gdk_pixbuf_get_option (pixbuf, "icc-profile");
|
||||
if (icc_profile_base64)
|
||||
{
|
||||
guchar *icc_data;
|
||||
gsize icc_len;
|
||||
GBytes *bytes;
|
||||
|
||||
icc_data = g_base64_decode (icc_profile_base64, &icc_len);
|
||||
bytes = g_bytes_new_take (icc_data, icc_len);
|
||||
color_state = gdk_color_state_new_from_icc_profile (bytes, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
if (!color_state)
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
return color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_new_for_pixbuf:
|
||||
* @pixbuf: a `GdkPixbuf`
|
||||
@@ -452,24 +509,31 @@ gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes;
|
||||
GdkColorState *color_state;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||
|
||||
color_state = gdk_color_state_from_pixbuf (pixbuf);
|
||||
|
||||
bytes = g_bytes_new_with_free_func (gdk_pixbuf_get_pixels (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf)
|
||||
* (gsize) gdk_pixbuf_get_rowstride (pixbuf),
|
||||
g_object_unref,
|
||||
g_object_ref (pixbuf));
|
||||
texture = gdk_memory_texture_new (gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf),
|
||||
gdk_pixbuf_get_has_alpha (pixbuf)
|
||||
? GDK_MEMORY_GDK_PIXBUF_ALPHA
|
||||
: GDK_MEMORY_GDK_PIXBUF_OPAQUE,
|
||||
bytes,
|
||||
gdk_pixbuf_get_rowstride (pixbuf));
|
||||
|
||||
texture = gdk_memory_texture_new_with_color_state (gdk_pixbuf_get_width (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf),
|
||||
gdk_pixbuf_get_has_alpha (pixbuf)
|
||||
? GDK_MEMORY_GDK_PIXBUF_ALPHA
|
||||
: GDK_MEMORY_GDK_PIXBUF_OPAQUE,
|
||||
color_state,
|
||||
bytes,
|
||||
gdk_pixbuf_get_rowstride (pixbuf));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
gdk_color_state_unref (color_state);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -727,13 +791,32 @@ gdk_texture_get_height (GdkTexture *texture)
|
||||
return texture->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_get_color_state: (attributes org.gtk.Method.get_property=color-state)
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Returns the color state associsated with @texture.
|
||||
*
|
||||
* Returns: (transfer none): the color state of the `GdkTexture`
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_texture_get_color_state (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), NULL);
|
||||
|
||||
return texture->color_state;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_do_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data, stride);
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, color_state, data, stride);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -829,7 +912,8 @@ gdk_texture_set_diff (GdkTexture *self,
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
gdk_texture_download_surface (GdkTexture *texture)
|
||||
gdk_texture_download_surface (GdkTexture *texture,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
cairo_surface_t *surface;
|
||||
cairo_status_t surface_status;
|
||||
@@ -841,10 +925,13 @@ gdk_texture_download_surface (GdkTexture *texture)
|
||||
if (surface_status != CAIRO_STATUS_SUCCESS)
|
||||
g_warning ("%s: surface error: %s", __FUNCTION__,
|
||||
cairo_status_to_string (surface_status));
|
||||
else
|
||||
gdk_texture_do_download (texture,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
color_state,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
|
||||
gdk_texture_download (texture,
|
||||
cairo_image_surface_get_data (surface),
|
||||
cairo_image_surface_get_stride (surface));
|
||||
cairo_surface_mark_dirty (surface);
|
||||
|
||||
return surface;
|
||||
@@ -891,6 +978,7 @@ gdk_texture_download (GdkTexture *texture,
|
||||
|
||||
gdk_texture_do_download (texture,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
gdk_color_state_get_srgb (),
|
||||
data,
|
||||
stride);
|
||||
}
|
||||
|
@@ -83,6 +83,9 @@ int gdk_texture_get_height (GdkTexture
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkMemoryFormat gdk_texture_get_format (GdkTexture *self) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_texture_get_color_state (GdkTexture *self);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_texture_download (GdkTexture *texture,
|
||||
guchar *data,
|
||||
|
@@ -39,6 +39,7 @@
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkTextureDownloader, gdk_texture_downloader,
|
||||
gdk_texture_downloader_copy,
|
||||
@@ -51,6 +52,7 @@ gdk_texture_downloader_init (GdkTextureDownloader *self,
|
||||
{
|
||||
self->texture = g_object_ref (texture);
|
||||
self->format = GDK_MEMORY_DEFAULT;
|
||||
self->color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -103,6 +105,7 @@ gdk_texture_downloader_copy (const GdkTextureDownloader *self)
|
||||
|
||||
copy = gdk_texture_downloader_new (self->texture);
|
||||
gdk_texture_downloader_set_format (copy, self->format);
|
||||
gdk_texture_downloader_set_color_state (copy, self->color_state);
|
||||
|
||||
return copy;
|
||||
}
|
||||
@@ -121,6 +124,8 @@ gdk_texture_downloader_free (GdkTextureDownloader *self)
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
gdk_texture_downloader_finish (self);
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
@@ -199,6 +204,39 @@ gdk_texture_downloader_get_format (const GdkTextureDownloader *self)
|
||||
return self->format;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_downloader_set_color_state:
|
||||
* @self: a texture downloader
|
||||
* @color_state: the color state to use
|
||||
*
|
||||
* Sets the color state that the data will be converted to.
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
void
|
||||
gdk_texture_downloader_set_color_state (GdkTextureDownloader *self,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = gdk_color_state_ref (color_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_downloader_get_color_state:
|
||||
* @self: a texture downloader
|
||||
*
|
||||
* Gets the color state that the data will be converted to.
|
||||
*
|
||||
* Returns: the color state
|
||||
*
|
||||
* Since: 4.16
|
||||
*/
|
||||
GdkColorState *
|
||||
gdk_texture_downloader_get_color_state (const GdkTextureDownloader *self)
|
||||
{
|
||||
return self->color_state;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_downloader_download_into:
|
||||
* @self: a texture downloader
|
||||
@@ -219,7 +257,7 @@ gdk_texture_downloader_download_into (const GdkTextureDownloader *self,
|
||||
g_return_if_fail (data != NULL);
|
||||
g_return_if_fail (stride >= gdk_texture_get_width (self->texture) * gdk_memory_format_bytes_per_pixel (self->format));
|
||||
|
||||
gdk_texture_do_download (self->texture, self->format, data, stride);
|
||||
gdk_texture_do_download (self->texture, self->format, self->color_state, data, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -250,7 +288,8 @@ gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
|
||||
g_return_val_if_fail (out_stride != NULL, NULL);
|
||||
|
||||
if (GDK_IS_MEMORY_TEXTURE (self->texture) &&
|
||||
gdk_texture_get_format (self->texture) == self->format)
|
||||
gdk_texture_get_format (self->texture) == self->format &&
|
||||
gdk_color_state_equal (self->texture->color_state, self->color_state))
|
||||
{
|
||||
GdkMemoryTexture *memtex = GDK_MEMORY_TEXTURE (self->texture);
|
||||
|
||||
@@ -260,7 +299,7 @@ gdk_texture_downloader_download_bytes (const GdkTextureDownloader *self,
|
||||
stride = self->texture->width * gdk_memory_format_bytes_per_pixel (self->format);
|
||||
data = g_malloc_n (stride, self->texture->height);
|
||||
|
||||
gdk_texture_do_download (self->texture, self->format, data, stride);
|
||||
gdk_texture_do_download (self->texture, self->format, self->color_state, data, stride);
|
||||
|
||||
*out_stride = stride;
|
||||
return g_bytes_new_take (data, stride * self->texture->height);
|
||||
|
@@ -49,6 +49,12 @@ void gdk_texture_downloader_set_format (GdkTextureDownl
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
GdkMemoryFormat gdk_texture_downloader_get_format (const GdkTextureDownloader *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
void gdk_texture_downloader_set_color_state (GdkTextureDownloader *self,
|
||||
GdkColorState *color_state);
|
||||
GDK_AVAILABLE_IN_4_16
|
||||
GdkColorState * gdk_texture_downloader_get_color_state (const GdkTextureDownloader *self);
|
||||
|
||||
|
||||
GDK_AVAILABLE_IN_4_10
|
||||
void gdk_texture_downloader_download_into (const GdkTextureDownloader *self,
|
||||
|
@@ -28,6 +28,7 @@ struct _GdkTextureDownloader
|
||||
/*< private >*/
|
||||
GdkTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
};
|
||||
|
||||
void gdk_texture_downloader_init (GdkTextureDownloader *self,
|
||||
|
@@ -26,6 +26,8 @@ struct _GdkTexture
|
||||
int width;
|
||||
int height;
|
||||
|
||||
GdkColorState *color_state;
|
||||
|
||||
gpointer render_key;
|
||||
gpointer render_data;
|
||||
GDestroyNotify render_notify;
|
||||
@@ -46,6 +48,7 @@ struct _GdkTextureClass {
|
||||
/* mandatory: Download in the given format into data */
|
||||
void (* download) (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
};
|
||||
@@ -53,10 +56,12 @@ struct _GdkTextureClass {
|
||||
gboolean gdk_texture_can_load (GBytes *bytes);
|
||||
|
||||
GdkTexture * gdk_texture_new_for_surface (cairo_surface_t *surface);
|
||||
cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture);
|
||||
cairo_surface_t * gdk_texture_download_surface (GdkTexture *texture,
|
||||
GdkColorState *color_state);
|
||||
|
||||
void gdk_texture_do_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
void gdk_texture_diff (GdkTexture *self,
|
||||
|
@@ -74,6 +74,8 @@ typedef cairo_rectangle_int_t GdkRectangle;
|
||||
|
||||
/* Forward declarations of commonly used types */
|
||||
typedef struct _GdkRGBA GdkRGBA;
|
||||
typedef struct _GdkColor GdkColor;
|
||||
typedef struct _GdkColorState GdkColorState;
|
||||
typedef struct _GdkContentFormats GdkContentFormats;
|
||||
typedef struct _GdkContentProvider GdkContentProvider;
|
||||
typedef struct _GdkCursor GdkCursor;
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "gdkdmabuftextureprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdkmemorytexture.h"
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include <math.h>
|
||||
|
||||
@@ -647,15 +648,18 @@ gdk_vulkan_context_begin_frame (GdkDrawContext *draw_context,
|
||||
{
|
||||
if (priv->formats[depth].gdk_format != priv->formats[priv->current_format].gdk_format)
|
||||
{
|
||||
GdkMemoryDepth old_format = priv->current_format;
|
||||
GError *error = NULL;
|
||||
|
||||
priv->current_format = depth;
|
||||
if (!gdk_vulkan_context_check_swapchain (context, &error))
|
||||
{
|
||||
g_warning ("%s", error->message);
|
||||
g_error_free (error);
|
||||
priv->current_format = old_format;
|
||||
return;
|
||||
}
|
||||
}
|
||||
priv->current_format = depth;
|
||||
}
|
||||
for (i = 0; i < priv->n_images; i++)
|
||||
{
|
||||
@@ -1294,6 +1298,15 @@ gdk_vulkan_context_get_image_format (GdkVulkanContext *context)
|
||||
return priv->formats[priv->current_format].vk_format.format;
|
||||
}
|
||||
|
||||
GdkMemoryFormat
|
||||
gdk_vulkan_context_get_memory_format (GdkVulkanContext *context)
|
||||
{
|
||||
GdkVulkanContextPrivate *priv = gdk_vulkan_context_get_instance_private (context);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_VULKAN_CONTEXT (context), GDK_MEMORY_DEFAULT);
|
||||
|
||||
return priv->formats[priv->current_format].gdk_format;
|
||||
}
|
||||
/**
|
||||
* gdk_vulkan_context_get_n_images:
|
||||
* @context: a `GdkVulkanContext`
|
||||
|
@@ -94,6 +94,7 @@ VkDevice gdk_vulkan_context_get_device (GdkVulk
|
||||
VkQueue gdk_vulkan_context_get_queue (GdkVulkanContext *context);
|
||||
uint32_t gdk_vulkan_context_get_queue_family_index (GdkVulkanContext *context);
|
||||
VkFormat gdk_vulkan_context_get_image_format (GdkVulkanContext *context);
|
||||
GdkMemoryFormat gdk_vulkan_context_get_memory_format (GdkVulkanContext *context);
|
||||
uint32_t gdk_vulkan_context_get_n_images (GdkVulkanContext *context);
|
||||
VkImage gdk_vulkan_context_get_image (GdkVulkanContext *context,
|
||||
guint id);
|
||||
|
@@ -24,6 +24,8 @@
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gdktexture.h"
|
||||
#include "gdktexturedownloaderprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
@@ -143,9 +145,12 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
guint width, height, stride;
|
||||
unsigned char *data = NULL;
|
||||
unsigned char *row[1];
|
||||
JOCTET *icc_data;
|
||||
unsigned int icc_len;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
G_GNUC_UNUSED guint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
@@ -169,6 +174,9 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
g_bytes_get_data (input_bytes, NULL),
|
||||
g_bytes_get_size (input_bytes));
|
||||
|
||||
/* save color space */
|
||||
jpeg_save_markers (&info, JPEG_APP0 + 2, 0xFFFF);
|
||||
|
||||
jpeg_read_header (&info, TRUE);
|
||||
jpeg_start_decompress (&info);
|
||||
|
||||
@@ -226,19 +234,35 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
if (jpeg_read_icc_profile (&info, &icc_data, &icc_len))
|
||||
{
|
||||
GBytes *icc_bytes = g_bytes_new_with_free_func (icc_data, icc_len, free, icc_data);
|
||||
color_state = gdk_color_state_new_from_icc_profile (icc_bytes, error);
|
||||
g_bytes_unref (icc_bytes);
|
||||
}
|
||||
else
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
jpeg_finish_decompress (&info);
|
||||
jpeg_destroy_decompress (&info);
|
||||
|
||||
bytes = g_bytes_new_take (data, stride * height);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
format,
|
||||
bytes, stride);
|
||||
if (color_state)
|
||||
{
|
||||
texture = gdk_memory_texture_new_with_color_state (width, height,
|
||||
format,
|
||||
color_state,
|
||||
bytes, stride);
|
||||
}
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
g_clear_pointer (&color_state, gdk_color_state_unref);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
gdk_profiler_end_mark (before, "Load jpeg", NULL);
|
||||
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
@@ -257,9 +281,12 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
gsize texstride;
|
||||
guchar *row;
|
||||
int width, height;
|
||||
GdkColorState *color_state;
|
||||
GBytes *bytes;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
color_state = gdk_texture_get_color_state (texture);
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
@@ -298,6 +325,15 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
|
||||
jpeg_start_compress (&info, TRUE);
|
||||
|
||||
bytes = gdk_color_state_save_to_icc_profile (color_state, NULL);
|
||||
if (bytes)
|
||||
{
|
||||
jpeg_write_icc_profile (&info,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
|
||||
while (info.next_scanline < info.image_height)
|
||||
{
|
||||
row = (guchar *) texdata + info.next_scanline * texstride;
|
||||
|
@@ -20,11 +20,14 @@
|
||||
#include "gdkpngprivate.h"
|
||||
|
||||
#include <glib/gi18n-lib.h>
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkcolorstateprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytexture.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktexturedownloaderprivate.h"
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -126,6 +129,182 @@ png_simple_warning_callback (png_structp png,
|
||||
{
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Color profile handling */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean cicp_chunk_read;
|
||||
int color_primaries;
|
||||
int transfer_function;
|
||||
int matrix_coefficients;
|
||||
int full_range;
|
||||
} CICPData;
|
||||
|
||||
static int
|
||||
png_read_chunk_func (png_structp png,
|
||||
png_unknown_chunkp chunk)
|
||||
{
|
||||
if (strcmp ((char *) chunk->name, "cICP") == 0 &&
|
||||
chunk->size == 4)
|
||||
{
|
||||
CICPData *cicp = png_get_user_chunk_ptr (png);
|
||||
|
||||
cicp->cicp_chunk_read = TRUE;
|
||||
|
||||
cicp->color_primaries = chunk->data[0];
|
||||
cicp->transfer_function = chunk->data[1];
|
||||
cicp->matrix_coefficients = chunk->data[2];
|
||||
cicp->full_range = chunk->data[3];
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static GdkColorState *
|
||||
gdk_png_get_color_state (png_struct *png,
|
||||
png_info *info)
|
||||
{
|
||||
GdkColorState *color_state;
|
||||
guchar *icc_data;
|
||||
png_uint_32 icc_len;
|
||||
char *name;
|
||||
double gamma;
|
||||
cmsCIExyY whitepoint;
|
||||
cmsCIExyYTRIPLE primaries;
|
||||
cmsToneCurve *curve;
|
||||
cmsHPROFILE lcms_profile;
|
||||
int intent;
|
||||
CICPData *cicp;
|
||||
|
||||
cicp = png_get_user_chunk_ptr (png);
|
||||
|
||||
if (cicp->cicp_chunk_read)
|
||||
{
|
||||
color_state = gdk_color_state_new_from_cicp_data (cicp->color_primaries,
|
||||
cicp->transfer_function,
|
||||
cicp->matrix_coefficients,
|
||||
cicp->full_range);
|
||||
if (color_state)
|
||||
{
|
||||
g_debug ("Color state from cICP data: %s\n", gdk_color_state_get_name (color_state));
|
||||
return color_state;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_debug ("Failed to create color state from cICP data: %d/%d/%d %d\n",
|
||||
cicp->color_primaries,
|
||||
cicp->transfer_function,
|
||||
cicp->matrix_coefficients,
|
||||
cicp->full_range);
|
||||
}
|
||||
}
|
||||
|
||||
if (png_get_iCCP (png, info, &name, NULL, &icc_data, &icc_len))
|
||||
{
|
||||
GBytes *bytes = g_bytes_new (icc_data, icc_len);
|
||||
|
||||
color_state = gdk_color_state_new_from_icc_profile (bytes, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
if (color_state)
|
||||
return color_state;
|
||||
}
|
||||
|
||||
if (png_get_sRGB (png, info, &intent))
|
||||
return gdk_color_state_get_srgb ();
|
||||
|
||||
/* If neither of those is valid, the result is sRGB */
|
||||
if (!png_get_valid (png, info, PNG_INFO_gAMA) &&
|
||||
!png_get_valid (png, info, PNG_INFO_cHRM))
|
||||
return gdk_color_state_get_srgb ();
|
||||
|
||||
if (!png_get_gAMA (png, info, &gamma))
|
||||
gamma = 2.4;
|
||||
|
||||
if (!png_get_cHRM (png, info,
|
||||
&whitepoint.x, &whitepoint.y,
|
||||
&primaries.Red.x, &primaries.Red.y,
|
||||
&primaries.Green.x, &primaries.Green.y,
|
||||
&primaries.Blue.x, &primaries.Blue.y))
|
||||
{
|
||||
if (gamma == 2.4)
|
||||
return gdk_color_state_get_srgb ();
|
||||
|
||||
whitepoint = (cmsCIExyY) { 0.3127, 0.3290, 1.0 };
|
||||
primaries = (cmsCIExyYTRIPLE) {
|
||||
{ 0.6400, 0.3300, 1.0 },
|
||||
{ 0.3000, 0.6000, 1.0 },
|
||||
{ 0.1500, 0.0600, 1.0 }
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
primaries.Red.Y = 1.0;
|
||||
primaries.Green.Y = 1.0;
|
||||
primaries.Blue.Y = 1.0;
|
||||
}
|
||||
|
||||
curve = cmsBuildGamma (NULL, 1.0 / gamma);
|
||||
lcms_profile = cmsCreateRGBProfile (&whitepoint,
|
||||
&primaries,
|
||||
(cmsToneCurve*[3]) { curve, curve, curve });
|
||||
color_state = gdk_color_state_new_from_lcms_profile (lcms_profile);
|
||||
/* FIXME: errors? */
|
||||
if (color_state == NULL)
|
||||
color_state = gdk_color_state_get_srgb ();
|
||||
cmsFreeToneCurve (curve);
|
||||
|
||||
return color_state;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_png_set_color_state (png_struct *png,
|
||||
png_info *info,
|
||||
GdkColorState *color_state,
|
||||
png_byte *chunk_data)
|
||||
{
|
||||
int cp, tc, mc;
|
||||
gboolean fr;
|
||||
|
||||
if (gdk_color_state_save_to_cicp_data (color_state, &cp, &tc, &mc, &fr, NULL))
|
||||
{
|
||||
png_unknown_chunk chunk = {
|
||||
.name = { 'c', 'I', 'C', 'P', '\0' },
|
||||
.data = chunk_data,
|
||||
.size = 4,
|
||||
.location = PNG_HAVE_IHDR,
|
||||
};
|
||||
|
||||
chunk_data[0] = (png_byte)cp;
|
||||
chunk_data[1] = (png_byte)tc;
|
||||
chunk_data[2] = (png_byte)mc;
|
||||
chunk_data[3] = (png_byte)fr;
|
||||
|
||||
g_debug ("got cicp %d/%d/%d %d\n", cp, tc, mc, fr);
|
||||
|
||||
png_set_unknown_chunks (png, info, &chunk, 1);
|
||||
}
|
||||
else if (color_state == gdk_color_state_get_srgb ())
|
||||
{
|
||||
png_set_sRGB_gAMA_and_cHRM (png, info, /* FIXME */ PNG_sRGB_INTENT_PERCEPTUAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
GBytes *bytes = gdk_color_state_save_to_icc_profile (color_state, NULL);
|
||||
if (bytes)
|
||||
{
|
||||
png_set_iCCP (png, info,
|
||||
"ICC profile",
|
||||
0,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
@@ -147,8 +326,11 @@ gdk_load_png (GBytes *bytes,
|
||||
guchar *buffer = NULL;
|
||||
guchar **row_pointers = NULL;
|
||||
GBytes *out_bytes;
|
||||
GdkColorState *color_state;
|
||||
GdkTexture *texture;
|
||||
int bpp;
|
||||
CICPData cicp = { FALSE, };
|
||||
|
||||
G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
io.data = (guchar *)g_bytes_get_data (bytes, &io.size);
|
||||
@@ -169,6 +351,7 @@ gdk_load_png (GBytes *bytes,
|
||||
g_error ("Out of memory");
|
||||
|
||||
png_set_read_fn (png, &io, png_read_func);
|
||||
png_set_read_user_chunk_fn (png, &cicp, png_read_chunk_func);
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
@@ -266,6 +449,8 @@ gdk_load_png (GBytes *bytes,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_state = gdk_png_get_color_state (png, info);
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
if (!g_size_checked_mul (&stride, width, bpp) ||
|
||||
!g_size_checked_add (&stride, stride, (8 - stride % 8) % 8))
|
||||
@@ -281,6 +466,7 @@ gdk_load_png (GBytes *bytes,
|
||||
|
||||
if (!buffer || !row_pointers)
|
||||
{
|
||||
gdk_color_state_unref (color_state);
|
||||
g_free (buffer);
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
@@ -297,8 +483,11 @@ gdk_load_png (GBytes *bytes,
|
||||
png_read_end (png, info);
|
||||
|
||||
out_bytes = g_bytes_new_take (buffer, height * stride);
|
||||
texture = gdk_memory_texture_new (width, height, format, out_bytes, stride);
|
||||
texture = gdk_memory_texture_new_with_color_state (width, height,
|
||||
format, color_state,
|
||||
out_bytes, stride);
|
||||
g_bytes_unref (out_bytes);
|
||||
gdk_color_state_unref (color_state);
|
||||
|
||||
if (options && png_get_text (png, info, &text, &num_texts))
|
||||
{
|
||||
@@ -337,11 +526,14 @@ gdk_save_png (GdkTexture *texture)
|
||||
GBytes *bytes;
|
||||
gsize stride;
|
||||
const guchar *data;
|
||||
GdkColorState *color_state;
|
||||
int png_format;
|
||||
int depth;
|
||||
png_byte chunk_data[4];
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
color_state = gdk_texture_get_color_state (texture);
|
||||
format = gdk_texture_get_format (texture);
|
||||
|
||||
switch (format)
|
||||
@@ -436,6 +628,8 @@ gdk_save_png (GdkTexture *texture)
|
||||
/* 2^31-1 is the maximum size for PNG files */
|
||||
png_set_user_limits (png, (1u << 31) - 1, (1u << 31) - 1);
|
||||
|
||||
png_set_keep_unknown_chunks (png, PNG_HANDLE_CHUNK_ALWAYS, NULL, 0);
|
||||
|
||||
info = png_create_info_struct (png);
|
||||
if (!info)
|
||||
{
|
||||
@@ -465,6 +659,8 @@ gdk_save_png (GdkTexture *texture)
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
gdk_png_set_color_state (png, info, color_state, chunk_data);
|
||||
|
||||
png_write_info (png, info);
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
|
@@ -24,6 +24,7 @@
|
||||
#include "gdkmemorytexture.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktexturedownloaderprivate.h"
|
||||
#include "gdkcolorstate.h"
|
||||
|
||||
#include <tiffio.h>
|
||||
|
||||
@@ -219,6 +220,49 @@ tiff_open_write (GBytes **result)
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Color profile handling */
|
||||
|
||||
static GdkColorState *
|
||||
gdk_tiff_get_color_state (TIFF *tiff)
|
||||
{
|
||||
const char *icc_data;
|
||||
guint icc_len;
|
||||
|
||||
if (TIFFGetField (tiff, TIFFTAG_ICCPROFILE, &icc_len, &icc_data))
|
||||
{
|
||||
GBytes *icc_bytes;
|
||||
GdkColorState *color_state;
|
||||
|
||||
icc_bytes = g_bytes_new (icc_data, icc_len);
|
||||
color_state = gdk_color_state_new_from_icc_profile (icc_bytes, NULL);
|
||||
g_bytes_unref (icc_bytes);
|
||||
|
||||
if (color_state)
|
||||
return color_state;
|
||||
}
|
||||
|
||||
return gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_tiff_set_color_state (TIFF *tiff,
|
||||
GdkColorState *color_state)
|
||||
{
|
||||
GBytes *bytes;
|
||||
|
||||
bytes = gdk_color_state_save_to_icc_profile (color_state, NULL);
|
||||
|
||||
if (bytes)
|
||||
{
|
||||
TIFFSetField (tiff, TIFFTAG_ICCPROFILE,
|
||||
g_bytes_get_size (bytes),
|
||||
g_bytes_get_data (bytes, NULL));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
@@ -282,6 +326,7 @@ gdk_save_tiff (GdkTexture *texture)
|
||||
GBytes *bytes, *result = NULL;
|
||||
GdkTextureDownloader downloader;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorState *color_state;
|
||||
const FormatData *fdata = NULL;
|
||||
|
||||
tif = tiff_open_write (&result);
|
||||
@@ -289,6 +334,7 @@ gdk_save_tiff (GdkTexture *texture)
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
format = gdk_texture_get_format (texture);
|
||||
color_state = gdk_texture_get_color_state (texture);
|
||||
fdata = &format_data[format];
|
||||
|
||||
if (fdata == NULL)
|
||||
@@ -308,6 +354,8 @@ gdk_save_tiff (GdkTexture *texture)
|
||||
TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, fdata->photometric);
|
||||
TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
|
||||
gdk_tiff_set_color_state (tif, color_state);
|
||||
|
||||
gdk_texture_downloader_init (&downloader, texture);
|
||||
gdk_texture_downloader_set_format (&downloader, fdata->format);
|
||||
bytes = gdk_texture_downloader_download_bytes (&downloader, &stride);
|
||||
@@ -344,6 +392,7 @@ load_fallback (TIFF *tif,
|
||||
int width, height;
|
||||
guchar *data;
|
||||
GBytes *bytes;
|
||||
GdkColorState *color_state;
|
||||
GdkTexture *texture;
|
||||
|
||||
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &width);
|
||||
@@ -360,12 +409,15 @@ load_fallback (TIFF *tif,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_state = gdk_tiff_get_color_state (tif);
|
||||
|
||||
bytes = g_bytes_new_take (data, width * height * 4);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
bytes,
|
||||
width * 4);
|
||||
texture = gdk_memory_texture_new_with_color_state (width, height,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
color_state,
|
||||
bytes,
|
||||
width * 4);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
@@ -390,6 +442,7 @@ gdk_load_tiff (GBytes *input_bytes,
|
||||
gsize stride;
|
||||
int bpp;
|
||||
GBytes *bytes;
|
||||
GdkColorState *color_state;
|
||||
GdkTexture *texture;
|
||||
G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
@@ -490,13 +543,16 @@ gdk_load_tiff (GBytes *input_bytes,
|
||||
line += stride;
|
||||
}
|
||||
|
||||
color_state = gdk_tiff_get_color_state (tif);
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
bytes = g_bytes_new_take (data, width * height * bpp);
|
||||
|
||||
texture = gdk_memory_texture_new (width, height,
|
||||
format,
|
||||
bytes, width * bpp);
|
||||
texture = gdk_memory_texture_new_with_color_state (width, height,
|
||||
format, color_state,
|
||||
bytes, width * bpp);
|
||||
g_bytes_unref (bytes);
|
||||
gdk_color_state_unref (color_state);
|
||||
|
||||
TIFFClose (tif);
|
||||
|
||||
|
@@ -6,6 +6,8 @@ gdk_public_sources = files([
|
||||
'gdkcairo.c',
|
||||
'gdkcairocontext.c',
|
||||
'gdkclipboard.c',
|
||||
'gdkcolor.c',
|
||||
'gdkcolorstate.c',
|
||||
'gdkcontentdeserializer.c',
|
||||
'gdkcontentformats.c',
|
||||
'gdkcontentprovider.c',
|
||||
@@ -75,6 +77,9 @@ gdk_public_headers = files([
|
||||
'gdkcairo.h',
|
||||
'gdkcairocontext.h',
|
||||
'gdkclipboard.h',
|
||||
'gdkcolor.h',
|
||||
'gdkcolorimpl.h',
|
||||
'gdkcolorstate.h',
|
||||
'gdkcontentdeserializer.h',
|
||||
'gdkcontentformats.h',
|
||||
'gdkcontentprovider.h',
|
||||
@@ -224,6 +229,7 @@ gdk_deps = [
|
||||
fontconfig_dep,
|
||||
platform_gio_dep,
|
||||
pangocairo_dep,
|
||||
lcms2_dep,
|
||||
vulkan_dep,
|
||||
libdrm_dep,
|
||||
png_dep,
|
||||
|
@@ -158,6 +158,9 @@ gdk_wayland_cairo_context_begin_frame (GdkDrawContext *draw_context,
|
||||
else
|
||||
self->paint_surface = gdk_wayland_cairo_context_create_surface (self);
|
||||
|
||||
gdk_cairo_surface_set_color_state (self->paint_surface,
|
||||
gdk_surface_get_color_state (gdk_draw_context_get_surface (draw_context)));
|
||||
|
||||
surface_region = gdk_wayland_cairo_context_surface_get_region (self->paint_surface);
|
||||
if (surface_region)
|
||||
cairo_region_union (region, surface_region);
|
||||
|
@@ -3866,9 +3866,25 @@ pointer_surface_leave (void *data,
|
||||
pointer_surface_update_scale (device);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_surface_preferred_buffer_scale (void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
int32_t factor)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_surface_preferred_buffer_transform (void *data,
|
||||
struct wl_surface *wl_surface,
|
||||
uint32_t transform)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_surface_listener pointer_surface_listener = {
|
||||
pointer_surface_enter,
|
||||
pointer_surface_leave
|
||||
pointer_surface_leave,
|
||||
pointer_surface_preferred_buffer_scale,
|
||||
pointer_surface_preferred_buffer_transform,
|
||||
};
|
||||
|
||||
static void
|
||||
|
@@ -47,6 +47,7 @@ create_cairo_surface_for_surface (GdkSurface *surface,
|
||||
|
||||
cairo_surface = cairo_win32_surface_create_with_format (hdc, CAIRO_FORMAT_ARGB32);
|
||||
cairo_surface_set_device_scale (cairo_surface, scale, scale);
|
||||
gdk_cairo_surface_set_color_state (cairo_surface, gdk_surface_get_color_state (surface));
|
||||
|
||||
return cairo_surface;
|
||||
}
|
||||
|
@@ -49,6 +49,7 @@ create_cairo_surface_for_surface (GdkSurface *surface)
|
||||
gdk_surface_get_width (surface) * scale,
|
||||
gdk_surface_get_height (surface) * scale);
|
||||
cairo_surface_set_device_scale (cairo_surface, scale, scale);
|
||||
gdk_cairo_surface_set_color_state (cairo_surface, gdk_surface_get_color_state (surface));
|
||||
|
||||
return cairo_surface;
|
||||
}
|
||||
|
@@ -1405,6 +1405,71 @@ gdk_x11_display_init_leader_surface (GdkX11Display *self)
|
||||
self->leader_window_title_set = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
voidXFree (gpointer data)
|
||||
{
|
||||
XFree (data);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_x11_display_check_color_state (GdkX11Display *self)
|
||||
{
|
||||
GdkDisplay *display = GDK_DISPLAY (self);
|
||||
GdkX11Screen *screen;
|
||||
char *atom_name;
|
||||
Atom type;
|
||||
int result;
|
||||
int format;
|
||||
gulong nitems;
|
||||
gulong bytes_after;
|
||||
guchar *data;
|
||||
GBytes *bytes;
|
||||
|
||||
screen = self->screen;
|
||||
if (screen->screen_num > 0)
|
||||
atom_name = g_strdup_printf ("_ICC_PROFILE_%d", screen->screen_num);
|
||||
else
|
||||
atom_name = g_strdup ("_ICC_PROFILE");
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = gdk_color_state_get_srgb ();
|
||||
|
||||
gdk_x11_display_error_trap_push (display);
|
||||
result = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display),
|
||||
screen->xroot_window,
|
||||
gdk_x11_get_xatom_by_name_for_display (display, atom_name),
|
||||
0, G_MAXLONG, False, XA_CARDINAL, &type,
|
||||
&format, &nitems,
|
||||
&bytes_after, &data);
|
||||
gdk_x11_display_error_trap_pop_ignored (display);
|
||||
|
||||
g_free (atom_name);
|
||||
|
||||
if (result != Success || type != XA_CARDINAL || nitems <= 0)
|
||||
return;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case 8:
|
||||
bytes = g_bytes_new_with_free_func (data, nitems, voidXFree, data);
|
||||
break;
|
||||
case 16:
|
||||
bytes = g_bytes_new_with_free_func (data, sizeof (short) * nitems, voidXFree, data);
|
||||
break;
|
||||
case 32:
|
||||
bytes = g_bytes_new_with_free_func (data, sizeof (long) * nitems, voidXFree, data);
|
||||
break;
|
||||
default:
|
||||
XFree (data);
|
||||
return;
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
self->color_state = gdk_color_state_new_from_icc_profile (bytes, NULL);
|
||||
if (!self->color_state)
|
||||
self->color_state = gdk_color_state_get_srgb ();
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_x11_display_open:
|
||||
* @display_name: (nullable): name of the X display.
|
||||
@@ -1475,6 +1540,9 @@ gdk_x11_display_open (const char *display_name)
|
||||
/* initialize the display's screens */
|
||||
display_x11->screen = _gdk_x11_screen_new (display, DefaultScreen (display_x11->xdisplay));
|
||||
|
||||
/* We want this for the leader surface already */
|
||||
gdk_x11_display_check_color_state (display_x11);
|
||||
|
||||
/* If GL is available we want to pick better default/rgba visuals,
|
||||
* as we care about GLX details such as alpha/depth/stencil depth,
|
||||
* stereo and double buffering
|
||||
@@ -1923,15 +1991,17 @@ gdk_x11_display_ungrab (GdkDisplay *display)
|
||||
static void
|
||||
gdk_x11_display_dispose (GObject *object)
|
||||
{
|
||||
GdkX11Display *display_x11 = GDK_X11_DISPLAY (object);
|
||||
GdkX11Display *self = GDK_X11_DISPLAY (object);
|
||||
|
||||
if (display_x11->event_source)
|
||||
if (self->event_source)
|
||||
{
|
||||
g_source_destroy (display_x11->event_source);
|
||||
g_source_unref (display_x11->event_source);
|
||||
display_x11->event_source = NULL;
|
||||
g_source_destroy (self->event_source);
|
||||
g_source_unref (self->event_source);
|
||||
self->event_source = NULL;
|
||||
}
|
||||
|
||||
g_clear_pointer (&self->color_state, gdk_color_state_unref);
|
||||
|
||||
G_OBJECT_CLASS (gdk_x11_display_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@@ -127,6 +127,9 @@ struct _GdkX11Display
|
||||
guint have_damage;
|
||||
#endif
|
||||
|
||||
/* Stored in the ICC_PROFILE rootwindow prop */
|
||||
GdkColorState *color_state;
|
||||
|
||||
/* If GL is not supported, store the error here */
|
||||
GError *gl_error;
|
||||
|
||||
|
@@ -926,6 +926,8 @@ setup_toplevel_window (GdkSurface *surface)
|
||||
|
||||
/* This will set WM_CLIENT_MACHINE and WM_LOCALE_NAME */
|
||||
XSetWMProperties (xdisplay, xid, NULL, NULL, NULL, 0, NULL, NULL, NULL);
|
||||
|
||||
gdk_surface_set_color_state (surface, GDK_X11_DISPLAY (display)->color_state);
|
||||
|
||||
if (!gdk_running_in_sandbox ())
|
||||
{
|
||||
@@ -3136,7 +3138,7 @@ gdk_surface_update_icon (GdkSurface *surface,
|
||||
|
||||
toplevel->icon_pixmap = gdk_x11_surface_create_pixmap_surface (surface, width, height);
|
||||
|
||||
cairo_surface = gdk_texture_download_surface (best_icon);
|
||||
cairo_surface = gdk_texture_download_surface (best_icon, gdk_color_state_get_srgb ());
|
||||
|
||||
cr = cairo_create (toplevel->icon_pixmap);
|
||||
cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
|
||||
|
@@ -477,7 +477,7 @@ get_colorized_texture (GdkTexture *texture,
|
||||
return g_object_ref (colorized->texture);
|
||||
}
|
||||
|
||||
surface = gdk_texture_download_surface (texture);
|
||||
surface = gdk_texture_download_surface (texture, gdk_color_state_get_srgb ());
|
||||
image_surface = cairo_surface_map_to_image (surface, NULL);
|
||||
data = cairo_image_surface_get_data (image_surface);
|
||||
width = cairo_image_surface_get_width (image_surface);
|
||||
|
@@ -972,7 +972,7 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
|
||||
if (texture_id == 0)
|
||||
{
|
||||
downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture));
|
||||
downloaded_texture = gdk_memory_texture_from_texture (texture);
|
||||
|
||||
/* The download_texture() call may have switched the GL context. Make sure
|
||||
* the right context is at work again.
|
||||
@@ -1471,8 +1471,7 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
}
|
||||
|
||||
slices = g_new0 (GskGLTextureSlice, n_slices);
|
||||
memtex = gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture));
|
||||
memtex = gdk_memory_texture_from_texture (texture);
|
||||
|
||||
if (ensure_mipmap)
|
||||
{
|
||||
|
@@ -281,9 +281,11 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
gdk_color_state_get_srgb (),
|
||||
cairo_image_surface_get_data (surface),
|
||||
stride,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
gdk_color_state_get_srgb (),
|
||||
width, height);
|
||||
stride = width * 4;
|
||||
gl_format = GL_RGBA;
|
||||
|
@@ -106,7 +106,7 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
|
||||
icon_data->source_texture = g_object_ref (key);
|
||||
|
||||
/* actually upload the texture */
|
||||
surface = gdk_texture_download_surface (key);
|
||||
surface = gdk_texture_download_surface (key, gdk_color_state_get_srgb ());
|
||||
surface_data = cairo_image_surface_get_data (surface);
|
||||
gdk_gl_context_push_debug_group_printf (gdk_gl_context_get_current (),
|
||||
"Uploading texture");
|
||||
@@ -116,8 +116,11 @@ gsk_gl_icon_library_add (GskGLIconLibrary *self,
|
||||
pixel_data = free_data = g_malloc (width * height * 4);
|
||||
gdk_memory_convert (pixel_data, width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
gdk_color_state_get_srgb (),
|
||||
surface_data, cairo_image_surface_get_stride (surface),
|
||||
GDK_MEMORY_DEFAULT, width, height);
|
||||
GDK_MEMORY_DEFAULT,
|
||||
gdk_texture_get_color_state (key),
|
||||
width, height);
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
@@ -104,6 +104,7 @@ static void
|
||||
gsk_gl_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader_,
|
||||
GdkDmabufTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorState *color_state,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -125,6 +126,7 @@ gsk_gl_renderer_dmabuf_downloader_download (GdkDmabufDownloader *downloader_,
|
||||
|
||||
downloader = gdk_texture_downloader_new (native);
|
||||
gdk_texture_downloader_set_format (downloader, format);
|
||||
gdk_texture_downloader_set_color_state (downloader, color_state);
|
||||
gdk_texture_downloader_download_into (downloader, data, stride);
|
||||
gdk_texture_downloader_free (downloader);
|
||||
|
||||
|
@@ -57,6 +57,8 @@
|
||||
#define MAX_GRADIENT_STOPS 6
|
||||
#define SHADOW_EXTRA_SIZE 4
|
||||
|
||||
G_GNUC_BEGIN_IGNORE_DEPRECATIONS
|
||||
|
||||
/* Make sure gradient stops fits in packed array_count */
|
||||
G_STATIC_ASSERT ((MAX_GRADIENT_STOPS * 5) < (1 << GSK_GL_UNIFORM_ARRAY_BITS));
|
||||
|
||||
@@ -300,6 +302,7 @@ node_supports_2d_transform (const GskRenderNode *node)
|
||||
case GSK_FILL_NODE:
|
||||
case GSK_STROKE_NODE:
|
||||
case GSK_SUBSURFACE_NODE:
|
||||
case GSK_COLOR_STATE_NODE:
|
||||
return TRUE;
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
@@ -357,6 +360,7 @@ node_supports_transform (const GskRenderNode *node)
|
||||
case GSK_FILL_NODE:
|
||||
case GSK_STROKE_NODE:
|
||||
case GSK_SUBSURFACE_NODE:
|
||||
case GSK_COLOR_STATE_NODE:
|
||||
return TRUE;
|
||||
|
||||
case GSK_SHADOW_NODE:
|
||||
@@ -4228,6 +4232,10 @@ gsk_gl_render_job_visit_node (GskGLRenderJob *job,
|
||||
gsk_gl_render_job_visit_subsurface_node (job, node);
|
||||
break;
|
||||
|
||||
case GSK_COLOR_STATE_NODE:
|
||||
gsk_gl_render_job_visit_node (job, gsk_color_state_node_get_child (node));
|
||||
break;
|
||||
|
||||
case GSK_NOT_A_RENDER_NODE:
|
||||
default:
|
||||
g_assert_not_reached ();
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuprintprivate.h"
|
||||
#include "gskrectprivate.h"
|
||||
#include "gskgpucolorconvertopprivate.h"
|
||||
|
||||
#include "gpu/shaders/gskgpublendmodeinstance.h"
|
||||
|
||||
@@ -23,10 +24,13 @@ gsk_gpu_blend_mode_op_print_instance (GskGpuShaderOp *shader,
|
||||
{
|
||||
GskGpuBlendmodeInstance *instance = (GskGpuBlendmodeInstance *) instance_;
|
||||
|
||||
gsk_gpu_print_enum (string, GSK_TYPE_BLEND_MODE, shader->variation & 0xff);
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->bottom_id);
|
||||
gsk_gpu_print_enum (string, GSK_TYPE_BLEND_MODE, shader->variation);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->top_id);
|
||||
if ((shader->variation >> 8) != 0)
|
||||
gsk_gpu_print_color_conversion_triple (string, shader->variation >> 8);
|
||||
}
|
||||
|
||||
static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
|
||||
@@ -53,6 +57,7 @@ static const GskGpuShaderOpClass GSK_GPU_BLEND_MODE_OP_CLASS = {
|
||||
void
|
||||
gsk_gpu_blend_mode_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
GdkColorState *target_color_state,
|
||||
GskGpuDescriptors *desc,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
@@ -60,14 +65,19 @@ gsk_gpu_blend_mode_op (GskGpuFrame *frame,
|
||||
GskBlendMode blend_mode,
|
||||
guint32 bottom_descriptor,
|
||||
const graphene_rect_t *bottom_rect,
|
||||
GdkColorState *bottom_color_state,
|
||||
guint32 top_descriptor,
|
||||
const graphene_rect_t *top_rect)
|
||||
const graphene_rect_t *top_rect,
|
||||
GdkColorState *top_color_state)
|
||||
{
|
||||
GskGpuBlendmodeInstance *instance;
|
||||
|
||||
gsk_gpu_shader_op_alloc (frame,
|
||||
&GSK_GPU_BLEND_MODE_OP_CLASS,
|
||||
blend_mode,
|
||||
blend_mode |
|
||||
(gsk_gpu_color_conversion_triple (bottom_color_state,
|
||||
top_color_state,
|
||||
target_color_state) << 8),
|
||||
clip,
|
||||
desc,
|
||||
&instance);
|
||||
|
@@ -8,15 +8,18 @@ G_BEGIN_DECLS
|
||||
|
||||
void gsk_gpu_blend_mode_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
GdkColorState *target_color_state,
|
||||
GskGpuDescriptors *desc,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
float opacity,
|
||||
GskBlendMode blend_mode,
|
||||
guint32 start_descriptor,
|
||||
const graphene_rect_t *start_rect,
|
||||
guint32 end_descriptor,
|
||||
const graphene_rect_t *end_rect);
|
||||
guint32 bottom_descriptor,
|
||||
const graphene_rect_t *bottom_rect,
|
||||
GdkColorState *bottom_color_state,
|
||||
guint32 top_descriptor,
|
||||
const graphene_rect_t *top_rect,
|
||||
GdkColorState *top_color_state);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -62,7 +62,7 @@ gsk_gpu_blur_op_full (GskGpuFrame *frame,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const graphene_vec2_t *blur_direction,
|
||||
const GdkRGBA *blur_color)
|
||||
const GdkColor *blur_color)
|
||||
{
|
||||
GskGpuBlurInstance *instance;
|
||||
|
||||
@@ -76,7 +76,7 @@ gsk_gpu_blur_op_full (GskGpuFrame *frame,
|
||||
gsk_gpu_rect_to_float (rect, offset, instance->rect);
|
||||
gsk_gpu_rect_to_float (tex_rect, offset, instance->tex_rect);
|
||||
graphene_vec2_to_float (blur_direction, instance->blur_direction);
|
||||
gsk_gpu_rgba_to_float (blur_color, instance->blur_color);
|
||||
gsk_gpu_color_to_float (blur_color, instance->blur_color);
|
||||
instance->tex_id = descriptor;
|
||||
}
|
||||
|
||||
@@ -90,6 +90,10 @@ gsk_gpu_blur_op (GskGpuFrame *frame,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const graphene_vec2_t *blur_direction)
|
||||
{
|
||||
GdkColor color;
|
||||
|
||||
gdk_color_init_from_rgba (&color, &GDK_RGBA_TRANSPARENT);
|
||||
|
||||
gsk_gpu_blur_op_full (frame,
|
||||
0,
|
||||
clip,
|
||||
@@ -99,7 +103,7 @@ gsk_gpu_blur_op (GskGpuFrame *frame,
|
||||
offset,
|
||||
tex_rect,
|
||||
blur_direction,
|
||||
&GDK_RGBA_TRANSPARENT);
|
||||
&color);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -111,7 +115,7 @@ gsk_gpu_blur_shadow_op (GskGpuFrame *frame,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const graphene_vec2_t *blur_direction,
|
||||
const GdkRGBA *shadow_color)
|
||||
const GdkColor *shadow_color)
|
||||
{
|
||||
gsk_gpu_blur_op_full (frame,
|
||||
VARIATION_COLORIZE,
|
||||
|
@@ -23,7 +23,7 @@ void gsk_gpu_blur_shadow_op (GskGpuF
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const graphene_vec2_t *blur_direction,
|
||||
const GdkRGBA *shadow_color);
|
||||
const GdkColor *shadow_color);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -20,8 +20,10 @@ static gboolean
|
||||
color_equal (const float *color1,
|
||||
const float *color2)
|
||||
{
|
||||
return gdk_rgba_equal (&(GdkRGBA) { color1[0], color1[1], color1[2], color1[3] },
|
||||
&(GdkRGBA) { color1[0], color1[1], color1[2], color1[3] });
|
||||
return color1[0] == color2[0] &&
|
||||
color1[1] == color2[1] &&
|
||||
color1[2] == color2[2] &&
|
||||
color1[3] == color2[3];
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -100,7 +102,7 @@ gsk_gpu_border_op (GskGpuFrame *frame,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_point_t *inside_offset,
|
||||
const float widths[4],
|
||||
const GdkRGBA colors[4])
|
||||
const GdkColor colors[4])
|
||||
{
|
||||
GskGpuBorderInstance *instance;
|
||||
guint i;
|
||||
@@ -117,7 +119,7 @@ gsk_gpu_border_op (GskGpuFrame *frame,
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
instance->border_widths[i] = widths[i];
|
||||
gsk_gpu_rgba_to_float (&colors[i], &instance->border_colors[4 * i]);
|
||||
gsk_gpu_color_to_float (&colors[i], &instance->border_colors[4 * i]);
|
||||
}
|
||||
instance->offset[0] = inside_offset->x;
|
||||
instance->offset[1] = inside_offset->y;
|
||||
|
@@ -13,7 +13,7 @@ void gsk_gpu_border_op (GskGpuF
|
||||
const graphene_point_t *offset,
|
||||
const graphene_point_t *inside_offset,
|
||||
const float widths[4],
|
||||
const GdkRGBA colors[4]);
|
||||
const GdkColor colors[4]);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -82,7 +82,7 @@ gsk_gpu_box_shadow_op (GskGpuFrame *frame,
|
||||
float spread,
|
||||
float blur_radius,
|
||||
const graphene_point_t *offset,
|
||||
const GdkRGBA *color)
|
||||
const GdkColor *color)
|
||||
{
|
||||
GskGpuBoxshadowInstance *instance;
|
||||
|
||||
@@ -98,7 +98,7 @@ gsk_gpu_box_shadow_op (GskGpuFrame *frame,
|
||||
|
||||
gsk_gpu_rect_to_float (bounds, offset, instance->bounds);
|
||||
gsk_rounded_rect_to_float (outline, offset, instance->outline);
|
||||
gsk_gpu_rgba_to_float (color, instance->color);
|
||||
gsk_gpu_color_to_float (color, instance->color);
|
||||
instance->shadow_offset[0] = shadow_offset->x;
|
||||
instance->shadow_offset[1] = shadow_offset->y;
|
||||
instance->shadow_spread = spread;
|
||||
|
@@ -16,7 +16,7 @@ void gsk_gpu_box_shadow_op (
|
||||
float spread,
|
||||
float blur_radius,
|
||||
const graphene_point_t *offset,
|
||||
const GdkRGBA *color);
|
||||
const GdkColor *color);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -4,8 +4,6 @@
|
||||
|
||||
#include "gskgpuopprivate.h"
|
||||
#include "gskgpuprintprivate.h"
|
||||
/* for gsk_gpu_rgba_to_float() */
|
||||
#include "gskgpushaderopprivate.h"
|
||||
|
||||
typedef struct _GskGpuClearOp GskGpuClearOp;
|
||||
|
||||
@@ -14,7 +12,7 @@ struct _GskGpuClearOp
|
||||
GskGpuOp op;
|
||||
|
||||
cairo_rectangle_int_t rect;
|
||||
GdkRGBA color;
|
||||
float color[4];
|
||||
};
|
||||
|
||||
static void
|
||||
@@ -29,21 +27,19 @@ gsk_gpu_clear_op_print (GskGpuOp *op,
|
||||
guint indent)
|
||||
{
|
||||
GskGpuClearOp *self = (GskGpuClearOp *) op;
|
||||
float rgba[4];
|
||||
|
||||
gsk_gpu_print_op (string, indent, "clear");
|
||||
gsk_gpu_print_int_rect (string, &self->rect);
|
||||
gsk_gpu_rgba_to_float (&self->color, rgba);
|
||||
gsk_gpu_print_rgba (string, rgba);
|
||||
gsk_gpu_print_rgba (string, self->color);
|
||||
gsk_gpu_print_newline (string);
|
||||
}
|
||||
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
static void
|
||||
gsk_gpu_init_clear_value (VkClearValue *value,
|
||||
const GdkRGBA *rgba)
|
||||
gsk_gpu_init_clear_value (VkClearValue *value,
|
||||
const float color[4])
|
||||
{
|
||||
gsk_gpu_rgba_to_float (rgba, value->color.float32);
|
||||
memcpy (value->color.float32, color, sizeof (float) * 4);
|
||||
}
|
||||
|
||||
static GskGpuOp *
|
||||
@@ -54,7 +50,7 @@ gsk_gpu_clear_op_vk_command (GskGpuOp *op,
|
||||
GskGpuClearOp *self = (GskGpuClearOp *) op;
|
||||
VkClearValue clear_value;
|
||||
|
||||
gsk_gpu_init_clear_value (&clear_value, &self->color);
|
||||
gsk_gpu_init_clear_value (&clear_value, self->color);
|
||||
|
||||
vkCmdClearAttachments (state->vk_command_buffer,
|
||||
1,
|
||||
@@ -92,7 +88,7 @@ gsk_gpu_clear_op_gl_command (GskGpuOp *op,
|
||||
else
|
||||
glScissor (self->rect.x, self->rect.y, self->rect.width, self->rect.height);
|
||||
|
||||
glClearColor (self->color.red, self->color.green, self->color.blue, self->color.alpha);
|
||||
glClearColor (self->color[0], self->color[1], self->color[2], self->color[3]);
|
||||
glClear (GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glScissor (scissor[0], scissor[1], scissor[2], scissor[3]);
|
||||
@@ -114,12 +110,12 @@ static const GskGpuOpClass GSK_GPU_CLEAR_OP_CLASS = {
|
||||
void
|
||||
gsk_gpu_clear_op (GskGpuFrame *frame,
|
||||
const cairo_rectangle_int_t *rect,
|
||||
const GdkRGBA *color)
|
||||
const GdkColor *color)
|
||||
{
|
||||
GskGpuClearOp *self;
|
||||
|
||||
self = (GskGpuClearOp *) gsk_gpu_op_alloc (frame, &GSK_GPU_CLEAR_OP_CLASS);
|
||||
|
||||
self->rect = *rect;
|
||||
self->color = *color;
|
||||
memcpy (self->color, color->values, sizeof (float) * 4);
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ G_BEGIN_DECLS
|
||||
|
||||
void gsk_gpu_clear_op (GskGpuFrame *frame,
|
||||
const cairo_rectangle_int_t *rect,
|
||||
const GdkRGBA *color);
|
||||
const GdkColor *color);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
112
gsk/gpu/gskgpucolorconvertop.c
Normal file
@@ -0,0 +1,112 @@
|
||||
#include "config.h"
|
||||
|
||||
#include "gskgpucolorconvertopprivate.h"
|
||||
|
||||
#include "gskgpuframeprivate.h"
|
||||
#include "gskgpuprintprivate.h"
|
||||
#include "gskrectprivate.h"
|
||||
|
||||
#include "gpu/shaders/gskgpucolorconvertinstance.h"
|
||||
|
||||
typedef struct _GskGpuColorConvertOp GskGpuColorConvertOp;
|
||||
|
||||
struct _GskGpuColorConvertOp
|
||||
{
|
||||
GskGpuShaderOp op;
|
||||
};
|
||||
|
||||
static void
|
||||
gsk_gpu_color_convert_op_print_instance (GskGpuShaderOp *shader,
|
||||
gpointer instance_,
|
||||
GString *string)
|
||||
{
|
||||
GskGpuColorconvertInstance *instance = (GskGpuColorconvertInstance *) instance_;
|
||||
|
||||
gsk_gpu_print_rect (string, instance->rect);
|
||||
gsk_gpu_print_image_descriptor (string, shader->desc, instance->tex_id);
|
||||
gsk_gpu_print_color_conversion (string, shader->variation);
|
||||
}
|
||||
|
||||
static const GskGpuShaderOpClass GSK_GPU_COLOR_CONVERT_OP_CLASS = {
|
||||
{
|
||||
GSK_GPU_OP_SIZE (GskGpuColorConvertOp),
|
||||
GSK_GPU_STAGE_SHADER,
|
||||
gsk_gpu_shader_op_finish,
|
||||
gsk_gpu_shader_op_print,
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
gsk_gpu_shader_op_vk_command,
|
||||
#endif
|
||||
gsk_gpu_shader_op_gl_command
|
||||
},
|
||||
"gskgpucolorconvert",
|
||||
sizeof (GskGpuColorconvertInstance),
|
||||
#ifdef GDK_RENDERING_VULKAN
|
||||
&gsk_gpu_colorconvert_info,
|
||||
#endif
|
||||
gsk_gpu_color_convert_op_print_instance,
|
||||
gsk_gpu_colorconvert_setup_attrib_locations,
|
||||
gsk_gpu_colorconvert_setup_vao
|
||||
};
|
||||
|
||||
void
|
||||
gsk_gpu_color_convert_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
GdkColorState *from,
|
||||
GdkColorState *to,
|
||||
GskGpuDescriptors *desc,
|
||||
guint32 descriptor,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *tex_rect)
|
||||
{
|
||||
GskGpuColorconvertInstance *instance;
|
||||
|
||||
gsk_gpu_shader_op_alloc (frame,
|
||||
&GSK_GPU_COLOR_CONVERT_OP_CLASS,
|
||||
gsk_gpu_color_conversion (from, to),
|
||||
clip,
|
||||
desc,
|
||||
&instance);
|
||||
|
||||
gsk_gpu_rect_to_float (rect, offset, instance->rect);
|
||||
gsk_gpu_rect_to_float (tex_rect, offset, instance->tex_rect);
|
||||
instance->tex_id = descriptor;
|
||||
}
|
||||
|
||||
guint
|
||||
gsk_gpu_color_conversion (GdkColorState *from,
|
||||
GdkColorState *to)
|
||||
{
|
||||
if (from == to)
|
||||
return 0;
|
||||
|
||||
if (!GDK_IS_NAMED_COLOR_STATE (from) || !GDK_IS_NAMED_COLOR_STATE (to))
|
||||
{
|
||||
g_warning ("FIXME: Implement support for ICC color transforms");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GDK_NAMED_COLOR_STATE_ID (from) |
|
||||
(GDK_NAMED_COLOR_STATE_ID (to) << 16);
|
||||
}
|
||||
|
||||
guint
|
||||
gsk_gpu_color_conversion_triple (GdkColorState *from1,
|
||||
GdkColorState *from2,
|
||||
GdkColorState *to)
|
||||
{
|
||||
if (from1 == to && from2 == to)
|
||||
return 0;
|
||||
|
||||
if (!GDK_IS_NAMED_COLOR_STATE (from1) ||
|
||||
!GDK_IS_NAMED_COLOR_STATE (from2) ||
|
||||
!GDK_IS_NAMED_COLOR_STATE (to))
|
||||
{
|
||||
g_warning ("FIXME: Implement support for ICC color transforms");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return GDK_NAMED_COLOR_STATE_ID (from1) |
|
||||
(GDK_NAMED_COLOR_STATE_ID (from2) << 5) |
|
||||
(GDK_NAMED_COLOR_STATE_ID (to) << 10);
|
||||
}
|
27
gsk/gpu/gskgpucolorconvertopprivate.h
Normal file
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "gskgpushaderopprivate.h"
|
||||
|
||||
#include <graphene.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
void gsk_gpu_color_convert_op (GskGpuFrame *frame,
|
||||
GskGpuShaderClip clip,
|
||||
GdkColorState *from,
|
||||
GdkColorState *to,
|
||||
GskGpuDescriptors *desc,
|
||||
guint32 descriptor,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *tex_rect);
|
||||
|
||||
/* For lack of a better place */
|
||||
guint gsk_gpu_color_conversion (GdkColorState *from,
|
||||
GdkColorState *to);
|
||||
guint gsk_gpu_color_conversion_triple (GdkColorState *from1,
|
||||
GdkColorState *from2,
|
||||
GdkColorState *to);
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -56,7 +56,7 @@ gsk_gpu_colorize_op (GskGpuFrame *frame,
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const GdkRGBA *color)
|
||||
const GdkColor *color)
|
||||
{
|
||||
GskGpuColorizeInstance *instance;
|
||||
|
||||
@@ -70,5 +70,5 @@ gsk_gpu_colorize_op (GskGpuFrame *frame,
|
||||
gsk_gpu_rect_to_float (rect, offset, instance->rect);
|
||||
gsk_gpu_rect_to_float (tex_rect, offset, instance->tex_rect);
|
||||
instance->tex_id = descriptor;
|
||||
gsk_gpu_rgba_to_float (color, instance->color);
|
||||
gsk_gpu_color_to_float (color, instance->color);
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@ void gsk_gpu_colorize_op (GskGpuF
|
||||
const graphene_rect_t *rect,
|
||||
const graphene_point_t *offset,
|
||||
const graphene_rect_t *tex_rect,
|
||||
const GdkRGBA *color);
|
||||
const GdkColor *color);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|