Compare commits
18 Commits
wip/smcv/t
...
wip/otte/c
Author | SHA1 | Date | |
---|---|---|---|
|
abbd7f0c92 | ||
|
c70a8def57 | ||
|
37edec1dc8 | ||
|
fdf9cfd5c8 | ||
|
5206d02a0d | ||
|
e20c403f9b | ||
|
6b00c98c81 | ||
|
1c8cf6ae72 | ||
|
755d5d5f14 | ||
|
ea73fc2b31 | ||
|
65f709f55e | ||
|
e590014aff | ||
|
995a74e188 | ||
|
0b06e32efa | ||
|
7054181863 | ||
|
d95353c1bc | ||
|
ab4837d311 | ||
|
b7630f26df |
BIN
demos/widget-factory/color-profile-check.jpeg
Normal file
BIN
demos/widget-factory/color-profile-check.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
BIN
demos/widget-factory/color-profile-check.png
Normal file
BIN
demos/widget-factory/color-profile-check.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
demos/widget-factory/color-profile-check.tiff
Normal file
BIN
demos/widget-factory/color-profile-check.tiff
Normal file
Binary file not shown.
BIN
demos/widget-factory/linear-gradient-color.png
Normal file
BIN
demos/widget-factory/linear-gradient-color.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 213 B |
BIN
demos/widget-factory/linear-gradient-monochrome.png
Normal file
BIN
demos/widget-factory/linear-gradient-monochrome.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 220 B |
BIN
demos/widget-factory/srgb-gradient-color.png
Normal file
BIN
demos/widget-factory/srgb-gradient-color.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 154 B |
BIN
demos/widget-factory/srgb-gradient-monochrome.png
Normal file
BIN
demos/widget-factory/srgb-gradient-monochrome.png
Normal file
Binary file not shown.
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);
|
||||
}
|
||||
|
@@ -118,5 +118,12 @@
|
||||
<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>
|
||||
<file>color-profile-check.png</file>
|
||||
<file>color-profile-check.jpeg</file>
|
||||
<file>color-profile-check.tiff</file>
|
||||
</gresource>
|
||||
</gresources>
|
||||
|
@@ -1342,13 +1342,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>
|
||||
@@ -1357,13 +1517,91 @@ Suspendisse feugiat quam quis dolor accumsan cursus.</property>
|
||||
<object class="GtkNotebookPage">
|
||||
<property name="position">1</property>
|
||||
<property name="child">
|
||||
<object class="GtkBox" id="box10">
|
||||
<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">image loading</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="GtkImage">
|
||||
<property name="paintable">resource:///org/gtk/WidgetFactory4/color-profile-check.png</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">PNG</property>
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">1</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="paintable">resource:///org/gtk/WidgetFactory4/color-profile-check.jpeg</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">JPEG</property>
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">2</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="paintable">resource:///org/gtk/WidgetFactory4/color-profile-check.tiff</property>
|
||||
<layout>
|
||||
<property name="column">0</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel">
|
||||
<property name="label">TIFF</property>
|
||||
<property name="hexpand">1</property>
|
||||
<layout>
|
||||
<property name="column">1</property>
|
||||
<property name="row">3</property>
|
||||
</layout>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</property>
|
||||
<property name="tab">
|
||||
<object class="GtkLabel" id="label9">
|
||||
<property name="label" translatable="1">page 2</property>
|
||||
<property name="label" translatable="1">Images</property>
|
||||
</object>
|
||||
</property>
|
||||
</object>
|
||||
|
@@ -31,6 +31,8 @@
|
||||
#include <gdk/gdkcairo.h>
|
||||
#include <gdk/gdkcairocontext.h>
|
||||
#include <gdk/gdkclipboard.h>
|
||||
#include <gdk/gdkcolor.h>
|
||||
#include <gdk/gdkcolorspace.h>
|
||||
#include <gdk/gdkconfig.h>
|
||||
#include <gdk/gdkcontentdeserializer.h>
|
||||
#include <gdk/gdkcontentformats.h>
|
||||
|
260
gdk/gdkcolor.c
Normal file
260
gdk/gdkcolor.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/* 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 "gdkcolor.h"
|
||||
|
||||
#include "gdkcolorspaceprivate.h"
|
||||
#include "gdkrgba.h"
|
||||
|
||||
/**
|
||||
* GdkColor:
|
||||
*
|
||||
* GdkColor is a high level description of a color for use in a color managed context.
|
||||
*
|
||||
* FIXME: Add stuff about colors in the real world and looking at `GdkColorSpace` for
|
||||
* how this is important.
|
||||
*
|
||||
* If you only want to use RGB colors, consider using `GdkRGBA` instead.
|
||||
*/
|
||||
|
||||
#define GDK_IS_COLOR(self) ((self) != NULL)
|
||||
|
||||
struct _GdkColor
|
||||
{
|
||||
GdkColorSpace *color_space;
|
||||
float components[]; /* alpha is last component, so that RGBA is in exactly that order */
|
||||
};
|
||||
|
||||
G_DEFINE_BOXED_TYPE (GdkColor, gdk_color,
|
||||
gdk_color_copy, gdk_color_free)
|
||||
|
||||
static GdkColor *
|
||||
gdk_color_alloc (GdkColorSpace *space)
|
||||
{
|
||||
gsize n_components = gdk_color_space_get_n_components (space);
|
||||
GdkColor *self;
|
||||
|
||||
self = g_malloc (sizeof (GdkColor) + n_components * sizeof (float));
|
||||
|
||||
self->color_space = g_object_ref (space);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_new:
|
||||
* @space: the color space of the color
|
||||
* @alpha: the alpha value for this color
|
||||
* @components: (array length=n_components) (nullable): an array of
|
||||
* component values for this color
|
||||
* @n_components: number of components
|
||||
*
|
||||
* Creates a new GdkColor representing the color for the given component
|
||||
* values in the given color space.
|
||||
*
|
||||
* The alpha value is independent of the component values (also known as
|
||||
* "unassociated" or "component values are not premultiplied").
|
||||
*
|
||||
* If the number of components passed is larger than the color space's
|
||||
* components, extra values will be discarded. If it is smaller, the
|
||||
* remaining components will be initialized as 0.
|
||||
*
|
||||
* Returns: a new GdkColor.
|
||||
**/
|
||||
GdkColor *
|
||||
gdk_color_new (GdkColorSpace *space,
|
||||
float alpha,
|
||||
float *components,
|
||||
gsize n_components)
|
||||
{
|
||||
gsize n_color_components;
|
||||
GdkColor *self;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_COLOR_SPACE (space), NULL);
|
||||
g_return_val_if_fail (components != NULL || n_components == 0, NULL);
|
||||
|
||||
self = gdk_color_alloc (space);
|
||||
n_color_components = gdk_color_space_get_n_components (space);
|
||||
if (n_components)
|
||||
memcpy (self->components, components, MIN (n_components, n_color_components));
|
||||
if (n_components < n_color_components)
|
||||
memset (&self->components[n_components], 0, sizeof (float) * (n_color_components - n_components));
|
||||
self->components[n_color_components] = alpha;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
G_STATIC_ASSERT (sizeof (GdkRGBA) == 4 * sizeof (float));
|
||||
|
||||
/**
|
||||
* gdk_color_new_from_rgba:
|
||||
* @rgba: a GdkRGBA
|
||||
*
|
||||
* Creates a new GdkColor from the given GdkRGBA.
|
||||
*
|
||||
* Returns: a new GdkColor
|
||||
**/
|
||||
GdkColor *
|
||||
gdk_color_new_from_rgba (const GdkRGBA *rgba)
|
||||
{
|
||||
GdkColor *self;
|
||||
|
||||
g_return_val_if_fail (rgba != NULL, NULL);
|
||||
|
||||
self = gdk_color_alloc (gdk_color_space_get_srgb ());
|
||||
memcpy (self->components, rgba, sizeof (GdkRGBA));
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_copy:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Copies the color.
|
||||
*
|
||||
* Returns: a copy of the color.
|
||||
**/
|
||||
GdkColor *
|
||||
gdk_color_copy (const GdkColor *self)
|
||||
{
|
||||
GdkColor *copy;
|
||||
|
||||
copy = gdk_color_alloc (self->color_space);
|
||||
memcpy (copy->components,
|
||||
self->components,
|
||||
sizeof (float) * (gdk_color_space_get_n_components (self->color_space) + 1));
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_free:
|
||||
* @self: a #GdkColor
|
||||
*
|
||||
* Frees a `GdkColor`.
|
||||
**/
|
||||
void
|
||||
gdk_color_free (GdkColor *self)
|
||||
{
|
||||
g_object_unref (self->color_space);
|
||||
g_free (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_get_color_space:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Returns the color space that this color is defined in.
|
||||
*
|
||||
* Returns: the color space this color is defined in
|
||||
**/
|
||||
GdkColorSpace *
|
||||
gdk_color_get_color_space (const GdkColor *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_COLOR (self), gdk_color_space_get_srgb ());
|
||||
|
||||
return self->color_space;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_get_alpha:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Gets the alpha value of this color. Alpha values range from 0.0
|
||||
* (fully translucent) to 1.0 (fully opaque).
|
||||
*
|
||||
* Returns: The alpha value
|
||||
**/
|
||||
float
|
||||
gdk_color_get_alpha (const GdkColor *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_COLOR (self), 1.f);
|
||||
|
||||
return self->components[gdk_color_space_get_n_components (self->color_space)];
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_get_components:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Returns the array of component values for this color.
|
||||
*
|
||||
* For an RGB color, this will be an array of 3 values with intensities of
|
||||
* the red, green and blue components, respectively, in a range from 0 to 1.
|
||||
*
|
||||
* Other color spaces that are not RGB colors can have a different amount of
|
||||
* components with different meanings and different ranges.
|
||||
*
|
||||
* Returns: the component values
|
||||
**/
|
||||
const float *
|
||||
gdk_color_get_components (const GdkColor *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_COLOR (self), NULL);
|
||||
|
||||
return self->components;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_get_n_components:
|
||||
* @self: a `GdkColor`
|
||||
*
|
||||
* Gets the number of components of this color. This will be the number of
|
||||
* components returned by gdk_color_get_components().
|
||||
*
|
||||
* Returns: the number of components
|
||||
**/
|
||||
gsize
|
||||
gdk_color_get_n_components (const GdkColor *self)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_COLOR (self), 3);
|
||||
|
||||
return gdk_color_space_get_n_components (self->color_space);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_convert:
|
||||
* @self: a `GdkColor`
|
||||
* @space: the color space to convert to
|
||||
*
|
||||
* Converts a color into a different colorspace, potentially
|
||||
* tone-mapping it if it is out of gamut.
|
||||
*
|
||||
* Returns: a new color in the new colorspace.
|
||||
**/
|
||||
GdkColor *
|
||||
gdk_color_convert (const GdkColor *self,
|
||||
GdkColorSpace *space)
|
||||
{
|
||||
GdkColor *result;
|
||||
gsize n_components;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_COLOR (self), NULL);
|
||||
g_return_val_if_fail (GDK_IS_COLOR_SPACE (space), NULL);
|
||||
|
||||
result = gdk_color_alloc (space);
|
||||
n_components = gdk_color_space_get_n_components (self->color_space);
|
||||
result->components[n_components] = self->components[n_components];
|
||||
GDK_COLOR_SPACE_GET_CLASS (space)->convert_color (space, result->components, self);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
70
gdk/gdkcolor.h
Normal file
70
gdk/gdkcolor.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* gdkcolor.h
|
||||
*
|
||||
* Copyright 2021 (c) 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_COLOR_H__
|
||||
#define __GDK_COLOR_H__
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdkversionmacros.h>
|
||||
#include <gdk/gdktypes.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_COLOR (gdk_color_get_type ())
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GType gdk_color_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColor * gdk_color_new (GdkColorSpace *space,
|
||||
float alpha,
|
||||
float *components,
|
||||
gsize n_components);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColor * gdk_color_new_from_rgba (const GdkRGBA *rgba);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColor * gdk_color_copy (const GdkColor *self);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
void gdk_color_free (GdkColor *self);
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColorSpace * gdk_color_get_color_space (const GdkColor *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
float gdk_color_get_alpha (const GdkColor *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
const float * gdk_color_get_components (const GdkColor *self) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
gsize gdk_color_get_n_components (const GdkColor *self) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColor * gdk_color_convert (const GdkColor *self,
|
||||
GdkColorSpace *space);
|
||||
/*
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColor * gdk_color_mix (const GdkColor *self,
|
||||
const GdkColor *other,
|
||||
double progress,
|
||||
GdkColorSpace *space);
|
||||
*/
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_COLOR_H__ */
|
15
gdk/gdkcolorprofileprivate.h
Normal file
15
gdk/gdkcolorprofileprivate.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef __GDK_COLOR_PROFILE_PRIVATE_H__
|
||||
#define __GDK_COLOR_PROFILE_PRIVATE_H__
|
||||
|
||||
#include "gdkcolorprofile.h"
|
||||
|
||||
#include <lcms2.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
|
||||
cmsHPROFILE * gdk_color_profile_get_lcms_profile (GdkColorProfile *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_COLOR_PROFILE_PRIVATE_H__ */
|
312
gdk/gdkcolorspace.c
Normal file
312
gdk/gdkcolorspace.c
Normal file
@@ -0,0 +1,312 @@
|
||||
/* gdkcolorspace.c
|
||||
*
|
||||
* Copyright 2021 (c) 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* GdkColorSpace:
|
||||
*
|
||||
* `GdkColorSpace` is used to describe color spaces.
|
||||
*
|
||||
* Tell developers what a color space is instead of just linking to
|
||||
* https://en.wikipedia.org/wiki/Color_space
|
||||
*
|
||||
* `GdkColorSpace` objects are immutable and therefore threadsafe.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "gdkcolorspaceprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
#include "gdklcmscolorspaceprivate.h"
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
|
||||
//static GParamSpec *properties[N_PROPS];
|
||||
|
||||
G_DEFINE_TYPE (GdkColorSpace, gdk_color_space, G_TYPE_OBJECT)
|
||||
|
||||
static gboolean
|
||||
gdk_color_space_default_supports_format (GdkColorSpace *self,
|
||||
GdkMemoryFormat format)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_color_space_default_save_to_icc_profile (GdkColorSpace *self,
|
||||
GError **error)
|
||||
{
|
||||
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||
_("This color space does not support ICC profiles"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_color_space_default_convert_color (GdkColorSpace *self,
|
||||
float *components,
|
||||
const GdkColor *source)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_color_space_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
//GdkColorSpace *self = GDK_COLOR_SPACE (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_color_space_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
//GdkColorSpace *self = GDK_COLOR_SPACE (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_color_space_dispose (GObject *object)
|
||||
{
|
||||
//GdkColorSpace *self = GDK_COLOR_SPACE (object);
|
||||
|
||||
G_OBJECT_CLASS (gdk_color_space_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_color_space_class_init (GdkColorSpaceClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
klass->supports_format = gdk_color_space_default_supports_format;
|
||||
klass->save_to_icc_profile = gdk_color_space_default_save_to_icc_profile;
|
||||
klass->convert_color = gdk_color_space_default_convert_color;
|
||||
|
||||
gobject_class->set_property = gdk_color_space_set_property;
|
||||
gobject_class->get_property = gdk_color_space_get_property;
|
||||
gobject_class->dispose = gdk_color_space_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_color_space_init (GdkColorSpace *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_space_get_srgb:
|
||||
*
|
||||
* Returns the color profile representing the sRGB color space.
|
||||
*
|
||||
* If you don't know anything about color profiles but need one for
|
||||
* use with some function, this one is most likely the right one.
|
||||
*
|
||||
* Returns: (transfer none): the color profile for the sRGB
|
||||
* color space.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GdkColorSpace *
|
||||
gdk_color_space_get_srgb (void)
|
||||
{
|
||||
static GdkColorSpace *srgb_profile;
|
||||
|
||||
if (g_once_init_enter (&srgb_profile))
|
||||
{
|
||||
GdkColorSpace *new_profile;
|
||||
|
||||
new_profile = gdk_lcms_color_space_new_from_lcms_profile (cmsCreate_sRGBProfile ());
|
||||
|
||||
g_once_init_leave (&srgb_profile, new_profile);
|
||||
}
|
||||
|
||||
return srgb_profile;
|
||||
}
|
||||
|
||||
GdkColorSpace *
|
||||
gdk_color_space_get_named (GdkNamedColorSpace name)
|
||||
{
|
||||
static GdkColorSpace *space_array[GDK_NAMED_COLOR_SPACE_N_SPACES];
|
||||
static GdkColorSpace **color_spaces;
|
||||
|
||||
g_return_val_if_fail (name < GDK_NAMED_COLOR_SPACE_N_SPACES, gdk_color_space_get_srgb ());
|
||||
|
||||
if (g_once_init_enter (&color_spaces))
|
||||
{
|
||||
static const cmsCIExyY D65 = { 0.3127, 0.3290, 1.0 };
|
||||
static const cmsFloat64Number srgb_tonecurve[5] = { 2.4, 1. / 1.055, 0.055 / 1.055, 1. / 12.92, 0.04045 };
|
||||
static const cmsFloat64Number rec709_tonecurve[5] = { 1.0 / 0.45, 1.0 / 1.099, 0.099 / 1.099, 1.0 / 4.5, 0.081 };
|
||||
cmsToneCurve *curve;
|
||||
cmsHPROFILE lcms_profile;
|
||||
|
||||
space_array[GDK_NAMED_COLOR_SPACE_SRGB] = g_object_ref (gdk_color_space_get_srgb ());
|
||||
|
||||
curve = cmsBuildGamma (NULL, 1.0);
|
||||
lcms_profile = cmsCreateRGBProfile (&D65,
|
||||
&(cmsCIExyYTRIPLE) {
|
||||
{ 0.640, 0.330, 1.0 },
|
||||
{ 0.300, 0.600, 1.0 },
|
||||
{ 0.150, 0.060, 1.0 }
|
||||
},
|
||||
(cmsToneCurve*[3]) { curve, curve, curve });
|
||||
cmsFreeToneCurve (curve);
|
||||
space_array[GDK_NAMED_COLOR_SPACE_SRGB_LINEAR] = gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
|
||||
|
||||
space_array[GDK_NAMED_COLOR_SPACE_XYZ_D50] = gdk_lcms_color_space_new_from_lcms_profile (cmsCreateXYZProfile ());
|
||||
/* XXX: This needs a D65 whitepoint here */
|
||||
space_array[GDK_NAMED_COLOR_SPACE_XYZ_D65] = gdk_lcms_color_space_new_from_lcms_profile (cmsCreateXYZProfile ());
|
||||
|
||||
curve = cmsBuildParametricToneCurve (NULL, 4, srgb_tonecurve);
|
||||
lcms_profile = cmsCreateRGBProfile (&D65,
|
||||
&(cmsCIExyYTRIPLE) {
|
||||
{ 0.680, 0.320, 1.0 },
|
||||
{ 0.265, 0.690, 1.0 },
|
||||
{ 0.150, 0.060, 1.0 }
|
||||
},
|
||||
(cmsToneCurve*[3]) { curve, curve, curve });
|
||||
cmsFreeToneCurve (curve);
|
||||
space_array[GDK_NAMED_COLOR_SPACE_DISPLAY_P3] = gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
|
||||
|
||||
curve = cmsBuildGamma(NULL, 2.19921875);
|
||||
lcms_profile = cmsCreateRGBProfile (&D65,
|
||||
&(cmsCIExyYTRIPLE) {
|
||||
{ 0.640, 0.330, 1.0 },
|
||||
{ 0.210, 0.710, 1.0 },
|
||||
{ 0.150, 0.060, 1.0 }
|
||||
},
|
||||
(cmsToneCurve*[3]) { curve, curve, curve });
|
||||
cmsFreeToneCurve (curve);
|
||||
space_array[GDK_NAMED_COLOR_SPACE_A98_RGB] = gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
|
||||
|
||||
curve = cmsBuildParametricToneCurve (NULL, 4, rec709_tonecurve);
|
||||
lcms_profile = cmsCreateRGBProfile (cmsD50_xyY (),
|
||||
&(cmsCIExyYTRIPLE) {
|
||||
{ 0.734699, 0.265301, 1.0 },
|
||||
{ 0.159597, 0.840403, 1.0 },
|
||||
{ 0.036598, 0.000105, 1.0 }
|
||||
},
|
||||
(cmsToneCurve*[3]) { curve, curve, curve });
|
||||
cmsFreeToneCurve (curve);
|
||||
space_array[GDK_NAMED_COLOR_SPACE_PROPHOTO_RGB] = gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
|
||||
|
||||
curve = cmsBuildParametricToneCurve (NULL, 4, rec709_tonecurve);
|
||||
lcms_profile = cmsCreateRGBProfile (&D65,
|
||||
&(cmsCIExyYTRIPLE) {
|
||||
{ 0.708, 0.292, 1.0 },
|
||||
{ 0.170, 0.797, 1.0 },
|
||||
{ 0.131, 0.046, 1.0 }
|
||||
},
|
||||
(cmsToneCurve*[3]) { curve, curve, curve });
|
||||
cmsFreeToneCurve (curve);
|
||||
space_array[GDK_NAMED_COLOR_SPACE_REC2020] = gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
|
||||
|
||||
g_once_init_leave (&color_spaces, space_array);
|
||||
}
|
||||
|
||||
return color_spaces[name];
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_space_supports_format:
|
||||
* @self: a `GdkColorSpace`
|
||||
* @format: the format to check
|
||||
*
|
||||
* Checks if this color space can be used with textures in the given format.
|
||||
*
|
||||
* Returns: %TRUE if this colorspace supports the format
|
||||
*
|
||||
* Since: 4.6
|
||||
**/
|
||||
gboolean
|
||||
gdk_color_space_supports_format (GdkColorSpace *self,
|
||||
GdkMemoryFormat format)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_COLOR_SPACE (self), FALSE);
|
||||
g_return_val_if_fail (format < GDK_MEMORY_N_FORMATS, FALSE);
|
||||
|
||||
return GDK_COLOR_SPACE_GET_CLASS (self)->supports_format (self, format);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_space_save_to_icc_profile:
|
||||
* @self: a `GdkColorSpace`
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Saves the color space to an
|
||||
* [ICC profile](https://en.wikipedia.org/wiki/ICC_profile).
|
||||
*
|
||||
* Some color spaces cannot be represented as ICC profiles. In
|
||||
* that case, an error will be set and %NULL will be returned.
|
||||
*
|
||||
* Returns: A new `GBytes` containing the ICC profile
|
||||
*
|
||||
* Since: 4.6
|
||||
**/
|
||||
GBytes *
|
||||
gdk_color_space_save_to_icc_profile (GdkColorSpace *self,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_COLOR_SPACE (self), NULL);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
||||
|
||||
return GDK_COLOR_SPACE_GET_CLASS (self)->save_to_icc_profile (self, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_space_equal:
|
||||
* @profile1: (type GdkColorSpace): a `GdkColorSpace`
|
||||
* @profile2: (type GdkColorSpace): another `GdkColorSpace`
|
||||
*
|
||||
* Compares two `GdkColorSpace`s for equality.
|
||||
*
|
||||
* Note that this function is not guaranteed to be perfect and two equal
|
||||
* profiles may compare not equal. However, different profiles will
|
||||
* never compare equal.
|
||||
*
|
||||
* Returns: %TRUE if the two color profiles compare equal
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
gboolean
|
||||
gdk_color_space_equal (gconstpointer profile1,
|
||||
gconstpointer profile2)
|
||||
{
|
||||
return profile1 == profile2;
|
||||
}
|
||||
|
70
gdk/gdkcolorspace.h
Normal file
70
gdk/gdkcolorspace.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* gdkcolorspace.h
|
||||
*
|
||||
* Copyright 2021 (c) 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_COLOR_SPACE_H__
|
||||
#define __GDK_COLOR_SPACE_H__
|
||||
|
||||
#if !defined (__GDK_H_INSIDE__) && !defined (GTK_COMPILATION)
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdkenums.h>
|
||||
#include <gdk/gdktypes.h>
|
||||
#include <gdk/gdkversionmacros.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_COLOR_SPACE (gdk_color_space_get_type ())
|
||||
|
||||
#define GDK_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_COLOR_SPACE, GdkColorSpace))
|
||||
#define GDK_IS_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_COLOR_SPACE))
|
||||
#define GDK_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_COLOR_SPACE, GdkColorSpaceClass))
|
||||
#define GDK_IS_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_COLOR_SPACE))
|
||||
#define GDK_COLOR_SPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_COLOR_SPACE, GdkColorSpaceClass))
|
||||
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkColorSpace, g_object_unref)
|
||||
|
||||
typedef struct _GdkColorSpaceClass GdkColorSpaceClass;
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GType gdk_color_space_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColorSpace * gdk_color_space_get_srgb (void) G_GNUC_CONST;
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColorSpace * gdk_color_space_get_named (GdkNamedColorSpace name) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColorSpace * gdk_color_space_new_from_icc_profile (GBytes *icc_profile,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
gboolean gdk_color_space_supports_format (GdkColorSpace *self,
|
||||
GdkMemoryFormat format);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GBytes * gdk_color_space_save_to_icc_profile (GdkColorSpace *self,
|
||||
GError **error);
|
||||
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
gboolean gdk_color_space_equal (gconstpointer profile1,
|
||||
gconstpointer profile2);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_COLOR_SPACE_H__ */
|
37
gdk/gdkcolorspaceprivate.h
Normal file
37
gdk/gdkcolorspaceprivate.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef __GDK_COLOR_SPACE_PRIVATE_H__
|
||||
#define __GDK_COLOR_SPACE_PRIVATE_H__
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
struct _GdkColorSpace
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
gsize n_components;
|
||||
};
|
||||
|
||||
struct _GdkColorSpaceClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* supports_format) (GdkColorSpace *self,
|
||||
GdkMemoryFormat format);
|
||||
GBytes * (* save_to_icc_profile) (GdkColorSpace *self,
|
||||
GError **error);
|
||||
|
||||
void (* convert_color) (GdkColorSpace *self,
|
||||
float *components,
|
||||
const GdkColor *source);
|
||||
};
|
||||
|
||||
static inline gsize
|
||||
gdk_color_space_get_n_components (GdkColorSpace *self)
|
||||
{
|
||||
return self->n_components;
|
||||
}
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_COLOR_SPACE_PRIVATE_H__ */
|
@@ -331,6 +331,50 @@ typedef enum {
|
||||
GDK_MEMORY_N_FORMATS
|
||||
} GdkMemoryFormat;
|
||||
|
||||
/**
|
||||
* GdkNamedColorSpace:
|
||||
* @GDK_NAMED_COLOR_SPACE_SRGB: the sRGB color space,
|
||||
* see gdk_color_space_get_srgb() for details
|
||||
* @GDK_NAMED_COLOR_SPACE_SRGB_LINEAR: the same sRGB color space, but
|
||||
* with a linear light tone curve
|
||||
* @GDK_NAMED_COLOR_SPACE_XYZ_D50: the CIE XYZ color space, with the D50
|
||||
* white point
|
||||
* @GDK_NAMED_COLOR_SPACE_XYZ_D65: the CIE CYZ color space, with the D65
|
||||
* white point
|
||||
* @GDK_NAMED_COLOR_SPACE_DISPLAY_P3: the [DCI P3](https://en.wikipedia.org/wiki/DCI-P3)
|
||||
* color space with a D65 whitepoint as created by Apple
|
||||
* @GDK_NAMED_COLOR_SPACE_A98_RGB: the [Adobe 1998 RGB](https://en.wikipedia.org/wiki/Adobe_RGB_color_space)
|
||||
* color space
|
||||
* @GDK_NAMED_COLOR_SPACE_PROPHOTO_RGB: the [ProPhoto RGB](https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space)
|
||||
* color space
|
||||
* @GDK_NAMED_COLOR_SPACE_REC2020: the [Rec 2020](https://en.wikipedia.org/wiki/Rec._2020)
|
||||
* color space
|
||||
* @GDK_NAMED_COLOR_SPACE_N_SPACES: The number of named color spaces.
|
||||
* This value will change as more color spaces get added, so do not
|
||||
* rely on its concrete integer.
|
||||
*
|
||||
*
|
||||
* The list of predefined color spaces. GDK provides the common
|
||||
* color spaces used by CSS and other standards so applications can make
|
||||
* use of them.
|
||||
*
|
||||
* More color spaces may be added in the future.
|
||||
*
|
||||
* Since: 4.6
|
||||
**/
|
||||
typedef enum {
|
||||
GDK_NAMED_COLOR_SPACE_SRGB,
|
||||
GDK_NAMED_COLOR_SPACE_SRGB_LINEAR,
|
||||
GDK_NAMED_COLOR_SPACE_XYZ_D50,
|
||||
GDK_NAMED_COLOR_SPACE_XYZ_D65,
|
||||
GDK_NAMED_COLOR_SPACE_DISPLAY_P3,
|
||||
GDK_NAMED_COLOR_SPACE_A98_RGB,
|
||||
GDK_NAMED_COLOR_SPACE_PROPHOTO_RGB,
|
||||
GDK_NAMED_COLOR_SPACE_REC2020,
|
||||
|
||||
GDK_NAMED_COLOR_SPACE_N_SPACES
|
||||
} GdkNamedColorSpace;
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_ENUMS_H__ */
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "gdkgltextureprivate.h"
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
@@ -114,6 +115,7 @@ typedef struct _Download Download;
|
||||
struct _Download
|
||||
{
|
||||
GdkMemoryFormat format;
|
||||
GdkColorSpace *color_space;
|
||||
guchar *data;
|
||||
gsize stride;
|
||||
};
|
||||
@@ -156,6 +158,7 @@ gdk_gl_texture_do_download (gpointer texture_,
|
||||
expected_stride = texture->width * gdk_memory_format_bytes_per_pixel (download->format);
|
||||
|
||||
if (download->stride == expected_stride &&
|
||||
download->color_space == texture->color_space &&
|
||||
!gdk_gl_context_get_use_es (self->context) &&
|
||||
gdk_memory_format_gl_format (download->format, TRUE, &gl_internal_format, &gl_format, &gl_type))
|
||||
{
|
||||
@@ -180,6 +183,7 @@ gdk_gl_texture_do_download (gpointer texture_,
|
||||
actual_format = GDK_MEMORY_R8G8B8A8_PREMULTIPLIED; /* pray */
|
||||
|
||||
if (download->format == actual_format &&
|
||||
download->color_space == texture->color_space &&
|
||||
(download->stride == expected_stride))
|
||||
{
|
||||
glReadPixels (0, 0,
|
||||
@@ -202,9 +206,11 @@ gdk_gl_texture_do_download (gpointer texture_,
|
||||
gdk_memory_convert (download->data,
|
||||
download->stride,
|
||||
download->format,
|
||||
download->color_space,
|
||||
pixels,
|
||||
texture->width * actual_bpp,
|
||||
actual_format,
|
||||
texture->color_space,
|
||||
texture->width,
|
||||
texture->height);
|
||||
|
||||
@@ -218,6 +224,7 @@ gdk_gl_texture_do_download (gpointer texture_,
|
||||
static void
|
||||
gdk_gl_texture_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -226,11 +233,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_space, data, stride);
|
||||
return;
|
||||
}
|
||||
|
||||
download.format = format;
|
||||
download.color_space = color_space;
|
||||
download.data = data;
|
||||
download.stride = stride;
|
||||
|
||||
@@ -285,7 +293,8 @@ gdk_gl_texture_release (GdkGLTexture *self)
|
||||
|
||||
texture = GDK_TEXTURE (self);
|
||||
self->saved = GDK_TEXTURE (gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture)));
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_color_space (texture)));
|
||||
|
||||
if (self->destroy)
|
||||
{
|
||||
|
153
gdk/gdklcmscolorspace.c
Normal file
153
gdk/gdklcmscolorspace.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/* gdklcmscolorspace.c
|
||||
*
|
||||
* Copyright 2021 (c) 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 "gdklcmscolorspaceprivate.h"
|
||||
|
||||
#include "gdkintl.h"
|
||||
|
||||
struct _GdkLcmsColorSpace
|
||||
{
|
||||
GdkColorSpace parent_instance;
|
||||
|
||||
cmsHPROFILE lcms_profile;
|
||||
};
|
||||
|
||||
struct _GdkLcmsColorSpaceClass
|
||||
{
|
||||
GdkColorSpaceClass parent_class;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GdkLcmsColorSpace, gdk_lcms_color_space, GDK_TYPE_COLOR_SPACE)
|
||||
|
||||
static gboolean
|
||||
gdk_lcms_color_space_supports_format (GdkColorSpace *space,
|
||||
GdkMemoryFormat format)
|
||||
{
|
||||
GdkLcmsColorSpace *self = GDK_LCMS_COLOR_SPACE (space);
|
||||
|
||||
return cmsGetColorSpace (self->lcms_profile) == cmsSigRgbData;
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
gdk_lcms_color_space_save_to_icc_profile (GdkColorSpace *space,
|
||||
GError **error)
|
||||
{
|
||||
GdkLcmsColorSpace *self = GDK_LCMS_COLOR_SPACE (space);
|
||||
cmsUInt32Number size;
|
||||
guchar *data;
|
||||
|
||||
size = 0;
|
||||
if (!cmsSaveProfileToMem (self->lcms_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 (self->lcms_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);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_lcms_color_space_dispose (GObject *object)
|
||||
{
|
||||
GdkLcmsColorSpace *self = GDK_LCMS_COLOR_SPACE (object);
|
||||
|
||||
g_clear_pointer (&self->lcms_profile, cmsCloseProfile);
|
||||
|
||||
G_OBJECT_CLASS (gdk_lcms_color_space_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_lcms_color_space_class_init (GdkLcmsColorSpaceClass *klass)
|
||||
{
|
||||
GdkColorSpaceClass *color_space_class = GDK_COLOR_SPACE_CLASS (klass);
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
color_space_class->supports_format = gdk_lcms_color_space_supports_format;
|
||||
color_space_class->save_to_icc_profile = gdk_lcms_color_space_save_to_icc_profile;
|
||||
|
||||
gobject_class->dispose = gdk_lcms_color_space_dispose;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_lcms_color_space_init (GdkLcmsColorSpace *self)
|
||||
{
|
||||
}
|
||||
|
||||
GdkColorSpace *
|
||||
gdk_lcms_color_space_new_from_lcms_profile (cmsHPROFILE lcms_profile)
|
||||
{
|
||||
GdkLcmsColorSpace *result;
|
||||
|
||||
result = g_object_new (GDK_TYPE_LCMS_COLOR_SPACE, NULL);
|
||||
result->lcms_profile = lcms_profile;
|
||||
|
||||
return GDK_COLOR_SPACE (result);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_color_space_new_from_icc_profile:
|
||||
* @icc_profile: The ICC profiles given as a `GBytes`
|
||||
* @error: Return location for an error
|
||||
*
|
||||
* Creates a new color profile for the given ICC profile data.
|
||||
*
|
||||
* if the profile is not valid, %NULL is returned and an error
|
||||
* is raised.
|
||||
*
|
||||
* Returns: a new `GdkLcmsColorSpace` or %NULL on error
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GdkColorSpace *
|
||||
gdk_color_space_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_lcms_color_space_new_from_lcms_profile (lcms_profile);
|
||||
}
|
||||
|
||||
cmsHPROFILE
|
||||
gdk_lcms_color_space_get_lcms_profile (GdkLcmsColorSpace *self)
|
||||
{
|
||||
return self->lcms_profile;
|
||||
}
|
49
gdk/gdklcmscolorspaceprivate.h
Normal file
49
gdk/gdklcmscolorspaceprivate.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/* gdklcmscolorspace.h
|
||||
*
|
||||
* Copyright 2021 (c) 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __GDK_LCMS_COLOR_SPACE_PRIVATE_H__
|
||||
#define __GDK_LCMS_COLOR_SPACE_PRIVATE_H__
|
||||
|
||||
#include "gdkcolorspaceprivate.h"
|
||||
|
||||
#include <lcms2.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GDK_TYPE_LCMS_COLOR_SPACE (gdk_lcms_color_space_get_type ())
|
||||
|
||||
#define GDK_LCMS_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_LCMS_COLOR_SPACE, GdkLcmsColorSpace))
|
||||
#define GDK_IS_LCMS_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_LCMS_COLOR_SPACE))
|
||||
#define GDK_LCMS_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_LCMS_COLOR_SPACE, GdkLcmsColorSpaceClass))
|
||||
#define GDK_IS_LCMS_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_LCMS_COLOR_SPACE))
|
||||
#define GDK_LCMS_COLOR_SPACE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_LCMS_COLOR_SPACE, GdkLcmsColorSpaceClass))
|
||||
|
||||
typedef struct _GdkLcmsColorSpace GdkLcmsColorSpace;
|
||||
typedef struct _GdkLcmsColorSpaceClass GdkLcmsColorSpaceClass;
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkLcmsColorSpace, g_object_unref)
|
||||
|
||||
GType gdk_lcms_color_space_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GdkColorSpace * gdk_lcms_color_space_new_from_lcms_profile (cmsHPROFILE lcms_profile);
|
||||
|
||||
cmsHPROFILE gdk_lcms_color_space_get_lcms_profile (GdkLcmsColorSpace *self);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_LCMS_COLOR_SPACE_PRIVATE_H__ */
|
@@ -21,6 +21,9 @@
|
||||
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
|
||||
#include "gdkcolorspaceprivate.h"
|
||||
#include "gdklcmscolorspaceprivate.h"
|
||||
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
#include <epoxy/gl.h>
|
||||
@@ -465,14 +468,17 @@ void
|
||||
gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
GdkColorSpace *dest_space,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
GdkColorSpace *src_space,
|
||||
gsize width,
|
||||
gsize height)
|
||||
{
|
||||
const GdkMemoryFormatDescription *dest_desc = &memory_formats[dest_format];
|
||||
const GdkMemoryFormatDescription *src_desc = &memory_formats[src_format];
|
||||
cmsHTRANSFORM transform;
|
||||
float *tmp;
|
||||
gsize y;
|
||||
|
||||
@@ -481,17 +487,46 @@ gdk_memory_convert (guchar *dest_data,
|
||||
|
||||
tmp = g_new (float, width * 4);
|
||||
|
||||
if (gdk_color_space_equal (src_space, dest_space))
|
||||
{
|
||||
transform = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
transform = cmsCreateTransform (gdk_lcms_color_space_get_lcms_profile (GDK_LCMS_COLOR_SPACE (src_space)),
|
||||
TYPE_RGBA_FLT,
|
||||
gdk_lcms_color_space_get_lcms_profile (GDK_LCMS_COLOR_SPACE (dest_space)),
|
||||
TYPE_RGBA_FLT,
|
||||
INTENT_PERCEPTUAL,
|
||||
cmsFLAGS_COPY_ALPHA);
|
||||
}
|
||||
|
||||
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 (transform)
|
||||
{
|
||||
if (src_desc->alpha == GDK_MEMORY_ALPHA_PREMULTIPLIED)
|
||||
unpremultiply (tmp, width);
|
||||
cmsDoTransform (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;
|
||||
}
|
||||
|
||||
g_free (tmp);
|
||||
g_clear_pointer (&transform, cmsDeleteTransform);
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#define __GDK_MEMORY_CONVERT_PRIVATE_H__
|
||||
|
||||
#include "gdkenums.h"
|
||||
#include "gdktypes.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@@ -43,9 +44,11 @@ gboolean gdk_memory_format_gl_format (GdkMemoryFormat
|
||||
void gdk_memory_convert (guchar *dest_data,
|
||||
gsize dest_stride,
|
||||
GdkMemoryFormat dest_format,
|
||||
GdkColorSpace *dest_space,
|
||||
const guchar *src_data,
|
||||
gsize src_stride,
|
||||
GdkMemoryFormat src_format,
|
||||
GdkColorSpace *src_space,
|
||||
gsize width,
|
||||
gsize height);
|
||||
|
||||
|
@@ -21,6 +21,7 @@
|
||||
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkmemoryformatprivate.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,
|
||||
GdkColorSpace *color_space,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -65,9 +67,11 @@ gdk_memory_texture_download (GdkTexture *texture,
|
||||
|
||||
gdk_memory_convert (data, stride,
|
||||
format,
|
||||
color_space,
|
||||
(guchar *) g_bytes_get_data (self->bytes, NULL),
|
||||
self->stride,
|
||||
texture->format,
|
||||
gdk_texture_get_color_space (texture),
|
||||
gdk_texture_get_width (texture),
|
||||
gdk_texture_get_height (texture));
|
||||
}
|
||||
@@ -136,6 +140,9 @@ gdk_memory_sanitize (GBytes *bytes,
|
||||
* The `GBytes` must contain @stride x @height pixels
|
||||
* in the given format.
|
||||
*
|
||||
* This function calls [ctor@Gdk.MemoryTexture.new_with_color_profile]
|
||||
* with the sRGB profile.
|
||||
*
|
||||
* Returns: A newly-created `GdkTexture`
|
||||
*/
|
||||
GdkTexture *
|
||||
@@ -144,11 +151,51 @@ gdk_memory_texture_new (int width,
|
||||
GdkMemoryFormat format,
|
||||
GBytes *bytes,
|
||||
gsize stride)
|
||||
{
|
||||
g_return_val_if_fail (width > 0, NULL);
|
||||
g_return_val_if_fail (height > 0, NULL);
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
|
||||
return gdk_memory_texture_new_with_color_space (width, height,
|
||||
format,
|
||||
gdk_color_space_get_srgb (),
|
||||
bytes, stride);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_memory_texture_new_with_color_space:
|
||||
* @width: the width of the texture
|
||||
* @height: the height of the texture
|
||||
* @format: the format of the data
|
||||
* @color_space: the color space for the pixels. The color space
|
||||
* must be compatible with the format.
|
||||
* @bytes: the `GBytes` containing the pixel data
|
||||
* @stride: rowstride for the data
|
||||
*
|
||||
* Creates a new texture for a blob of image data.
|
||||
*
|
||||
* The `GBytes` must contain @stride x @height pixels
|
||||
* in the given format.
|
||||
*
|
||||
* Returns: A newly-created `GdkTexture`
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GdkTexture *
|
||||
gdk_memory_texture_new_with_color_space (int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space,
|
||||
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 (GDK_IS_COLOR_SPACE (color_space), NULL);
|
||||
g_return_val_if_fail (gdk_color_space_supports_format (color_space, format), NULL);
|
||||
g_return_val_if_fail (bytes != NULL, NULL);
|
||||
g_return_val_if_fail (stride >= width * gdk_memory_format_bytes_per_pixel (format), NULL);
|
||||
|
||||
@@ -157,6 +204,7 @@ gdk_memory_texture_new (int width,
|
||||
self = g_object_new (GDK_TYPE_MEMORY_TEXTURE,
|
||||
"width", width,
|
||||
"height", height,
|
||||
"color-space", color_space,
|
||||
NULL);
|
||||
|
||||
GDK_TEXTURE (self)->format = format;
|
||||
@@ -189,11 +237,12 @@ gdk_memory_texture_new_subtexture (GdkMemoryTexture *source,
|
||||
size = source->stride * (height - 1) + x * bpp;
|
||||
bytes = g_bytes_new_from_bytes (source->bytes, offset, size);
|
||||
|
||||
result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
texture->format,
|
||||
bytes,
|
||||
source->stride);
|
||||
result = gdk_memory_texture_new_with_color_space (texture->width,
|
||||
texture->height,
|
||||
texture->format,
|
||||
texture->color_space,
|
||||
bytes,
|
||||
source->stride);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return result;
|
||||
@@ -201,7 +250,8 @@ gdk_memory_texture_new_subtexture (GdkMemoryTexture *source,
|
||||
|
||||
GdkMemoryTexture *
|
||||
gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
GdkMemoryFormat format)
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space)
|
||||
{
|
||||
GdkTexture *result;
|
||||
GBytes *bytes;
|
||||
@@ -221,13 +271,14 @@ gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
stride = texture->width * gdk_memory_format_bytes_per_pixel (format);
|
||||
data = g_malloc_n (stride, texture->height);
|
||||
|
||||
gdk_texture_do_download (texture, format, data, stride);
|
||||
gdk_texture_do_download (texture, format, color_space, data, stride);
|
||||
bytes = g_bytes_new_take (data, stride);
|
||||
result = gdk_memory_texture_new (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
bytes,
|
||||
stride);
|
||||
result = gdk_memory_texture_new_with_color_space (texture->width,
|
||||
texture->height,
|
||||
format,
|
||||
color_space,
|
||||
bytes,
|
||||
stride);
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return GDK_MEMORY_TEXTURE (result);
|
||||
|
@@ -60,14 +60,21 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GdkMemoryTexture, g_object_unref)
|
||||
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GType gdk_memory_texture_get_type (void) G_GNUC_CONST;
|
||||
GType gdk_memory_texture_get_type (void) G_GNUC_CONST;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
GdkTexture * gdk_memory_texture_new (int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
GBytes *bytes,
|
||||
gsize stride);
|
||||
GdkTexture * gdk_memory_texture_new (int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
GBytes *bytes,
|
||||
gsize stride);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkTexture * gdk_memory_texture_new_with_color_space (int width,
|
||||
int height,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space,
|
||||
GBytes *bytes,
|
||||
gsize stride);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
@@ -30,7 +30,8 @@ G_BEGIN_DECLS
|
||||
#define GDK_MEMORY_GDK_PIXBUF_ALPHA GDK_MEMORY_R8G8B8A8
|
||||
|
||||
GdkMemoryTexture * gdk_memory_texture_from_texture (GdkTexture *texture,
|
||||
GdkMemoryFormat format);
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space);
|
||||
GdkTexture * gdk_memory_texture_new_subtexture (GdkMemoryTexture *texture,
|
||||
int x,
|
||||
int y,
|
||||
|
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "gdkpixbuf.h"
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdksurface.h"
|
||||
@@ -245,7 +246,8 @@ gdk_pixbuf_get_from_texture (GdkTexture *texture)
|
||||
|
||||
memtex = gdk_memory_texture_from_texture (texture,
|
||||
alpha ? GDK_MEMORY_GDK_PIXBUF_ALPHA
|
||||
: GDK_MEMORY_GDK_PIXBUF_OPAQUE);
|
||||
: GDK_MEMORY_GDK_PIXBUF_OPAQUE,
|
||||
gdk_color_space_get_srgb ());
|
||||
|
||||
return gdk_pixbuf_new_from_data (gdk_memory_texture_get_data (memtex),
|
||||
GDK_COLORSPACE_RGB,
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "gdksurface.h"
|
||||
|
||||
#include "gdk-private.h"
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkcontentprovider.h"
|
||||
#include "gdkdeviceprivate.h"
|
||||
#include "gdkdisplayprivate.h"
|
||||
@@ -74,6 +75,8 @@ struct _GdkSurfacePrivate
|
||||
gboolean egl_surface_high_depth;
|
||||
#endif
|
||||
|
||||
GdkColorSpace *color_space;
|
||||
|
||||
gpointer widget;
|
||||
};
|
||||
|
||||
@@ -88,13 +91,14 @@ enum {
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_COLOR_SPACE,
|
||||
PROP_CURSOR,
|
||||
PROP_DISPLAY,
|
||||
PROP_FRAME_CLOCK,
|
||||
PROP_MAPPED,
|
||||
PROP_WIDTH,
|
||||
PROP_HEIGHT,
|
||||
PROP_MAPPED,
|
||||
PROP_SCALE_FACTOR,
|
||||
PROP_WIDTH,
|
||||
LAST_PROP
|
||||
};
|
||||
|
||||
@@ -476,7 +480,7 @@ gdk_surface_event_marshallerv (GClosure *closure,
|
||||
static void
|
||||
gdk_surface_init (GdkSurface *surface)
|
||||
{
|
||||
/* 0-initialization is good for all other fields. */
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (surface);
|
||||
|
||||
surface->state = 0;
|
||||
surface->fullscreen_mode = GDK_FULLSCREEN_ON_CURRENT_MONITOR;
|
||||
@@ -485,8 +489,10 @@ gdk_surface_init (GdkSurface *surface)
|
||||
|
||||
surface->alpha = 255;
|
||||
|
||||
priv->color_space = g_object_ref (gdk_color_space_get_srgb ());
|
||||
|
||||
surface->device_cursor = g_hash_table_new_full (NULL, NULL,
|
||||
NULL, g_object_unref);
|
||||
NULL, g_object_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -500,6 +506,24 @@ gdk_surface_class_init (GdkSurfaceClass *klass)
|
||||
|
||||
klass->beep = gdk_surface_real_beep;
|
||||
|
||||
/**
|
||||
* GdkSurface:color-space: (attributes org.gtk.Property.get=gdk_surface_get_color_space)
|
||||
*
|
||||
* The color space for rendering to the surface
|
||||
*
|
||||
* This space is negotiated between GTK and the compositor.
|
||||
*
|
||||
* The color space 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 space that is going to be used.
|
||||
*/
|
||||
properties[PROP_COLOR_SPACE] =
|
||||
g_param_spec_object ("color-space",
|
||||
P_("Color space"),
|
||||
P_("The preferred color space of the surface"),
|
||||
GDK_TYPE_COLOR_SPACE,
|
||||
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)
|
||||
*
|
||||
@@ -713,6 +737,7 @@ static void
|
||||
gdk_surface_finalize (GObject *object)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (object);
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (surface);
|
||||
|
||||
g_clear_handle_id (&surface->request_motion_id, g_source_remove);
|
||||
|
||||
@@ -729,6 +754,7 @@ gdk_surface_finalize (GObject *object)
|
||||
g_clear_object (&surface->cursor);
|
||||
g_clear_pointer (&surface->device_cursor, g_hash_table_destroy);
|
||||
g_clear_pointer (&surface->devices_inside, g_list_free);
|
||||
g_clear_object (&priv->color_space);
|
||||
|
||||
g_clear_object (&surface->display);
|
||||
|
||||
@@ -783,6 +809,10 @@ gdk_surface_get_property (GObject *object,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_COLOR_SPACE:
|
||||
g_value_set_object (value, gdk_surface_get_color_space (surface));
|
||||
break;
|
||||
|
||||
case PROP_CURSOR:
|
||||
g_value_set_object (value, gdk_surface_get_cursor (surface));
|
||||
break;
|
||||
@@ -2049,6 +2079,40 @@ gdk_surface_get_height (GdkSurface *surface)
|
||||
return surface->height;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_surface_set_color_space (GdkSurface *self,
|
||||
GdkColorSpace *color_space)
|
||||
{
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
|
||||
|
||||
if (gdk_color_space_equal (priv->color_space, color_space))
|
||||
return;
|
||||
|
||||
g_set_object (&priv->color_space, color_space);
|
||||
|
||||
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_COLOR_SPACE]);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_surface_get_color_space: (attributes org.gtk.Method.get_property=color-space)
|
||||
* @self: a `GdkSurface`
|
||||
*
|
||||
* Returns the color space for rendering to the given @surface.
|
||||
*
|
||||
* Renderers will need to provide data in this color space.
|
||||
*
|
||||
* Returns: (transfer none): The color space of @surface
|
||||
*/
|
||||
GdkColorSpace *
|
||||
gdk_surface_get_color_space (GdkSurface *self)
|
||||
{
|
||||
GdkSurfacePrivate *priv = gdk_surface_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SURFACE (self), gdk_color_space_get_srgb ());
|
||||
|
||||
return priv->color_space;
|
||||
}
|
||||
|
||||
/*
|
||||
* gdk_surface_get_origin:
|
||||
* @surface: a `GdkSurface`
|
||||
|
@@ -86,17 +86,19 @@ GDK_AVAILABLE_IN_ALL
|
||||
GdkCursor *gdk_surface_get_device_cursor (GdkSurface *surface,
|
||||
GdkDevice *device);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gdk_surface_get_width (GdkSurface *surface);
|
||||
int gdk_surface_get_width (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gdk_surface_get_height (GdkSurface *surface);
|
||||
int gdk_surface_get_height (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_surface_translate_coordinates (GdkSurface *from,
|
||||
GdkSurface *to,
|
||||
double *x,
|
||||
double *y);
|
||||
int gdk_surface_get_scale_factor (GdkSurface *surface);
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColorSpace * gdk_surface_get_color_space (GdkSurface *self);
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_surface_translate_coordinates (GdkSurface *from,
|
||||
GdkSurface *to,
|
||||
double *x,
|
||||
double *y);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gdk_surface_get_scale_factor (GdkSurface *surface);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_surface_get_device_position (GdkSurface *surface,
|
||||
|
@@ -171,6 +171,8 @@ void gdk_surface_set_state (GdkSurface *surface,
|
||||
|
||||
void gdk_surface_set_is_mapped (GdkSurface *surface,
|
||||
gboolean is_mapped);
|
||||
void gdk_surface_set_color_space (GdkSurface *self,
|
||||
GdkColorSpace *color_space);
|
||||
|
||||
GdkMonitor * gdk_surface_get_layout_monitor (GdkSurface *surface,
|
||||
GdkPopupLayout *layout,
|
||||
|
142
gdk/gdktexture.c
142
gdk/gdktexture.c
@@ -31,6 +31,11 @@
|
||||
* instance; you can only make a copy of it, via [method@Gdk.Texture.download]
|
||||
* or [method@Gdk.Texture.download_float].
|
||||
*
|
||||
* A `GdkColorSpace` is part of every GdkTexture that describes the internal
|
||||
* representation of the pixel data. This is most relevant when creating
|
||||
* textures yourself as you can choose the color space you provide your
|
||||
* pixel data in.
|
||||
*
|
||||
* `GdkTexture` is an immutable object: That means you cannot change
|
||||
* anything about it other than increasing the reference count via
|
||||
* g_object_ref().
|
||||
@@ -40,6 +45,7 @@
|
||||
|
||||
#include "gdktextureprivate.h"
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkpaintable.h"
|
||||
@@ -60,8 +66,9 @@ gtk_snapshot_append_texture (GdkSnapshot *snapshot,
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_WIDTH,
|
||||
PROP_COLOR_SPACE,
|
||||
PROP_HEIGHT,
|
||||
PROP_WIDTH,
|
||||
|
||||
N_PROPS
|
||||
};
|
||||
@@ -224,6 +231,7 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GdkTexture, gdk_texture, G_TYPE_OBJECT,
|
||||
static void
|
||||
gdk_texture_default_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
@@ -240,14 +248,20 @@ gdk_texture_set_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_WIDTH:
|
||||
self->width = g_value_get_int (value);
|
||||
case PROP_COLOR_SPACE:
|
||||
self->color_space = g_value_dup_object (value);
|
||||
if (self->color_space == NULL)
|
||||
self->color_space = g_object_ref (gdk_color_space_get_srgb ());
|
||||
break;
|
||||
|
||||
case PROP_HEIGHT:
|
||||
self->height = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
case PROP_WIDTH:
|
||||
self->width = g_value_get_int (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@@ -264,14 +278,18 @@ gdk_texture_get_property (GObject *gobject,
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_WIDTH:
|
||||
g_value_set_int (value, self->width);
|
||||
case PROP_COLOR_SPACE:
|
||||
g_value_set_object (value, self->color_space);
|
||||
break;
|
||||
|
||||
case PROP_HEIGHT:
|
||||
g_value_set_int (value, self->height);
|
||||
break;
|
||||
|
||||
case PROP_WIDTH:
|
||||
g_value_set_int (value, self->width);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
@@ -284,6 +302,7 @@ gdk_texture_dispose (GObject *object)
|
||||
GdkTexture *self = GDK_TEXTURE (object);
|
||||
|
||||
gdk_texture_clear_render_data (self);
|
||||
g_clear_object (&self->color_space);
|
||||
|
||||
G_OBJECT_CLASS (gdk_texture_parent_class)->dispose (object);
|
||||
}
|
||||
@@ -300,14 +319,31 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
gobject_class->dispose = gdk_texture_dispose;
|
||||
|
||||
/**
|
||||
* GdkTexture:width: (attributes org.gtk.Property.get=gdk_texture_get_width)
|
||||
* GdkTexture:color-space: (attributes org.gtk.Property.get=gdk_texture_get_color_space)
|
||||
*
|
||||
* The width of the texture, in pixels.
|
||||
* The color space associated with texture.
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
properties[PROP_WIDTH] =
|
||||
g_param_spec_int ("width",
|
||||
"Width",
|
||||
"The width of the texture",
|
||||
properties[PROP_COLOR_SPACE] =
|
||||
g_param_spec_object ("color-space",
|
||||
P_("Color Space"),
|
||||
P_("The associated color space"),
|
||||
GDK_TYPE_COLOR_SPACE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS |
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkTexture:height: (attributes org.gtk.Property.get=gdk_texture_get_height)
|
||||
*
|
||||
* The height of the texture, in pixels.
|
||||
*/
|
||||
properties[PROP_HEIGHT] =
|
||||
g_param_spec_int ("height",
|
||||
P_("Height"),
|
||||
P_("The height of the texture"),
|
||||
1,
|
||||
G_MAXINT,
|
||||
1,
|
||||
@@ -317,14 +353,14 @@ gdk_texture_class_init (GdkTextureClass *klass)
|
||||
G_PARAM_EXPLICIT_NOTIFY);
|
||||
|
||||
/**
|
||||
* GdkTexture:height: (attributes org.gtk.Property.get=gdk_texture_get_height)
|
||||
* GdkTexture:width: (attributes org.gtk.Property.get=gdk_texture_get_width)
|
||||
*
|
||||
* The height of the texture, in pixels.
|
||||
* The width of the texture, in pixels.
|
||||
*/
|
||||
properties[PROP_HEIGHT] =
|
||||
g_param_spec_int ("height",
|
||||
"Height",
|
||||
"The height of the texture",
|
||||
properties[PROP_WIDTH] =
|
||||
g_param_spec_int ("width",
|
||||
P_("Width"),
|
||||
P_("The width of the texture"),
|
||||
1,
|
||||
G_MAXINT,
|
||||
1,
|
||||
@@ -378,6 +414,30 @@ gdk_texture_new_for_surface (cairo_surface_t *surface)
|
||||
return texture;
|
||||
}
|
||||
|
||||
static GdkColorSpace*
|
||||
gdk_color_space_get_from_pixbuf (GdkPixbuf *pixbuf)
|
||||
{
|
||||
const char *icc_profile_base64;
|
||||
GdkColorSpace *space = 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);
|
||||
space = gdk_color_space_new_from_icc_profile (bytes, NULL);
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
if (!space)
|
||||
space = g_object_ref (gdk_color_space_get_srgb ());
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_new_for_pixbuf:
|
||||
* @pixbuf: a `GdkPixbuf`
|
||||
@@ -395,23 +455,28 @@ gdk_texture_new_for_pixbuf (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
GBytes *bytes;
|
||||
GdkColorSpace *space;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
|
||||
|
||||
space = gdk_color_space_get_from_pixbuf (pixbuf);
|
||||
bytes = g_bytes_new_with_free_func (gdk_pixbuf_get_pixels (pixbuf),
|
||||
gdk_pixbuf_get_height (pixbuf)
|
||||
* 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_space (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,
|
||||
space,
|
||||
bytes,
|
||||
gdk_pixbuf_get_rowstride (pixbuf));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
g_object_unref (space);
|
||||
|
||||
return texture;
|
||||
}
|
||||
@@ -670,13 +735,32 @@ gdk_texture_get_height (GdkTexture *texture)
|
||||
return texture->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_texture_get_color_space: (attributes org.gtk.Method.get_property=color-space)
|
||||
* @texture: a `GdkTexture`
|
||||
*
|
||||
* Returns the color space associated with @texture.
|
||||
*
|
||||
* Returns: (transfer none): the color space of the `GdkTexture`
|
||||
*
|
||||
* Since: 4.6
|
||||
*/
|
||||
GdkColorSpace *
|
||||
gdk_texture_get_color_space (GdkTexture *texture)
|
||||
{
|
||||
g_return_val_if_fail (GDK_IS_TEXTURE (texture), 0);
|
||||
|
||||
return texture->color_space;
|
||||
}
|
||||
|
||||
void
|
||||
gdk_texture_do_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space,
|
||||
guchar *data,
|
||||
gsize stride)
|
||||
{
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, data,stride);
|
||||
GDK_TEXTURE_GET_CLASS (texture)->download (texture, format, color_space, data, stride);
|
||||
}
|
||||
|
||||
cairo_surface_t *
|
||||
@@ -717,6 +801,9 @@ gdk_texture_download_surface (GdkTexture *texture)
|
||||
* %CAIRO_FORMAT_ARGB32, so every downloaded pixel requires
|
||||
* 4 bytes of memory.
|
||||
*
|
||||
* The downloaded data will be in the sRGB color space, no matter the
|
||||
* color space of the texture.
|
||||
*
|
||||
* Downloading a texture into a Cairo image surface:
|
||||
* ```c
|
||||
* surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
||||
@@ -739,6 +826,7 @@ gdk_texture_download (GdkTexture *texture,
|
||||
|
||||
gdk_texture_do_download (texture,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
gdk_color_space_get_srgb (),
|
||||
data,
|
||||
stride);
|
||||
}
|
||||
@@ -758,6 +846,9 @@ gdk_texture_download (GdkTexture *texture,
|
||||
* may need to be upsampled if it was not already available in this
|
||||
* format.
|
||||
*
|
||||
* The downloaded data will be in the sRGB color space, no matter the
|
||||
* color space of the texture.
|
||||
*
|
||||
* You may want to use [method@Gdk.Texture.download] instead if you don't
|
||||
* need high dynamic range support.
|
||||
*
|
||||
@@ -781,6 +872,7 @@ gdk_texture_download_float (GdkTexture *texture,
|
||||
|
||||
gdk_texture_do_download (texture,
|
||||
GDK_MEMORY_R32G32B32A32_FLOAT_PREMULTIPLIED,
|
||||
gdk_color_space_get_srgb (),
|
||||
(guchar *) data,
|
||||
stride);
|
||||
}
|
||||
|
@@ -84,6 +84,8 @@ GDK_AVAILABLE_IN_ALL
|
||||
int gdk_texture_get_width (GdkTexture *texture) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
int gdk_texture_get_height (GdkTexture *texture) G_GNUC_PURE;
|
||||
GDK_AVAILABLE_IN_4_6
|
||||
GdkColorSpace * gdk_texture_get_color_space (GdkTexture *texture) G_GNUC_PURE;
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_texture_download (GdkTexture *texture,
|
||||
|
@@ -18,6 +18,7 @@ struct _GdkTexture
|
||||
GdkMemoryFormat format;
|
||||
int width;
|
||||
int height;
|
||||
GdkColorSpace *color_space;
|
||||
|
||||
gpointer render_key;
|
||||
gpointer render_data;
|
||||
@@ -30,6 +31,7 @@ struct _GdkTextureClass {
|
||||
/* mandatory: Download in the given format into data */
|
||||
void (* download) (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
};
|
||||
@@ -41,6 +43,7 @@ cairo_surface_t * gdk_texture_download_surface (GdkTexture
|
||||
|
||||
void gdk_texture_do_download (GdkTexture *texture,
|
||||
GdkMemoryFormat format,
|
||||
GdkColorSpace *color_space,
|
||||
guchar *data,
|
||||
gsize stride);
|
||||
GdkMemoryFormat gdk_texture_get_format (GdkTexture *self);
|
||||
|
@@ -73,6 +73,8 @@ typedef cairo_rectangle_int_t GdkRectangle;
|
||||
|
||||
/* Forward declarations of commonly used types */
|
||||
typedef struct _GdkRGBA GdkRGBA;
|
||||
typedef struct _GdkColor GdkColor;
|
||||
typedef struct _GdkColorSpace GdkColorSpace;
|
||||
typedef struct _GdkContentFormats GdkContentFormats;
|
||||
typedef struct _GdkContentProvider GdkContentProvider;
|
||||
typedef struct _GdkCursor GdkCursor;
|
||||
|
@@ -19,9 +19,10 @@
|
||||
|
||||
#include "gdkjpegprivate.h"
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdktexture.h"
|
||||
|
||||
#include "gdkprofilerprivate.h"
|
||||
|
||||
@@ -141,9 +142,12 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
guint width, height, stride;
|
||||
unsigned char *data;
|
||||
unsigned char *row[1];
|
||||
JOCTET *icc_data;
|
||||
unsigned int icc_len;
|
||||
GBytes *bytes;
|
||||
GdkTexture *texture;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorSpace *space;
|
||||
G_GNUC_UNUSED guint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
@@ -163,6 +167,9 @@ gdk_load_jpeg (GBytes *input_bytes,
|
||||
g_bytes_get_data (input_bytes, NULL),
|
||||
g_bytes_get_size (input_bytes));
|
||||
|
||||
/* save color profile */
|
||||
jpeg_save_markers (&info, JPEG_APP0 + 2, 0xFFFF);
|
||||
|
||||
jpeg_read_header (&info, TRUE);
|
||||
jpeg_start_decompress (&info);
|
||||
|
||||
@@ -220,14 +227,31 @@ 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);
|
||||
space = gdk_color_space_new_from_icc_profile (icc_bytes, error);
|
||||
g_bytes_unref (icc_bytes);
|
||||
}
|
||||
else
|
||||
space = g_object_ref (gdk_color_space_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 (space)
|
||||
{
|
||||
texture = gdk_memory_texture_new_with_color_space (width, height,
|
||||
format,
|
||||
space,
|
||||
bytes,
|
||||
stride);
|
||||
g_object_unref (space);
|
||||
}
|
||||
else
|
||||
texture = NULL;
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
@@ -250,9 +274,12 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
gsize texstride;
|
||||
guchar *row;
|
||||
int width, height;
|
||||
GdkColorSpace *space;
|
||||
GBytes *bytes;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
space = gdk_texture_get_color_space (texture);
|
||||
|
||||
info.err = jpeg_std_error (&jerr.pub);
|
||||
jerr.pub.error_exit = fatal_error_handler;
|
||||
@@ -280,13 +307,27 @@ gdk_save_jpeg (GdkTexture *texture)
|
||||
|
||||
jpeg_mem_dest (&info, &data, &size);
|
||||
|
||||
jpeg_start_compress (&info, TRUE);
|
||||
|
||||
bytes = gdk_color_space_save_to_icc_profile (space, NULL);
|
||||
if (bytes != NULL)
|
||||
{
|
||||
jpeg_write_icc_profile (&info,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
g_bytes_unref (bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
space = gdk_color_space_get_srgb ();
|
||||
}
|
||||
|
||||
memtex = gdk_memory_texture_from_texture (texture,
|
||||
GDK_MEMORY_R8G8B8);
|
||||
GDK_MEMORY_R8G8B8,
|
||||
space);
|
||||
texdata = gdk_memory_texture_get_data (memtex);
|
||||
texstride = gdk_memory_texture_get_stride (memtex);
|
||||
|
||||
jpeg_start_compress (&info, TRUE);
|
||||
|
||||
while (info.next_scanline < info.image_height)
|
||||
{
|
||||
row = (guchar *) texdata + info.next_scanline * texstride;
|
||||
|
@@ -19,13 +19,15 @@
|
||||
|
||||
#include "gdkpngprivate.h"
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdklcmscolorspaceprivate.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
#include "gdkprofilerprivate.h"
|
||||
#include "gdktexture.h"
|
||||
#include "gdktextureprivate.h"
|
||||
#include "gsk/gl/fp16private.h"
|
||||
|
||||
#include <png.h>
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -127,6 +129,102 @@ png_simple_warning_callback (png_structp png,
|
||||
{
|
||||
}
|
||||
|
||||
static GdkColorSpace *
|
||||
gdk_png_get_color_space (png_struct *png,
|
||||
png_info *info,
|
||||
GError **error)
|
||||
{
|
||||
GdkColorSpace *space;
|
||||
guchar *icc_data;
|
||||
png_uint_32 icc_len;
|
||||
char *name;
|
||||
double gamma;
|
||||
cmsCIExyY whitepoint;
|
||||
cmsCIExyYTRIPLE primaries;
|
||||
cmsToneCurve *curve;
|
||||
cmsHPROFILE lcms_profile;
|
||||
int intent;
|
||||
|
||||
if (png_get_iCCP (png, info, &name, NULL, &icc_data, &icc_len))
|
||||
{
|
||||
GBytes *bytes = g_bytes_new (icc_data, icc_len);
|
||||
|
||||
space = gdk_color_space_new_from_icc_profile (bytes, error);
|
||||
g_bytes_unref (bytes);
|
||||
return space;
|
||||
}
|
||||
|
||||
if (png_get_sRGB (png, info, &intent))
|
||||
return g_object_ref (gdk_color_space_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 g_object_ref (gdk_color_space_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 g_object_ref (gdk_color_space_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 });
|
||||
space = gdk_lcms_color_space_new_from_lcms_profile (lcms_profile);
|
||||
cmsFreeToneCurve (curve);
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_png_set_color_space (png_struct *png,
|
||||
png_info *info,
|
||||
GdkColorSpace *space)
|
||||
{
|
||||
/* FIXME: allow deconstructing RGB color spaces into gAMA and cHRM instead of
|
||||
* falling back to iCCP */
|
||||
if (space == gdk_color_space_get_srgb ())
|
||||
{
|
||||
png_set_sRGB_gAMA_and_cHRM (png, info, /* FIXME */ PNG_sRGB_INTENT_PERCEPTUAL);
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GBytes *bytes = gdk_color_space_save_to_icc_profile (space, NULL);
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
png_set_iCCP (png, info,
|
||||
"ICC profile",
|
||||
0,
|
||||
g_bytes_get_data (bytes, NULL),
|
||||
g_bytes_get_size (bytes));
|
||||
g_bytes_unref (bytes);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
@@ -144,6 +242,7 @@ gdk_load_png (GBytes *bytes,
|
||||
guchar *buffer = NULL;
|
||||
guchar **row_pointers = NULL;
|
||||
GBytes *out_bytes;
|
||||
GdkColorSpace *color_space;
|
||||
GdkTexture *texture;
|
||||
int bpp;
|
||||
G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
@@ -255,6 +354,13 @@ gdk_load_png (GBytes *bytes,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
color_space = gdk_png_get_color_space (png, info, error);
|
||||
if (color_space == NULL)
|
||||
{
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bpp = gdk_memory_format_bytes_per_pixel (format);
|
||||
stride = width * bpp;
|
||||
if (stride % 8)
|
||||
@@ -265,6 +371,7 @@ gdk_load_png (GBytes *bytes,
|
||||
|
||||
if (!buffer || !row_pointers)
|
||||
{
|
||||
g_object_unref (color_space);
|
||||
g_free (buffer);
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
@@ -281,8 +388,12 @@ 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_space (width, height,
|
||||
format,
|
||||
color_space,
|
||||
out_bytes, stride);
|
||||
g_bytes_unref (out_bytes);
|
||||
g_object_unref (color_space);
|
||||
|
||||
g_free (row_pointers);
|
||||
png_destroy_read_struct (&png, &info, NULL);
|
||||
@@ -309,12 +420,14 @@ gdk_save_png (GdkTexture *texture)
|
||||
int y;
|
||||
GdkMemoryTexture *memtex;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorSpace *color_space;
|
||||
int png_format;
|
||||
int depth;
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
format = gdk_texture_get_format (texture);
|
||||
color_space = gdk_texture_get_color_space (texture);
|
||||
|
||||
switch (format)
|
||||
{
|
||||
@@ -385,7 +498,7 @@ gdk_save_png (GdkTexture *texture)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memtex = gdk_memory_texture_from_texture (texture, format);
|
||||
memtex = gdk_memory_texture_from_texture (texture, format, gdk_color_space_get_srgb ());
|
||||
|
||||
if (sigsetjmp (png_jmpbuf (png), 1))
|
||||
{
|
||||
@@ -403,8 +516,13 @@ gdk_save_png (GdkTexture *texture)
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
if (!gdk_png_set_color_space (png, info, color_space))
|
||||
color_space = gdk_color_space_get_srgb ();
|
||||
|
||||
png_write_info (png, info);
|
||||
|
||||
memtex = gdk_memory_texture_from_texture (texture, format, color_space);
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
png_set_swap (png);
|
||||
#endif
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "gdktiffprivate.h"
|
||||
|
||||
#include "gdkcolorspace.h"
|
||||
#include "gdkintl.h"
|
||||
#include "gdkmemoryformatprivate.h"
|
||||
#include "gdkmemorytextureprivate.h"
|
||||
@@ -220,6 +221,49 @@ tiff_open_write (GBytes **result)
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Color profile handling */
|
||||
|
||||
static GdkColorSpace *
|
||||
gdk_tiff_get_color_space (TIFF *tiff,
|
||||
GError **error)
|
||||
{
|
||||
const char *icc_data;
|
||||
guint icc_len;
|
||||
|
||||
if (TIFFGetField (tiff, TIFFTAG_ICCPROFILE, &icc_len, &icc_data))
|
||||
{
|
||||
GBytes *icc_bytes;
|
||||
GdkColorSpace *space;
|
||||
|
||||
icc_bytes = g_bytes_new (icc_data, icc_len);
|
||||
space = gdk_color_space_new_from_icc_profile (icc_bytes, error);
|
||||
g_bytes_unref (icc_bytes);
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
return g_object_ref (gdk_color_space_get_srgb ());
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gdk_tiff_set_color_space (TIFF *tiff,
|
||||
GdkColorSpace *space)
|
||||
{
|
||||
GBytes *bytes = gdk_color_space_save_to_icc_profile (space, NULL);
|
||||
|
||||
if (bytes == NULL)
|
||||
return FALSE;
|
||||
|
||||
TIFFSetField (tiff, TIFFTAG_ICCPROFILE,
|
||||
g_bytes_get_size (bytes),
|
||||
g_bytes_get_data (bytes, NULL));
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Public API */
|
||||
|
||||
@@ -266,12 +310,14 @@ gdk_save_tiff (GdkTexture *texture)
|
||||
GBytes *result = NULL;
|
||||
GdkMemoryTexture *memtex;
|
||||
GdkMemoryFormat format;
|
||||
GdkColorSpace *space;
|
||||
const FormatData *fdata = NULL;
|
||||
|
||||
tif = tiff_open_write (&result);
|
||||
|
||||
width = gdk_texture_get_width (texture);
|
||||
height = gdk_texture_get_height (texture);
|
||||
space = gdk_texture_get_color_space (texture);
|
||||
format = gdk_texture_get_format (texture);
|
||||
fdata = &format_data[format];
|
||||
|
||||
@@ -289,10 +335,15 @@ gdk_save_tiff (GdkTexture *texture)
|
||||
if (fdata->alpha_samples)
|
||||
TIFFSetField (tif, TIFFTAG_EXTRASAMPLES, 1, &fdata->alpha_samples);
|
||||
|
||||
if (!gdk_tiff_set_color_space (tif, space))
|
||||
space = gdk_color_space_get_srgb ();
|
||||
|
||||
TIFFSetField (tif, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
|
||||
TIFFSetField (tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
|
||||
|
||||
memtex = gdk_memory_texture_from_texture (texture, fdata->format);
|
||||
memtex = gdk_memory_texture_from_texture (texture,
|
||||
fdata->format,
|
||||
space);
|
||||
data = gdk_memory_texture_get_data (memtex);
|
||||
stride = gdk_memory_texture_get_stride (memtex);
|
||||
|
||||
@@ -320,8 +371,9 @@ gdk_save_tiff (GdkTexture *texture)
|
||||
}
|
||||
|
||||
static GdkTexture *
|
||||
load_fallback (TIFF *tif,
|
||||
GError **error)
|
||||
load_fallback (TIFF *tif,
|
||||
GdkColorSpace *space,
|
||||
GError **error)
|
||||
{
|
||||
int width, height;
|
||||
guchar *data;
|
||||
@@ -331,25 +383,36 @@ load_fallback (TIFF *tif,
|
||||
TIFFGetField (tif, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetField (tif, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
data = g_malloc (width * height * 4);
|
||||
data = g_try_malloc_n (width * 4, height);
|
||||
if (data == NULL)
|
||||
{
|
||||
g_set_error (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_TOO_LARGE,
|
||||
_("Not enough memory for image size %ux%u"), width, height);
|
||||
g_object_unref (space);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!TIFFReadRGBAImageOriented (tif, width, height, (guint32 *)data, ORIENTATION_TOPLEFT, 1))
|
||||
{
|
||||
g_set_error_literal (error,
|
||||
GDK_TEXTURE_ERROR, GDK_TEXTURE_ERROR_CORRUPT_IMAGE,
|
||||
_("Failed to load RGB data from TIFF file"));
|
||||
g_object_unref (space);
|
||||
g_free (data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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_space (width, height,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
space,
|
||||
bytes,
|
||||
width * 4);
|
||||
|
||||
g_bytes_unref (bytes);
|
||||
g_object_unref (space);
|
||||
|
||||
return texture;
|
||||
}
|
||||
@@ -372,6 +435,7 @@ gdk_load_tiff (GBytes *input_bytes,
|
||||
gsize stride;
|
||||
int bpp;
|
||||
GBytes *bytes;
|
||||
GdkColorSpace *space;
|
||||
GdkTexture *texture;
|
||||
G_GNUC_UNUSED gint64 before = GDK_PROFILER_CURRENT_TIME;
|
||||
|
||||
@@ -388,6 +452,13 @@ gdk_load_tiff (GBytes *input_bytes,
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_IMAGEWIDTH, &width);
|
||||
TIFFGetFieldDefaulted (tif, TIFFTAG_IMAGELENGTH, &height);
|
||||
|
||||
space = gdk_tiff_get_color_space (tif, error);
|
||||
if (space == NULL)
|
||||
{
|
||||
TIFFClose (tif);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (samples_per_pixel == 4)
|
||||
{
|
||||
guint16 extra;
|
||||
@@ -400,7 +471,7 @@ gdk_load_tiff (GBytes *input_bytes,
|
||||
|
||||
if (alpha_samples != 0 && alpha_samples != EXTRASAMPLE_ASSOCALPHA && alpha_samples != EXTRASAMPLE_UNASSALPHA)
|
||||
{
|
||||
texture = load_fallback (tif, error);
|
||||
texture = load_fallback (tif, space, error);
|
||||
TIFFClose (tif);
|
||||
return texture;
|
||||
}
|
||||
@@ -429,7 +500,7 @@ gdk_load_tiff (GBytes *input_bytes,
|
||||
TIFFIsTiled (tif) ||
|
||||
orientation != ORIENTATION_TOPLEFT)
|
||||
{
|
||||
texture = load_fallback (tif, error);
|
||||
texture = load_fallback (tif, space, error);
|
||||
TIFFClose (tif);
|
||||
return texture;
|
||||
}
|
||||
@@ -467,10 +538,11 @@ gdk_load_tiff (GBytes *input_bytes,
|
||||
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_space (width, height,
|
||||
format, space,
|
||||
bytes, width * bpp);
|
||||
g_bytes_unref (bytes);
|
||||
g_object_unref (space);
|
||||
|
||||
TIFFClose (tif);
|
||||
|
||||
|
@@ -4,6 +4,8 @@ gdk_public_sources = files([
|
||||
'gdkcairo.c',
|
||||
'gdkcairocontext.c',
|
||||
'gdkclipboard.c',
|
||||
'gdkcolor.c',
|
||||
'gdkcolorspace.c',
|
||||
'gdkcontentdeserializer.c',
|
||||
'gdkcontentformats.c',
|
||||
'gdkcontentprovider.c',
|
||||
@@ -30,6 +32,7 @@ gdk_public_sources = files([
|
||||
'gdkhsla.c',
|
||||
'gdkkeys.c',
|
||||
'gdkkeyuni.c',
|
||||
'gdklcmscolorspace.c',
|
||||
'gdkmemoryformat.c',
|
||||
'gdkmemorytexture.c',
|
||||
'gdkmonitor.c',
|
||||
@@ -64,6 +67,8 @@ gdk_public_headers = files([
|
||||
'gdkcairo.h',
|
||||
'gdkcairocontext.h',
|
||||
'gdkclipboard.h',
|
||||
'gdkcolor.h',
|
||||
'gdkcolorspace.h',
|
||||
'gdkcontentdeserializer.h',
|
||||
'gdkcontentformats.h',
|
||||
'gdkcontentprovider.h',
|
||||
@@ -205,6 +210,7 @@ gdk_deps = [
|
||||
fontconfig_dep,
|
||||
platform_gio_dep,
|
||||
pangocairo_dep,
|
||||
lcms2_dep,
|
||||
vulkan_dep,
|
||||
png_dep,
|
||||
tiff_dep,
|
||||
|
@@ -1403,6 +1403,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_space (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_object (&self->color_space);
|
||||
self->color_space = g_object_ref (gdk_color_space_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_object (&self->color_space);
|
||||
self->color_space = gdk_color_space_new_from_icc_profile (bytes, NULL);
|
||||
if (!self->color_space)
|
||||
self->color_space = g_object_ref (gdk_color_space_get_srgb ());
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_x11_display_open:
|
||||
* @display_name: (nullable): name of the X display.
|
||||
@@ -1470,6 +1535,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_space (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
|
||||
@@ -1915,15 +1983,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_object (&self->color_space);
|
||||
|
||||
G_OBJECT_CLASS (gdk_x11_display_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
|
@@ -128,6 +128,9 @@ struct _GdkX11Display
|
||||
guint have_damage;
|
||||
#endif
|
||||
|
||||
/* Stored in the ICC_PROFILE rootwindow prop */
|
||||
GdkColorSpace *color_space;
|
||||
|
||||
/* If GL is not supported, store the error here */
|
||||
GError *gl_error;
|
||||
|
||||
|
@@ -1011,6 +1011,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_space (surface, GDK_X11_DISPLAY (display)->color_space);
|
||||
|
||||
if (!gdk_running_in_sandbox ())
|
||||
{
|
||||
|
@@ -1381,7 +1381,7 @@ gsk_gl_command_queue_do_upload_texture (GskGLCommandQueue *self,
|
||||
}
|
||||
}
|
||||
|
||||
memtex = gdk_memory_texture_from_texture (texture, data_format);
|
||||
memtex = gdk_memory_texture_from_texture (texture, data_format, gdk_color_space_get_srgb ());
|
||||
data = gdk_memory_texture_get_data (memtex);
|
||||
stride = gdk_memory_texture_get_stride (memtex);
|
||||
bpp = gdk_memory_format_bytes_per_pixel (data_format);
|
||||
|
@@ -774,10 +774,6 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
/* A GL texture from the same GL context is a simple task... */
|
||||
return gdk_gl_texture_get_id (gl_texture);
|
||||
}
|
||||
else
|
||||
{
|
||||
downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -786,10 +782,12 @@ gsk_gl_driver_load_texture (GskGLDriver *self,
|
||||
if (t->min_filter == min_filter && t->mag_filter == mag_filter)
|
||||
return t->texture_id;
|
||||
}
|
||||
|
||||
downloaded_texture = gdk_memory_texture_from_texture (texture, gdk_texture_get_format (texture));
|
||||
}
|
||||
|
||||
downloaded_texture = gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_color_space (texture));
|
||||
|
||||
/* The download_texture() call may have switched the GL context. Make sure
|
||||
* the right context is at work again. */
|
||||
gdk_gl_context_make_current (context);
|
||||
@@ -1251,7 +1249,8 @@ gsk_gl_driver_add_texture_slices (GskGLDriver *self,
|
||||
n_slices = cols * rows;
|
||||
slices = g_new0 (GskGLTextureSlice, n_slices);
|
||||
memtex = gdk_memory_texture_from_texture (texture,
|
||||
gdk_texture_get_format (texture));
|
||||
gdk_texture_get_format (texture),
|
||||
gdk_texture_get_color_space (texture));
|
||||
|
||||
for (guint col = 0; col < cols; col ++)
|
||||
{
|
||||
|
@@ -238,9 +238,11 @@ gsk_gl_glyph_library_upload_glyph (GskGLGlyphLibrary *self,
|
||||
gdk_memory_convert (pixel_data,
|
||||
width * 4,
|
||||
GDK_MEMORY_R8G8B8A8_PREMULTIPLIED,
|
||||
gdk_color_space_get_srgb (),
|
||||
cairo_image_surface_get_data (surface),
|
||||
width * 4,
|
||||
GDK_MEMORY_DEFAULT,
|
||||
gdk_color_space_get_srgb (),
|
||||
width, height);
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <gdk/gdkcolorspace.h>
|
||||
#include <gdk/gdkglcontextprivate.h>
|
||||
#include <gdk/gdkmemoryformatprivate.h>
|
||||
#include <gdk/gdkprofilerprivate.h>
|
||||
@@ -116,8 +117,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_space_get_srgb (),
|
||||
surface_data, cairo_image_surface_get_stride (surface),
|
||||
GDK_MEMORY_DEFAULT, width, height);
|
||||
GDK_MEMORY_DEFAULT,
|
||||
gdk_color_space_get_srgb (),
|
||||
width, height);
|
||||
gl_format = GL_RGBA;
|
||||
gl_type = GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
@@ -16,6 +16,7 @@ fribidi_req = '>= 0.19.7'
|
||||
cairo_req = '>= 1.14.0'
|
||||
gdk_pixbuf_req = '>= 2.30.0'
|
||||
introspection_req = '>= 1.39.0'
|
||||
lcms2_req = '>= 2.8'
|
||||
wayland_proto_req = '>= 1.21'
|
||||
wayland_req = '>= 1.16.91'
|
||||
graphene_req = '>= 1.9.1'
|
||||
@@ -379,6 +380,8 @@ pango_dep = dependency('pango', version: pango_req,
|
||||
fallback : ['pango', 'libpango_dep'])
|
||||
fribidi_dep = dependency('fribidi', version: fribidi_req,
|
||||
fallback : ['fribidi', 'libfribidi_dep'])
|
||||
lcms2_dep = dependency('lcms2', version: lcms2_req,
|
||||
fallback : ['lcms2', 'liblcms2_dep'])
|
||||
|
||||
# Require PangoFT2 if on X11 or wayland
|
||||
require_pangoft2 = wayland_enabled or x11_enabled
|
||||
|
6
subprojects/lcms2.wrap
Normal file
6
subprojects/lcms2.wrap
Normal file
@@ -0,0 +1,6 @@
|
||||
[wrap-git]
|
||||
directory=lcms2
|
||||
url=https://github.com/mm2/Little-CMS.git
|
||||
revision=master
|
||||
patch_directory=lcms2
|
||||
depth=1
|
14
subprojects/packagefiles/lcms2/meson.build
Normal file
14
subprojects/packagefiles/lcms2/meson.build
Normal file
@@ -0,0 +1,14 @@
|
||||
project('lcms2', 'c',
|
||||
version : '2.12',
|
||||
meson_version : '>=0.56.0',
|
||||
)
|
||||
|
||||
mod = import('unstable_external_project')
|
||||
|
||||
p = mod.add_project('configure',
|
||||
configure_options : ['--prefix=@PREFIX@',
|
||||
'--libdir=@PREFIX@/@LIBDIR@',
|
||||
],
|
||||
)
|
||||
|
||||
liblcms2_dep = p.dependency('lcms2')
|
Reference in New Issue
Block a user