2008-11-05 02:06:36 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
|
|
|
* gimpprojectable.c
|
|
|
|
* Copyright (C) 2008 Michael Natterer <mitch@gimp.org>
|
|
|
|
*
|
2009-01-18 06:28:01 +08:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
2008-11-05 02:06:36 +08:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-18 06:28:01 +08:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2008-11-05 02:06:36 +08:00
|
|
|
* (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
|
2018-07-12 05:27:07 +08:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2008-11-05 02:06:36 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2013-10-15 07:58:39 +08:00
|
|
|
#include <gdk-pixbuf/gdk-pixbuf.h>
|
2008-11-05 02:06:36 +08:00
|
|
|
#include <gegl.h>
|
|
|
|
|
|
|
|
#include "core-types.h"
|
|
|
|
|
|
|
|
#include "gimpmarshal.h"
|
|
|
|
#include "gimpprojectable.h"
|
|
|
|
#include "gimpviewable.h"
|
|
|
|
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
2009-08-26 19:06:55 +08:00
|
|
|
INVALIDATE,
|
2008-11-05 02:06:36 +08:00
|
|
|
FLUSH,
|
2008-11-05 07:22:45 +08:00
|
|
|
STRUCTURE_CHANGED,
|
2018-08-04 00:12:01 +08:00
|
|
|
BOUNDS_CHANGED,
|
2008-11-05 02:06:36 +08:00
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2018-05-27 16:23:24 +08:00
|
|
|
G_DEFINE_INTERFACE (GimpProjectable, gimp_projectable, GIMP_TYPE_VIEWABLE)
|
2008-11-05 02:06:36 +08:00
|
|
|
|
|
|
|
|
|
|
|
static guint projectable_signals[LAST_SIGNAL] = { 0 };
|
|
|
|
|
|
|
|
|
2018-05-27 16:23:24 +08:00
|
|
|
/* private functions */
|
|
|
|
|
2008-11-05 02:06:36 +08:00
|
|
|
|
|
|
|
static void
|
2018-05-27 16:23:24 +08:00
|
|
|
gimp_projectable_default_init (GimpProjectableInterface *iface)
|
2008-11-05 02:06:36 +08:00
|
|
|
{
|
2018-05-27 16:23:24 +08:00
|
|
|
projectable_signals[INVALIDATE] =
|
|
|
|
g_signal_new ("invalidate",
|
|
|
|
G_TYPE_FROM_CLASS (iface),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpProjectableInterface, invalidate),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__INT_INT_INT_INT,
|
|
|
|
G_TYPE_NONE, 4,
|
|
|
|
G_TYPE_INT,
|
|
|
|
G_TYPE_INT,
|
|
|
|
G_TYPE_INT,
|
|
|
|
G_TYPE_INT);
|
|
|
|
|
|
|
|
projectable_signals[FLUSH] =
|
|
|
|
g_signal_new ("flush",
|
|
|
|
G_TYPE_FROM_CLASS (iface),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpProjectableInterface, flush),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__BOOLEAN,
|
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
G_TYPE_BOOLEAN);
|
|
|
|
|
|
|
|
projectable_signals[STRUCTURE_CHANGED] =
|
|
|
|
g_signal_new ("structure-changed",
|
|
|
|
G_TYPE_FROM_CLASS (iface),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpProjectableInterface, structure_changed),
|
|
|
|
NULL, NULL,
|
|
|
|
gimp_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
2018-08-04 00:12:01 +08:00
|
|
|
|
|
|
|
projectable_signals[BOUNDS_CHANGED] =
|
|
|
|
g_signal_new ("bounds-changed",
|
|
|
|
G_TYPE_FROM_CLASS (iface),
|
|
|
|
G_SIGNAL_RUN_FIRST,
|
|
|
|
G_STRUCT_OFFSET (GimpProjectableInterface, bounds_changed),
|
|
|
|
NULL, NULL,
|
2019-08-02 04:01:58 +08:00
|
|
|
gimp_marshal_VOID__INT_INT,
|
|
|
|
G_TYPE_NONE, 2,
|
2018-08-04 00:12:01 +08:00
|
|
|
G_TYPE_INT,
|
|
|
|
G_TYPE_INT);
|
2008-11-05 02:06:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* public functions */
|
|
|
|
|
|
|
|
void
|
2009-08-26 19:06:55 +08:00
|
|
|
gimp_projectable_invalidate (GimpProjectable *projectable,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint width,
|
|
|
|
gint height)
|
2008-11-05 02:06:36 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
|
2009-08-26 19:06:55 +08:00
|
|
|
g_signal_emit (projectable, projectable_signals[INVALIDATE], 0,
|
2008-11-05 02:06:36 +08:00
|
|
|
x, y, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_projectable_flush (GimpProjectable *projectable,
|
|
|
|
gboolean preview_invalidated)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
|
|
|
|
g_signal_emit (projectable, projectable_signals[FLUSH], 0,
|
|
|
|
preview_invalidated);
|
|
|
|
}
|
|
|
|
|
2008-11-05 07:22:45 +08:00
|
|
|
void
|
|
|
|
gimp_projectable_structure_changed (GimpProjectable *projectable)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
|
|
|
|
g_signal_emit (projectable, projectable_signals[STRUCTURE_CHANGED], 0);
|
|
|
|
}
|
|
|
|
|
2018-08-04 00:12:01 +08:00
|
|
|
void
|
|
|
|
gimp_projectable_bounds_changed (GimpProjectable *projectable,
|
|
|
|
gint old_x,
|
2019-08-02 04:01:58 +08:00
|
|
|
gint old_y)
|
2018-08-04 00:12:01 +08:00
|
|
|
{
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
|
|
|
|
g_signal_emit (projectable, projectable_signals[BOUNDS_CHANGED], 0,
|
2019-08-02 04:01:58 +08:00
|
|
|
old_x, old_y);
|
2018-08-04 00:12:01 +08:00
|
|
|
}
|
|
|
|
|
2008-11-05 02:06:36 +08:00
|
|
|
GimpImage *
|
|
|
|
gimp_projectable_get_image (GimpProjectable *projectable)
|
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), NULL);
|
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
2008-11-05 02:06:36 +08:00
|
|
|
|
|
|
|
if (iface->get_image)
|
|
|
|
return iface->get_image (projectable);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2012-03-30 03:09:37 +08:00
|
|
|
const Babl *
|
|
|
|
gimp_projectable_get_format (GimpProjectable *projectable)
|
2009-09-13 01:24:01 +08:00
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
|
|
|
|
2012-03-30 03:09:37 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), NULL);
|
2009-09-13 01:24:01 +08:00
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
2009-09-13 01:24:01 +08:00
|
|
|
|
2012-03-30 03:09:37 +08:00
|
|
|
if (iface->get_format)
|
|
|
|
return iface->get_format (projectable);
|
2009-09-13 01:24:01 +08:00
|
|
|
|
2015-09-03 03:23:13 +08:00
|
|
|
return 0;
|
2009-09-13 01:24:01 +08:00
|
|
|
}
|
|
|
|
|
2009-08-24 21:54:59 +08:00
|
|
|
void
|
|
|
|
gimp_projectable_get_offset (GimpProjectable *projectable,
|
|
|
|
gint *x,
|
|
|
|
gint *y)
|
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
g_return_if_fail (x != NULL);
|
|
|
|
g_return_if_fail (y != NULL);
|
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
2009-08-24 21:54:59 +08:00
|
|
|
|
|
|
|
*x = 0;
|
|
|
|
*y = 0;
|
|
|
|
|
|
|
|
if (iface->get_offset)
|
|
|
|
iface->get_offset (projectable, x, y);
|
|
|
|
}
|
|
|
|
|
2019-08-02 04:01:58 +08:00
|
|
|
GeglRectangle
|
|
|
|
gimp_projectable_get_bounding_box (GimpProjectable *projectable)
|
2008-11-06 04:10:51 +08:00
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
2019-08-02 04:01:58 +08:00
|
|
|
GeglRectangle result = {};
|
2008-11-06 04:10:51 +08:00
|
|
|
|
2019-08-02 04:01:58 +08:00
|
|
|
g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), result);
|
2008-11-06 04:10:51 +08:00
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
2008-11-06 04:10:51 +08:00
|
|
|
|
2019-08-02 04:01:58 +08:00
|
|
|
if (iface->get_bounding_box)
|
|
|
|
result = iface->get_bounding_box (projectable);
|
2008-11-06 04:10:51 +08:00
|
|
|
|
2019-08-02 04:01:58 +08:00
|
|
|
return result;
|
2008-11-06 04:10:51 +08:00
|
|
|
}
|
|
|
|
|
2008-11-05 02:06:36 +08:00
|
|
|
GeglNode *
|
|
|
|
gimp_projectable_get_graph (GimpProjectable *projectable)
|
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_PROJECTABLE (projectable), NULL);
|
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
2008-11-05 02:06:36 +08:00
|
|
|
|
|
|
|
if (iface->get_graph)
|
|
|
|
return iface->get_graph (projectable);
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-11-05 04:13:12 +08:00
|
|
|
|
app: add gimp_projectable_{begin,end}_render()
In pass-through mode, the group layer-stack's input is connected to
the backdrop. However, when rendering the group's projection, we
want to render the stack independently of the backdrop.
Unfortunately, we can't use the stack's graph as a subgraph of two
different graphs.
To work around that, the next few commits add a mechanism for a
projectable to be notified before and after its graph is being
rendered. We use this mechanism to disconnect the stack's graph
from the backdrop before rendering the projection, and reconnect
it afterwards. Yep, it's ugly, but it's better than having to
maintain n copies of (each node of) the graph (each nesting level
requires an extra copy.)
This commit adds {begin,end}_render() functions to GimpProjectable.
These functions should be called right before/after rendering the
projectable's graph.
2017-04-23 02:12:20 +08:00
|
|
|
void
|
|
|
|
gimp_projectable_begin_render (GimpProjectable *projectable)
|
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
app: add gimp_projectable_{begin,end}_render()
In pass-through mode, the group layer-stack's input is connected to
the backdrop. However, when rendering the group's projection, we
want to render the stack independently of the backdrop.
Unfortunately, we can't use the stack's graph as a subgraph of two
different graphs.
To work around that, the next few commits add a mechanism for a
projectable to be notified before and after its graph is being
rendered. We use this mechanism to disconnect the stack's graph
from the backdrop before rendering the projection, and reconnect
it afterwards. Yep, it's ugly, but it's better than having to
maintain n copies of (each node of) the graph (each nesting level
requires an extra copy.)
This commit adds {begin,end}_render() functions to GimpProjectable.
These functions should be called right before/after rendering the
projectable's graph.
2017-04-23 02:12:20 +08:00
|
|
|
|
|
|
|
if (iface->begin_render)
|
|
|
|
iface->begin_render (projectable);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gimp_projectable_end_render (GimpProjectable *projectable)
|
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
app: add gimp_projectable_{begin,end}_render()
In pass-through mode, the group layer-stack's input is connected to
the backdrop. However, when rendering the group's projection, we
want to render the stack independently of the backdrop.
Unfortunately, we can't use the stack's graph as a subgraph of two
different graphs.
To work around that, the next few commits add a mechanism for a
projectable to be notified before and after its graph is being
rendered. We use this mechanism to disconnect the stack's graph
from the backdrop before rendering the projection, and reconnect
it afterwards. Yep, it's ugly, but it's better than having to
maintain n copies of (each node of) the graph (each nesting level
requires an extra copy.)
This commit adds {begin,end}_render() functions to GimpProjectable.
These functions should be called right before/after rendering the
projectable's graph.
2017-04-23 02:12:20 +08:00
|
|
|
|
|
|
|
if (iface->end_render)
|
|
|
|
iface->end_render (projectable);
|
|
|
|
}
|
|
|
|
|
2008-11-05 04:13:12 +08:00
|
|
|
void
|
|
|
|
gimp_projectable_invalidate_preview (GimpProjectable *projectable)
|
|
|
|
{
|
|
|
|
GimpProjectableInterface *iface;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_PROJECTABLE (projectable));
|
|
|
|
|
2019-07-19 01:19:01 +08:00
|
|
|
iface = GIMP_PROJECTABLE_GET_IFACE (projectable);
|
2008-11-05 04:13:12 +08:00
|
|
|
|
|
|
|
if (iface->invalidate_preview)
|
|
|
|
iface->invalidate_preview (projectable);
|
|
|
|
}
|