summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2011-08-06 12:18:32 +0000
committerKrzysztof Kosiński <tweenk.pl@gmail.com>2011-08-06 12:18:32 +0000
commit4dd33aa4d5c57706c7f64f63391174954160a308 (patch)
treeb9d4ea1278348836a718c5e6aaeaff9f82c790bf /src/display
parentPer-item render cache. (diff)
downloadinkscape-4dd33aa4d5c57706c7f64f63391174954160a308.tar.gz
inkscape-4dd33aa4d5c57706c7f64f63391174954160a308.zip
Rewrite NRArenaItem hierarchy into C++
(bzr r10347.1.21)
Diffstat (limited to 'src/display')
-rw-r--r--src/display/Makefile_insert22
-rw-r--r--src/display/canvas-arena.cpp95
-rw-r--r--src/display/canvas-arena.h15
-rw-r--r--src/display/display-forward.h8
-rw-r--r--src/display/drawing-group.cpp141
-rw-r--r--src/display/drawing-group.h61
-rw-r--r--src/display/drawing-image.cpp263
-rw-r--r--src/display/drawing-image.h66
-rw-r--r--src/display/drawing-item.cpp620
-rw-r--r--src/display/drawing-item.h168
-rw-r--r--src/display/drawing-shape.cpp340
-rw-r--r--src/display/drawing-shape.h64
-rw-r--r--src/display/drawing-text.cpp275
-rw-r--r--src/display/drawing-text.h84
-rw-r--r--src/display/grayscale.cpp2
-rw-r--r--src/display/nr-arena-forward.h51
-rw-r--r--src/display/nr-arena-glyphs.cpp439
-rw-r--r--src/display/nr-arena-glyphs.h108
-rw-r--r--src/display/nr-arena-group.cpp300
-rw-r--r--src/display/nr-arena-group.h61
-rw-r--r--src/display/nr-arena-image.cpp390
-rw-r--r--src/display/nr-arena-image.h66
-rw-r--r--src/display/nr-arena-item.cpp932
-rw-r--r--src/display/nr-arena-item.h205
-rw-r--r--src/display/nr-arena-shape.cpp565
-rw-r--r--src/display/nr-arena-shape.h72
-rw-r--r--src/display/nr-arena.cpp23
-rw-r--r--src/display/nr-arena.h23
-rw-r--r--src/display/nr-filter-diffuselighting.cpp1
-rw-r--r--src/display/nr-filter-image.cpp19
-rw-r--r--src/display/nr-filter-slot.cpp3
-rw-r--r--src/display/nr-filter-slot.h7
-rw-r--r--src/display/nr-filter.cpp28
-rw-r--r--src/display/nr-filter.h11
-rw-r--r--src/display/rendermode.h8
35 files changed, 2213 insertions, 3323 deletions
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert
index 53f87efb1..1c51f19a0 100644
--- a/src/display/Makefile_insert
+++ b/src/display/Makefile_insert
@@ -25,8 +25,18 @@ ink_common_sources += \
display/curve.h \
display/drawing-context.cpp \
display/drawing-context.h \
+ display/drawing-group.cpp \
+ display/drawing-group.h \
+ display/drawing-image.cpp \
+ display/drawing-image.h \
+ display/drawing-item.cpp \
+ display/drawing-item.h \
+ display/drawing-shape.cpp \
+ display/drawing-shape.h \
display/drawing-surface.cpp \
display/drawing-surface.h \
+ display/drawing-text.cpp \
+ display/drawing-text.h \
display/gnome-canvas-acetate.cpp \
display/gnome-canvas-acetate.h \
display/grayscale.cpp \
@@ -35,19 +45,9 @@ ink_common_sources += \
display/guideline.h \
display/nr-3dutils.cpp \
display/nr-3dutils.h \
+ display/nr-arena.h \
display/nr-arena.cpp \
display/nr-arena-forward.h \
- display/nr-arena-glyphs.cpp \
- display/nr-arena-glyphs.h \
- display/nr-arena-group.cpp \
- display/nr-arena-group.h \
- display/nr-arena.h \
- display/nr-arena-image.cpp \
- display/nr-arena-image.h \
- display/nr-arena-item.cpp \
- display/nr-arena-item.h \
- display/nr-arena-shape.cpp \
- display/nr-arena-shape.h \
display/nr-filter-blend.cpp \
display/nr-filter-blend.h \
display/nr-filter-colormatrix.cpp \
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index 0f653a258..81416fefb 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -16,12 +16,15 @@
#include "display/sp-canvas-util.h"
#include "helper/sp-marshal.h"
#include "display/nr-arena.h"
-#include "display/nr-arena-group.h"
#include "display/canvas-arena.h"
#include "display/cairo-utils.h"
#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing-group.h"
#include "display/drawing-surface.h"
+using namespace Inkscape;
+
enum {
ARENA_EVENT,
LAST_SIGNAL
@@ -31,6 +34,7 @@ static void sp_canvas_arena_class_init(SPCanvasArenaClass *klass);
static void sp_canvas_arena_init(SPCanvasArena *group);
static void sp_canvas_arena_destroy(GtkObject *object);
+static void sp_canvas_arena_item_deleted(SPCanvasArena *arena, Inkscape::DrawingItem *item);
static void sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf);
static double sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
@@ -39,7 +43,7 @@ static gint sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event);
static gint sp_canvas_arena_send_event (SPCanvasArena *arena, GdkEvent *event);
-static void sp_canvas_arena_request_update (NRArena *arena, NRArenaItem *item, void *data);
+static void sp_canvas_arena_request_update (NRArena *arena, DrawingItem *item, void *data);
static void sp_canvas_arena_request_render (NRArena *arena, NRRectL *area, void *data);
NRArenaEventVector carenaev = {
@@ -105,10 +109,16 @@ sp_canvas_arena_init (SPCanvasArena *arena)
arena->sticky = FALSE;
arena->arena = NRArena::create();
+ nr_object_ref(arena->arena);
arena->arena->canvasarena = arena;
- arena->root = NRArenaGroup::create(arena->arena);
- nr_arena_group_set_transparent (NR_ARENA_GROUP (arena->root), TRUE);
- nr_arena_item_set_cache(arena->root, true);
+ arena->arena->item_deleted.connect(
+ sigc::bind<0>(
+ sigc::ptr_fun(&sp_canvas_arena_item_deleted),
+ arena));
+
+ arena->root = new DrawingGroup(arena->arena);
+ arena->root->setPickChildren(true);
+ arena->root->setCached(true);
arena->active = NULL;
@@ -120,22 +130,11 @@ sp_canvas_arena_destroy (GtkObject *object)
{
SPCanvasArena *arena = SP_CANVAS_ARENA (object);
- if (arena->active) {
- nr_object_unref ((NRObject *) arena->active);
- arena->active = NULL;
- }
-
- if (arena->root) {
- nr_arena_item_unref (arena->root);
- arena->root = NULL;
- }
-
- if (arena->arena) {
- nr_active_object_remove_listener_by_data ((NRActiveObject *) arena->arena, arena);
+ delete arena->root;
- nr_object_unref ((NRObject *) arena->arena);
- arena->arena = NULL;
- }
+ nr_active_object_remove_listener_by_data ((NRActiveObject *) arena->arena, arena);
+ nr_object_unref ((NRObject *) arena->arena);
+ arena->arena = NULL;
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@@ -149,14 +148,12 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
if (((SPCanvasItemClass *) parent_class)->update)
(* ((SPCanvasItemClass *) parent_class)->update) (item, affine, flags);
- arena->gc.transform = affine;
+ arena->ctx.ctm = affine;
- guint reset;
- reset = (flags & SP_CANVAS_UPDATE_AFFINE)? NR_ARENA_ITEM_STATE_ALL : NR_ARENA_ITEM_STATE_NONE;
+ unsigned reset = flags & SP_CANVAS_UPDATE_AFFINE ? DrawingItem::STATE_ALL : 0;
+ arena->root->update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_ALL, reset);
- nr_arena_item_invoke_update (arena->root, Geom::IntRect::infinite(), &arena->gc, NR_ARENA_ITEM_STATE_ALL, reset);
-
- Geom::OptIntRect b = arena->root->bbox;
+ Geom::OptIntRect b = arena->root->visualBounds();
if (b) {
item->x1 = b->left() - 1;
item->y1 = b->top() - 1;
@@ -166,7 +163,7 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
if (arena->cursor) {
/* Mess with enter/leave notifiers */
- NRArenaItem *new_arena = nr_arena_item_invoke_pick (arena->root, arena->c, arena->arena->delta, arena->sticky);
+ DrawingItem *new_arena = arena->root->pick(arena->c, arena->arena->delta, arena->sticky);
if (new_arena != arena->active) {
GdkEventCrossing ec;
ec.window = GTK_WIDGET (item->canvas)->window;
@@ -180,10 +177,7 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
ec.type = GDK_LEAVE_NOTIFY;
sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
}
- /* fixme: This is not optimal - better track ::destroy (Lauris) */
- if (arena->active) nr_object_unref ((NRObject *) arena->active);
arena->active = new_arena;
- if (arena->active) nr_object_ref ((NRObject *) arena->active);
if (arena->active) {
ec.type = GDK_ENTER_NOTIFY;
sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
@@ -193,6 +187,14 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
}
static void
+sp_canvas_arena_item_deleted(SPCanvasArena *arena, Inkscape::DrawingItem *item)
+{
+ if (arena->active == item) {
+ arena->active = NULL;
+ }
+}
+
+static void
sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
{
// todo: handle NR_ARENA_ITEM_RENDER_NO_CACHE
@@ -203,10 +205,8 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
Inkscape::DrawingContext ct(buf->ct, r->min());
- nr_arena_item_invoke_update (arena->root, Geom::IntRect::infinite(), &arena->gc,
- NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
- NR_ARENA_ITEM_STATE_NONE);
- nr_arena_item_invoke_render (ct, arena->root, *r, 0);
+ arena->root->update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_ALL, 0);
+ arena->root->render(ct, *r, 0);
}
static double
@@ -214,11 +214,8 @@ sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_
{
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
- nr_arena_item_invoke_update (arena->root, Geom::IntRect::infinite(), &arena->gc,
- NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_PICK,
- NR_ARENA_ITEM_STATE_NONE);
-
- NRArenaItem *picked = nr_arena_item_invoke_pick (arena->root, p, arena->arena->delta, arena->sticky);
+ arena->root->update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK, 0);
+ DrawingItem *picked = arena->root->pick(p, arena->arena->delta, arena->sticky);
arena->picked = picked;
@@ -244,7 +241,7 @@ sp_canvas_arena_viewbox_changed (SPCanvasItem *item, Geom::IntRect const &new_ar
static gint
sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
{
- NRArenaItem *new_arena;
+ Inkscape::DrawingItem *new_arena;
/* fixme: This sucks, we have to handle enter/leave notifiers */
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
@@ -256,7 +253,6 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
if (!arena->cursor) {
if (arena->active) {
//g_warning ("Cursor entered to arena with already active item");
- nr_object_unref ((NRObject *) arena->active);
}
arena->cursor = TRUE;
@@ -264,9 +260,8 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
arena->c = Geom::Point(event->crossing.x, event->crossing.y);
/* fixme: Not sure abut this, but seems the right thing (Lauris) */
- nr_arena_item_invoke_update (arena->root, Geom::IntRect::infinite(), &arena->gc, NR_ARENA_ITEM_STATE_PICK, NR_ARENA_ITEM_STATE_NONE);
- arena->active = nr_arena_item_invoke_pick (arena->root, arena->c, arena->arena->delta, arena->sticky);
- if (arena->active) nr_object_ref ((NRObject *) arena->active);
+ arena->root->update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK, 0);
+ arena->active = arena->root->pick(arena->c, arena->arena->delta, arena->sticky);
ret = sp_canvas_arena_send_event (arena, event);
}
break;
@@ -274,7 +269,6 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
case GDK_LEAVE_NOTIFY:
if (arena->cursor) {
ret = sp_canvas_arena_send_event (arena, event);
- if (arena->active) nr_object_unref ((NRObject *) arena->active);
arena->active = NULL;
arena->cursor = FALSE;
}
@@ -285,8 +279,8 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
arena->c = Geom::Point(event->motion.x, event->motion.y);
/* fixme: Not sure abut this, but seems the right thing (Lauris) */
- nr_arena_item_invoke_update (arena->root, Geom::IntRect::infinite(), &arena->gc, NR_ARENA_ITEM_STATE_PICK, NR_ARENA_ITEM_STATE_NONE);
- new_arena = nr_arena_item_invoke_pick (arena->root, arena->c, arena->arena->delta, arena->sticky);
+ arena->root->update(Geom::IntRect::infinite(), arena->ctx, DrawingItem::STATE_PICK, 0);
+ new_arena = arena->root->pick(arena->c, arena->arena->delta, arena->sticky);
if (new_arena != arena->active) {
GdkEventCrossing ec;
ec.window = event->motion.window;
@@ -300,9 +294,7 @@ sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
ec.type = GDK_LEAVE_NOTIFY;
ret = sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
}
- if (arena->active) nr_object_unref ((NRObject *) arena->active);
arena->active = new_arena;
- if (arena->active) nr_object_ref ((NRObject *) arena->active);
if (arena->active) {
ec.type = GDK_ENTER_NOTIFY;
ret = sp_canvas_arena_send_event (arena, (GdkEvent *) &ec);
@@ -332,7 +324,7 @@ sp_canvas_arena_send_event (SPCanvasArena *arena, GdkEvent *event)
}
static void
-sp_canvas_arena_request_update (NRArena */*arena*/, NRArenaItem */*item*/, void *data)
+sp_canvas_arena_request_update (NRArena */*arena*/, DrawingItem */*item*/, void *data)
{
sp_canvas_item_request_update (SP_CANVAS_ITEM (data));
}
@@ -373,7 +365,8 @@ sp_canvas_arena_render_surface (SPCanvasArena *ca, cairo_surface_t *surface, NRR
Geom::OptIntRect area = r.upgrade_2geom();
if (!area) return;
Inkscape::DrawingContext ct(surface, area->min());
- nr_arena_item_invoke_render (ct, ca->root, *area, 0);
+ ca->root->update(Geom::IntRect::infinite(), ca->ctx, DrawingItem::STATE_ALL, 0);
+ ca->root->render(ct, *area, 0);
}
diff --git a/src/display/canvas-arena.h b/src/display/canvas-arena.h
index 4cfeccb5a..e63a524f2 100644
--- a/src/display/canvas-arena.h
+++ b/src/display/canvas-arena.h
@@ -15,9 +15,10 @@
#include <cairo.h>
#include <2geom/rect.h>
+#include "display/display-forward.h"
+#include "display/drawing-item.h"
#include "display/sp-canvas.h"
#include "display/sp-canvas-item.h"
-#include "display/nr-arena-item.h"
G_BEGIN_DECLS
@@ -38,19 +39,19 @@ struct _SPCanvasArena {
Geom::Point c; // what is this?
NRArena *arena;
- NRArenaItem *root;
- NRGC gc;
+ Inkscape::DrawingGroup *root;
+ Inkscape::UpdateContext ctx;
- NRArenaItem *active;
+ Inkscape::DrawingItem *active;
/* fixme: */
- NRArenaItem *picked;
- gdouble delta;
+ Inkscape::DrawingItem *picked;
+ double delta;
};
struct _SPCanvasArenaClass {
SPCanvasItemClass parent_class;
- gint (* arena_event) (SPCanvasArena *carena, NRArenaItem *item, GdkEvent *event);
+ gint (* arena_event) (SPCanvasArena *carena, Inkscape::DrawingItem *item, GdkEvent *event);
};
GType sp_canvas_arena_get_type (void);
diff --git a/src/display/display-forward.h b/src/display/display-forward.h
index 288da829a..d7e7d72ab 100644
--- a/src/display/display-forward.h
+++ b/src/display/display-forward.h
@@ -11,9 +11,17 @@ struct SPCanvasGroup;
struct SPCanvasGroupClass;
class SPCurve;
+class NRArena;
+
namespace Inkscape {
class DrawingContext;
class DrawingSurface;
+class DrawingItem;
+class DrawingGroup;
+class DrawingImage;
+class DrawingShape;
+class DrawingGlyphs;
+class DrawingText;
namespace Display {
class TemporaryItem;
diff --git a/src/display/drawing-group.cpp b/src/display/drawing-group.cpp
new file mode 100644
index 000000000..2d40f0a83
--- /dev/null
+++ b/src/display/drawing-group.cpp
@@ -0,0 +1,141 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing-group.h"
+#include "libnr/nr-values.h"
+#include "nr-arena.h"
+#include "style.h"
+
+namespace Inkscape {
+
+DrawingGroup::DrawingGroup(Drawing *drawing)
+ : DrawingItem(drawing)
+ , _style(NULL)
+ , _child_transform(NULL)
+{}
+
+DrawingGroup::~DrawingGroup()
+{
+ if (_style)
+ sp_style_unref(_style);
+}
+
+void
+DrawingGroup::setPickChildren(bool p)
+{
+ _pick_children = p;
+}
+
+void
+DrawingGroup::setStyle(SPStyle *style)
+{
+ _setStyleCommon(_style, style);
+}
+
+void
+DrawingGroup::setChildTransform(Geom::Affine const &new_trans)
+{
+ Geom::Affine current;
+ if (_child_transform) {
+ current = *_child_transform;
+ }
+
+ if (!Geom::are_near(current, new_trans, NR_EPSILON)) {
+ // mark the area where the object was for redraw.
+ _markForRendering();
+ if (new_trans.isIdentity()) {
+ delete _child_transform; // delete NULL; is safe
+ _child_transform = NULL;
+ } else {
+ _child_transform = new Geom::Affine(new_trans);
+ }
+ _markForUpdate(STATE_ALL, true);
+ }
+}
+
+unsigned
+DrawingGroup::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ unsigned beststate = STATE_ALL;
+ bool outline = (_drawing->rendermode == RENDERMODE_OUTLINE);
+
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ UpdateContext child_ctx(ctx);
+ if (_child_transform) {
+ child_ctx.ctm = *_child_transform * ctx.ctm;
+ }
+ i->update(area, child_ctx, flags, reset);
+ }
+ if (beststate & STATE_BBOX) {
+ _bbox = Geom::OptIntRect();
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ if (i->visible()) {
+ _bbox.unionWith(outline ? i->geometricBounds() : i->visualBounds());
+ }
+ }
+ }
+ return beststate;
+}
+
+void
+DrawingGroup::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->render(ct, area, flags);
+ }
+}
+
+void
+DrawingGroup::_clipItem(DrawingContext &ct, Geom::IntRect const &area)
+{
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->clip(ct, area);
+ }
+}
+
+DrawingItem *
+DrawingGroup::_pickItem(Geom::Point const &p, double delta)
+{
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingItem *picked = i->pick(p, delta, false);
+ if (picked) {
+ return _pick_children ? picked : this;
+ }
+ }
+ return NULL;
+}
+
+bool
+DrawingGroup::_canClip()
+{
+ return true;
+}
+
+bool is_drawing_group(DrawingItem *item)
+{
+ return dynamic_cast<DrawingGroup *>(item) != NULL;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-group.h b/src/display/drawing-group.h
new file mode 100644
index 000000000..f7d6a2be3
--- /dev/null
+++ b/src/display/drawing-group.h
@@ -0,0 +1,61 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_GROUP_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_GROUP_H
+
+#include "display/drawing-item.h"
+
+class SPStyle;
+
+namespace Inkscape {
+
+class DrawingGroup
+ : public DrawingItem
+{
+public:
+ DrawingGroup(Drawing *drawing);
+ ~DrawingGroup();
+
+ bool pickChildren() { return _pick_children; }
+ void setPickChildren(bool p);
+
+ void setStyle(SPStyle *style);
+ void setChildTransform(Geom::Affine const &new_trans);
+
+protected:
+ unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual void _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags);
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta);
+ virtual bool _canClip();
+
+ SPStyle *_style;
+ Geom::Affine *_child_transform;
+};
+
+bool is_drawing_group(DrawingItem *item);
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp
new file mode 100644
index 000000000..ea6f6ce3c
--- /dev/null
+++ b/src/display/drawing-image.cpp
@@ -0,0 +1,263 @@
+/**
+ * @file
+ * @brief Bitmap image belonging to an SVG drawing
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/drawing-context.h"
+#include "display/drawing-image.h"
+#include "nr-arena.h"
+#include "preferences.h"
+#include "style.h"
+
+namespace Inkscape {
+
+DrawingImage::DrawingImage(Drawing *drawing)
+ : DrawingItem(drawing)
+ , _pixbuf(NULL)
+ , _surface(NULL)
+ , _style(NULL)
+{}
+
+DrawingImage::~DrawingImage()
+{
+ if (_style)
+ sp_style_unref(_style);
+ if (_pixbuf) {
+ cairo_surface_destroy(_surface);
+ g_object_unref(_pixbuf);
+ }
+}
+
+void
+DrawingImage::setARGB32Pixbuf(GdkPixbuf *pb)
+{
+ // when done in this order, it won't break if pb == image->pixbuf and the refcount is 1
+ if (pb != NULL) {
+ g_object_ref (pb);
+ }
+ if (_pixbuf != NULL) {
+ g_object_unref(_pixbuf);
+ cairo_surface_destroy(_surface);
+ }
+ _pixbuf = pb;
+ _surface = pb ? ink_cairo_surface_create_for_argb32_pixbuf(pb) : NULL;
+
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingImage::setStyle(SPStyle *style)
+{
+ _setStyleCommon(_style, style);
+}
+
+void
+DrawingImage::setScale(double sx, double sy)
+{
+ _scale = Geom::Scale(sx, sy);
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingImage::setOrigin(Geom::Point const &o)
+{
+ _origin = o;
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingImage::setClipbox(Geom::Rect const &box)
+{
+ _clipbox = box;
+ _markForUpdate(STATE_ALL, false);
+}
+
+Geom::Rect
+DrawingImage::bounds() const
+{
+ if (!_pixbuf) return _clipbox;
+
+ double pw = gdk_pixbuf_get_width(_pixbuf);
+ double ph = gdk_pixbuf_get_height(_pixbuf);
+ double vw = pw * _scale[Geom::X];
+ double vh = ph * _scale[Geom::Y];
+ Geom::Point wh(vw, vh);
+ Geom::Rect view(_origin, _origin+wh);
+ Geom::OptRect res = _clipbox & view;
+ Geom::Rect ret = res ? *res : _clipbox;
+
+ return ret;
+}
+
+unsigned
+DrawingImage::_updateItem(Geom::IntRect const &, UpdateContext const &, unsigned, unsigned)
+{
+ _markForRendering();
+
+ // Calculate bbox
+ if (_pixbuf) {
+ Geom::Rect r = bounds() * _ctm;
+ _bbox = r.roundOutwards();
+ } else {
+ _bbox = Geom::OptIntRect();
+ }
+
+ return STATE_ALL;
+}
+
+void
+DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ bool outline = (_drawing->rendermode == RENDERMODE_OUTLINE);
+
+ if (!outline) {
+ if (!_pixbuf) return;
+
+ Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+ ct.newPath();
+ ct.rectangle(_clipbox);
+ ct.clip();
+
+ ct.translate(_origin);
+ ct.scale(_scale);
+ ct.setSource(_surface, 0, 0);
+
+ cairo_matrix_t tt;
+ Geom::Affine total;
+ cairo_get_matrix(ct.raw(), &tt);
+ ink_matrix_to_2geom(total, tt);
+
+ if (total.expansionX() > 1.0 || total.expansionY() > 1.0) {
+ cairo_pattern_t *p = cairo_get_source(ct.raw());
+ cairo_pattern_set_filter(p, CAIRO_FILTER_NEAREST);
+ }
+ //ct.paint(_opacity);
+ ct.paint();
+
+ } else { // outline; draw a rect instead
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
+
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+ ct.newPath();
+
+ Geom::Rect r = bounds();
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
+
+ ct.moveTo(c00);
+ // the box
+ ct.lineTo(c10);
+ ct.lineTo(c11);
+ ct.lineTo(c01);
+ ct.lineTo(c00);
+ // the diagonals
+ ct.lineTo(c11);
+ ct.moveTo(c10);
+ ct.lineTo(c01);
+ }
+
+ ct.setLineWidth(0.5);
+ ct.setSource(rgba);
+ ct.stroke();
+ }
+}
+
+/** Calculates the closest distance from p to the segment a1-a2*/
+static double
+distance_to_segment (Geom::Point const &p, Geom::Point const &a1, Geom::Point const &a2)
+{
+ // calculate sides of the triangle and their squares
+ double d1 = Geom::L2(p - a1);
+ double d1_2 = d1 * d1;
+ double d2 = Geom::L2(p - a2);
+ double d2_2 = d2 * d2;
+ double a = Geom::L2(a1 - a2);
+ double a_2 = a * a;
+
+ // if one of the angles at the base is > 90, return the corresponding side
+ if (d1_2 + a_2 <= d2_2) return d1;
+ if (d2_2 + a_2 <= d1_2) return d2;
+
+ // otherwise calculate the height to the base
+ double peri = (a + d1 + d2)/2;
+ return (2*sqrt(peri * (peri - a) * (peri - d1) * (peri - d2))/a);
+}
+
+DrawingItem *
+DrawingImage::_pickItem(Geom::Point const &p, double delta)
+{
+ if (!_pixbuf) return NULL;
+
+ bool outline = (_drawing->rendermode == RENDERMODE_OUTLINE);
+
+ if (outline) {
+ Geom::Rect r = bounds();
+
+ Geom::Point c00 = r.corner(0);
+ Geom::Point c01 = r.corner(3);
+ Geom::Point c11 = r.corner(2);
+ Geom::Point c10 = r.corner(1);
+
+ // frame
+ if (distance_to_segment (p, c00, c10) < delta) return this;
+ if (distance_to_segment (p, c10, c11) < delta) return this;
+ if (distance_to_segment (p, c11, c01) < delta) return this;
+ if (distance_to_segment (p, c01, c00) < delta) return this;
+
+ // diagonals
+ if (distance_to_segment (p, c00, c11) < delta) return this;
+ if (distance_to_segment (p, c10, c01) < delta) return this;
+
+ return NULL;
+
+ } else {
+ unsigned char *const pixels = gdk_pixbuf_get_pixels(_pixbuf);
+ int width = gdk_pixbuf_get_width(_pixbuf);
+ int height = gdk_pixbuf_get_height(_pixbuf);
+ int rowstride = gdk_pixbuf_get_rowstride(_pixbuf);
+
+ Geom::Point tp = p * _ctm.inverse();
+ Geom::Rect r = bounds();
+
+ if (!r.contains(tp))
+ return NULL;
+
+ double vw = width * _scale[Geom::X];
+ double vh = height * _scale[Geom::Y];
+ int ix = floor((tp[Geom::X] - _origin[Geom::X]) / vw * width);
+ int iy = floor((tp[Geom::Y] - _origin[Geom::Y]) / vh * height);
+
+ if ((ix < 0) || (iy < 0) || (ix >= width) || (iy >= height))
+ return NULL;
+
+ unsigned char *pix_ptr = pixels + iy * rowstride + ix * 4;
+ // pick if the image is less than 99% transparent
+ float alpha = (pix_ptr[3] / 255.0f) * _opacity;
+ return alpha > 0.01 ? this : NULL;
+ }
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-image.h b/src/display/drawing-image.h
new file mode 100644
index 000000000..570c10360
--- /dev/null
+++ b/src/display/drawing-image.h
@@ -0,0 +1,66 @@
+/**
+ * @file
+ * @brief Bitmap image belonging to an SVG drawing
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_IMAGE_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_IMAGE_H
+
+#include <cairo.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <2geom/transforms.h>
+
+#include "display/drawing-item.h"
+
+namespace Inkscape {
+
+class DrawingImage
+ : public DrawingItem
+{
+public:
+ DrawingImage(Drawing *drawing);
+ ~DrawingImage();
+
+ void setARGB32Pixbuf(GdkPixbuf *pb);
+ void setStyle(SPStyle *style);
+ void setScale(double sx, double sy);
+ void setOrigin(Geom::Point const &o);
+ void setClipbox(Geom::Rect const &box);
+ Geom::Rect bounds() const;
+
+protected:
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual void _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta);
+
+ GdkPixbuf *_pixbuf;
+ cairo_surface_t *_surface;
+ SPStyle *_style;
+
+ // TODO: the following three should probably be merged into a new Geom::Viewbox object
+ Geom::Rect _clipbox; ///< for preserveAspectRatio
+ Geom::Point _origin;
+ Geom::Scale _scale;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
new file mode 100644
index 000000000..318ff28e7
--- /dev/null
+++ b/src/display/drawing-item.cpp
@@ -0,0 +1,620 @@
+/**
+ * @file
+ * @brief Canvas item belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/cairo-templates.h"
+#include "display/drawing-context.h"
+#include "display/drawing-item.h"
+#include "display/drawing-group.h"
+#include "display/drawing-surface.h"
+#include "nr-arena.h"
+#include "nr-filter.h"
+#include "preferences.h"
+#include "style.h"
+
+namespace Inkscape {
+
+DrawingItem::DrawingItem(Drawing *drawing)
+ : _drawing(drawing)
+ , _parent(NULL)
+ , _key(0)
+ , _opacity(1.0)
+ , _transform(NULL)
+ , _clip(NULL)
+ , _mask(NULL)
+ , _filter(NULL)
+ , _user_data(NULL)
+ , _cache(NULL)
+ , _state(0)
+ , _visible(true)
+ , _sensitive(true)
+ , _cached(0)
+ , _propagate(0)
+// , _renders_opacity(0)
+ , _clip_child(0)
+ , _mask_child(0)
+ , _pick_children(0)
+{
+ nr_object_ref(_drawing);
+}
+
+DrawingItem::~DrawingItem()
+{
+ _drawing->item_deleted.emit(this);
+ //if (!_children.empty()) {
+ // g_warning("Removing item with children");
+ //}
+
+ // remove from the set of cached items
+ if (_cached) {
+ _drawing->cached_items.erase(this);
+ }
+ // remove this item from parent's children list
+ // due to the effect of clearChildren(), this only happens for the top-level deleted item
+ if (_parent) {
+ _markForRendering();
+ // we cannot call setClip(NULL) or setMask(NULL),
+ // because that would be an endless loop
+ if (_clip_child) {
+ _parent->_clip = NULL;
+ } else if (_mask_child) {
+ _parent->_mask = NULL;
+ } else {
+ ChildrenList::iterator ithis = _parent->_children.iterator_to(*this);
+ _parent->_children.erase(ithis);
+ }
+ _parent->_markForUpdate(STATE_ALL, false);
+ }
+ clearChildren();
+ delete _transform;
+ delete _clip;
+ delete _mask;
+ delete _filter;
+ nr_object_unref(_drawing);
+}
+
+DrawingItem *
+DrawingItem::parent() const
+{
+ //if (_clip_child || _mask_child)
+ // return NULL;
+
+ return _parent;
+}
+
+void
+DrawingItem::appendChild(DrawingItem *item)
+{
+ item->_parent = this;
+ _children.push_back(*item);
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingItem::prependChild(DrawingItem *item)
+{
+ item->_parent = this;
+ _children.push_front(*item);
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingItem::clearChildren()
+{
+ // prevent children from referencing the parent during deletion
+ // this way, children won't try to remove themselves from a list
+ // from which they have already been removed by clear_and_dispose
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->_parent = NULL;
+ }
+ _children.clear_and_dispose(DeleteDisposer());
+}
+
+void
+DrawingItem::setTransform(Geom::Affine const &new_trans)
+{
+ Geom::Affine current;
+ if (_transform) {
+ current = *_transform;
+ }
+
+ if (!Geom::are_near(current, new_trans, NR_EPSILON)) {
+ // mark the area where the object was for redraw.
+ _markForRendering();
+ if (new_trans.isIdentity()) {
+ delete _transform; // delete NULL; is safe
+ _transform = NULL;
+ } else {
+ _transform = new Geom::Affine(new_trans);
+ }
+ _markForUpdate(STATE_ALL, true);
+ }
+}
+
+void
+DrawingItem::setOpacity(float opacity)
+{
+ _opacity = opacity;
+ _markForRendering();
+}
+
+void
+DrawingItem::setVisible(bool v)
+{
+ _visible = v;
+ _markForRendering();
+}
+
+void
+DrawingItem::setSensitive(bool s)
+{
+ _sensitive = s;
+}
+
+void
+DrawingItem::setCached(bool c)
+{
+ _cached = c;
+ if (c) {
+ _drawing->cached_items.insert(this);
+ } else {
+ _drawing->cached_items.erase(this);
+ }
+ _markForUpdate(STATE_CACHE, false);
+}
+
+void
+DrawingItem::setClip(DrawingItem *item)
+{
+ _markForRendering();
+ delete _clip;
+ _clip = item;
+ if (item) {
+ item->_parent = this;
+ item->_clip_child = true;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
+void
+DrawingItem::setMask(DrawingItem *item)
+{
+ _markForRendering();
+ delete _mask;
+ _mask = item;
+ if (item) {
+ item->_parent = this;
+ item->_mask_child = true;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
+void
+DrawingItem::setZOrder(unsigned z)
+{
+ if (!_parent) return;
+
+ ChildrenList::iterator it = _parent->_children.iterator_to(*this);
+ _parent->_children.erase(it);
+
+ ChildrenList::iterator i = _parent->_children.begin();
+ std::advance(i, std::min(z, unsigned(_parent->_children.size())));
+ _parent->_children.insert(i, *this);
+ _markForRendering();
+}
+
+void
+DrawingItem::setItemBounds(Geom::OptRect const &bounds)
+{
+ _item_bbox = bounds;
+}
+
+void
+DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ bool render_filters = (_drawing->rendermode == Inkscape::RENDERMODE_NORMAL);
+ bool outline = (_drawing->rendermode == Inkscape::RENDERMODE_OUTLINE);
+
+ // Set reset flags according to propagation status
+ if (_propagate) {
+ reset |= ~_state;
+ _propagate = FALSE;
+ }
+ _state &= ~reset; // reset state of this item
+
+ if ((~_state & flags) == 0) return; // nothing to do
+
+ // TODO this might be wrong
+ if (_state & STATE_BBOX) {
+ // we have up-to-date bbox
+ if (!area.intersects(outline ? _bbox : _drawbox)) return;
+ }
+
+ UpdateContext child_ctx(ctx);
+ if (_transform) {
+ child_ctx.ctm = *_transform * ctx.ctm;
+ }
+ /* Remember the transformation matrix */
+ Geom::Affine ctm_change = _ctm.inverse() * child_ctx.ctm;
+ _ctm = child_ctx.ctm;
+
+ // update _bbox
+ _state = _updateItem(area, child_ctx, flags, reset);
+
+ // compute drawbox
+ if (_filter && render_filters && _item_bbox) {
+ _drawbox = _filter->compute_drawbox(this, *_item_bbox);
+ } else {
+ _drawbox = _bbox;
+ }
+
+ // Clipping
+ if (_clip) {
+ _clip->update(area, child_ctx, flags, reset);
+ if (outline) {
+ _bbox.unionWith(_clip->_bbox);
+ } else {
+ _drawbox.intersectWith(_clip->_bbox);
+ }
+ }
+ // masking
+ if (_mask) {
+ _mask->update(area, child_ctx, flags, reset);
+ if (outline) {
+ _bbox.unionWith(_mask->_bbox);
+ } else {
+ // for masking, we need full drawbox of mask
+ _drawbox.intersectWith(_mask->_drawbox);
+ }
+ }
+
+ // update cache if enabled
+ if (_cached) {
+ Geom::OptIntRect cl = _drawing->cache_limit;
+ cl.intersectWith(_drawbox);
+ if (cl) {
+ if (_cache) {
+ // this takes care of invalidation on transform
+ _cache->resizeAndTransform(*cl, ctm_change);
+ } else {
+ _cache = new Inkscape::DrawingCache(*cl);
+ // the cache is initially dirty
+ }
+ } else {
+ // disable cache for this item - not visible
+ delete _cache;
+ _cache = NULL;
+ }
+ }
+
+ // now that we know drawbox, dirty the corresponding rect on canvas
+ // unless filtered, groups do not need to render by themselves, only their members
+ if (!is_drawing_group(this) || (_filter && render_filters)) {
+ if (flags & ~STATE_CACHE) {
+ _markForRendering();
+ }
+ }
+}
+
+struct MaskLuminanceToAlpha {
+ guint32 operator()(guint32 in) {
+ EXTRACT_ARGB32(in, a, r, g, b)
+ // the operation of unpremul -> luminance-to-alpha -> multiply by alpha
+ // is equivalent to luminance-to-alpha on premultiplied color values
+ // original computation in double: r*0.2125 + g*0.7154 + b*0.0721
+ guint32 ao = r*109 + g*366 + b*37; // coeffs add up to 512
+ return ((ao + 256) << 15) & 0xff000000; // equivalent to ((ao + 256) / 512) << 24
+ }
+};
+
+void
+DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ bool outline = (_drawing->rendermode == Inkscape::RENDERMODE_OUTLINE);
+ bool render_filters = (_drawing->rendermode == Inkscape::RENDERMODE_NORMAL);
+
+ /* If we are invisible, just return successfully */
+ if (!_visible) return;
+
+ if (outline) {
+ _renderOutline(ct, area, flags);
+ return;
+ }
+
+ // carea is the bounding box for intermediate rendering.
+ Geom::OptIntRect carea = Geom::intersect(area, _drawbox);
+ if (!carea) return;
+
+ // render from cache
+ if (_cached && _cache) {
+ if (_cache->paintFromCache(ct, *carea))
+ return;
+ }
+
+ // expand carea to contain the dependent area of filters.
+ if (_filter && render_filters) {
+ _filter->area_enlarge(*carea, this);
+ carea.intersectWith(_drawbox);
+ }
+
+ // determine whether this shape needs intermediate rendering.
+ bool needs_intermediate_rendering = false;
+ bool &nir = needs_intermediate_rendering;
+ bool needs_opacity = (_opacity < 0.995);
+
+ // this item needs an intermediate rendering if:
+ nir |= (_clip != NULL); // 1. it has a clipping path
+ nir |= (_mask != NULL); // 2. it has a mask
+ nir |= (_filter != NULL && render_filters); // 3. it has a filter
+ nir |= needs_opacity; // 4. it is non-opaque
+
+ /* How the rendering is done.
+ *
+ * Clipping, masking and opacity are done by rendering them to a surface
+ * and then compositing the object's rendering onto it with the IN operator.
+ * The object itself is rendered to a group.
+ *
+ * Opacity is done by rendering the clipping path with an alpha
+ * value corresponding to the opacity. If there is no clipping path,
+ * the entire intermediate surface is painted with alpha corresponding
+ * to the opacity value.
+ */
+
+ // short-circuit the simple case.
+ if (!needs_intermediate_rendering) {
+ if (_cached && _cache) {
+ Inkscape::DrawingContext cachect(*_cache);
+ cachect.rectangle(area);
+ cachect.clip();
+
+ { // 1. clear the corresponding part of cache
+ Inkscape::DrawingContext::Save save(cachect);
+ cachect.setSource(0,0,0,0);
+ cachect.setOperator(CAIRO_OPERATOR_SOURCE);
+ cachect.paint();
+ }
+ // 2. render to cache
+ _renderItem(cachect, *carea, flags);
+ // 3. copy from cache to output
+ Inkscape::DrawingContext::Save save(ct);
+ ct.rectangle(*carea);
+ ct.clip();
+ ct.setSource(_cache);
+ ct.paint();
+ // 4. mark as clean
+ _cache->markClean(area);
+ return;
+ } else {
+ _renderItem(ct, *carea, flags);
+ return;
+ }
+ }
+
+ DrawingSurface intermediate(*carea);
+ DrawingContext ict(intermediate);
+
+ // 1. Render clipping path with alpha = opacity.
+ ict.setSource(0,0,0,_opacity);
+ // Since clip can be combined with opacity, the result could be incorrect
+ // for overlapping clip children. To fix this we use the SOURCE operator
+ // instead of the default OVER.
+ ict.setOperator(CAIRO_OPERATOR_SOURCE);
+ if (_clip) {
+ _clip->clip(ict, *carea); // fixme: carea or area?
+ } else {
+ // if there is no clipping path, fill the entire surface with alpha = opacity.
+ ict.paint();
+ }
+ ict.setOperator(CAIRO_OPERATOR_OVER); // reset back to default
+
+ // 2. Render the mask if present and compose it with the clipping path + opacity.
+ if (_mask) {
+ ict.pushGroup();
+ _mask->render(ict, *carea, flags);
+
+ cairo_surface_t *mask_s = ict.rawTarget();
+ // Convert mask's luminance to alpha
+ ink_cairo_surface_filter(mask_s, mask_s, MaskLuminanceToAlpha());
+ ict.popGroupToSource();
+ ict.setOperator(CAIRO_OPERATOR_IN);
+ ict.paint();
+ ict.setOperator(CAIRO_OPERATOR_OVER);
+ }
+
+ // 3. Render object itself.
+ ict.pushGroup();
+ _renderItem(ict, *carea, flags);
+
+ // 4. Apply filter.
+ if (_filter && render_filters) {
+ _filter->render(this, ct, ict);
+ // Note that because the object was rendered to a group,
+ // the internals of the filter need to use cairo_get_group_target()
+ // instead of cairo_get_target().
+ }
+
+ // 5. Render object inside the composited mask + clip
+ ict.popGroupToSource();
+ ict.setOperator(CAIRO_OPERATOR_IN);
+ ict.paint();
+
+ // 6. Paint the completed rendering onto the base context (or into cache)
+ if (_cached && _cache) {
+ DrawingContext cachect(*_cache);
+ cachect.rectangle(area);
+ cachect.clip();
+ cachect.setOperator(CAIRO_OPERATOR_SOURCE);
+ cachect.setSource(&intermediate);
+ cachect.paint();
+ _cache->markClean(area);
+ }
+ ct.setSource(&intermediate);
+ ct.paint();
+ ct.setSource(0,0,0,0);
+ // the call above is to clear a ref on the intermediate surface held by ct
+}
+
+void
+DrawingItem::_renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ // intersect with bbox rather than drawbox, as we want to render things outside
+ // of the clipping path as well
+ Geom::OptIntRect carea = Geom::intersect(area, _bbox);
+ if (!carea) return;
+
+ // just render everything: item, clip, mask
+ // First, render the object itself
+ _renderItem(ct, *carea, flags);
+
+ // render clip and mask, if any
+ guint32 saved_rgba = _drawing->outlinecolor; // save current outline color
+ // render clippath as an object, using a different color
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ if (_clip) {
+ _drawing->outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
+ _clip->render(ct, *carea, flags);
+ }
+ // render mask as an object, using a different color
+ if (_mask) {
+ _drawing->outlinecolor = prefs->getInt("/options/wireframecolors/masks", 0x0000ffff); // blue masks
+ _mask->render(ct, *carea, flags);
+ }
+ _drawing->outlinecolor = saved_rgba; // restore outline color
+}
+
+void
+DrawingItem::clip(Inkscape::DrawingContext &ct, Geom::IntRect const &area)
+{
+ // don't bother if the object does not implement clipping (e.g. DrawingImage)
+ if (!_canClip()) return;
+ if (!_visible) return;
+ if (!area.intersects(_bbox)) return;
+
+ // The item used as the clipping path itself has a clipping path.
+ // Render this item's clipping path onto a temporary surface, then composite it
+ // with the item using the IN operator
+ if (_clip) {
+ ct.pushAlphaGroup();
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.setSource(0,0,0,1);
+ _clip->clip(ct, area);
+ }
+ ct.pushAlphaGroup();
+ }
+
+ // rasterize the clipping path
+ _clipItem(ct, area);
+
+ if (_clip) {
+ ct.popGroupToSource();
+ ct.setOperator(CAIRO_OPERATOR_IN);
+ ct.paint();
+ ct.popGroupToSource();
+ ct.setOperator(CAIRO_OPERATOR_SOURCE);
+ ct.paint();
+ }
+}
+
+DrawingItem *
+DrawingItem::pick(Geom::Point const &p, double delta, bool sticky)
+{
+ // Sometimes there's no BBOX in state, reason unknown (bug 992817)
+ // I made this not an assert to remove the warning
+ if (!(_state & STATE_BBOX) || !(_state & STATE_PICK))
+ return NULL;
+
+ if (!sticky && !(_visible && _sensitive))
+ return NULL;
+
+ if (!_bbox) return NULL;
+ Geom::Rect expanded(*_bbox);
+ expanded.expandBy(delta);
+
+ if (expanded.contains(p)) {
+ return _pickItem(p, delta);
+ }
+ return NULL;
+}
+
+void
+DrawingItem::_markForRendering()
+{
+ bool outline = (_drawing->rendermode == Inkscape::RENDERMODE_OUTLINE);
+ Geom::OptIntRect dirty = outline ? _bbox : _drawbox;
+ if (!dirty) return;
+
+ // dirty the caches of all parents
+ for (DrawingItem *i = this; i; i = i->_parent) {
+ if (i->_cached && i->_cache) {
+ i->_cache->markDirty(*dirty);
+ }
+ }
+
+ nr_arena_request_render_rect (_drawing, dirty);
+}
+
+void
+DrawingItem::_markForUpdate(unsigned flags, bool propagate)
+{
+ // here we can't simply assign because a previous markForUpdate call
+ // could have had propagate=true even if this one has propagate=false
+ if (propagate)
+ _propagate = true;
+
+ if (_state & flags) {
+ _state &= ~flags;
+ if (_parent) {
+ _parent->_markForUpdate(flags, false);
+ } else {
+ nr_arena_request_update (_drawing, this);
+ }
+ }
+}
+
+void
+DrawingItem::_setStyleCommon(SPStyle *&_style, SPStyle *style)
+{
+ if (style) sp_style_ref(style);
+ if (_style) sp_style_unref(_style);
+ _style = style;
+
+ // if group has a filter
+ if (style->filter.set && style->getFilter()) {
+ if (!_filter) {
+ int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
+ _filter = new Inkscape::Filters::Filter(primitives);
+ }
+ sp_filter_build_renderer(SP_FILTER(style->getFilter()), _filter);
+ } else {
+ // no filter set for this group
+ delete _filter;
+ _filter = NULL;
+ }
+
+ /*
+ if (style && style->enable_background.set
+ && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
+ _background_new = true;
+ }*/
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h
new file mode 100644
index 000000000..b34ddf0e4
--- /dev/null
+++ b/src/display/drawing-item.h
@@ -0,0 +1,168 @@
+/**
+ * @file
+ * @brief Canvas item belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+#include <exception>
+#include <boost/intrusive/list.hpp>
+#include <2geom/rect.h>
+#include <2geom/affine.h>
+
+class NRArena;
+class SPStyle;
+void nr_arena_set_cache_limit(NRArena *, Geom::OptIntRect const &);
+
+namespace Inkscape {
+
+typedef ::NRArena Drawing;
+class DrawingContext;
+class DrawingCache;
+class DrawingItem;
+namespace Filters { class Filter; }
+
+struct UpdateContext {
+ Geom::Affine ctm;
+};
+
+class InvalidItemException : public std::exception {
+ virtual const char *what() const throw() {
+ return "Invalid item in drawing";
+ }
+};
+
+typedef boost::intrusive::list_base_hook<> ChildrenListHook;
+
+class DrawingItem
+ : public ChildrenListHook
+{
+public:
+ enum RenderFlags {
+ RENDER_DEFAULT = 0,
+ RENDER_CACHE_ONLY = 1,
+ RENDER_BYPASS_CACHE = 2
+ };
+ enum StateFlags {
+ STATE_NONE = 0,
+ STATE_BBOX = (1<<0), // geometric bounding box is up-to-date
+ STATE_DRAWBOX = (1<<1), // visual bounding box is up-to-date
+ STATE_CACHE = (1<<2), // cache extents and clean area are up-to-date
+ STATE_PICK = (1<<3), // can process pick requests
+ STATE_RENDER = (1<<4), // can be rendered
+ STATE_ALL = (1<<5)-1
+ };
+ typedef boost::intrusive::list<DrawingItem> ChildrenList;
+
+ DrawingItem(Drawing *drawing);
+ virtual ~DrawingItem();
+
+ Geom::OptIntRect geometricBounds() const { return _bbox; }
+ Geom::OptIntRect visualBounds() const { return _drawbox; }
+ Geom::OptRect itemBounds() const { return _item_bbox; }
+ Geom::Affine ctm() const { return _ctm; }
+ Geom::Affine transform() const { return _transform ? *_transform : Geom::identity(); }
+ Drawing *drawing() const { return _drawing; }
+ DrawingItem *parent() const;
+
+ void appendChild(DrawingItem *item);
+ void prependChild(DrawingItem *item);
+ void clearChildren();
+
+ bool visible() const { return _visible; }
+ void setVisible(bool v);
+ bool sensitive() const { return _sensitive; }
+ void setSensitive(bool v);
+ bool cached() const { return _cached; }
+ void setCached(bool c);
+
+ void setOpacity(float opacity);
+ void setTransform(Geom::Affine const &trans);
+ void setClip(DrawingItem *item);
+ void setMask(DrawingItem *item);
+ void setZOrder(unsigned z);
+ void setItemBounds(Geom::OptRect const &bounds);
+
+ void setKey(unsigned key) { _key = key; }
+ unsigned key() const { return _key; }
+ void setData(void *data) { _user_data = data; }
+ void *data() const { return _user_data; }
+
+ void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = STATE_ALL, unsigned reset = 0);
+ void render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags = 0);
+ void clip(DrawingContext &ct, Geom::IntRect const &area);
+ DrawingItem *pick(Geom::Point const &p, double delta, bool sticky);
+
+protected:
+ void _renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsigned flags);
+ void _markForUpdate(unsigned state, bool propagate);
+ void _markForRendering();
+ void _setStyleCommon(SPStyle *&_style, SPStyle *style);
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset) { return 0; }
+ virtual void _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags) {}
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area) {}
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta) { return NULL; }
+ virtual bool _canClip() { return false; }
+
+ Drawing *_drawing;
+ DrawingItem *_parent;
+ ChildrenList _children;
+
+ unsigned _key; ///< Some SPItems can have more than one NRArenaItem;
+ /// this value is a hack used to distinguish between them
+ float _opacity;
+
+ Geom::Affine *_transform; ///< Incremental transform from parent to this item's coords
+ Geom::Affine _ctm; ///< Total transform from item coords to display coords
+ Geom::OptIntRect _bbox; ///< Bounding box in display (pixel) coords
+ Geom::OptIntRect _drawbox; ///< Bounding box enlarged by filters, shrinked by clips and masks
+ Geom::OptRect _item_bbox; ///< Bounding box in item coordinates
+
+ DrawingItem *_clip;
+ DrawingItem *_mask;
+ Inkscape::Filters::Filter *_filter;
+ void *_user_data; ///< Used to associate DrawingItems with SPItems that created them
+ DrawingCache *_cache;
+
+ unsigned _state : 8;
+ unsigned _visible : 1;
+ unsigned _sensitive : 1; ///< Whether this item responds to events
+ unsigned _cached : 1; ///< Whether the rendering is stored for reuse
+ unsigned _propagate : 1; ///< Whether to call update for all children on next update
+ //unsigned _renders_opacity : 1; ///< Whether object needs temporary surface for opacity
+ unsigned _clip_child : 1; ///< If set, this is not a child of _parent, but a clipping path
+ unsigned _mask_child : 1; ///< If set, this is not a child of _parent, but a mask
+ unsigned _pick_children : 1; ///< For groups: if true, children are returned from pick(),
+ /// otherwise the group is returned
+
+ // temporary hacks until I rewrite NRArena to Inkscape::Drawing
+ friend class NRArena;
+ friend void ::nr_arena_set_cache_limit(NRArena *, Geom::OptIntRect const &);
+};
+
+struct DeleteDisposer {
+ void operator()(DrawingItem *item) { delete item; }
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp
new file mode 100644
index 000000000..1a56eea9b
--- /dev/null
+++ b/src/display/drawing-shape.cpp
@@ -0,0 +1,340 @@
+/**
+ * @file
+ * @brief Shape (styled path) belonging to an SVG drawing
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+#include <2geom/curves.h>
+#include <2geom/pathvector.h>
+#include <2geom/svg-path.h>
+#include <2geom/svg-path-parser.h>
+
+#include "display/cairo-utils.h"
+#include "display/canvas-arena.h"
+#include "display/canvas-bpath.h"
+#include "display/curve.h"
+#include "display/drawing-context.h"
+#include "display/drawing-group.h"
+#include "display/drawing-shape.h"
+#include "display/nr-arena.h"
+#include "helper/geom-curves.h"
+#include "helper/geom.h"
+#include "libnr/nr-convert2geom.h"
+#include "preferences.h"
+#include "style.h"
+#include "svg/svg.h"
+
+namespace Inkscape {
+
+DrawingShape::DrawingShape(Drawing *drawing)
+ : DrawingItem(drawing)
+ , _curve(NULL)
+ , _style(NULL)
+ , _last_pick(NULL)
+ , _repick_after(0)
+{}
+
+DrawingShape::~DrawingShape()
+{
+ if (_style)
+ sp_style_unref(_style);
+ if (_curve)
+ _curve->unref();
+}
+
+void
+DrawingShape::setPath(SPCurve *curve)
+{
+ _markForRendering();
+
+ if (_curve) {
+ _curve->unref();
+ _curve = NULL;
+ }
+ if (curve) {
+ _curve = curve;
+ curve->ref();
+ }
+
+ _markForUpdate(STATE_ALL, false);
+}
+
+void
+DrawingShape::setStyle(SPStyle *style)
+{
+ _setStyleCommon(_style, style);
+ _nrstyle.set(style);
+}
+
+void
+DrawingShape::setPaintBox(Geom::Rect const &box)
+{
+ _paintbox = box;
+ _markForUpdate(STATE_ALL, false);
+}
+
+unsigned
+DrawingShape::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ Geom::OptRect boundingbox;
+
+ unsigned beststate = STATE_ALL;
+
+ // update markers
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->update(area, ctx, flags, reset);
+ }
+
+ if (!(flags & STATE_RENDER)) {
+ /* We do not have to create rendering structures */
+ if (flags & STATE_BBOX) {
+ if (_curve) {
+ boundingbox = bounds_exact_transformed(_curve->get_pathvector(), ctx.ctm);
+ if (boundingbox) {
+ _bbox = boundingbox->roundOutwards();
+ } else {
+ _bbox = Geom::OptIntRect();
+ }
+ }
+ if (beststate & STATE_BBOX) {
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ _bbox.unionWith(i->geometricBounds());
+ }
+ }
+ }
+ return (flags | _state);
+ }
+
+ boundingbox = Geom::OptRect();
+ bool outline = (_drawing->rendermode == RENDERMODE_OUTLINE);
+
+ // clear Cairo data to force update
+ _nrstyle.update();
+
+ if (_curve) {
+ boundingbox = bounds_exact_transformed(_curve->get_pathvector(), ctx.ctm);
+
+ if (boundingbox && (_nrstyle.stroke.type != NRStyle::PAINT_NONE || outline)) {
+ float width, scale;
+ scale = ctx.ctm.descrim();
+ width = std::max(0.125f, _nrstyle.stroke_width * scale);
+ if ( fabs(_nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
+ boundingbox->expandBy(width);
+ }
+ // those pesky miters, now
+ float miterMax = width * _nrstyle.miter_limit;
+ if ( miterMax > 0.01 ) {
+ // grunt mode. we should compute the various miters instead
+ // (one for each point on the curve)
+ boundingbox->expandBy(miterMax);
+ }
+ }
+ }
+
+ _bbox = boundingbox ? boundingbox->roundOutwards() : Geom::OptIntRect();
+
+ if (!_curve ||
+ !_style ||
+ _curve->is_empty() ||
+ (( _nrstyle.fill.type != NRStyle::PAINT_NONE ) &&
+ ( _nrstyle.stroke.type != NRStyle::PAINT_NONE && !outline) ))
+ {
+ return STATE_ALL;
+ }
+
+ if (beststate & STATE_BBOX) {
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ _bbox.unionWith(i->geometricBounds());
+ }
+ }
+
+ return STATE_ALL;
+}
+
+void
+DrawingShape::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ if (!_curve || !_style) return;
+ if (!area.intersects(_bbox)) return; // skip if not within bounding box
+
+ bool outline = (_drawing->rendermode == RENDERMODE_OUTLINE);
+
+ if (outline) {
+ guint32 rgba = _drawing->outlinecolor;
+
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+ ct.path(_curve->get_pathvector());
+ }
+ { Inkscape::DrawingContext::Save save(ct);
+ ct.setSource(rgba);
+ ct.setLineWidth(0.5);
+ ct.setTolerance(1.25);
+ ct.stroke();
+ }
+ } else {
+ bool has_stroke, has_fill;
+ // we assume the context has no path
+ Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+
+ // update fill and stroke paints.
+ // this cannot be done during nr_arena_shape_update, because we need a Cairo context
+ // to render svg:pattern
+ has_fill = _nrstyle.prepareFill(ct, _paintbox);
+ has_stroke = _nrstyle.prepareStroke(ct, _paintbox);
+ has_stroke &= (_nrstyle.stroke_width != 0);
+
+ if (has_fill || has_stroke) {
+ // TODO: remove segments outside of bbox when no dashes present
+ ct.path(_curve->get_pathvector());
+ if (has_fill) {
+ _nrstyle.applyFill(ct);
+ ct.fillPreserve();
+ }
+ if (has_stroke) {
+ _nrstyle.applyStroke(ct);
+ ct.strokePreserve();
+ }
+ ct.newPath(); // clear path
+ } // has fill or stroke pattern
+ }
+
+ // marker rendering
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->render(ct, area, flags);
+ }
+}
+
+void
+DrawingShape::_clipItem(DrawingContext &ct, Geom::IntRect const &area)
+{
+ if (!_curve) return;
+
+ Inkscape::DrawingContext::Save save(ct);
+ // handle clip-rule
+ if (_style) {
+ if (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
+ ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
+ } else {
+ ct.setFillRule(CAIRO_FILL_RULE_WINDING);
+ }
+ }
+ ct.transform(_ctm);
+ ct.path(_curve->get_pathvector());
+ ct.fill();
+}
+
+DrawingItem *
+DrawingShape::_pickItem(Geom::Point const &p, double delta)
+{
+ if (_repick_after > 0)
+ --_repick_after;
+
+ if (_repick_after > 0) // we are a slow, huge path. skip this pick, returning what was returned last time
+ return _last_pick;
+
+ if (!_curve) return NULL;
+ if (!_style) return NULL;
+
+ bool outline = (_drawing->rendermode == RENDERMODE_OUTLINE);
+
+ if (SP_SCALE24_TO_FLOAT(_style->opacity.value) == 0 && !outline)
+ // fully transparent, no pick unless outline mode
+ return NULL;
+
+ GTimeVal tstart, tfinish;
+ g_get_current_time (&tstart);
+
+ double width;
+ if (outline) {
+ width = 0.5;
+ } else if (_nrstyle.stroke.type != NRStyle::PAINT_NONE && _nrstyle.stroke.opacity > 1e-3) {
+ float const scale = _ctm.descrim();
+ width = std::max(0.125f, _nrstyle.stroke_width * scale) / 2;
+ } else {
+ width = 0;
+ }
+
+ double dist = Geom::infinity();
+ int wind = 0;
+ bool needfill = (_nrstyle.fill.type != NRStyle::PAINT_NONE
+ && _nrstyle.fill.opacity > 1e-3 && !outline);
+
+ if (_drawing->canvasarena) {
+ Geom::Rect viewbox = _drawing->canvasarena->item.canvas->getViewbox();
+ viewbox.expandBy (width);
+ pathv_matrix_point_bbox_wind_distance(_curve->get_pathvector(), _ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, &viewbox);
+ } else {
+ pathv_matrix_point_bbox_wind_distance(_curve->get_pathvector(), _ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, NULL);
+ }
+
+ g_get_current_time (&tfinish);
+ glong this_pick = (tfinish.tv_sec - tstart.tv_sec) * 1000000 + (tfinish.tv_usec - tstart.tv_usec);
+ //g_print ("pick time %lu\n", this_pick);
+
+ if (this_pick > 10000) { // slow picking, remember to skip several new picks
+ _repick_after = this_pick / 5000;
+ }
+
+ // covered by fill?
+ if (needfill) {
+ if (!_style->fill_rule.computed) {
+ if (wind != 0) {
+ _last_pick = this;
+ return this;
+ }
+ } else {
+ if (wind & 0x1) {
+ _last_pick = this;
+ return this;
+ }
+ }
+ }
+
+ // close to the edge, as defined by strokewidth and delta?
+ // this ignores dashing (as if the stroke is solid) and always works as if caps are round
+ if (needfill || width > 0) { // if either fill or stroke visible,
+ if ((dist - width) < delta) {
+ _last_pick = this;
+ return this;
+ }
+ }
+
+ // if not picked on the shape itself, try its markers
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingItem *ret = i->pick(p, delta, false);
+ if (ret) {
+ _last_pick = this;
+ return this;
+ }
+ }
+
+ _last_pick = NULL;
+ return NULL;
+}
+
+bool
+DrawingShape::_canClip()
+{
+ return true;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-shape.h b/src/display/drawing-shape.h
new file mode 100644
index 000000000..7fd16374e
--- /dev/null
+++ b/src/display/drawing-shape.h
@@ -0,0 +1,64 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_SHAPE_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_SHAPE_H
+
+#include "display/drawing-item.h"
+#include "display/nr-style.h"
+
+class SPStyle;
+class SPCurve;
+
+namespace Inkscape {
+
+class DrawingShape
+ : public DrawingItem
+{
+public:
+ DrawingShape(Drawing *drawing);
+ ~DrawingShape();
+
+ void setPath(SPCurve *curve);
+ void setStyle(SPStyle *style);
+ void setPaintBox(Geom::Rect const &box);
+
+protected:
+ unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual void _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags);
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta);
+ virtual bool _canClip();
+
+ SPCurve *_curve;
+ SPStyle *_style;
+ NRStyle _nrstyle;
+
+ Geom::OptRect _paintbox;
+ DrawingItem *_last_pick;
+ unsigned _repick_after;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
new file mode 100644
index 000000000..784888bd7
--- /dev/null
+++ b/src/display/drawing-text.cpp
@@ -0,0 +1,275 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "display/cairo-utils.h"
+#include "display/canvas-bpath.h" // for SPWindRule (WTF!)
+#include "display/drawing-context.h"
+#include "display/drawing-surface.h"
+#include "display/drawing-text.h"
+#include "display/nr-arena.h"
+#include "helper/geom.h"
+#include "libnrtype/font-instance.h"
+#include "style.h"
+
+namespace Inkscape {
+
+DrawingGlyphs::DrawingGlyphs(Drawing *drawing)
+ : DrawingItem(drawing)
+ , _glyph_transform(NULL)
+ , _font(NULL)
+ , _glyph(0)
+{}
+
+DrawingGlyphs::~DrawingGlyphs()
+{
+ if (_font) {
+ _font->Unref();
+ _font = NULL;
+ }
+ delete _glyph_transform;
+}
+
+void
+DrawingGlyphs::setGlyph(font_instance *font, int glyph, Geom::Affine const &trans)
+{
+ _markForRendering();
+
+ if (trans.isIdentity()) {
+ delete _glyph_transform; // delete NULL; is safe
+ _glyph_transform = NULL;
+ } else {
+ _glyph_transform = new Geom::Affine(trans);
+ }
+
+ if (font) font->Ref();
+ if (_font) _font->Unref();
+ _font = font;
+ _glyph = glyph;
+
+ _markForUpdate(STATE_ALL, false);
+}
+
+unsigned
+DrawingGlyphs::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ DrawingText *ggroup = dynamic_cast<DrawingText *>(_parent);
+ if (!ggroup) throw InvalidItemException();
+
+ if (!_font || !ggroup->_style) return STATE_ALL;
+ if (ggroup->_nrstyle.fill.type == NRStyle::PAINT_NONE &&
+ ggroup->_nrstyle.stroke.type == NRStyle::PAINT_NONE)
+ {
+ return STATE_ALL;
+ }
+
+ Geom::OptRect b;
+ Geom::Affine t = _glyph_transform ? *_glyph_transform * ctx.ctm : ctx.ctm;
+ _x = t[4];
+ _y = t[5];
+
+ b = bounds_exact_transformed(*_font->PathVector(_glyph), t);
+ if (b && ggroup->_nrstyle.stroke.type != NRStyle::PAINT_NONE) {
+ float width, scale;
+ scale = ctx.ctm.descrim();
+ width = MAX(0.125, ggroup->_nrstyle.stroke_width * scale);
+ if ( fabs(ggroup->_nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
+ b->expandBy(width);
+ }
+ // those pesky miters, now
+ float miterMax = width * ggroup->_nrstyle.miter_limit;
+ if ( miterMax > 0.01 ) {
+ // grunt mode. we should compute the various miters instead
+ // (one for each point on the curve)
+ b->expandBy(miterMax);
+ }
+ }
+
+ if (b) {
+ _bbox = b->roundOutwards();
+ } else {
+ _bbox = Geom::OptIntRect();
+ }
+
+ return STATE_ALL;
+}
+
+DrawingItem *
+DrawingGlyphs::_pickItem(Geom::Point const &p, double delta)
+{
+ if (!_font || !_bbox) return NULL;
+
+ // With text we take a simple approach: pick if the point is in a characher bbox
+ Geom::Rect expanded(*_bbox);
+ expanded.expandBy(delta);
+ if (expanded.contains(p)) return this;
+ return NULL;
+}
+
+
+
+DrawingText::DrawingText(Drawing *drawing)
+ : DrawingGroup(drawing)
+{}
+
+DrawingText::~DrawingText()
+{}
+
+void
+DrawingText::clear()
+{
+ _markForRendering();
+ _children.clear_and_dispose(DeleteDisposer());
+}
+
+void
+DrawingText::addComponent(font_instance *font, int glyph, Geom::Affine const &trans)
+{
+ if (!font || !font->PathVector(glyph)) return;
+
+ _markForRendering();
+ DrawingGlyphs *ng = new DrawingGlyphs(_drawing);
+ ng->setGlyph(font, glyph, trans);
+ appendChild(ng);
+}
+
+void
+DrawingText::setStyle(SPStyle *style)
+{
+ _nrstyle.set(style);
+ DrawingGroup::setStyle(style);
+}
+
+void
+DrawingText::setPaintBox(Geom::OptRect const &box)
+{
+ _paintbox = box;
+ _markForUpdate(STATE_ALL, false);
+}
+
+unsigned
+DrawingText::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ _nrstyle.update();
+ return DrawingGroup::_updateItem(area, ctx, flags, reset);
+}
+
+void
+DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+{
+ if (_drawing->rendermode == RENDERMODE_OUTLINE) {
+ DrawingContext::Save save(ct);
+ guint32 rgba = _drawing->outlinecolor;
+ ct.setSource(rgba);
+ ct.setTolerance(1.25); // low quality, but good enough for outline mode
+ ct.newPath();
+ ct.transform(_ctm);
+
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(ct);
+ if (g->_glyph_transform) {
+ ct.transform(*g->_glyph_transform);
+ }
+ ct.path(*g->_font->PathVector(g->_glyph));
+ ct.fill();
+ }
+ return;
+ }
+
+ // NOTE: this is very similar to drawing-shape.cpp; the only difference is in path feeding
+ bool has_stroke, has_fill;
+
+ Inkscape::DrawingContext::Save save(ct);
+ ct.transform(_ctm);
+
+ has_fill = _nrstyle.prepareFill(ct, _paintbox);
+ has_stroke = _nrstyle.prepareStroke(ct, _paintbox);
+
+ if (has_fill || has_stroke) {
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(ct);
+ if (g->_glyph_transform) {
+ ct.transform(*g->_glyph_transform);
+ }
+ ct.path(*g->_font->PathVector(g->_glyph));
+ }
+
+ if (has_fill) {
+ _nrstyle.applyFill(ct);
+ ct.fillPreserve();
+ }
+ if (has_stroke) {
+ _nrstyle.applyStroke(ct);
+ ct.strokePreserve();
+ }
+ ct.newPath(); // clear path
+ }
+}
+
+void
+DrawingText::_clipItem(DrawingContext &ct, Geom::IntRect const &area)
+{
+ Inkscape::DrawingContext::Save save(ct);
+
+ // handle clip-rule
+ if (_style) {
+ if (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
+ ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
+ } else {
+ ct.setFillRule(CAIRO_FILL_RULE_WINDING);
+ }
+ }
+ ct.transform(_ctm);
+
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ DrawingGlyphs *g = dynamic_cast<DrawingGlyphs *>(&*i);
+ if (!g) throw InvalidItemException();
+
+ Inkscape::DrawingContext::Save save(ct);
+ if (g->_glyph_transform) {
+ ct.transform(*g->_glyph_transform);
+ }
+ ct.path(*g->_font->PathVector(g->_glyph));
+ }
+ ct.fill();
+}
+
+DrawingItem *
+DrawingText::_pickItem(Geom::Point const &p, double delta)
+{
+ DrawingItem *picked = DrawingGroup::_pickItem(p, delta);
+ if (picked) return this;
+ return NULL;
+}
+
+bool
+DrawingText::_canClip()
+{
+ return true;
+}
+
+} // end namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/drawing-text.h b/src/display/drawing-text.h
new file mode 100644
index 000000000..58fecc067
--- /dev/null
+++ b/src/display/drawing-text.h
@@ -0,0 +1,84 @@
+/**
+ * @file
+ * @brief Group belonging to an SVG drawing element
+ *//*
+ * Authors:
+ * Krzysztof Kosiński <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2011 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_TEXT_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_TEXT_H
+
+#include "display/drawing-group.h"
+#include "display/nr-style.h"
+
+class SPStyle;
+class font_instance;
+
+namespace Inkscape {
+
+class DrawingGlyphs
+ : public DrawingItem
+{
+public:
+ DrawingGlyphs(Drawing *drawing);
+ ~DrawingGlyphs();
+
+ void setGlyph(font_instance *font, int glyph, Geom::Affine const &trans);
+
+protected:
+ unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta);
+
+ Geom::Affine *_glyph_transform;
+ font_instance *_font;
+ int _glyph;
+ float _x, _y;
+
+ friend class DrawingText;
+};
+
+class DrawingText
+ : public DrawingGroup
+{
+public:
+ DrawingText(Drawing *drawing);
+ ~DrawingText();
+
+ void clear();
+ void addComponent(font_instance *font, int glyph, Geom::Affine const &trans);
+ void setStyle(SPStyle *style);
+ void setPaintBox(Geom::OptRect const &box);
+
+protected:
+ unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+ virtual void _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags);
+ virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual DrawingItem *_pickItem(Geom::Point const &p, double delta);
+ virtual bool _canClip();
+
+ Geom::OptRect _paintbox;
+ NRStyle _nrstyle;
+
+ friend class DrawingGlyphs;
+};
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_ITEM_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/grayscale.cpp b/src/display/grayscale.cpp
index 745a08c1e..e468044d3 100644
--- a/src/display/grayscale.cpp
+++ b/src/display/grayscale.cpp
@@ -82,7 +82,7 @@ guchar luminance(guchar r, guchar g, guchar b) {
*/
bool activeDesktopIsGrayscale() {
if (SP_ACTIVE_DESKTOP) {
- return (SP_ACTIVE_DESKTOP->getColorMode() == Inkscape::COLORRENDERMODE_GRAYSCALE);
+ return (SP_ACTIVE_DESKTOP->getColorMode() == Inkscape::COLORMODE_GRAYSCALE);
} else {
return false;
}
diff --git a/src/display/nr-arena-forward.h b/src/display/nr-arena-forward.h
deleted file mode 100644
index 5a5cf228a..000000000
--- a/src/display/nr-arena-forward.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef __NR_ARENA_FORWARD_H__
-#define __NR_ARENA_FORWARD_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-struct NRArena;
-struct NRArenaClass;
-
-struct NRArenaItem;
-struct NRArenaItemClass;
-
-struct NRArenaGroup;
-struct NRArenaGroupClass;
-
-struct NRArenaShape;
-struct NRArenaShapeClass;
-
-struct NRArenaShapeGroup;
-struct NRArenaShapeGroupClass;
-
-struct NRArenaImage;
-struct NRArenaImageClass;
-
-struct NRArenaGlyphs;
-struct NRArenaGlyphsClass;
-
-struct NRArenaGlyphsGroup;
-struct NRArenaGlyphsGroupClass;
-
-#endif
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp
deleted file mode 100644
index 99b0a004e..000000000
--- a/src/display/nr-arena-glyphs.cpp
+++ /dev/null
@@ -1,439 +0,0 @@
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2002 Lauris Kaplinski
- *
- * Released under GNU GPL
- *
- */
-
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-#include <cairo.h>
-#include <2geom/affine.h>
-#include <2geom/rect.h>
-#include "libnr/nr-convert2geom.h"
-#include "style.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-glyphs.h"
-#include "display/cairo-utils.h"
-#include "display/drawing-context.h"
-#include "helper/geom.h"
-
-#ifdef test_glyph_liv
-#include "../display/canvas-bpath.h"
-#include "libnrtype/font-instance.h"
-
-// defined in nr-arena-shape.cpp
-void nr_pixblock_render_shape_mask_or(NRPixBlock &m, Shape *theS);
-#endif
-
-#ifdef ENABLE_SVG_FONTS
-#include "nr-svgfonts.h"
-#endif //#ifdef ENABLE_SVG_FONTS
-
-static void nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass);
-static void nr_arena_glyphs_init(NRArenaGlyphs *glyphs);
-static void nr_arena_glyphs_finalize(NRObject *object);
-
-static guint nr_arena_glyphs_update(NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, guint state, guint reset);
-static NRArenaItem *nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point const &p, double delta, unsigned int sticky);
-
-static NRArenaItemClass *glyphs_parent_class;
-
-NRType
-nr_arena_glyphs_get_type(void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type(NR_TYPE_ARENA_ITEM,
- "NRArenaGlyphs",
- sizeof(NRArenaGlyphsClass),
- sizeof(NRArenaGlyphs),
- (void (*)(NRObjectClass *)) nr_arena_glyphs_class_init,
- (void (*)(NRObject *)) nr_arena_glyphs_init);
- }
- return type;
-}
-
-static void
-nr_arena_glyphs_class_init(NRArenaGlyphsClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- glyphs_parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_glyphs_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGlyphs>;
-
- item_class->update = nr_arena_glyphs_update;
- item_class->pick = nr_arena_glyphs_pick;
-}
-
-static void
-nr_arena_glyphs_init(NRArenaGlyphs *glyphs)
-{
- glyphs->g_transform.setIdentity();
- glyphs->font = NULL;
- glyphs->glyph = 0;
- glyphs->x = glyphs->y = 0.0;
-}
-
-static void
-nr_arena_glyphs_finalize(NRObject *object)
-{
- NRArenaGlyphs *glyphs = static_cast<NRArenaGlyphs *>(object);
-
- if (glyphs->font) {
- glyphs->font->Unref();
- glyphs->font=NULL;
- }
-
- ((NRObjectClass *) glyphs_parent_class)->finalize(object);
-}
-
-static guint
-nr_arena_glyphs_update(NRArenaItem *item, Geom::IntRect const &/*area*/, NRGC *gc, guint /*state*/, guint /*reset*/)
-{
- NRArenaGlyphs *glyphs = NR_ARENA_GLYPHS(item);
- NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item->parent);
-
- if (!glyphs->font || !ggroup->style)
- return NR_ARENA_ITEM_STATE_ALL;
- if (ggroup->nrstyle.fill.type == NRStyle::PAINT_NONE && ggroup->nrstyle.stroke.type == NRStyle::PAINT_NONE)
- return NR_ARENA_ITEM_STATE_ALL;
-
- Geom::OptRect b;
- Geom::Affine t = glyphs->g_transform * gc->transform;
- glyphs->x = t[4];
- glyphs->y = t[5];
-
- b = bounds_exact_transformed(*glyphs->font->PathVector(glyphs->glyph), t);
- if (b && ggroup->nrstyle.stroke.type != NRStyle::PAINT_NONE) {
- float width, scale;
- scale = gc->transform.descrim();
- width = MAX(0.125, ggroup->nrstyle.stroke_width * scale);
- if ( fabs(ggroup->nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
- b->expandBy(width);
- }
- // those pesky miters, now
- float miterMax = width * ggroup->nrstyle.miter_limit;
- if ( miterMax > 0.01 ) {
- // grunt mode. we should compute the various miters instead
- // (one for each point on the curve)
- b->expandBy(miterMax);
- }
- }
-
- if (b) {
- item->bbox = b->roundOutwards();
- } else {
- item->bbox = Geom::OptIntRect();
- }
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-static NRArenaItem *
-nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point const &p, gdouble delta, unsigned int /*sticky*/)
-{
- NRArenaGlyphs *glyphs;
-
- glyphs = NR_ARENA_GLYPHS(item);
-
- if (!glyphs->font ) return NULL;
- if (!item->bbox) return NULL;
-
- // With text we take a simple approach: pick if the point is in a characher bbox
- Geom::Rect expanded(*item->bbox);
- expanded.expandBy(delta);
- if (expanded.contains(p))
- return item;
- return NULL;
-}
-
-void
-nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int /*lieutenant*/, font_instance *font, gint glyph, Geom::Affine const *transform)
-{
- nr_return_if_fail(glyphs != NULL);
- nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs));
-
- nr_arena_item_request_render(NR_ARENA_ITEM(glyphs));
-
- if (transform) {
- glyphs->g_transform = *transform;
- } else {
- glyphs->g_transform.setIdentity();
- }
-
- if (font) font->Ref();
- if (glyphs->font) glyphs->font->Unref();
- glyphs->font=font;
- glyphs->glyph = glyph;
-
- nr_arena_item_request_update(NR_ARENA_ITEM(glyphs), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-static void nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass);
-static void nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group);
-static void nr_arena_glyphs_group_finalize(NRObject *object);
-
-static guint nr_arena_glyphs_group_update(NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, guint state, guint reset);
-static unsigned int nr_arena_glyphs_group_render(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags);
-static unsigned int nr_arena_glyphs_group_clip(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area);
-static NRArenaItem *nr_arena_glyphs_group_pick(NRArenaItem *item, Geom::Point const &p, gdouble delta, unsigned int sticky);
-
-static NRArenaGroupClass *group_parent_class;
-
-NRType
-nr_arena_glyphs_group_get_type(void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type(NR_TYPE_ARENA_GROUP,
- "NRArenaGlyphsGroup",
- sizeof(NRArenaGlyphsGroupClass),
- sizeof(NRArenaGlyphsGroup),
- (void (*)(NRObjectClass *)) nr_arena_glyphs_group_class_init,
- (void (*)(NRObject *)) nr_arena_glyphs_group_init);
- }
- return type;
-}
-
-static void
-nr_arena_glyphs_group_class_init(NRArenaGlyphsGroupClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- group_parent_class = (NRArenaGroupClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_glyphs_group_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGlyphsGroup>;
-
- item_class->update = nr_arena_glyphs_group_update;
- item_class->render = nr_arena_glyphs_group_render;
- item_class->clip = nr_arena_glyphs_group_clip;
- item_class->pick = nr_arena_glyphs_group_pick;
-}
-
-static void
-nr_arena_glyphs_group_init(NRArenaGlyphsGroup *group)
-{
- group->style = NULL;
-}
-
-static void
-nr_arena_glyphs_group_finalize(NRObject *object)
-{
- NRArenaGlyphsGroup *group = static_cast<NRArenaGlyphsGroup *>(object);
-
- if (group->style) {
- sp_style_unref(group->style);
- group->style = NULL;
- }
-
- ((NRObjectClass *) group_parent_class)->finalize(object);
-}
-
-static guint
-nr_arena_glyphs_group_update(NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, guint state, guint reset)
-{
- NRArenaGlyphsGroup *group = NR_ARENA_GLYPHS_GROUP(item);
-
- group->nrstyle.update();
-
- if (((NRArenaItemClass *) group_parent_class)->update)
- return ((NRArenaItemClass *) group_parent_class)->update(item, area, gc, state, reset);
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-
-static unsigned int
-nr_arena_glyphs_group_render(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int /*flags*/)
-{
- NRArenaItem *child = 0;
-
- NRArenaGroup *group = NR_ARENA_GROUP(item);
- NRArenaGlyphsGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item);
-
- if (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE) {
- Inkscape::DrawingContext::Save save(ct);
- guint32 rgba = item->arena->outlinecolor;
- ct.setSource(rgba);
- ct.setTolerance(1.25); // low quality, but good enough for outline mode
- ct.newPath();
- ct.transform(ggroup->ctm);
-
- for (child = group->children; child != NULL; child = child->next) {
- NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
-
- Geom::PathVector const * pathv = g->font->PathVector(g->glyph);
- Geom::Affine transform = g->g_transform;
-
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(transform);
- ct.path(*pathv);
- ct.fill();
- }
- return item->state;
- }
-
- // NOTE: this is very similar to nr-arena-shape.cpp; the only difference is path feeding
- bool has_stroke, has_fill;
-
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(ggroup->ctm);
-
- has_fill = ggroup->nrstyle.prepareFill(ct, ggroup->paintbox);
- has_stroke = ggroup->nrstyle.prepareStroke(ct, ggroup->paintbox);
-
- if (has_fill || has_stroke) {
- for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) {
- NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
- Geom::PathVector const &pathv = *g->font->PathVector(g->glyph);
-
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(g->g_transform);
- ct.path(pathv);
- }
-
- if (has_fill) {
- ggroup->nrstyle.applyFill(ct);
- ct.fillPreserve();
- }
- if (has_stroke) {
- ggroup->nrstyle.applyStroke(ct);
- ct.strokePreserve();
- }
- ct.newPath(); // clear path
- } // has fill or stroke pattern
-
- return item->state;
-}
-
-static unsigned int nr_arena_glyphs_group_clip(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &/*area*/)
-{
- NRArenaGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item);
-
- Inkscape::DrawingContext::Save save(ct);
-
- // handle clip-rule
- if (ggroup->style) {
- if (ggroup->style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
- ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
- } else {
- ct.setFillRule(CAIRO_FILL_RULE_WINDING);
- }
- }
- ct.transform(ggroup->ctm);
-
- for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) {
- NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
- Geom::PathVector const &pathv = *g->font->PathVector(g->glyph);
-
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(g->g_transform);
- ct.path(pathv);
- }
- ct.fill();
-
- return item->state;
-}
-
-static NRArenaItem *
-nr_arena_glyphs_group_pick(NRArenaItem *item, Geom::Point const &p, gdouble delta, unsigned int sticky)
-{
- NRArenaItem *picked = NULL;
-
- if (((NRArenaItemClass *) group_parent_class)->pick)
- picked = ((NRArenaItemClass *) group_parent_class)->pick(item, p, delta, sticky);
-
- if (picked) picked = item;
-
- return picked;
-}
-
-void
-nr_arena_glyphs_group_clear(NRArenaGlyphsGroup *sg)
-{
- NRArenaGroup *group = NR_ARENA_GROUP(sg);
-
- nr_arena_item_request_render(NR_ARENA_ITEM(group));
-
- while (group->children) {
- nr_arena_item_remove_child(NR_ARENA_ITEM(group), group->children);
- }
-}
-
-void
-nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, int glyph, Geom::Affine const &transform)
-{
- NRArenaGroup *group;
-
- group = NR_ARENA_GROUP(sg);
-
- Geom::PathVector const * pathv = ( font
- ? font->PathVector(glyph)
- : NULL );
- if ( pathv ) {
- nr_arena_item_request_render(NR_ARENA_ITEM(group));
-
- NRArenaItem *new_arena = NRArenaGlyphs::create(group->arena);
- nr_arena_item_append_child(NR_ARENA_ITEM(group), new_arena);
- nr_arena_item_unref(new_arena);
- nr_arena_glyphs_set_path(NR_ARENA_GLYPHS(new_arena), NULL, FALSE, font, glyph, &transform);
- }
-}
-
-void
-nr_arena_glyphs_group_set_style(NRArenaGlyphsGroup *sg, SPStyle *style)
-{
- nr_return_if_fail(sg != NULL);
- nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(sg));
-
- if (style) sp_style_ref(style);
- if (sg->style) sp_style_unref(sg->style);
- sg->style = style;
-
- sg->nrstyle.set(style);
-
- nr_arena_item_request_update(NR_ARENA_ITEM(sg), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_glyphs_group_set_paintbox(NRArenaGlyphsGroup *gg, NRRect const *pbox)
-{
- nr_return_if_fail(gg != NULL);
- nr_return_if_fail(NR_IS_ARENA_GLYPHS_GROUP(gg));
- nr_return_if_fail(pbox != NULL);
-
- gg->paintbox = pbox->upgrade_2geom();
-
- nr_arena_item_request_update(NR_ARENA_ITEM(gg), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-glyphs.h b/src/display/nr-arena-glyphs.h
deleted file mode 100644
index 4b2aed7b9..000000000
--- a/src/display/nr-arena-glyphs.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef SEEN_NR_ARENA_GLYPHS_H
-#define SEEN_NR_ARENA_GLYPHS_H
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2002 Lauris Kaplinski
- *
- * Released under GNU GPL
- *
- */
-
-#define NR_TYPE_ARENA_GLYPHS (nr_arena_glyphs_get_type ())
-#define NR_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_GLYPHS, NRArenaGlyphs))
-#define NR_IS_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_GLYPHS))
-
-#include "libnrtype/nrtype-forward.h"
-#include "display/display-forward.h"
-#include "forward.h"
-#include "display/nr-arena-item.h"
-#include "display/nr-style.h"
-
-#define test_glyph_liv
-
-struct SPCurve;
-class Shape;
-class SPPainter;
-
-NRType nr_arena_glyphs_get_type (void);
-
-struct NRArenaGlyphs : public NRArenaItem {
- /* Glyphs data */
- Geom::Affine g_transform;
-
- font_instance *font;
- gint glyph;
- float x, y;
-
- static NRArenaGlyphs *create(NRArena *arena) {
- NRArenaGlyphs *obj=reinterpret_cast<NRArenaGlyphs *>(nr_object_new(NR_TYPE_ARENA_GLYPHS));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaGlyphsClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_glyphs_set_path ( NRArenaGlyphs *glyphs,
- SPCurve *curve, unsigned int lieutenant,
- font_instance *font, int glyph,
- Geom::Affine const *transform );
-void nr_arena_glyphs_set_style (NRArenaGlyphs *glyphs, SPStyle *style);
-
-/* Integrated group of component glyphss */
-
-typedef struct NRArenaGlyphsGroup NRArenaGlyphsGroup;
-typedef struct NRArenaGlyphsGroupClass NRArenaGlyphsGroupClass;
-
-#include "nr-arena-group.h"
-
-#define NR_TYPE_ARENA_GLYPHS_GROUP (nr_arena_glyphs_group_get_type ())
-#define NR_ARENA_GLYPHS_GROUP(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_GLYPHS_GROUP, NRArenaGlyphsGroup))
-#define NR_IS_ARENA_GLYPHS_GROUP(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_GLYPHS_GROUP))
-
-NRType nr_arena_glyphs_group_get_type (void);
-
-struct NRArenaGlyphsGroup : public NRArenaGroup {
- Geom::OptRect paintbox;
- NRStyle nrstyle;
-
- static NRArenaGlyphsGroup *create(NRArena *arena) {
- NRArenaGlyphsGroup *obj=reinterpret_cast<NRArenaGlyphsGroup *>(nr_object_new(NR_TYPE_ARENA_GLYPHS_GROUP));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaGlyphsGroupClass {
- NRArenaGroupClass parent_class;
-};
-
-/* Utility functions */
-
-void nr_arena_glyphs_group_clear (NRArenaGlyphsGroup *group);
-
-void nr_arena_glyphs_group_add_component (NRArenaGlyphsGroup *group, font_instance *font, int glyph, Geom::Affine const &transform);
-
-void nr_arena_glyphs_group_set_style (NRArenaGlyphsGroup *group, SPStyle *style);
-
-void nr_arena_glyphs_group_set_paintbox (NRArenaGlyphsGroup *group, const NRRect *pbox);
-
-#endif // SEEN_NR_ARENA_GLYPHS_H
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
deleted file mode 100644
index 1f7c421d0..000000000
--- a/src/display/nr-arena-group.cpp
+++ /dev/null
@@ -1,300 +0,0 @@
-#define __NR_ARENA_GROUP_C__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "display/canvas-bpath.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-group.h"
-#include "display/nr-filter.h"
-#include "display/nr-filter-types.h"
-#include "display/rendermode.h"
-#include "style.h"
-#include "sp-filter.h"
-#include "sp-filter-reference.h"
-#include "filters/blend.h"
-#include "display/nr-filter-blend.h"
-#include "helper/geom.h"
-#include "display/drawing-context.h"
-
-static void nr_arena_group_class_init (NRArenaGroupClass *klass);
-static void nr_arena_group_init (NRArenaGroup *group);
-
-static NRArenaItem *nr_arena_group_children (NRArenaItem *item);
-static NRArenaItem *nr_arena_group_last_child (NRArenaItem *item);
-static void nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-static void nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child);
-static void nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
-static unsigned int nr_arena_group_update (NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, unsigned int state, unsigned int reset);
-static unsigned int nr_arena_group_render (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags);
-static unsigned int nr_arena_group_clip (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area);
-static NRArenaItem *nr_arena_group_pick (NRArenaItem *item, Geom::Point const &p, double delta, unsigned int sticky);
-
-static NRArenaItemClass *parent_class;
-
-NRType
-nr_arena_group_get_type (void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
- "NRArenaGroup",
- sizeof (NRArenaGroupClass),
- sizeof (NRArenaGroup),
- (void (*) (NRObjectClass *)) nr_arena_group_class_init,
- (void (*) (NRObject *)) nr_arena_group_init);
- }
- return type;
-}
-
-static void
-nr_arena_group_class_init (NRArenaGroupClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaGroup>;
-
- item_class->children = nr_arena_group_children;
- item_class->last_child = nr_arena_group_last_child;
- item_class->add_child = nr_arena_group_add_child;
- item_class->set_child_position = nr_arena_group_set_child_position;
- item_class->remove_child = nr_arena_group_remove_child;
- item_class->update = nr_arena_group_update;
- item_class->render = nr_arena_group_render;
- item_class->clip = nr_arena_group_clip;
- item_class->pick = nr_arena_group_pick;
-}
-
-static void
-nr_arena_group_init (NRArenaGroup *group)
-{
- group->transparent = FALSE;
- group->children = NULL;
- group->last = NULL;
- group->style = NULL;
- group->child_transform.setIdentity();
-}
-
-static NRArenaItem *
-nr_arena_group_children (NRArenaItem *item)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- return group->children;
-}
-
-static NRArenaItem *
-nr_arena_group_last_child (NRArenaItem *item)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- return group->last;
-}
-
-static void
-nr_arena_group_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- if (!ref) {
- group->children = nr_arena_item_attach (item, child, NULL, group->children);
- } else {
- ref->next = nr_arena_item_attach (item, child, ref, ref->next);
- }
-
- if (ref == group->last) group->last = child;
-
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-static void
-nr_arena_group_remove_child (NRArenaItem *item, NRArenaItem *child)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- if (child == group->last) group->last = child->prev;
-
- if (child->prev) {
- nr_arena_item_detach (item, child);
- } else {
- group->children = nr_arena_item_detach (item, child);
- }
-
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-static void
-nr_arena_group_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- if (child == group->last) group->last = child->prev;
-
- if (child->prev) {
- nr_arena_item_detach (item, child);
- } else {
- group->children = nr_arena_item_detach (item, child);
- }
-
- if (!ref) {
- group->children = nr_arena_item_attach (item, child, NULL, group->children);
- } else {
- ref->next = nr_arena_item_attach (item, child, ref, ref->next);
- }
-
- if (ref == group->last) group->last = child;
-
- nr_arena_item_request_render (child);
-}
-
-static unsigned int
-nr_arena_group_update (NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, unsigned int state, unsigned int reset)
-{
- unsigned int newstate;
- NRArenaGroup *group = NR_ARENA_GROUP (item);
- unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- NRGC cgc(gc);
- cgc.transform = group->child_transform * gc->transform;
- newstate = nr_arena_item_invoke_update (child, area, &cgc, state, reset);
- beststate = beststate & newstate;
- }
-
- if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
- item->bbox = Geom::OptIntRect();
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- if (child->visible)
- item->bbox.unionWith(outline ? child->bbox : child->drawbox);
- }
- }
-
- return beststate;
-}
-
-void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
-{
- g_return_if_fail(group != NULL);
- g_return_if_fail(NR_IS_ARENA_GROUP(group));
-
- if (style) sp_style_ref(style);
- if (group->style) sp_style_unref(group->style);
- group->style = style;
-
- //if group has a filter
- if (style->filter.set && style->getFilter()) {
- if (!group->filter) {
- int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
- group->filter = new Inkscape::Filters::Filter(primitives);
- }
- sp_filter_build_renderer(SP_FILTER(style->getFilter()), group->filter);
- } else {
- //no filter set for this group
- delete group->filter;
- group->filter = NULL;
- }
-
- if (style && style->enable_background.set
- && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
- group->background_new = true;
- }
-}
-
-static unsigned int
-nr_arena_group_render (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- unsigned int ret = item->state;
-
- /* Just compose children into parent buffer */
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_item_invoke_render (ct, child, area, flags);
- if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
- }
-
- return ret;
-}
-
-static unsigned int
-nr_arena_group_clip (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
- unsigned int ret = item->state;
-
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_item_invoke_clip (ct, child, area);
- if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
- }
-
- return ret;
-}
-
-static NRArenaItem *
-nr_arena_group_pick (NRArenaItem *item, Geom::Point const &p, double delta, unsigned int sticky)
-{
- NRArenaGroup *group = NR_ARENA_GROUP (item);
-
- for (NRArenaItem *child = group->last; child != NULL; child = child->prev) {
- NRArenaItem *picked = nr_arena_item_invoke_pick (child, p, delta, sticky);
- if (picked)
- return (group->transparent) ? picked : item;
- }
-
- return NULL;
-}
-
-void
-nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent)
-{
- nr_return_if_fail (group != NULL);
- nr_return_if_fail (NR_IS_ARENA_GROUP (group));
-
- group->transparent = transparent;
-}
-
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t)
-{
- Geom::Affine nt(t);
- nr_arena_group_set_child_transform(group, &nt);
-}
-
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t)
-{
- if (!t) t = &GEOM_MATRIX_IDENTITY;
-
- if (!Geom::matrix_equalp(*t, group->child_transform, NR_EPSILON)) {
- nr_arena_item_request_render (NR_ARENA_ITEM (group));
- group->child_transform = *t;
- nr_arena_item_request_update (NR_ARENA_ITEM (group), NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-group.h b/src/display/nr-arena-group.h
deleted file mode 100644
index 58394643c..000000000
--- a/src/display/nr-arena-group.h
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __NR_ARENA_GROUP_H__
-#define __NR_ARENA_GROUP_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@ximian.com>
- *
- * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc.
- *
- * Released under GNU GPL
- *
- */
-
-#define NR_TYPE_ARENA_GROUP (nr_arena_group_get_type ())
-#define NR_ARENA_GROUP(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_GROUP, NRArenaGroup))
-#define NR_IS_ARENA_GROUP(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_GROUP))
-
-#include "nr-arena-item.h"
-#include "style.h"
-
-NRType nr_arena_group_get_type (void);
-
-struct NRArenaGroup : public NRArenaItem{
- unsigned int transparent : 1;
- NRArenaItem *children;
- NRArenaItem *last;
- Geom::Affine child_transform;
- SPStyle *style;
-
- static NRArenaGroup *create(NRArena *arena) {
- NRArenaGroup *obj = reinterpret_cast<NRArenaGroup *>(nr_object_new(NR_TYPE_ARENA_GROUP));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaGroupClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_group_set_transparent(NRArenaGroup *group, unsigned int transparent);
-
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t);
-void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t);
-void nr_arena_group_set_style(NRArenaGroup *group, SPStyle *style);
-
-#endif
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
deleted file mode 100644
index 5336fcda9..000000000
--- a/src/display/nr-arena-image.cpp
+++ /dev/null
@@ -1,390 +0,0 @@
-#define __NR_ARENA_IMAGE_C__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <2geom/transforms.h>
-#include "../preferences.h"
-#include "nr-arena-image.h"
-#include "style.h"
-#include "display/cairo-utils.h"
-#include "display/drawing-context.h"
-#include "display/nr-arena.h"
-#include "display/nr-filter.h"
-#include "sp-filter.h"
-#include "sp-filter-reference.h"
-
-int nr_arena_image_x_sample = 1;
-int nr_arena_image_y_sample = 1;
-
-/*
- * NRArenaCanvasImage
- *
- */
-
-static void nr_arena_image_class_init (NRArenaImageClass *klass);
-static void nr_arena_image_init (NRArenaImage *image);
-static void nr_arena_image_finalize (NRObject *object);
-
-static unsigned int nr_arena_image_update (NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, unsigned int state, unsigned int reset);
-static unsigned int nr_arena_image_render (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags);
-static NRArenaItem *nr_arena_image_pick (NRArenaItem *item, Geom::Point const &p, double delta, unsigned int sticky);
-static Geom::Rect nr_arena_image_rect (NRArenaImage *image);
-
-static NRArenaItemClass *parent_class;
-
-NRType
-nr_arena_image_get_type (void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type (NR_TYPE_ARENA_ITEM,
- "NRArenaImage",
- sizeof (NRArenaImageClass),
- sizeof (NRArenaImage),
- (void (*) (NRObjectClass *)) nr_arena_image_class_init,
- (void (*) (NRObject *)) nr_arena_image_init);
- }
- return type;
-}
-
-static void
-nr_arena_image_class_init (NRArenaImageClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_image_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaImage>;
-
- item_class->update = nr_arena_image_update;
- item_class->render = nr_arena_image_render;
- item_class->pick = nr_arena_image_pick;
-}
-
-static void
-nr_arena_image_init (NRArenaImage *image)
-{
- image->pixbuf = NULL;
- image->ctm.setIdentity();
- image->clipbox = Geom::Rect();
- image->ox = image->oy = 0.0;
- image->sx = image->sy = 1.0;
-
- image->style = 0;
- image->render_opacity = TRUE;
-}
-
-static void
-nr_arena_image_finalize (NRObject *object)
-{
- NRArenaImage *image = NR_ARENA_IMAGE (object);
-
- if (image->pixbuf != NULL) {
- g_object_unref(image->pixbuf);
- cairo_surface_destroy(image->surface);
- }
- if (image->style)
- sp_style_unref(image->style);
-
- ((NRObjectClass *) parent_class)->finalize (object);
-}
-
-static unsigned int
-nr_arena_image_update( NRArenaItem *item, Geom::IntRect const &/*area*/, NRGC *gc, unsigned int /*state*/, unsigned int /*reset*/ )
-{
- // clear old bbox
- nr_arena_item_request_render(item);
-
- NRArenaImage *image = NR_ARENA_IMAGE (item);
-
- /* Copy affine */
- image->ctm = gc->transform;
-
- /* Calculate bbox */
- if (image->pixbuf) {
- Geom::Rect r = nr_arena_image_rect(image) * gc->transform;
- item->bbox = r.roundOutwards();
- } else {
- item->bbox = Geom::OptIntRect();
- }
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-static unsigned int nr_arena_image_render(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &/*area*/, unsigned int /*flags*/ )
-{
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- NRArenaImage *image = NR_ARENA_IMAGE (item);
-
- if (!outline) {
- if (!image->pixbuf) {
- return item->state;
- }
-
- // FIXME: at the moment gdk_cairo_set_source_pixbuf creates an ARGB copy
- // of the pixbuf. Fix this in Cairo and/or GDK.
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(image->ctm);
- ct.newPath();
- ct.rectangle(image->clipbox);
- ct.clip();
-
- ct.translate(image->ox, image->oy);
- ct.scale(image->sx, image->sy);
- ct.setSource(image->surface, 0, 0);
-
- cairo_matrix_t tt;
- Geom::Affine total;
- cairo_get_matrix(ct.raw(), &tt);
- ink_matrix_to_2geom(total, tt);
-
- if (total.expansionX() > 1.0 || total.expansionY() > 1.0) {
- cairo_pattern_t *p = cairo_get_source(ct.raw());
- cairo_pattern_set_filter(p, CAIRO_FILTER_NEAREST);
- }
- ct.paint(((double) item->opacity) / 255.0);
-
- } else { // outline; draw a rect instead
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- guint32 rgba = prefs->getInt("/options/wireframecolors/images", 0xff0000ff);
-
- { Inkscape::DrawingContext::Save save(ct);
- ct.transform(image->ctm);
- ct.newPath();
-
- Geom::Rect r = nr_arena_image_rect (image);
- Geom::Point c00 = r.corner(0);
- Geom::Point c01 = r.corner(3);
- Geom::Point c11 = r.corner(2);
- Geom::Point c10 = r.corner(1);
-
- ct.moveTo(c00);
- // the box
- ct.lineTo(c10);
- ct.lineTo(c11);
- ct.lineTo(c01);
- ct.lineTo(c00);
- // the diagonals
- ct.lineTo(c11);
- ct.moveTo(c10);
- ct.lineTo(c01);
- }
-
- ct.setLineWidth(0.5);
- ct.setSource(rgba);
- ct.stroke();
- }
- return item->state;
-}
-
-/** Calculates the closest distance from p to the segment a1-a2*/
-double
-distance_to_segment (Geom::Point const &p, Geom::Point const &a1, Geom::Point const &a2)
-{
- // calculate sides of the triangle and their squares
- double d1 = Geom::L2(p - a1);
- double d1_2 = d1 * d1;
- double d2 = Geom::L2(p - a2);
- double d2_2 = d2 * d2;
- double a = Geom::L2(a1 - a2);
- double a_2 = a * a;
-
- // if one of the angles at the base is > 90, return the corresponding side
- if (d1_2 + a_2 <= d2_2) return d1;
- if (d2_2 + a_2 <= d1_2) return d2;
-
- // otherwise calculate the height to the base
- double peri = (a + d1 + d2)/2;
- return (2*sqrt(peri * (peri - a) * (peri - d1) * (peri - d2))/a);
-}
-
-static NRArenaItem *
-nr_arena_image_pick( NRArenaItem *item, Geom::Point const &p, double delta, unsigned int /*sticky*/ )
-{
- NRArenaImage *image = NR_ARENA_IMAGE (item);
-
- if (!image->pixbuf) return NULL;
-
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- if (outline) {
- Geom::Rect r = nr_arena_image_rect (image);
-
- Geom::Point c00 = r.corner(0);
- Geom::Point c01 = r.corner(3);
- Geom::Point c11 = r.corner(2);
- Geom::Point c10 = r.corner(1);
-
- // frame
- if (distance_to_segment (p, c00, c10) < delta) return item;
- if (distance_to_segment (p, c10, c11) < delta) return item;
- if (distance_to_segment (p, c11, c01) < delta) return item;
- if (distance_to_segment (p, c01, c00) < delta) return item;
-
- // diagonals
- if (distance_to_segment (p, c00, c11) < delta) return item;
- if (distance_to_segment (p, c10, c01) < delta) return item;
-
- return NULL;
-
- } else {
-
- unsigned char *const pixels = gdk_pixbuf_get_pixels(image->pixbuf);
- int const width = gdk_pixbuf_get_width(image->pixbuf);
- int const height = gdk_pixbuf_get_height(image->pixbuf);
- int const rowstride = gdk_pixbuf_get_rowstride(image->pixbuf);
-
- Geom::Point tp = p * image->ctm.inverse();
- Geom::Rect r = nr_arena_image_rect(image);
-
- if (!r.contains(tp))
- return NULL;
-
- double vw = width * image->sx;
- double vh = height * image->sy;
- int ix = floor((tp[Geom::X] - image->ox) / vw * width);
- int iy = floor((tp[Geom::Y] - image->oy) / vh * height);
-
- if ((ix < 0) || (iy < 0) || (ix >= width) || (iy >= height))
- return NULL;
-
- unsigned char *pix_ptr = pixels + iy * rowstride + ix * 4;
- // is the alpha not transparent?
- return (pix_ptr[3] > 0) ? item : NULL;
- }
-}
-
-Geom::Rect
-nr_arena_image_rect (NRArenaImage *image)
-{
- Geom::Rect r = image->clipbox;
-
- if (image->pixbuf) {
- double pw = gdk_pixbuf_get_width(image->pixbuf);
- double ph = gdk_pixbuf_get_height(image->pixbuf);
- double vw = pw * image->sx;
- double vh = ph * image->sy;
- Geom::Point p(image->ox, image->oy);
- Geom::Point wh(vw, vh);
- Geom::Rect view(p, p+wh);
- Geom::OptRect res = r & view;
- r = res ? *res : r;
- }
-
- return r;
-}
-
-/* Utility */
-
-void
-nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- // when done in this order, it won't break if pb == image->pixbuf and the refcount is 1
- if (pb != NULL) {
- g_object_ref (pb);
- }
- if (image->pixbuf != NULL) {
- g_object_unref(image->pixbuf);
- cairo_surface_destroy(image->surface);
- }
- image->pixbuf = pb;
- image->surface = pb ? ink_cairo_surface_create_for_argb32_pixbuf(pb) : NULL;
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- image->clipbox = clip;
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- image->ox = origin[Geom::X];
- image->oy = origin[Geom::Y];
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy)
-{
- nr_return_if_fail (image != NULL);
- nr_return_if_fail (NR_IS_ARENA_IMAGE (image));
-
- image->sx = sx;
- image->sy = sy;
-
- nr_arena_item_request_update (NR_ARENA_ITEM (image), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style)
-{
- g_return_if_fail(image != NULL);
- g_return_if_fail(NR_IS_ARENA_IMAGE(image));
-
- if (style) sp_style_ref(style);
- if (image->style) sp_style_unref(image->style);
- image->style = style;
-
- //if image has a filter
- if (style->filter.set && style->getFilter()) {
- if (!image->filter) {
- int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
- image->filter = new Inkscape::Filters::Filter(primitives);
- }
- sp_filter_build_renderer(SP_FILTER(style->getFilter()), image->filter);
- } else {
- //no filter set for this image
- delete image->filter;
- image->filter = NULL;
- }
-
- if (style && style->enable_background.set
- && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
- image->background_new = true;
- }
-
- nr_arena_item_request_update(image, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-image.h b/src/display/nr-arena-image.h
deleted file mode 100644
index 6fa9223dd..000000000
--- a/src/display/nr-arena-image.h
+++ /dev/null
@@ -1,66 +0,0 @@
-#ifndef __NR_ARENA_IMAGE_H__
-#define __NR_ARENA_IMAGE_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <gdk-pixbuf/gdk-pixbuf.h>
-#include <2geom/rect.h>
-#include "nr-arena-item.h"
-#include "style.h"
-
-#define NR_TYPE_ARENA_IMAGE (nr_arena_image_get_type ())
-#define NR_ARENA_IMAGE(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_IMAGE, NRArenaImage))
-#define NR_IS_ARENA_IMAGE(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_IMAGE))
-
-NRType nr_arena_image_get_type (void);
-
-struct NRArenaImage : public NRArenaItem {
- GdkPixbuf *pixbuf;
- cairo_surface_t *surface;
-
- Geom::Affine ctm;
- Geom::Rect clipbox;
- double ox, oy;
- double sx, sy;
-
- SPStyle *style;
-
- static NRArenaImage *create(NRArena *arena) {
- NRArenaImage *obj=reinterpret_cast<NRArenaImage *>(nr_object_new(NR_TYPE_ARENA_IMAGE));
- obj->init(arena);
- return obj;
- }
-};
-
-struct NRArenaImageClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_image_set_argb32_pixbuf (NRArenaImage *image, GdkPixbuf *pb);
-void nr_arena_image_set_style (NRArenaImage *image, SPStyle *style);
-void nr_arena_image_set_clipbox (NRArenaImage *image, Geom::Rect const &clip);
-void nr_arena_image_set_origin (NRArenaImage *image, Geom::Point const &origin);
-void nr_arena_image_set_scale (NRArenaImage *image, double sx, double sy);
-
-#endif
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
deleted file mode 100644
index 264b8ab10..000000000
--- a/src/display/nr-arena-item.cpp
+++ /dev/null
@@ -1,932 +0,0 @@
-#define __NR_ARENA_ITEM_C__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#define noNR_ARENA_ITEM_VERBOSE
-#define noNR_ARENA_ITEM_DEBUG_CASCADE
-
-#include <cstring>
-#include <string>
-#include <cairomm/cairomm.h>
-
-#include "display/cairo-utils.h"
-#include "display/cairo-templates.h"
-#include "display/drawing-context.h"
-#include "display/drawing-surface.h"
-#include "display/canvas-arena.h"
-#include "nr-arena.h"
-#include "nr-arena-item.h"
-#include "gc-core.h"
-#include "helper/geom.h"
-
-#include "nr-filter.h"
-#include "nr-arena-group.h"
-#include "preferences.h"
-
-namespace GC = Inkscape::GC;
-
-static void nr_arena_item_class_init (NRArenaItemClass *klass);
-static void nr_arena_item_init (NRArenaItem *item);
-static void nr_arena_item_private_finalize (NRObject *object);
-
-static NRObjectClass *parent_class;
-
-NRType
-nr_arena_item_get_type (void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type (NR_TYPE_OBJECT,
- "NRArenaItem",
- sizeof (NRArenaItemClass),
- sizeof (NRArenaItem),
- (void (*)(NRObjectClass *))
- nr_arena_item_class_init,
- (void (*)(NRObject *))
- nr_arena_item_init);
- }
- return type;
-}
-
-static void
-nr_arena_item_class_init (NRArenaItemClass *klass)
-{
- NRObjectClass *object_class;
-
- object_class = (NRObjectClass *) klass;
-
- parent_class = ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_item_private_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor < NRArenaItem >;
-}
-
-static void
-nr_arena_item_init (NRArenaItem *item)
-{
- item->arena = NULL;
- item->parent = NULL;
- item->next = item->prev = NULL;
-
- item->key = 0;
-
- item->state = 0;
- item->sensitive = TRUE;
- item->visible = TRUE;
-
- memset (&item->bbox, 0, sizeof (item->bbox));
- memset (&item->drawbox, 0, sizeof (item->drawbox));
- item->transform = NULL;
- item->ctm.setIdentity();
- item->opacity = 255;
- item->render_opacity = FALSE;
- item->render_cache = FALSE;
-
- item->transform = NULL;
- item->clip = NULL;
- item->mask = NULL;
- item->cache = NULL;
- item->data = NULL;
- item->filter = NULL;
- item->background_new = false;
-}
-
-static void
-nr_arena_item_private_finalize (NRObject *object)
-{
- NRArenaItem *item = static_cast < NRArenaItem * >(object);
-
- item->transform = NULL;
-
- if (item->clip)
- nr_arena_item_detach(item, item->clip);
- if (item->mask)
- nr_arena_item_detach(item, item->mask);
- delete item->cache;
-
- ((NRObjectClass *) (parent_class))->finalize (object);
-}
-
-NRArenaItem *
-nr_arena_item_children (NRArenaItem *item)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- if (NR_ARENA_ITEM_VIRTUAL (item, children))
- return NR_ARENA_ITEM_VIRTUAL (item, children) (item);
-
- return NULL;
-}
-
-NRArenaItem *
-nr_arena_item_last_child (NRArenaItem *item)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- if (NR_ARENA_ITEM_VIRTUAL (item, last_child)) {
- return NR_ARENA_ITEM_VIRTUAL (item, last_child) (item);
- } else {
- NRArenaItem *ref = nr_arena_item_children (item);
- if (ref)
- while (ref->next)
- ref = ref->next;
- return ref;
- }
-}
-
-void
-nr_arena_item_add_child (NRArenaItem *item, NRArenaItem *child,
- NRArenaItem *ref)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (child->parent == NULL);
- nr_return_if_fail (child->prev == NULL);
- nr_return_if_fail (child->next == NULL);
- nr_return_if_fail (child->arena == item->arena);
- nr_return_if_fail (child != ref);
- nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
- nr_return_if_fail (!ref || (ref->parent == item));
-
- if (NR_ARENA_ITEM_VIRTUAL (item, add_child))
- NR_ARENA_ITEM_VIRTUAL (item, add_child) (item, child, ref);
-}
-
-void
-nr_arena_item_remove_child (NRArenaItem *item, NRArenaItem *child)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (child->parent == item);
-
- if (NR_ARENA_ITEM_VIRTUAL (item, remove_child))
- NR_ARENA_ITEM_VIRTUAL (item, remove_child) (item, child);
-}
-
-void
-nr_arena_item_set_child_position (NRArenaItem *item, NRArenaItem *child,
- NRArenaItem *ref)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (child->parent == item);
- nr_return_if_fail (!ref || NR_IS_ARENA_ITEM (ref));
- nr_return_if_fail (!ref || (ref->parent == item));
-
- if (NR_ARENA_ITEM_VIRTUAL (item, set_child_position))
- NR_ARENA_ITEM_VIRTUAL (item, set_child_position) (item, child, ref);
-}
-
-NRArenaItem *
-nr_arena_item_ref (NRArenaItem *item)
-{
- nr_object_ref ((NRObject *) item);
-
- return item;
-}
-
-NRArenaItem *
-nr_arena_item_unref (NRArenaItem *item)
-{
- nr_object_unref ((NRObject *) item);
-
- return NULL;
-}
-
-unsigned int
-nr_arena_item_invoke_update (NRArenaItem *item, Geom::IntRect const &area, NRGC *gc,
- unsigned int state, unsigned int reset)
-{
- NRGC childgc (gc);
- bool filter = (item->arena->rendermode == Inkscape::RENDERMODE_NORMAL);
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
- NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (!(state & NR_ARENA_ITEM_STATE_INVALID),
- NR_ARENA_ITEM_STATE_INVALID);
-
-#ifdef NR_ARENA_ITEM_DEBUG_CASCADE
- printf ("Update %s:%p %x %x %x\n",
- nr_type_name_from_instance ((GTypeInstance *) item), item, state,
- item->state, reset);
-#endif
-
- /* return if in error */
- if (item->state & NR_ARENA_ITEM_STATE_INVALID)
- return item->state;
- /* Set reset flags according to propagation status */
- if (item->propagate) {
- reset |= ~item->state;
- item->propagate = FALSE;
- }
- /* Reset our state */
- item->state &= ~reset;
- /* Return if NOP */
- if (!(~item->state & state))
- return item->state;
- /* Test whether to return immediately */
- if (item->state & NR_ARENA_ITEM_STATE_BBOX) {
- // we have up-to-date bbox
- if (!area.intersects(outline ? item->bbox : item->drawbox))
- return item->state;
- }
-
- /* Set up local gc */
- childgc = *gc;
- if (item->transform) {
- childgc.transform = (*item->transform) * childgc.transform;
- }
- /* Remember the transformation matrix */
- Geom::Affine ctm_change = item->ctm.inverse() * childgc.transform;
- item->ctm = childgc.transform;
-
- /* Invoke the real method */
- // that will update bbox
- item->state = NR_ARENA_ITEM_VIRTUAL (item, update) (item, area, &childgc, state, reset);
- if (item->state & NR_ARENA_ITEM_STATE_INVALID)
- return item->state;
-
- /* Enlarge the drawbox to contain filter effects */
- if (item->filter && filter && item->item_bbox) {
- item->drawbox = item->filter->compute_drawbox(item, *item->item_bbox);
- } else {
- item->drawbox = item->bbox;
- }
-
- /* Clipping */
- if (item->clip) {
- // FIXME: since here we only need bbox, consider passing
- // ((state & !(NR_ARENA_ITEM_STATE_RENDER)) | NR_ARENA_ITEM_STATE_BBOX)
- // instead of state, so it does not have to create rendering structures in nr_arena_shape_update
- unsigned int newstate = nr_arena_item_invoke_update (item->clip, area, &childgc, state, reset);
- if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- if (outline) {
- item->bbox.unionWith(item->clip->bbox);
- } else {
- item->drawbox.intersectWith(item->clip->bbox);
- }
- }
- /* Masking */
- if (item->mask) {
- unsigned int newstate = nr_arena_item_invoke_update (item->mask, area, &childgc, state, reset);
- if (newstate & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- if (outline) {
- item->bbox.unionWith(item->mask->bbox);
- } else {
- // for masking, we need full drawbox of mask
- item->drawbox.intersectWith(item->mask->drawbox);
- }
- }
-
- // update cache if enabled
- if (item->render_cache) {
- Geom::OptIntRect cl = item->arena->cache_limit;
- cl.intersectWith(item->drawbox);
- if (cl) {
- if (item->cache) {
- // this takes care of invalidation on transform
- item->cache->resizeAndTransform(*cl, ctm_change);
- } else {
- item->cache = new Inkscape::DrawingCache(*cl);
- // the cache is initially dirty
- }
- } else {
- // disable cache for this item - not visible
- delete item->cache;
- item->cache = NULL;
- }
- }
-
- // now that we know drawbox, dirty the corresponding rect on canvas:
- if (!NR_IS_ARENA_GROUP(item) || (item->filter && filter)) {
- // unless filtered, groups do not need to render by themselves, only their members
- if (state & ~NR_ARENA_ITEM_STATE_CACHE) {
- nr_arena_item_request_render (item);
- }
- }
-
- return item->state;
-}
-
-struct MaskLuminanceToAlpha {
- guint32 operator()(guint32 in) {
- EXTRACT_ARGB32(in, a, r, g, b)
- // the operation of unpremul -> luminance-to-alpha -> multiply by alpha
- // is equivalent to luminance-to-alpha on premultiplied color values
- // original computation in double: r*0.2125 + g*0.7154 + b*0.0721
- guint32 ao = r*109 + g*366 + b*37; // coeffs add up to 512
- return ((ao + 256) << 15) & 0xff000000; // equivalent to ((ao + 256) / 512) << 24
- }
-};
-
-unsigned int
-nr_arena_item_invoke_render (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area,
- unsigned int flags)
-{
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
- bool filter = (item->arena->rendermode != Inkscape::RENDERMODE_OUTLINE &&
- item->arena->rendermode != Inkscape::RENDERMODE_NO_FILTERS);
-
- nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
- NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (item->state & NR_ARENA_ITEM_STATE_BBOX,
- item->state);
-
- /* If we are invisible, just return successfully */
- if (!item->visible)
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
-
- if (outline) {
- // intersect with bbox rather than drawbox, as we want to render things outside
- // of the clipping path as well
- Geom::OptIntRect carea = Geom::intersect(area, item->bbox);
- if (!carea)
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
-
- // No caching in outline mode for now; investigate if it really gives any advantage with cairo.
- // Also no attempts to clip anything; just render everything: item, clip, mask
- // First, render the object itself
- unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, *carea, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
-
- // render clip and mask, if any
- guint32 saved_rgba = item->arena->outlinecolor; // save current outline color
- // render clippath as an object, using a different color
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if (item->clip) {
- item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
- NR_ARENA_ITEM_VIRTUAL (item->clip, render) (ct, item->clip, *carea, flags);
- }
- // render mask as an object, using a different color
- if (item->mask) {
- item->arena->outlinecolor = prefs->getInt("/options/wireframecolors/masks", 0x0000ffff); // blue masks
- NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ct, item->mask, *carea, flags);
- }
- item->arena->outlinecolor = saved_rgba; // restore outline color
-
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- }
-
- // carea is the bounding box for intermediate rendering.
- Geom::OptIntRect carea = Geom::intersect(area, item->drawbox);
- if (!carea)
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
-
- // render from cache
- if (item->render_cache && item->cache) {
- if(item->cache->paintFromCache(ct, *carea))
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- }
-
- // expand carea to contain the dependent area of filters.
- if (item->filter && filter) {
- item->filter->area_enlarge(*carea, item);
- carea.intersectWith(item->drawbox);
- }
-
- using namespace Inkscape;
-
- unsigned state;
- unsigned retstate;
-
- // determine whether this shape needs intermediate rendering.
- bool needs_intermediate_rendering = false;
- bool &nir = needs_intermediate_rendering;
- bool needs_opacity = (item->opacity != 255 && !item->render_opacity);
-
- // this item needs an intermediate rendering if:
- nir |= (item->clip != NULL); // 1. it has a clipping path
- nir |= (item->mask != NULL); // 2. it has a mask
- nir |= (item->filter != NULL && filter); // 3. it has a filter
- nir |= needs_opacity; // 4. it is non-opaque
-
- double opacity = static_cast<double>(item->opacity) / 255.0;
-
- /* How the rendering is done.
- *
- * Clipping, masking and opacity are done by rendering them to a surface
- * and then compositing the object's rendering onto it with the IN operator.
- * The object itself is rendered to a group.
- *
- * Opacity is done by rendering the clipping path with an alpha
- * value corresponding to the opacity. If there is no clipping path,
- * the entire intermediate surface is painted with alpha corresponding
- * to the opacity value.
- */
-
- // short-circuit the simple case.
- if (!needs_intermediate_rendering) {
- if (item->render_cache && item->cache) {
- Inkscape::DrawingContext cachect(*item->cache);
- cachect.rectangle(area);
- cachect.clip();
-
- { // 1. clear the corresponding part of cache
- Inkscape::DrawingContext::Save save(cachect);
- cachect.setSource(0,0,0,0);
- cachect.setOperator(CAIRO_OPERATOR_SOURCE);
- cachect.paint();
- }
- // 2. render to cache
- state = NR_ARENA_ITEM_VIRTUAL (item, render) (cachect, item, *carea, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- // 3. copy from cache to output
- Inkscape::DrawingContext::Save save(ct);
- ct.rectangle(*carea);
- ct.clip();
- ct.setSource(item->cache);
- ct.paint();
- // 4. mark as clean
- item->cache->markClean(area);
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- } else {
- state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, *carea, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- }
- }
-
- DrawingSurface intermediate(*carea);
- DrawingContext ict(intermediate);
-
- // 1. Render clipping path with alpha = opacity.
- ict.setSource(0,0,0,opacity);
- // Since clip can be combined with opacity, the result could be incorrect
- // for overlapping clip children. To fix this we use the SOURCE operator
- // instead of the default OVER.
- ict.setOperator(CAIRO_OPERATOR_SOURCE);
- if (item->clip) {
- state = nr_arena_item_invoke_clip(ict, item->clip, *carea); // fixme: carea or area?
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
- goto cleanup;
- }
- } else {
- // if there is no clipping path, fill the entire surface with alpha = opacity.
- ict.paint();
- }
- // reset back to default
- ict.setOperator(CAIRO_OPERATOR_OVER);
-
- // 2. Render the mask if present and compose it with the clipping path + opacity.
- if (item->mask) {
- ict.pushGroup();
- state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ict, item->mask, *carea, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
- goto cleanup;
- }
- cairo_surface_t *mask_s = ict.rawTarget();
- // Convert mask's luminance to alpha
- ink_cairo_surface_filter(mask_s, mask_s, MaskLuminanceToAlpha());
- ict.popGroupToSource();
- ict.setOperator(CAIRO_OPERATOR_IN);
- ict.paint();
- ict.setOperator(CAIRO_OPERATOR_OVER);
- }
-
- // 3. Render object itself.
- ict.pushGroup();
- state = NR_ARENA_ITEM_VIRTUAL (item, render) (ict, item, *carea, flags);
- if (state & NR_ARENA_ITEM_STATE_INVALID) {
- retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
- goto cleanup;
- }
-
- // 4. Apply filter.
- if (item->filter && filter) {
- item->filter->render(item, ct, ict);
- // Note that because the object was rendered to a group,
- // the internals of the filter need to use cairo_get_group_target()
- // instead of cairo_get_target().
- }
-
- // 5. Render object inside the composited mask + clip
- ict.popGroupToSource();
- ict.setOperator(CAIRO_OPERATOR_IN);
- ict.paint();
-
- // 6. Paint the completed rendering onto the base context (or into cache)
- if (item->render_cache && item->cache) {
- DrawingContext cachect(*item->cache);
- cachect.rectangle(area);
- cachect.clip();
- cachect.setOperator(CAIRO_OPERATOR_SOURCE);
- cachect.setSource(&intermediate);
- cachect.paint();
- item->cache->markClean(area);
- }
- ct.setSource(&intermediate);
- ct.paint();
- ct.setSource(0,0,0,0);
- // the call above is to clear a ref on the intermediate surface held by ct
-
- retstate = item->state | NR_ARENA_ITEM_STATE_RENDER;
-
- cleanup:
- return retstate;
-}
-
-unsigned int
-nr_arena_item_invoke_clip (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area)
-{
- nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
- NR_ARENA_ITEM_STATE_INVALID);
-
- unsigned retstate = 0;
-
- // don't bother if the object does not implement clipping (e.g. NRArenaImage)
- if (!((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip)
- return retstate;
-
- if (item->visible && area.intersects(item->bbox)) {
- // The item used as the clipping path itself has a clipping path.
- // Render this item's clipping path onto a temporary surface, then composite it
- // with the item using the IN operator
- if (item->clip) {
- ct.pushAlphaGroup();
- { Inkscape::DrawingContext::Save save(ct);
- ct.setSource(0,0,0,1);
- nr_arena_item_invoke_clip(ct, item->clip, area);
- }
- ct.pushAlphaGroup();
- }
-
- // rasterize the clipping path
- retstate = ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
- clip (ct, item, area);
-
- if (item->clip) {
- ct.popGroupToSource();
- ct.setOperator(CAIRO_OPERATOR_IN);
- ct.paint();
- ct.popGroupToSource();
- ct.setOperator(CAIRO_OPERATOR_SOURCE);
- ct.paint();
- }
- }
-
- return retstate;
-}
-
-NRArenaItem *
-nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point const &p, double delta,
- unsigned int sticky)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- // Sometimes there's no BBOX in item->state, reason unknown (bug 992817); I made this not an assert to remove the warning
- if (!(item->state & NR_ARENA_ITEM_STATE_BBOX)
- || !(item->state & NR_ARENA_ITEM_STATE_PICK))
- return NULL;
-
- if (!sticky && !(item->visible && item->sensitive))
- return NULL;
-
- if (!item->bbox) return NULL;
- Geom::Rect expanded(*item->bbox);
- expanded.expandBy(delta);
-
- if (expanded.contains(p)) {
- if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->pick)
- return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
- pick (item, p, delta, sticky);
- }
-
- return NULL;
-}
-
-void
-nr_arena_item_request_update (NRArenaItem *item, unsigned int reset,
- unsigned int propagate)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (!(reset & NR_ARENA_ITEM_STATE_INVALID));
-
- if (propagate && !item->propagate)
- item->propagate = TRUE;
-
- if (item->state & reset) {
- item->state &= ~reset;
- if (item->parent) {
- nr_arena_item_request_update (item->parent, reset, FALSE);
- } else {
- nr_arena_request_update (item->arena, item);
- }
- }
-}
-
-void
-nr_arena_item_request_render (NRArenaItem *item)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
- Geom::OptIntRect dirty = outline ? item->bbox : item->drawbox;
- if (!dirty) return;
-
- // dirty the caches of all parents
- for (NRArenaItem *i = item; i; i = i->parent) {
- if (i->render_cache && i->cache) {
- i->cache->markDirty(*dirty);
- }
- }
-
- nr_arena_request_render_rect (item->arena, dirty);
-}
-
-/* Public */
-
-NRArenaItem *
-nr_arena_item_unparent (NRArenaItem *item)
-{
- nr_return_val_if_fail (item != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (item), NULL);
-
- nr_arena_item_request_render (item);
-
- if (item->parent) {
- nr_arena_item_remove_child (item->parent, item);
- }
-
- return NULL;
-}
-
-void
-nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child)
-{
- nr_return_if_fail (parent != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (parent));
- nr_return_if_fail (child != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (child));
- nr_return_if_fail (parent->arena == child->arena);
- nr_return_if_fail (child->parent == NULL);
- nr_return_if_fail (child->prev == NULL);
- nr_return_if_fail (child->next == NULL);
-
- nr_arena_item_add_child (parent, child, nr_arena_item_last_child (parent));
-}
-
-void
-nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const &transform)
-{
- Geom::Affine const t (transform);
- nr_arena_item_set_transform (item, &t);
-}
-
-void
-nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const *transform)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- if (!transform && !item->transform)
- return;
-
- const Geom::Affine *md = (item->transform) ? item->transform : &GEOM_MATRIX_IDENTITY;
- const Geom::Affine *ms = (transform) ? transform : &GEOM_MATRIX_IDENTITY;
-
- if (!Geom::matrix_equalp(*md, *ms, NR_EPSILON)) {
- // mark the area where the object was for redraw.
- nr_arena_item_request_render (item);
- if (!transform || transform->isIdentity()) {
- /* Set to identity affine */
- item->transform = NULL;
- } else {
- if (!item->transform)
- item->transform = new (GC::ATOMIC) Geom::Affine ();
- *item->transform = *transform;
- }
- // when update is called, the area where the object was moved
- // will be redrawn as well
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-void
-nr_arena_item_set_opacity (NRArenaItem *item, double opacity)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- nr_arena_item_request_render (item);
-
- item->opacity = (unsigned int) (opacity * 255.9999);
-}
-
-void
-nr_arena_item_set_sensitive (NRArenaItem *item, unsigned int sensitive)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- /* fixme: mess with pick/repick... */
-
- item->sensitive = sensitive;
-}
-
-void
-nr_arena_item_set_visible (NRArenaItem *item, unsigned int visible)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- item->visible = visible;
-
- nr_arena_item_request_render (item);
-}
-
-void
-nr_arena_item_set_clip (NRArenaItem *item, NRArenaItem *clip)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (!clip || NR_IS_ARENA_ITEM (clip));
-
- if (clip != item->clip) {
- nr_arena_item_request_render (item);
- if (item->clip)
- item->clip = nr_arena_item_detach (item, item->clip);
- if (clip)
- item->clip = nr_arena_item_attach (item, clip, NULL, NULL);
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-void
-nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_return_if_fail (!mask || NR_IS_ARENA_ITEM (mask));
-
- if (mask != item->mask) {
- nr_arena_item_request_render (item);
- if (item->mask)
- item->mask = nr_arena_item_detach (item, item->mask);
- if (mask)
- item->mask = nr_arena_item_attach (item, mask, NULL, NULL);
- nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE);
- }
-}
-
-void
-nr_arena_item_set_order (NRArenaItem *item, int order)
-{
- nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
-
- if (!item->parent)
- return;
-
- NRArenaItem *children = nr_arena_item_children (item->parent);
-
- NRArenaItem *ref = NULL;
- int pos = 0;
- for (NRArenaItem *child = children; child != NULL; child = child->next) {
- if (pos >= order)
- break;
- if (child != item) {
- ref = child;
- pos += 1;
- }
- }
-
- nr_arena_item_set_child_position (item->parent, item, ref);
-}
-
-void
-nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect const &bbox)
-{
- nr_return_if_fail(item != NULL);
- nr_return_if_fail(NR_IS_ARENA_ITEM(item));
-
- item->item_bbox = bbox;
-}
-
-void
-nr_arena_item_set_cache (NRArenaItem *item, bool cache)
-{
- if (cache) {
- item->render_cache = TRUE;
- item->arena->cached_items.insert(item);
- } else {
- item->render_cache = FALSE;
- item->arena->cached_items.erase(item);
- }
- nr_arena_item_request_update(item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/** Returns a background image for use with filter effects. */
-NRPixBlock *nr_arena_item_get_background(NRArenaItem const * /*item*/)
-{
- return NULL;
-}
-
-/* Helpers */
-
-NRArenaItem *
-nr_arena_item_attach (NRArenaItem *parent, NRArenaItem *child,
- NRArenaItem *prev, NRArenaItem *next)
-{
- nr_return_val_if_fail (parent != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
- nr_return_val_if_fail (child != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
- nr_return_val_if_fail (child->parent == NULL, NULL);
- nr_return_val_if_fail (child->prev == NULL, NULL);
- nr_return_val_if_fail (child->next == NULL, NULL);
- nr_return_val_if_fail (!prev || NR_IS_ARENA_ITEM (prev), NULL);
- nr_return_val_if_fail (!prev || (prev->parent == parent), NULL);
- nr_return_val_if_fail (!prev || (prev->next == next), NULL);
- nr_return_val_if_fail (!next || NR_IS_ARENA_ITEM (next), NULL);
- nr_return_val_if_fail (!next || (next->parent == parent), NULL);
- nr_return_val_if_fail (!next || (next->prev == prev), NULL);
-
- child->parent = parent;
- child->prev = prev;
- child->next = next;
-
- if (prev)
- prev->next = child;
- if (next)
- next->prev = child;
-
- return child;
-}
-
-NRArenaItem *
-nr_arena_item_detach (NRArenaItem *parent, NRArenaItem *child)
-{
- nr_return_val_if_fail (parent != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (parent), NULL);
- nr_return_val_if_fail (child != NULL, NULL);
- nr_return_val_if_fail (NR_IS_ARENA_ITEM (child), NULL);
- nr_return_val_if_fail (child->parent == parent, NULL);
-
- NRArenaItem *prev = child->prev;
- NRArenaItem *next = child->next;
-
- child->parent = NULL;
- child->prev = NULL;
- child->next = NULL;
-
- if (prev)
- prev->next = next;
- if (next)
- next->prev = prev;
-
- return next;
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
deleted file mode 100644
index 2c00c0bf3..000000000
--- a/src/display/nr-arena-item.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#ifndef SEEN_DISPLAY_NR_ARENA_ITEM_H
-#define SEEN_DISPLAY_NR_ARENA_ITEM_H
-
-#include <cairo.h>
-#include <2geom/affine.h>
-#include <2geom/rect.h>
-#include "libnr/nr-forward.h"
-#include "libnr/nr-rect-l.h"
-#include "libnr/nr-object.h"
-#include "gc-soft-ptr.h"
-#include "nr-arena-forward.h"
-
-namespace Inkscape {
-class DrawingContext;
-class DrawingCache;
-namespace Filters {
-class Filter;
-} }
-
-#define NR_TYPE_ARENA_ITEM (nr_arena_item_get_type ())
-#define NR_ARENA_ITEM(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA_ITEM, NRArenaItem))
-#define NR_IS_ARENA_ITEM(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA_ITEM))
-
-#define NR_ARENA_ITEM_VIRTUAL(i,m) (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (i))->m)
-
-/*
- * NRArenaItem state flags
- */
-
-/*
- * NR_ARENA_ITEM_STATE_INVALID
- *
- * If set or retuned indicates, that given object is in error.
- * Calling method has to return immediately, with appropriate
- * error flag.
- */
-
-#define NR_ARENA_ITEM_STATE_INVALID (1 << 0)
-
-
-#define NR_ARENA_ITEM_STATE_BBOX (1 << 1)
-#define NR_ARENA_ITEM_STATE_COVERAGE (1 << 2)
-#define NR_ARENA_ITEM_STATE_DRAFT (1 << 3)
-#define NR_ARENA_ITEM_STATE_RENDER (1 << 4)
-#define NR_ARENA_ITEM_STATE_CLIP (1 << 5)
-#define NR_ARENA_ITEM_STATE_MASK (1 << 6)
-#define NR_ARENA_ITEM_STATE_PICK (1 << 7)
-#define NR_ARENA_ITEM_STATE_IMAGE (1 << 8)
-#define NR_ARENA_ITEM_STATE_CACHE (1 << 9)
-
-#define NR_ARENA_ITEM_STATE_NONE 0x0000
-#define NR_ARENA_ITEM_STATE_ALL 0x03fe
-
-#define NR_ARENA_ITEM_STATE(i,s) (NR_ARENA_ITEM (i)->state & (s))
-#define NR_ARENA_ITEM_SET_STATE(i,s) (NR_ARENA_ITEM (i)->state |= (s))
-#define NR_ARENA_ITEM_UNSET_STATE(i,s) (NR_ARENA_ITEM (i)->state &= ~(s))
-
-#define NR_ARENA_ITEM_RENDER_NO_CACHE (1 << 0)
-#define NR_ARENA_ITEM_RENDER_CACHE (1 << 1)
-
-struct NRGC {
- NRGC(NRGC const *p) : parent(p) {}
- NRGC const *parent;
- Geom::Affine transform;
-};
-
-struct NRArenaItem : public NRObject {
-
- NRArena *arena;
- Inkscape::GC::soft_ptr<NRArenaItem> parent;
- NRArenaItem *next;
- Inkscape::GC::soft_ptr<NRArenaItem> prev;
-
- /* Item state */
- unsigned state : 16;
- /* Opacity itself */
- unsigned opacity : 8;
- unsigned propagate : 1;
- unsigned sensitive : 1;
- unsigned visible : 1;
- /* Whether items renders opacity itself */
- unsigned render_opacity : 1;
- unsigned render_cache : 1;
-
- unsigned int key; ///< Some SPItems can have more than one NRArenaItem,
- ///this value is a hack used to distinguish between them
-
- Geom::OptIntRect bbox; ///< Bounding box in pixel grid coordinates; (0,0) is at page origin
- Geom::OptIntRect drawbox; ///< Bounding box enlarged by filters, shrinked by clips and masks
- Geom::OptRect item_bbox; ///< Bounding box in item coordinates, required by filters
- Geom::Affine *transform; ///< Incremental transform of this item, as given by the transform= attribute
- Geom::Affine ctm; ///< Total transform from pixel grid to item coords
- NRArenaItem *clip; ///< Clipping path
- NRArenaItem *mask; ///< Mask
- Inkscape::Filters::Filter *filter; ///< Filter
- Inkscape::DrawingCache *cache; ///< Render cache
-
- void *data; ///< Anonymous data member - this is used to associate SPItems with arena items
-
- bool background_new;
-
- void init(NRArena *arena) {
- this->arena = arena;
- }
-};
-
-struct NRArenaItemClass : public NRObjectClass {
- NRArenaItem * (* children) (NRArenaItem *item);
- NRArenaItem * (* last_child) (NRArenaItem *item);
- void (* add_child) (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
- void (* remove_child) (NRArenaItem *item, NRArenaItem *child);
- void (* set_child_position) (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
- unsigned int (* update) (NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, unsigned int state, unsigned int reset);
- unsigned int (* render) (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags);
- unsigned int (* clip) (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area);
- NRArenaItem * (* pick) (NRArenaItem *item, Geom::Point const &p, double delta, unsigned int sticky);
-};
-
-#define NR_ARENA_ITEM_ARENA(ai) (((NRArenaItem *) (ai))->arena)
-
-NRType nr_arena_item_get_type (void);
-
-NRArenaItem *nr_arena_item_ref (NRArenaItem *item);
-NRArenaItem *nr_arena_item_unref (NRArenaItem *item);
-
-NRArenaItem *nr_arena_item_children (NRArenaItem *item);
-NRArenaItem *nr_arena_item_last_child (NRArenaItem *item);
-void nr_arena_item_add_child (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-void nr_arena_item_remove_child (NRArenaItem *item, NRArenaItem *child);
-void nr_arena_item_set_child_position (NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
-/*
- * Invoke update to given state, if item is inside area
- *
- * area == NULL is infinite
- * gc is PARENT gc for invoke, CHILD gc in corresponding virtual method
- * state - requested to state (bitwise or of requested flags)
- * reset - reset to state (bitwise or of flags to reset)
- */
-
-unsigned int nr_arena_item_invoke_update (NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, unsigned int state, unsigned int reset);
-
-unsigned int nr_arena_item_invoke_render(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags);
-
-unsigned int nr_arena_item_invoke_clip (Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area);
-NRArenaItem *nr_arena_item_invoke_pick (NRArenaItem *item, Geom::Point const &p, double delta, unsigned int sticky);
-
-void nr_arena_item_request_update (NRArenaItem *item, unsigned int reset, unsigned int propagate);
-void nr_arena_item_request_render (NRArenaItem *item);
-
-/* Public */
-
-NRArenaItem *nr_arena_item_unparent (NRArenaItem *item);
-
-void nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child);
-
-void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const &transform);
-void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const *transform);
-void nr_arena_item_set_opacity (NRArenaItem *item, double opacity);
-void nr_arena_item_set_sensitive (NRArenaItem *item, unsigned int sensitive);
-void nr_arena_item_set_visible (NRArenaItem *item, unsigned int visible);
-void nr_arena_item_set_clip (NRArenaItem *item, NRArenaItem *clip);
-void nr_arena_item_set_mask (NRArenaItem *item, NRArenaItem *mask);
-void nr_arena_item_set_order (NRArenaItem *item, int order);
-void nr_arena_item_set_item_bbox (NRArenaItem *item, Geom::OptRect const &bbox);
-void nr_arena_item_set_cache (NRArenaItem *item, bool cache);
-
-NRPixBlock *nr_arena_item_get_background (NRArenaItem const *item);
-
-/* Helpers */
-
-NRArenaItem *nr_arena_item_attach (NRArenaItem *parent, NRArenaItem *child, NRArenaItem *prev, NRArenaItem *next);
-NRArenaItem *nr_arena_item_detach (NRArenaItem *parent, NRArenaItem *child);
-
-#define NR_ARENA_ITEM_SET_DATA(i,v) (((NRArenaItem *) (i))->data = (v))
-#define NR_ARENA_ITEM_GET_DATA(i) (((NRArenaItem *) (i))->data)
-
-#define NR_ARENA_ITEM_SET_KEY(i,k) (((NRArenaItem *) (i))->key = (k))
-#define NR_ARENA_ITEM_GET_KEY(i) (((NRArenaItem *) (i))->key)
-
-#endif /* !SEEN_DISPLAY_NR_ARENA_ITEM_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
deleted file mode 100644
index ff985550c..000000000
--- a/src/display/nr-arena-shape.cpp
+++ /dev/null
@@ -1,565 +0,0 @@
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include <cairo.h>
-#include <glib.h>
-#include <fenv.h>
-#include <typeinfo>
-
-#include <2geom/curves.h>
-#include <2geom/pathvector.h>
-#include <2geom/svg-path.h>
-#include <2geom/svg-path-parser.h>
-#include "display/cairo-utils.h"
-#include "display/canvas-arena.h"
-#include "display/canvas-bpath.h"
-#include "display/curve.h"
-#include "display/drawing-context.h"
-#include "display/nr-arena.h"
-#include "display/nr-arena-shape.h"
-#include "display/nr-filter.h"
-#include "helper/geom-curves.h"
-#include "helper/geom.h"
-#include "libnr/nr-convert2geom.h"
-#include "preferences.h"
-#include "sp-filter.h"
-#include "sp-filter-reference.h"
-#include "style.h"
-#include "svg/svg.h"
-
-static void nr_arena_shape_class_init(NRArenaShapeClass *klass);
-static void nr_arena_shape_init(NRArenaShape *shape);
-static void nr_arena_shape_finalize(NRObject *object);
-
-static NRArenaItem *nr_arena_shape_children(NRArenaItem *item);
-static void nr_arena_shape_add_child(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-static void nr_arena_shape_remove_child(NRArenaItem *item, NRArenaItem *child);
-static void nr_arena_shape_set_child_position(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref);
-
-static guint nr_arena_shape_update(NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, guint state, guint reset);
-static unsigned int nr_arena_shape_render(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags);
-static guint nr_arena_shape_clip(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area);
-static NRArenaItem *nr_arena_shape_pick(NRArenaItem *item, Geom::Point const &p, double delta, unsigned int sticky);
-
-static NRArenaItemClass *shape_parent_class;
-
-NRType
-nr_arena_shape_get_type(void)
-{
- static NRType type = 0;
- if (!type) {
- type = nr_object_register_type(NR_TYPE_ARENA_ITEM,
- "NRArenaShape",
- sizeof(NRArenaShapeClass),
- sizeof(NRArenaShape),
- (void (*)(NRObjectClass *)) nr_arena_shape_class_init,
- (void (*)(NRObject *)) nr_arena_shape_init);
- }
- return type;
-}
-
-static void
-nr_arena_shape_class_init(NRArenaShapeClass *klass)
-{
- NRObjectClass *object_class;
- NRArenaItemClass *item_class;
-
- object_class = (NRObjectClass *) klass;
- item_class = (NRArenaItemClass *) klass;
-
- shape_parent_class = (NRArenaItemClass *) ((NRObjectClass *) klass)->parent;
-
- object_class->finalize = nr_arena_shape_finalize;
- object_class->cpp_ctor = NRObject::invoke_ctor<NRArenaShape>;
-
- item_class->children = nr_arena_shape_children;
- item_class->add_child = nr_arena_shape_add_child;
- item_class->set_child_position = nr_arena_shape_set_child_position;
- item_class->remove_child = nr_arena_shape_remove_child;
- item_class->update = nr_arena_shape_update;
- item_class->render = nr_arena_shape_render;
- item_class->clip = nr_arena_shape_clip;
- item_class->pick = nr_arena_shape_pick;
-}
-
-/**
- * Initializes the arena shape, setting all parameters to null, 0, false,
- * or other defaults
- */
-static void
-nr_arena_shape_init(NRArenaShape *shape)
-{
- shape->curve = NULL;
- shape->style = NULL;
- shape->markers = NULL;
- shape->last_pick = NULL;
- shape->repick_after = 0;
-}
-
-static void
-nr_arena_shape_finalize(NRObject *object)
-{
- NRArenaShape *shape = (NRArenaShape *) object;
-
- if (shape->style) sp_style_unref(shape->style);
- if (shape->curve) shape->curve->unref();
- shape->last_pick = NULL;
-
- ((NRObjectClass *) shape_parent_class)->finalize(object);
-}
-
-/**
- * Retrieves the markers from the item
- */
-static NRArenaItem *
-nr_arena_shape_children(NRArenaItem *item)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- return shape->markers;
-}
-
-/**
- * Attaches child to item, and if ref is not NULL, sets it and ref->next as
- * the prev and next items. If ref is NULL, then it sets the item's markers
- * as the next items.
- */
-static void
-nr_arena_shape_add_child(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- if (!ref) {
- shape->markers = nr_arena_item_attach(item, child, NULL, shape->markers);
- } else {
- ref->next = nr_arena_item_attach(item, child, ref, ref->next);
- }
-
- nr_arena_item_request_update(item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/**
- * Removes child from the shape. If there are no prev items in
- * the child, it sets items' markers to the next item in the child.
- */
-static void
-nr_arena_shape_remove_child(NRArenaItem *item, NRArenaItem *child)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- if (child->prev) {
- nr_arena_item_detach(item, child);
- } else {
- shape->markers = nr_arena_item_detach(item, child);
- }
-
- nr_arena_item_request_update(item, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/**
- * Detaches child from item, and if there are no previous items in child, it
- * sets item's markers to the child. It then attaches the child back onto the item.
- * If ref is null, it sets the markers to be the next item, otherwise it uses
- * the next/prev items in ref.
- */
-static void
-nr_arena_shape_set_child_position(NRArenaItem *item, NRArenaItem *child, NRArenaItem *ref)
-{
- NRArenaShape *shape = (NRArenaShape *) item;
-
- if (child->prev) {
- nr_arena_item_detach(item, child);
- } else {
- shape->markers = nr_arena_item_detach(item, child);
- }
-
- if (!ref) {
- shape->markers = nr_arena_item_attach(item, child, NULL, shape->markers);
- } else {
- ref->next = nr_arena_item_attach(item, child, ref, ref->next);
- }
-
- nr_arena_item_request_render(child);
-}
-
-/**
- * Updates the arena shape 'item' and all of its children, including the markers.
- */
-static guint
-nr_arena_shape_update(NRArenaItem *item, Geom::IntRect const &area, NRGC *gc, guint state, guint reset)
-{
- Geom::OptRect boundingbox;
-
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
-
- // update markers
- unsigned int newstate;
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- newstate = nr_arena_item_invoke_update(child, area, gc, state, reset);
- beststate = beststate & newstate;
- }
-
- if (!(state & NR_ARENA_ITEM_STATE_RENDER)) {
- /* We do not have to create rendering structures */
- if (state & NR_ARENA_ITEM_STATE_BBOX) {
- if (shape->curve) {
- boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
- if (boundingbox) {
- item->bbox = boundingbox->roundOutwards();
- } else {
- item->bbox = Geom::OptIntRect();
- }
- }
- if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- item->bbox.unionWith(child->bbox);
- }
- }
- }
- return (state | item->state);
- }
-
- boundingbox = Geom::OptRect();
-
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- // clear Cairo data to force update
- shape->nrstyle.update();
-
- if (shape->curve) {
- boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
-
- if (boundingbox && (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE || outline)) {
- float width, scale;
- scale = gc->transform.descrim();
- width = MAX(0.125, shape->nrstyle.stroke_width * scale);
- if ( fabs(shape->nrstyle.stroke_width * scale) > 0.01 ) { // FIXME: this is always true
- boundingbox->expandBy(width);
- }
- // those pesky miters, now
- float miterMax = width * shape->nrstyle.miter_limit;
- if ( miterMax > 0.01 ) {
- // grunt mode. we should compute the various miters instead
- // (one for each point on the curve)
- boundingbox->expandBy(miterMax);
- }
- }
- }
-
- item->bbox = boundingbox ? boundingbox->roundOutwards() : Geom::OptIntRect();
-
- if (!shape->curve ||
- !shape->style ||
- shape->curve->is_empty() ||
- (( shape->nrstyle.fill.type != NRStyle::PAINT_NONE ) &&
- ( shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && !outline) ))
- {
- //item->bbox = shape->approx_bbox;
- return NR_ARENA_ITEM_STATE_ALL;
- }
-
- if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- item->bbox.unionWith(child->bbox);
- }
- }
-
- return NR_ARENA_ITEM_STATE_ALL;
-}
-
-// cairo outline rendering:
-static unsigned int
-cairo_arena_shape_render_outline(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &/*area*/)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- guint32 rgba = NR_ARENA_ITEM(shape)->arena->outlinecolor;
-
- { Inkscape::DrawingContext::Save save(ct);
- ct.transform(shape->ctm);
- ct.path(shape->curve->get_pathvector());
- }
- { Inkscape::DrawingContext::Save save(ct);
- ct.setSource(rgba);
- ct.setLineWidth(0.5);
- ct.setTolerance(1.25);
- ct.stroke();
- }
-
- return item->state;
-}
-
-/**
- * Renders the item. Markers are just composed into the parent buffer.
- */
-static unsigned int
-nr_arena_shape_render(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &area, unsigned int flags)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- if (!shape->curve) return item->state;
- if (!shape->style) return item->state;
-
- // skip if not within bounding box
- if (!area.intersects(item->bbox)) {
- return item->state;
- }
-
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- if (outline) {
- // cairo outline rendering
- unsigned int ret = cairo_arena_shape_render_outline (ct, item, area);
- if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret;
- } else {
- bool has_stroke, has_fill;
- // we assume the context has no path
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(shape->ctm);
-
- // update fill and stroke paints.
- // this cannot be done during nr_arena_shape_update, because we need a Cairo context
- // to render svg:pattern
- has_fill = shape->nrstyle.prepareFill(ct, shape->paintbox);
- has_stroke = shape->nrstyle.prepareStroke(ct, shape->paintbox);
- has_stroke &= (shape->nrstyle.stroke_width != 0);
-
- if (has_fill || has_stroke) {
- // TODO: remove segments outside of bbox when no dashes present
- ct.path(shape->curve->get_pathvector());
- if (has_fill) {
- shape->nrstyle.applyFill(ct);
- ct.fillPreserve();
- }
- if (has_stroke) {
- shape->nrstyle.applyStroke(ct);
- ct.strokePreserve();
- }
- ct.newPath(); // clear path
- } // has fill or stroke pattern
- }
-
- // marker rendering
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- unsigned int ret = nr_arena_item_invoke_render(ct, child, area, flags);
- if (ret & NR_ARENA_ITEM_STATE_INVALID) return ret;
- }
-
- return item->state;
-}
-
-
-static guint nr_arena_shape_clip(Inkscape::DrawingContext &ct, NRArenaItem *item, Geom::IntRect const &/*area*/)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
- if (!shape->curve) {
- return item->state;
- }
-
- Inkscape::DrawingContext::Save save(ct);
- // handle clip-rule
- if (shape->style) {
- if (shape->style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
- ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
- } else {
- ct.setFillRule(CAIRO_FILL_RULE_WINDING);
- }
- }
- ct.transform(shape->ctm);
- ct.path(shape->curve->get_pathvector());
- ct.fill();
-
- return item->state;
-}
-
-static NRArenaItem *
-nr_arena_shape_pick(NRArenaItem *item, Geom::Point const &p, double delta, unsigned int /*sticky*/)
-{
- NRArenaShape *shape = NR_ARENA_SHAPE(item);
-
- if (shape->repick_after > 0)
- shape->repick_after--;
-
- if (shape->repick_after > 0) // we are a slow, huge path. skip this pick, returning what was returned last time
- return shape->last_pick;
-
- if (!shape->curve) return NULL;
- if (!shape->style) return NULL;
-
- bool outline = (NR_ARENA_ITEM(shape)->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
-
- if (SP_SCALE24_TO_FLOAT(shape->style->opacity.value) == 0 && !outline)
- // fully transparent, no pick unless outline mode
- return NULL;
-
- GTimeVal tstart, tfinish;
- g_get_current_time (&tstart);
-
- double width;
- if (outline) {
- width = 0.5;
- } else if (shape->nrstyle.stroke.type != NRStyle::PAINT_NONE && shape->nrstyle.stroke.opacity > 1e-3) {
- float const scale = shape->ctm.descrim();
- width = MAX(0.125, shape->nrstyle.stroke_width * scale) / 2;
- } else {
- width = 0;
- }
-
- double dist = Geom::infinity();
- int wind = 0;
- bool needfill = (shape->nrstyle.fill.type != NRStyle::PAINT_NONE
- && shape->nrstyle.fill.opacity > 1e-3 && !outline);
-
- if (item->arena->canvasarena) {
- Geom::Rect viewbox = item->arena->canvasarena->item.canvas->getViewbox();
- viewbox.expandBy (width);
- pathv_matrix_point_bbox_wind_distance(shape->curve->get_pathvector(), shape->ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, &viewbox);
- } else {
- pathv_matrix_point_bbox_wind_distance(shape->curve->get_pathvector(), shape->ctm, p, NULL, needfill? &wind : NULL, &dist, 0.5, NULL);
- }
-
- g_get_current_time (&tfinish);
- glong this_pick = (tfinish.tv_sec - tstart.tv_sec) * 1000000 + (tfinish.tv_usec - tstart.tv_usec);
- //g_print ("pick time %lu\n", this_pick);
-
- if (this_pick > 10000) { // slow picking, remember to skip several new picks
- shape->repick_after = this_pick / 5000;
- }
-
- // covered by fill?
- if (needfill) {
- if (!shape->style->fill_rule.computed) {
- if (wind != 0) {
- shape->last_pick = item;
- return item;
- }
- } else {
- if (wind & 0x1) {
- shape->last_pick = item;
- return item;
- }
- }
- }
-
- // close to the edge, as defined by strokewidth and delta?
- // this ignores dashing (as if the stroke is solid) and always works as if caps are round
- if (needfill || width > 0) { // if either fill or stroke visible,
- if ((dist - width) < delta) {
- shape->last_pick = item;
- return item;
- }
- }
-
- // if not picked on the shape itself, try its markers
- for (NRArenaItem *child = shape->markers; child != NULL; child = child->next) {
- NRArenaItem *ret = nr_arena_item_invoke_pick(child, p, delta, 0);
- if (ret) {
- shape->last_pick = item;
- return item;
- }
- }
-
- shape->last_pick = NULL;
- return NULL;
-}
-
-/**
- *
- * Requests a render of the shape, then if the shape is already a curve it
- * unrefs the old curve; if the new curve is valid it creates a copy of the
- * curve and adds it to the shape. Finally, it requests an update of the
- * arena for the shape.
- */
-void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve, bool /*justTrans*/)
-{
- g_return_if_fail(shape != NULL);
- g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
-
- nr_arena_item_request_render(NR_ARENA_ITEM(shape));
-
- if (shape->curve) {
- shape->curve->unref();
- shape->curve = NULL;
- }
-
- if (curve) {
- shape->curve = curve;
- curve->ref();
- }
-
- nr_arena_item_request_update(NR_ARENA_ITEM(shape), NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/** nr_arena_shape_set_style
- *
- * Unrefs any existing style and ref's to the given one, then requests an update of the arena
- */
-void
-nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style)
-{
- g_return_if_fail(shape != NULL);
- g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
- g_return_if_fail(style != NULL);
-
- sp_style_ref(style);
- if (shape->style) sp_style_unref(shape->style);
- shape->style = style;
-
- shape->nrstyle.set(style);
-
- //if shape has a filter
- if (style->filter.set && style->getFilter()) {
- if (!shape->filter) {
- int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
- shape->filter = new Inkscape::Filters::Filter(primitives);
- }
- sp_filter_build_renderer(SP_FILTER(style->getFilter()), shape->filter);
- } else {
- //no filter set for this shape
- delete shape->filter;
- shape->filter = NULL;
- }
-
- nr_arena_item_request_update(shape, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void
-nr_arena_shape_set_paintbox(NRArenaShape *shape, NRRect const *pbox)
-{
- g_return_if_fail(shape != NULL);
- g_return_if_fail(NR_IS_ARENA_SHAPE(shape));
- g_return_if_fail(pbox != NULL);
-
- shape->paintbox = pbox->upgrade_2geom();
-
- nr_arena_item_request_update(shape, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-void NRArenaShape::setPaintBox(Geom::Rect const &pbox)
-{
- paintbox = pbox;
-
- nr_arena_item_request_update(this, NR_ARENA_ITEM_STATE_ALL, FALSE);
-}
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h
deleted file mode 100644
index 317cff7fb..000000000
--- a/src/display/nr-arena-shape.h
+++ /dev/null
@@ -1,72 +0,0 @@
-#ifndef __NR_ARENA_SHAPE_H__
-#define __NR_ARENA_SHAPE_H__
-
-/*
- * RGBA display list system for inkscape
- *
- * Author:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * Copyright (C) 2001-2002 Lauris Kaplinski
- * Copyright (C) 2001 Ximian, Inc.
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#define NR_TYPE_ARENA_SHAPE (nr_arena_shape_get_type ())
-#define NR_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_SHAPE, NRArenaShape))
-#define NR_IS_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_SHAPE))
-
-#include <cairo.h>
-#include "display/display-forward.h"
-#include "forward.h"
-#include "nr-arena-item.h"
-#include "nr-style.h"
-#include "libnr/nr-rect.h"
-
-NRType nr_arena_shape_get_type (void);
-
-struct NRArenaShape : public NRArenaItem {
- /* Shape data */
- SPCurve *curve;
- SPStyle *style;
- NRStyle nrstyle;
- Geom::OptRect paintbox;
-
- /* Markers */
- NRArenaItem *markers;
-
- NRArenaItem *last_pick;
- guint repick_after;
-
- static NRArenaShape *create(NRArena *arena) {
- NRArenaShape *obj=reinterpret_cast<NRArenaShape *>(nr_object_new(NR_TYPE_ARENA_SHAPE));
- obj->init(arena);
- obj->key = 0;
- return obj;
- }
-
- void setPaintBox(Geom::Rect const &pbox);
-};
-
-struct NRArenaShapeClass {
- NRArenaItemClass parent_class;
-};
-
-void nr_arena_shape_set_path(NRArenaShape *shape, SPCurve *curve, bool justTrans);
-void nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style);
-void nr_arena_shape_set_paintbox(NRArenaShape *shape, NRRect const *pbox);
-
-
-#endif /* !__NR_ARENA_SHAPE_H__ */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/display/nr-arena.cpp b/src/display/nr-arena.cpp
index 735d44e9e..b3e962201 100644
--- a/src/display/nr-arena.cpp
+++ b/src/display/nr-arena.cpp
@@ -12,13 +12,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include "nr-arena-item.h"
-#include "nr-arena.h"
-#include "nr-filter-gaussian.h"
-#include "nr-filter-types.h"
+#include "display/drawing-item.h"
+#include "display/nr-arena.h"
+#include "display/nr-filter-gaussian.h"
+#include "display/nr-filter-types.h"
#include "preferences.h"
#include "color.h"
#include "libnr/nr-rect.h"
+#include "libnr/nr-rect-l.h"
static void nr_arena_class_init (NRArenaClass *klass);
static void nr_arena_init (NRArena *arena);
@@ -58,7 +59,7 @@ nr_arena_init (NRArena *arena)
arena->delta = 0; // to be set by desktop from prefs
arena->renderoffscreen = false; // use render values from preferences otherwise render exact
arena->rendermode = Inkscape::RENDERMODE_NORMAL; // default is normal render
- arena->colorrendermode = Inkscape::COLORRENDERMODE_NORMAL; // default is normal color
+ arena->colormode = Inkscape::COLORMODE_NORMAL; // default is normal color
arena->blurquality = BLUR_QUALITY_NORMAL;
arena->filterquality = Inkscape::Filters::FILTER_QUALITY_NORMAL;
arena->outlinecolor = 0xff; // black; to be set by desktop from bg color
@@ -72,14 +73,14 @@ nr_arena_finalize (NRObject *object)
}
void
-nr_arena_request_update (NRArena *arena, NRArenaItem *item)
+nr_arena_request_update (NRArena *arena, Inkscape::DrawingItem *item)
{
NRActiveObject *aobject = (NRActiveObject *) arena;
nr_return_if_fail (arena != NULL);
nr_return_if_fail (NR_IS_ARENA (arena));
nr_return_if_fail (item != NULL);
- nr_return_if_fail (NR_IS_ARENA_ITEM (item));
+
// setup render parameter
if (arena->renderoffscreen == false) {
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -89,7 +90,7 @@ nr_arena_request_update (NRArena *arena, NRArenaItem *item)
arena->blurquality = BLUR_QUALITY_BEST;
arena->filterquality = Inkscape::Filters::FILTER_QUALITY_BEST;
arena->rendermode = Inkscape::RENDERMODE_NORMAL;
- arena->colorrendermode = Inkscape::COLORRENDERMODE_NORMAL;
+ arena->colormode = Inkscape::COLORMODE_NORMAL;
}
if (aobject->callbacks) {
@@ -121,7 +122,7 @@ nr_arena_request_render_rect (NRArena *arena, Geom::OptIntRect const &area)
arena->blurquality = BLUR_QUALITY_BEST;
arena->filterquality = Inkscape::Filters::FILTER_QUALITY_BEST;
arena->rendermode = Inkscape::RENDERMODE_NORMAL;
- arena->colorrendermode = Inkscape::COLORRENDERMODE_NORMAL;
+ arena->colormode = Inkscape::COLORMODE_NORMAL;
}
NRRectL nr_area(*area);
if (aobject->callbacks) {
@@ -155,10 +156,10 @@ void
nr_arena_set_cache_limit (NRArena *arena, Geom::OptIntRect const &cache_limit)
{
arena->cache_limit = cache_limit;
- for (std::set<NRArenaItem *>::iterator i = arena->cached_items.begin();
+ for (std::set<Inkscape::DrawingItem *>::iterator i = arena->cached_items.begin();
i != arena->cached_items.end(); ++i)
{
- nr_arena_item_request_update(*i, NR_ARENA_ITEM_STATE_CACHE, FALSE);
+ (*i)->_markForUpdate(Inkscape::DrawingItem::STATE_CACHE, false);
}
}
diff --git a/src/display/nr-arena.h b/src/display/nr-arena.h
index 5d078e19d..a444ed505 100644
--- a/src/display/nr-arena.h
+++ b/src/display/nr-arena.h
@@ -13,9 +13,14 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <set>
#include <glib/gmacros.h>
-
+#include <sigc++/sigc++.h>
+#include <2geom/rect.h>
#include "display/rendermode.h"
+#include "libnr/nr-forward.h"
+#include "libnr/nr-object.h"
+#include "display/display-forward.h"
G_BEGIN_DECLS
@@ -27,19 +32,13 @@ G_END_DECLS
#define NR_ARENA(o) (NR_CHECK_INSTANCE_CAST ((o), NR_TYPE_ARENA, NRArena))
#define NR_IS_ARENA(o) (NR_CHECK_INSTANCE_TYPE ((o), NR_TYPE_ARENA))
-#include <set>
-#include <2geom/rect.h>
-#include <libnr/nr-forward.h>
-#include <libnr/nr-object.h>
-#include "nr-arena-forward.h"
-
class SPPainter;
NRType nr_arena_get_type (void);
struct NRArenaEventVector {
NRObjectEventVector parent;
- void (* request_update) (NRArena *arena, NRArenaItem *item, void *data);
+ void (* request_update) (NRArena *arena, Inkscape::DrawingItem *item, void *data);
void (* request_render) (NRArena *arena, NRRectL *area, void *data);
};
@@ -51,20 +50,22 @@ struct NRArena : public NRActiveObject {
double delta;
bool renderoffscreen; // if true then rendering must be exact
Inkscape::RenderMode rendermode;
- Inkscape::ColorRenderMode colorrendermode;
+ Inkscape::ColorMode colormode;
int blurquality; // will be updated during update from preferences
int filterquality; // will be updated during update from preferences
Geom::OptIntRect cache_limit;
- std::set<NRArenaItem *> cached_items;
+ std::set<Inkscape::DrawingItem *> cached_items;
guint32 outlinecolor;
SPCanvasArena *canvasarena; // may be NULL is this arena is not the screen but used for export etc.
+
+ sigc::signal<void, Inkscape::DrawingItem *> item_deleted;
};
struct NRArenaClass : public NRActiveObjectClass {
};
-void nr_arena_request_update (NRArena *arena, NRArenaItem *item);
+void nr_arena_request_update (NRArena *arena, Inkscape::DrawingItem *item);
void nr_arena_request_render_rect (NRArena *arena, Geom::OptIntRect const &area);
void nr_arena_set_renderoffscreen (NRArena *arena);
void nr_arena_set_cache_limit (NRArena *arena, Geom::OptIntRect const &cache_limit);
diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp
index eaed2a8bd..039e56bb0 100644
--- a/src/display/nr-filter-diffuselighting.cpp
+++ b/src/display/nr-filter-diffuselighting.cpp
@@ -16,7 +16,6 @@
#include "display/cairo-templates.h"
#include "display/cairo-utils.h"
#include "display/nr-3dutils.h"
-#include "display/nr-arena-item.h"
#include "display/nr-filter-diffuselighting.h"
#include "display/nr-filter-slot.h"
#include "display/nr-filter-units.h"
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 01d2eca64..55cd02697 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -15,7 +15,7 @@
#include "display/cairo-utils.h"
#include "display/drawing-context.h"
#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-item.h"
#include "display/nr-filter.h"
#include "display/nr-filter-image.h"
#include "display/nr-filter-units.h"
@@ -70,7 +70,7 @@ void FilterImage::render_cairo(FilterSlot &slot)
// TODO: do not recreate the rendering tree every time
// TODO: the entire thing is a hack, we should give filter primitives an "update" method
- // like the one for NRArenaItems
+ // like the one for DrawingItems
document->ensureUpToDate();
NRArena* arena = NRArena::create();
@@ -78,7 +78,7 @@ void FilterImage::render_cairo(FilterSlot &slot)
if (!optarea) return;
unsigned const key = SPItem::display_key_new(1);
- NRArenaItem* ai = SVGElem->invoke_show(arena, key, SP_ITEM_SHOW_DISPLAY);
+ DrawingItem *ai = SVGElem->invoke_show(arena, key, SP_ITEM_SHOW_DISPLAY);
if (!ai) {
g_warning("feImage renderer: error creating NRArenaItem for SVG Element");
@@ -104,15 +104,12 @@ void FilterImage::render_cairo(FilterSlot &slot)
ct.translate(render_rect.min());
// Update to renderable state
- NRGC gc(NULL);
- Geom::Affine t = Geom::identity();
- nr_arena_item_set_transform(ai, &t);
- gc.transform.setIdentity();
- nr_arena_item_invoke_update(ai, render_rect, &gc,
- NR_ARENA_ITEM_STATE_ALL,
- NR_ARENA_ITEM_STATE_NONE);
- nr_arena_item_invoke_render(ct, ai, render_rect, NR_ARENA_ITEM_RENDER_NO_CACHE);
+ UpdateContext ctx;
+ ai->setTransform(Geom::identity());
+ ai->update(render_rect, ctx, DrawingItem::STATE_ALL, 0);
+ ai->render(ct, render_rect, DrawingItem::RENDER_BYPASS_CACHE);
SVGElem->invoke_hide(key);
+ //delete ai; // should be deleted by hide() above
nr_object_unref((NRObject*) arena);
slot.set(_output, out);
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index 494d77749..d2f992859 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -17,7 +17,6 @@
#include <2geom/transforms.h>
#include "display/cairo-utils.h"
#include "display/drawing-context.h"
-#include "display/nr-arena-item.h"
#include "display/nr-filter-types.h"
#include "display/nr-filter-gaussian.h"
#include "display/nr-filter-slot.h"
@@ -26,7 +25,7 @@
namespace Inkscape {
namespace Filters {
-FilterSlot::FilterSlot(NRArenaItem *item, DrawingContext &bgct,
+FilterSlot::FilterSlot(DrawingItem *item, DrawingContext &bgct,
DrawingContext &graphic, FilterUnits const &u)
: _item(item)
, _source_graphic(graphic.rawTarget())
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index 6a86ded8c..1e7c3a5a6 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -19,17 +19,16 @@
#include "display/nr-filter-types.h"
#include "display/nr-filter-units.h"
-struct NRArenaItem;
-
namespace Inkscape {
class DrawingContext;
+class DrawingItem;
namespace Filters {
class FilterSlot {
public:
/** Creates a new FilterSlot object. */
- FilterSlot(NRArenaItem *item, DrawingContext &bgct,
+ FilterSlot(DrawingItem *item, DrawingContext &bgct,
DrawingContext &graphic, FilterUnits const &u);
/** Destroys the FilterSlot object and all its contents */
virtual ~FilterSlot();
@@ -73,7 +72,7 @@ public:
private:
typedef std::map<int, cairo_surface_t *> SlotMap;
SlotMap _slots;
- NRArenaItem *_item;
+ DrawingItem *_item;
//Geom::Rect _source_bbox; ///< bounding box of source graphic surface
//Geom::Rect _intermediate_bbox; ///< bounding box of intermediate surfaces
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 25ef80c17..abd102452 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -39,7 +39,7 @@
#include "display/nr-filter-turbulence.h"
#include "display/nr-arena.h"
-#include "display/nr-arena-item.h"
+#include "display/drawing-item.h"
#include "display/drawing-context.h"
#include <2geom/affine.h>
#include <2geom/rect.h>
@@ -97,7 +97,7 @@ Filter::~Filter()
}
-int Filter::render(NRArenaItem const *item, DrawingContext &bgct, DrawingContext &graphic)
+int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &bgct, DrawingContext &graphic)
{
if (_primitive.empty()) {
// when no primitives are defined, clear source graphic
@@ -108,14 +108,14 @@ int Filter::render(NRArenaItem const *item, DrawingContext &bgct, DrawingContext
return 1;
}
- FilterQuality const filterquality = (FilterQuality)item->arena->filterquality;
- int const blurquality = item->arena->blurquality;
+ FilterQuality const filterquality = (FilterQuality)item->drawing()->filterquality;
+ int const blurquality = item->drawing()->blurquality;
- Geom::Affine trans = item->ctm;
+ Geom::Affine trans = item->ctm();
Geom::Rect item_bbox;
{
- Geom::OptRect maybe_bbox = item->item_bbox;
+ Geom::OptRect maybe_bbox = item->itemBounds();
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return 1;
@@ -161,7 +161,7 @@ int Filter::render(NRArenaItem const *item, DrawingContext &bgct, DrawingContext
}
}
- FilterSlot slot(const_cast<NRArenaItem*>(item), bgct, graphic, units);
+ FilterSlot slot(const_cast<Inkscape::DrawingItem*>(item), bgct, graphic, units);
slot.set_quality(filterquality);
slot.set_blurquality(blurquality);
@@ -188,10 +188,10 @@ void Filter::set_primitive_units(SPFilterUnits unit) {
_primitive_units = unit;
}
-void Filter::area_enlarge(Geom::IntRect &bbox, NRArenaItem const *item) const {
+void Filter::area_enlarge(Geom::IntRect &bbox, Inkscape::DrawingItem const *item) const {
NRRectL b(bbox);
for (unsigned i = 0 ; i < _primitive.size() ; i++) {
- if (_primitive[i]) _primitive[i]->area_enlarge(b, item->ctm);
+ if (_primitive[i]) _primitive[i]->area_enlarge(b, item->ctm());
}
bbox = *b.upgrade_2geom();
@@ -208,7 +208,7 @@ void Filter::area_enlarge(Geom::IntRect &bbox, NRArenaItem const *item) const {
}
Geom::Rect item_bbox;
- Geom::OptRect maybe_bbox = item->item_bbox;
+ Geom::OptRect maybe_bbox = item->itemBounds();
if (maybe_bbox.isEmpty()) {
// Code below needs a bounding box
return;
@@ -216,9 +216,9 @@ void Filter::area_enlarge(Geom::IntRect &bbox, NRArenaItem const *item) const {
item_bbox = *maybe_bbox;
std::pair<double,double> res_low
- = _filter_resolution(item_bbox, item->ctm, filterquality);
+ = _filter_resolution(item_bbox, item->ctm(), filterquality);
//std::pair<double,double> res_full
- // = _filter_resolution(item_bbox, item->ctm, FILTER_QUALITY_BEST);
+ // = _filter_resolution(item_bbox, item->ctm(), FILTER_QUALITY_BEST);
double pixels_per_block = fmax(item_bbox.width() / res_low.first,
item_bbox.height() / res_low.second);
bbox.x0 -= (int)pixels_per_block;
@@ -228,10 +228,10 @@ void Filter::area_enlarge(Geom::IntRect &bbox, NRArenaItem const *item) const {
*/
}
-Geom::IntRect Filter::compute_drawbox(NRArenaItem const *item, Geom::Rect const &item_bbox) {
+Geom::IntRect Filter::compute_drawbox(Inkscape::DrawingItem const *item, Geom::Rect const &item_bbox) {
Geom::Rect enlarged = filter_effect_area(item_bbox);
- enlarged *= item->ctm;
+ enlarged *= item->ctm();
Geom::IntRect ret(enlarged.roundOutwards());
return ret;
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index 5cebf3ad3..31705f53b 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -21,21 +21,20 @@
#include "sp-filter-units.h"
#include "gc-managed.h"
-struct NRArenaItem;
-
namespace Inkscape {
class DrawingContext;
+class DrawingItem;
namespace Filters {
-class Filter : public Inkscape::GC::Managed<> {
+class Filter {
public:
/** Given background state from @a bgct and an intermediate rendering from the surface
* backing @a graphic, modify the contents of the surface backing @a graphic to represent
* the results of filter rendering. @a bgarea and @a area specify bounding boxes
* of both surfaces in world coordinates; Cairo contexts are assumed to be in default state
* (0,0 = surface origin, no path, OVER operator) */
- int render(NRArenaItem const *item, DrawingContext &bgct, DrawingContext &graphic);
+ int render(Inkscape::DrawingItem const *item, DrawingContext &bgct, DrawingContext &graphic);
/**
* Creates a new filter primitive under this filter object.
@@ -151,13 +150,13 @@ public:
* to be rendered so that after filtering, the original area is
* drawn correctly.
*/
- void area_enlarge(Geom::IntRect &area, NRArenaItem const *item) const;
+ void area_enlarge(Geom::IntRect &area, Inkscape::DrawingItem const *item) const;
/**
* Given an item bounding box (in user coords), this function enlarges it
* to contain the filter effects region and transforms it to screen
* coordinates
*/
- Geom::IntRect compute_drawbox(NRArenaItem const *item, Geom::Rect const &item_bbox);
+ Geom::IntRect compute_drawbox(Inkscape::DrawingItem const *item, Geom::Rect const &item_bbox);
/**
* Returns the filter effects area in user coordinate system.
* The given bounding box should be a bounding box as specified in
diff --git a/src/display/rendermode.h b/src/display/rendermode.h
index 8fc022bfb..cbd35de73 100644
--- a/src/display/rendermode.h
+++ b/src/display/rendermode.h
@@ -15,10 +15,10 @@ enum RenderMode {
RENDERMODE_OUTLINE
};
-enum ColorRenderMode {
- COLORRENDERMODE_NORMAL,
- COLORRENDERMODE_GRAYSCALE,
- COLORRENDERMODE_PRINT_COLORS_PREVIEW
+enum ColorMode {
+ COLORMODE_NORMAL,
+ COLORMODE_GRAYSCALE,
+ COLORMODE_PRINT_COLORS_PREVIEW
};
}