This also depends on the same settings to render brushes with theme colors, because this is data, not user interface. Therefore following theme colors is not necessarily what creators would expect.
848 lines
32 KiB
C
848 lines
32 KiB
C
/* GIMP - The GNU Image Manipulation Program
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
*
|
|
* gimpimageproxy.c
|
|
* Copyright (C) 2019 Ell
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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 General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <cairo.h>
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
|
#include <gegl.h>
|
|
|
|
#include "libgimpbase/gimpbase.h"
|
|
#include "libgimpcolor/gimpcolor.h"
|
|
|
|
#include "core-types.h"
|
|
|
|
#include "gegl/gimp-babl.h"
|
|
#include "gegl/gimp-gegl-loops.h"
|
|
|
|
#include "gimpimage.h"
|
|
#include "gimpimage-color-profile.h"
|
|
#include "gimpimage-preview.h"
|
|
#include "gimpimageproxy.h"
|
|
#include "gimppickable.h"
|
|
#include "gimpprojectable.h"
|
|
#include "gimptempbuf.h"
|
|
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
PROP_IMAGE,
|
|
PROP_SHOW_ALL,
|
|
PROP_BUFFER
|
|
};
|
|
|
|
|
|
struct _GimpImageProxyPrivate
|
|
{
|
|
GimpImage *image;
|
|
gboolean show_all;
|
|
|
|
GeglRectangle bounding_box;
|
|
gboolean frozen;
|
|
};
|
|
|
|
|
|
/* local function prototypes */
|
|
|
|
static void gimp_image_proxy_pickable_iface_init (GimpPickableInterface *iface);
|
|
static void gimp_image_proxy_color_managed_iface_init (GimpColorManagedInterface *iface);
|
|
|
|
static void gimp_image_proxy_finalize (GObject *object);
|
|
static void gimp_image_proxy_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec);
|
|
static void gimp_image_proxy_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec);
|
|
|
|
static gboolean gimp_image_proxy_get_size (GimpViewable *viewable,
|
|
gint *width,
|
|
gint *height);
|
|
static void gimp_image_proxy_get_preview_size (GimpViewable *viewable,
|
|
gint size,
|
|
gboolean is_popup,
|
|
gboolean dot_for_dot,
|
|
gint *width,
|
|
gint *height);
|
|
static gboolean gimp_image_proxy_get_popup_size (GimpViewable *viewable,
|
|
gint width,
|
|
gint height,
|
|
gboolean dot_for_dot,
|
|
gint *popup_width,
|
|
gint *popup_height);
|
|
static GimpTempBuf * gimp_image_proxy_get_new_preview (GimpViewable *viewable,
|
|
GimpContext *context,
|
|
gint width,
|
|
gint height,
|
|
GeglColor *color,
|
|
GeglColor *background);
|
|
static GdkPixbuf * gimp_image_proxy_get_new_pixbuf (GimpViewable *viewable,
|
|
GimpContext *context,
|
|
gint width,
|
|
gint height,
|
|
GeglColor *color,
|
|
GeglColor *background);
|
|
static gchar * gimp_image_proxy_get_description (GimpViewable *viewable,
|
|
gchar **tooltip);
|
|
|
|
static void gimp_image_proxy_flush (GimpPickable *pickable);
|
|
static const Babl * gimp_image_proxy_get_format (GimpPickable *pickable);
|
|
static const Babl * gimp_image_proxy_get_format_with_alpha (GimpPickable *pickable);
|
|
static GeglBuffer * gimp_image_proxy_get_buffer (GimpPickable *pickable);
|
|
static gboolean gimp_image_proxy_get_pixel_at (GimpPickable *pickable,
|
|
gint x,
|
|
gint y,
|
|
const Babl *format,
|
|
gpointer pixel);
|
|
static gdouble gimp_image_proxy_get_opacity_at (GimpPickable *pickable,
|
|
gint x,
|
|
gint y);
|
|
static void gimp_image_proxy_get_pixel_average (GimpPickable *pickable,
|
|
const GeglRectangle *rect,
|
|
const Babl *format,
|
|
gpointer pixel);
|
|
|
|
static const guint8 * gimp_image_proxy_get_icc_profile (GimpColorManaged *managed,
|
|
gsize *len);
|
|
static GimpColorProfile * gimp_image_proxy_get_color_profile (GimpColorManaged *managed);
|
|
static void gimp_image_proxy_profile_changed (GimpColorManaged *managed);
|
|
|
|
static void gimp_image_proxy_image_frozen_notify (GimpImage *image,
|
|
const GParamSpec *pspec,
|
|
GimpImageProxy *image_proxy);
|
|
static void gimp_image_proxy_image_invalidate_preview (GimpImage *image,
|
|
GimpImageProxy *image_proxy);
|
|
static void gimp_image_proxy_image_size_changed (GimpImage *image,
|
|
GimpImageProxy *image_proxy);
|
|
static void gimp_image_proxy_image_bounds_changed (GimpImage *image,
|
|
gint old_x,
|
|
gint old_y,
|
|
GimpImageProxy *image_proxy);
|
|
static void gimp_image_proxy_image_profile_changed (GimpImage *image,
|
|
GimpImageProxy *image_proxy);
|
|
|
|
static void gimp_image_proxy_set_image (GimpImageProxy *image_proxy,
|
|
GimpImage *image);
|
|
static GimpPickable * gimp_image_proxy_get_pickable (GimpImageProxy *image_proxy);
|
|
static void gimp_image_proxy_update_bounding_box (GimpImageProxy *image_proxy);
|
|
static void gimp_image_proxy_update_frozen (GimpImageProxy *image_proxy);
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (GimpImageProxy, gimp_image_proxy, GIMP_TYPE_VIEWABLE,
|
|
G_ADD_PRIVATE (GimpImageProxy)
|
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_PICKABLE,
|
|
gimp_image_proxy_pickable_iface_init)
|
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_COLOR_MANAGED,
|
|
gimp_image_proxy_color_managed_iface_init))
|
|
|
|
#define parent_class gimp_image_proxy_parent_class
|
|
|
|
|
|
/* private functions */
|
|
|
|
|
|
static void
|
|
gimp_image_proxy_class_init (GimpImageProxyClass *klass)
|
|
{
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
GimpViewableClass *viewable_class = GIMP_VIEWABLE_CLASS (klass);
|
|
|
|
object_class->finalize = gimp_image_proxy_finalize;
|
|
object_class->set_property = gimp_image_proxy_set_property;
|
|
object_class->get_property = gimp_image_proxy_get_property;
|
|
|
|
viewable_class->default_icon_name = "gimp-image";
|
|
viewable_class->get_size = gimp_image_proxy_get_size;
|
|
viewable_class->get_preview_size = gimp_image_proxy_get_preview_size;
|
|
viewable_class->get_popup_size = gimp_image_proxy_get_popup_size;
|
|
viewable_class->get_new_preview = gimp_image_proxy_get_new_preview;
|
|
viewable_class->get_new_pixbuf = gimp_image_proxy_get_new_pixbuf;
|
|
viewable_class->get_description = gimp_image_proxy_get_description;
|
|
|
|
g_object_class_install_property (object_class, PROP_IMAGE,
|
|
g_param_spec_object ("image",
|
|
NULL, NULL,
|
|
GIMP_TYPE_IMAGE,
|
|
GIMP_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT_ONLY));
|
|
|
|
g_object_class_install_property (object_class, PROP_SHOW_ALL,
|
|
g_param_spec_boolean ("show-all",
|
|
NULL, NULL,
|
|
FALSE,
|
|
GIMP_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT));
|
|
|
|
g_object_class_override_property (object_class, PROP_BUFFER, "buffer");
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_pickable_iface_init (GimpPickableInterface *iface)
|
|
{
|
|
iface->flush = gimp_image_proxy_flush;
|
|
iface->get_image = (gpointer) gimp_image_proxy_get_image;
|
|
iface->get_format = gimp_image_proxy_get_format;
|
|
iface->get_format_with_alpha = gimp_image_proxy_get_format_with_alpha;
|
|
iface->get_buffer = gimp_image_proxy_get_buffer;
|
|
iface->get_pixel_at = gimp_image_proxy_get_pixel_at;
|
|
iface->get_opacity_at = gimp_image_proxy_get_opacity_at;
|
|
iface->get_pixel_average = gimp_image_proxy_get_pixel_average;
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_color_managed_iface_init (GimpColorManagedInterface *iface)
|
|
{
|
|
iface->get_icc_profile = gimp_image_proxy_get_icc_profile;
|
|
iface->get_color_profile = gimp_image_proxy_get_color_profile;
|
|
iface->profile_changed = gimp_image_proxy_profile_changed;
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_init (GimpImageProxy *image_proxy)
|
|
{
|
|
image_proxy->priv = gimp_image_proxy_get_instance_private (image_proxy);
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_finalize (GObject *object)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (object);
|
|
|
|
gimp_image_proxy_set_image (image_proxy, NULL);
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_IMAGE:
|
|
gimp_image_proxy_set_image (image_proxy,
|
|
g_value_get_object (value));
|
|
break;
|
|
|
|
case PROP_SHOW_ALL:
|
|
gimp_image_proxy_set_show_all (image_proxy,
|
|
g_value_get_boolean (value));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (object);
|
|
|
|
switch (property_id)
|
|
{
|
|
case PROP_IMAGE:
|
|
g_value_set_object (value,
|
|
gimp_image_proxy_get_image (image_proxy));
|
|
break;
|
|
|
|
case PROP_SHOW_ALL:
|
|
g_value_set_boolean (value,
|
|
gimp_image_proxy_get_show_all (image_proxy));
|
|
break;
|
|
|
|
case PROP_BUFFER:
|
|
g_value_set_object (value,
|
|
gimp_pickable_get_buffer (
|
|
GIMP_PICKABLE (image_proxy)));
|
|
break;
|
|
|
|
default:
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
break;
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
gimp_image_proxy_get_size (GimpViewable *viewable,
|
|
gint *width,
|
|
gint *height)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (viewable);
|
|
|
|
*width = image_proxy->priv->bounding_box.width;
|
|
*height = image_proxy->priv->bounding_box.height;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_get_preview_size (GimpViewable *viewable,
|
|
gint size,
|
|
gboolean is_popup,
|
|
gboolean dot_for_dot,
|
|
gint *width,
|
|
gint *height)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (viewable);
|
|
GimpImage *image = image_proxy->priv->image;
|
|
gdouble xres;
|
|
gdouble yres;
|
|
gint viewable_width;
|
|
gint viewable_height;
|
|
|
|
gimp_image_get_resolution (image, &xres, &yres);
|
|
|
|
gimp_viewable_get_size (viewable, &viewable_width, &viewable_height);
|
|
|
|
gimp_viewable_calc_preview_size (viewable_width,
|
|
viewable_height,
|
|
size,
|
|
size,
|
|
dot_for_dot,
|
|
xres,
|
|
yres,
|
|
width,
|
|
height,
|
|
NULL);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_image_proxy_get_popup_size (GimpViewable *viewable,
|
|
gint width,
|
|
gint height,
|
|
gboolean dot_for_dot,
|
|
gint *popup_width,
|
|
gint *popup_height)
|
|
{
|
|
gint viewable_width;
|
|
gint viewable_height;
|
|
|
|
gimp_viewable_get_size (viewable, &viewable_width, &viewable_height);
|
|
|
|
if (viewable_width > width || viewable_height > height)
|
|
{
|
|
gboolean scaling_up;
|
|
|
|
gimp_viewable_calc_preview_size (viewable_width,
|
|
viewable_height,
|
|
width * 2,
|
|
height * 2,
|
|
dot_for_dot, 1.0, 1.0,
|
|
popup_width,
|
|
popup_height,
|
|
&scaling_up);
|
|
|
|
if (scaling_up)
|
|
{
|
|
*popup_width = viewable_width;
|
|
*popup_height = viewable_height;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static GimpTempBuf *
|
|
gimp_image_proxy_get_new_preview (GimpViewable *viewable,
|
|
GimpContext *context,
|
|
gint width,
|
|
gint height,
|
|
GeglColor *color G_GNUC_UNUSED,
|
|
GeglColor *background G_GNUC_UNUSED)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (viewable);
|
|
GimpImage *image = image_proxy->priv->image;
|
|
GimpPickable *pickable;
|
|
const Babl *format;
|
|
GeglRectangle bounding_box;
|
|
GimpTempBuf *buf;
|
|
gdouble scale_x;
|
|
gdouble scale_y;
|
|
gdouble scale;
|
|
|
|
pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
bounding_box = gimp_image_proxy_get_bounding_box (image_proxy);
|
|
|
|
scale_x = (gdouble) width / (gdouble) bounding_box.width;
|
|
scale_y = (gdouble) height / (gdouble) bounding_box.height;
|
|
|
|
scale = MIN (scale_x, scale_y);
|
|
|
|
format = gimp_image_get_preview_format (image);
|
|
|
|
buf = gimp_temp_buf_new (width, height, format);
|
|
|
|
gegl_buffer_get (gimp_pickable_get_buffer (pickable),
|
|
GEGL_RECTANGLE (bounding_box.x * scale,
|
|
bounding_box.y * scale,
|
|
width,
|
|
height),
|
|
scale,
|
|
gimp_temp_buf_get_format (buf),
|
|
gimp_temp_buf_get_data (buf),
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
|
|
|
|
return buf;
|
|
}
|
|
|
|
static GdkPixbuf *
|
|
gimp_image_proxy_get_new_pixbuf (GimpViewable *viewable,
|
|
GimpContext *context,
|
|
gint width,
|
|
gint height,
|
|
GeglColor *color G_GNUC_UNUSED,
|
|
GeglColor *background G_GNUC_UNUSED)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (viewable);
|
|
GimpImage *image = image_proxy->priv->image;
|
|
GimpPickable *pickable;
|
|
GeglRectangle bounding_box;
|
|
GdkPixbuf *pixbuf;
|
|
gdouble scale_x;
|
|
gdouble scale_y;
|
|
gdouble scale;
|
|
GimpColorTransform *transform;
|
|
|
|
pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
bounding_box = gimp_image_proxy_get_bounding_box (image_proxy);
|
|
|
|
scale_x = (gdouble) width / (gdouble) bounding_box.width;
|
|
scale_y = (gdouble) height / (gdouble) bounding_box.height;
|
|
|
|
scale = MIN (scale_x, scale_y);
|
|
|
|
pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
|
|
width, height);
|
|
|
|
transform = gimp_image_get_color_transform_to_srgb_u8 (image);
|
|
|
|
if (transform)
|
|
{
|
|
GimpTempBuf *temp_buf;
|
|
GeglBuffer *src_buf;
|
|
GeglBuffer *dest_buf;
|
|
|
|
temp_buf = gimp_temp_buf_new (width, height,
|
|
gimp_pickable_get_format (pickable));
|
|
|
|
gegl_buffer_get (gimp_pickable_get_buffer (pickable),
|
|
GEGL_RECTANGLE (bounding_box.x * scale,
|
|
bounding_box.y * scale,
|
|
width,
|
|
height),
|
|
scale,
|
|
gimp_temp_buf_get_format (temp_buf),
|
|
gimp_temp_buf_get_data (temp_buf),
|
|
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_CLAMP);
|
|
|
|
src_buf = gimp_temp_buf_create_buffer (temp_buf);
|
|
dest_buf = gimp_pixbuf_create_buffer (pixbuf);
|
|
|
|
gimp_temp_buf_unref (temp_buf);
|
|
|
|
gimp_color_transform_process_buffer (transform,
|
|
src_buf,
|
|
GEGL_RECTANGLE (0, 0,
|
|
width, height),
|
|
dest_buf,
|
|
GEGL_RECTANGLE (0, 0, 0, 0));
|
|
|
|
g_object_unref (src_buf);
|
|
g_object_unref (dest_buf);
|
|
}
|
|
else
|
|
{
|
|
gegl_buffer_get (gimp_pickable_get_buffer (pickable),
|
|
GEGL_RECTANGLE (bounding_box.x * scale,
|
|
bounding_box.y * scale,
|
|
width,
|
|
height),
|
|
scale,
|
|
gimp_pixbuf_get_format (pixbuf),
|
|
gdk_pixbuf_get_pixels (pixbuf),
|
|
gdk_pixbuf_get_rowstride (pixbuf),
|
|
GEGL_ABYSS_CLAMP);
|
|
}
|
|
|
|
return pixbuf;
|
|
}
|
|
|
|
static gchar *
|
|
gimp_image_proxy_get_description (GimpViewable *viewable,
|
|
gchar **tooltip)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (viewable);
|
|
GimpImage *image = image_proxy->priv->image;
|
|
|
|
if (tooltip)
|
|
*tooltip = g_strdup (gimp_image_get_display_path (image));
|
|
|
|
return g_strdup_printf ("%s-%d",
|
|
gimp_image_get_display_name (image),
|
|
gimp_image_get_id (image));
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_flush (GimpPickable *pickable)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (pickable);
|
|
GimpPickable *proxy_pickable;
|
|
|
|
proxy_pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
|
|
gimp_pickable_flush (proxy_pickable);
|
|
}
|
|
|
|
static const Babl *
|
|
gimp_image_proxy_get_format (GimpPickable *pickable)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (pickable);
|
|
GimpPickable *proxy_pickable;
|
|
|
|
proxy_pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
|
|
return gimp_pickable_get_format (proxy_pickable);
|
|
}
|
|
|
|
static const Babl *
|
|
gimp_image_proxy_get_format_with_alpha (GimpPickable *pickable)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (pickable);
|
|
GimpPickable *proxy_pickable;
|
|
|
|
proxy_pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
|
|
return gimp_pickable_get_format_with_alpha (proxy_pickable);
|
|
}
|
|
|
|
static GeglBuffer *
|
|
gimp_image_proxy_get_buffer (GimpPickable *pickable)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (pickable);
|
|
GimpPickable *proxy_pickable;
|
|
|
|
proxy_pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
|
|
return gimp_pickable_get_buffer (proxy_pickable);
|
|
}
|
|
|
|
static gboolean
|
|
gimp_image_proxy_get_pixel_at (GimpPickable *pickable,
|
|
gint x,
|
|
gint y,
|
|
const Babl *format,
|
|
gpointer pixel)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (pickable);
|
|
GimpPickable *proxy_pickable;
|
|
|
|
proxy_pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
|
|
return gimp_pickable_get_pixel_at (proxy_pickable, x, y, format, pixel);
|
|
}
|
|
|
|
static gdouble
|
|
gimp_image_proxy_get_opacity_at (GimpPickable *pickable,
|
|
gint x,
|
|
gint y)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (pickable);
|
|
GimpPickable *proxy_pickable;
|
|
|
|
proxy_pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
|
|
return gimp_pickable_get_opacity_at (proxy_pickable, x, y);
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_get_pixel_average (GimpPickable *pickable,
|
|
const GeglRectangle *rect,
|
|
const Babl *format,
|
|
gpointer pixel)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (pickable);
|
|
GimpPickable *proxy_pickable;
|
|
|
|
proxy_pickable = gimp_image_proxy_get_pickable (image_proxy);
|
|
|
|
gimp_pickable_get_pixel_average (proxy_pickable, rect, format, pixel);
|
|
}
|
|
|
|
static const guint8 *
|
|
gimp_image_proxy_get_icc_profile (GimpColorManaged *managed,
|
|
gsize *len)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (managed);
|
|
|
|
return gimp_color_managed_get_icc_profile (
|
|
GIMP_COLOR_MANAGED (image_proxy->priv->image),
|
|
len);
|
|
}
|
|
|
|
static GimpColorProfile *
|
|
gimp_image_proxy_get_color_profile (GimpColorManaged *managed)
|
|
{
|
|
GimpImageProxy *image_proxy = GIMP_IMAGE_PROXY (managed);
|
|
|
|
return gimp_color_managed_get_color_profile (
|
|
GIMP_COLOR_MANAGED (image_proxy->priv->image));
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_profile_changed (GimpColorManaged *managed)
|
|
{
|
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (managed));
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_image_frozen_notify (GimpImage *image,
|
|
const GParamSpec *pspec,
|
|
GimpImageProxy *image_proxy)
|
|
{
|
|
gimp_image_proxy_update_frozen (image_proxy);
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_image_invalidate_preview (GimpImage *image,
|
|
GimpImageProxy *image_proxy)
|
|
{
|
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (image_proxy));
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_image_size_changed (GimpImage *image,
|
|
GimpImageProxy *image_proxy)
|
|
{
|
|
gimp_image_proxy_update_bounding_box (image_proxy);
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_image_bounds_changed (GimpImage *image,
|
|
gint old_x,
|
|
gint old_y,
|
|
GimpImageProxy *image_proxy)
|
|
{
|
|
gimp_image_proxy_update_bounding_box (image_proxy);
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_image_profile_changed (GimpImage *image,
|
|
GimpImageProxy *image_proxy)
|
|
{
|
|
gimp_color_managed_profile_changed (GIMP_COLOR_MANAGED (image_proxy));
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_set_image (GimpImageProxy *image_proxy,
|
|
GimpImage *image)
|
|
{
|
|
if (image_proxy->priv->image)
|
|
{
|
|
g_signal_handlers_disconnect_by_func (
|
|
image_proxy->priv->image,
|
|
gimp_image_proxy_image_frozen_notify,
|
|
image_proxy);
|
|
g_signal_handlers_disconnect_by_func (
|
|
image_proxy->priv->image,
|
|
gimp_image_proxy_image_invalidate_preview,
|
|
image_proxy);
|
|
g_signal_handlers_disconnect_by_func (
|
|
image_proxy->priv->image,
|
|
gimp_image_proxy_image_size_changed,
|
|
image_proxy);
|
|
g_signal_handlers_disconnect_by_func (
|
|
image_proxy->priv->image,
|
|
gimp_image_proxy_image_bounds_changed,
|
|
image_proxy);
|
|
g_signal_handlers_disconnect_by_func (
|
|
image_proxy->priv->image,
|
|
gimp_image_proxy_image_profile_changed,
|
|
image_proxy);
|
|
|
|
g_object_unref (image_proxy->priv->image);
|
|
}
|
|
|
|
image_proxy->priv->image = image;
|
|
|
|
if (image_proxy->priv->image)
|
|
{
|
|
g_object_ref (image_proxy->priv->image);
|
|
|
|
g_signal_connect (
|
|
image_proxy->priv->image, "notify::frozen",
|
|
G_CALLBACK (gimp_image_proxy_image_frozen_notify),
|
|
image_proxy);
|
|
g_signal_connect (
|
|
image_proxy->priv->image, "invalidate-preview",
|
|
G_CALLBACK (gimp_image_proxy_image_invalidate_preview),
|
|
image_proxy);
|
|
g_signal_connect (
|
|
image_proxy->priv->image, "size-changed",
|
|
G_CALLBACK (gimp_image_proxy_image_size_changed),
|
|
image_proxy);
|
|
g_signal_connect (
|
|
image_proxy->priv->image, "bounds-changed",
|
|
G_CALLBACK (gimp_image_proxy_image_bounds_changed),
|
|
image_proxy);
|
|
g_signal_connect (
|
|
image_proxy->priv->image, "profile-changed",
|
|
G_CALLBACK (gimp_image_proxy_image_profile_changed),
|
|
image_proxy);
|
|
|
|
gimp_image_proxy_update_bounding_box (image_proxy);
|
|
gimp_image_proxy_update_frozen (image_proxy);
|
|
|
|
gimp_viewable_invalidate_preview (GIMP_VIEWABLE (image_proxy));
|
|
}
|
|
}
|
|
|
|
static GimpPickable *
|
|
gimp_image_proxy_get_pickable (GimpImageProxy *image_proxy)
|
|
{
|
|
GimpImage *image = image_proxy->priv->image;
|
|
|
|
if (! image_proxy->priv->show_all)
|
|
return GIMP_PICKABLE (image);
|
|
else
|
|
return GIMP_PICKABLE (gimp_image_get_projection (image));
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_update_bounding_box (GimpImageProxy *image_proxy)
|
|
{
|
|
GimpImage *image = image_proxy->priv->image;
|
|
GeglRectangle bounding_box;
|
|
|
|
if (gimp_viewable_preview_is_frozen (GIMP_VIEWABLE (image_proxy)))
|
|
return;
|
|
|
|
if (! image_proxy->priv->show_all)
|
|
{
|
|
bounding_box.x = 0;
|
|
bounding_box.y = 0;
|
|
bounding_box.width = gimp_image_get_width (image);
|
|
bounding_box.height = gimp_image_get_height (image);
|
|
}
|
|
else
|
|
{
|
|
bounding_box = gimp_projectable_get_bounding_box (
|
|
GIMP_PROJECTABLE (image));
|
|
}
|
|
|
|
if (! gegl_rectangle_equal (&bounding_box,
|
|
&image_proxy->priv->bounding_box))
|
|
{
|
|
image_proxy->priv->bounding_box = bounding_box;
|
|
|
|
gimp_viewable_size_changed (GIMP_VIEWABLE (image_proxy));
|
|
}
|
|
}
|
|
|
|
static void
|
|
gimp_image_proxy_update_frozen (GimpImageProxy *image_proxy)
|
|
{
|
|
gboolean frozen;
|
|
|
|
frozen = gimp_viewable_preview_is_frozen (
|
|
GIMP_VIEWABLE (image_proxy->priv->image));
|
|
|
|
if (frozen != image_proxy->priv->frozen)
|
|
{
|
|
image_proxy->priv->frozen = frozen;
|
|
|
|
if (frozen)
|
|
{
|
|
gimp_viewable_preview_freeze (GIMP_VIEWABLE (image_proxy));
|
|
}
|
|
else
|
|
{
|
|
gimp_viewable_preview_thaw (GIMP_VIEWABLE (image_proxy));
|
|
|
|
gimp_image_proxy_update_bounding_box (image_proxy);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
|
GimpImageProxy *
|
|
gimp_image_proxy_new (GimpImage *image)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_IMAGE (image), NULL);
|
|
|
|
return g_object_new (GIMP_TYPE_IMAGE_PROXY,
|
|
"image", image,
|
|
NULL);
|
|
}
|
|
|
|
GimpImage *
|
|
gimp_image_proxy_get_image (GimpImageProxy *image_proxy)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_IMAGE_PROXY (image_proxy), NULL);
|
|
|
|
return image_proxy->priv->image;
|
|
}
|
|
|
|
void
|
|
gimp_image_proxy_set_show_all (GimpImageProxy *image_proxy,
|
|
gboolean show_all)
|
|
{
|
|
g_return_if_fail (GIMP_IS_IMAGE_PROXY (image_proxy));
|
|
|
|
if (show_all != image_proxy->priv->show_all)
|
|
{
|
|
image_proxy->priv->show_all = show_all;
|
|
|
|
gimp_image_proxy_update_bounding_box (image_proxy);
|
|
}
|
|
}
|
|
|
|
gboolean
|
|
gimp_image_proxy_get_show_all (GimpImageProxy *image_proxy)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_IMAGE_PROXY (image_proxy), FALSE);
|
|
|
|
return image_proxy->priv->show_all;
|
|
}
|
|
|
|
GeglRectangle
|
|
gimp_image_proxy_get_bounding_box (GimpImageProxy *image_proxy)
|
|
{
|
|
g_return_val_if_fail (GIMP_IS_IMAGE_PROXY (image_proxy),
|
|
*GEGL_RECTANGLE (0, 0, 0, 0));
|
|
|
|
return image_proxy->priv->bounding_box;
|
|
}
|