summaryrefslogtreecommitdiffstats
path: root/src/display
diff options
context:
space:
mode:
Diffstat (limited to 'src/display')
-rw-r--r--src/display/canvas-arena.cpp8
-rw-r--r--src/display/canvas-axonomgrid.cpp2
-rw-r--r--src/display/canvas-grid.cpp2
-rw-r--r--src/display/curve.cpp1
-rw-r--r--src/display/drawing-context.cpp22
-rw-r--r--src/display/drawing-context.h6
-rw-r--r--src/display/drawing-group.cpp12
-rw-r--r--src/display/drawing-group.h4
-rw-r--r--src/display/drawing-image.cpp53
-rw-r--r--src/display/drawing-image.h2
-rw-r--r--src/display/drawing-item.cpp126
-rw-r--r--src/display/drawing-item.h12
-rw-r--r--src/display/drawing-shape.cpp166
-rw-r--r--src/display/drawing-shape.h11
-rw-r--r--src/display/drawing-surface.cpp62
-rw-r--r--src/display/drawing-surface.h2
-rw-r--r--src/display/drawing-text.cpp139
-rw-r--r--src/display/drawing-text.h8
-rw-r--r--src/display/drawing.cpp16
-rw-r--r--src/display/drawing.h2
-rw-r--r--src/display/nr-filter-component-transfer.cpp25
-rw-r--r--src/display/nr-filter-gaussian.cpp21
-rw-r--r--src/display/nr-filter-image.cpp15
-rw-r--r--src/display/nr-filter-offset.cpp16
-rw-r--r--src/display/nr-filter-primitive.cpp53
-rw-r--r--src/display/nr-filter-slot.cpp6
-rw-r--r--src/display/nr-filter-slot.h2
-rw-r--r--src/display/nr-filter-turbulence.cpp6
-rw-r--r--src/display/nr-filter.cpp27
-rw-r--r--src/display/nr-filter.h4
-rw-r--r--src/display/nr-style.cpp64
-rw-r--r--src/display/nr-style.h20
-rw-r--r--src/display/sodipodi-ctrlrect.cpp13
-rw-r--r--src/display/sp-canvas.cpp30
-rw-r--r--src/display/sp-canvas.h1
-rw-r--r--src/display/sp-ctrlquadr.h4
36 files changed, 588 insertions, 375 deletions
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index 8e25c1843..404a94828 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -216,10 +216,10 @@ sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
Geom::OptIntRect r = buf->rect;
if (!r || r->hasZeroArea()) return;
- Inkscape::DrawingContext ct(buf->ct, r->min());
+ Inkscape::DrawingContext dc(buf->ct, r->min());
arena->drawing.update(Geom::IntRect::infinite(), arena->ctx);
- arena->drawing.render(ct, *r);
+ arena->drawing.render(dc, *r);
}
static double
@@ -386,9 +386,9 @@ sp_canvas_arena_render_surface (SPCanvasArena *ca, cairo_surface_t *surface, Geo
g_return_if_fail (ca != NULL);
g_return_if_fail (SP_IS_CANVAS_ARENA (ca));
- Inkscape::DrawingContext ct(surface, r.min());
+ Inkscape::DrawingContext dc(surface, r.min());
ca->drawing.update(Geom::IntRect::infinite(), ca->ctx);
- ca->drawing.render(ct, r);
+ ca->drawing.render(dc, r);
}
/*
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp
index 858312f5b..312a8d655 100644
--- a/src/display/canvas-axonomgrid.cpp
+++ b/src/display/canvas-axonomgrid.cpp
@@ -141,7 +141,7 @@ attach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int
Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
#endif
} else {
- Gtk::HBox *space = manage (new Gtk::HBox);
+ Gtk::HBox *space = Gtk::manage (new Gtk::HBox);
space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y);
#if WITH_GTKMM_3_0
space->set_halign(Gtk::ALIGN_CENTER);
diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp
index 3c4ad9b00..4b1dbd1ed 100644
--- a/src/display/canvas-grid.cpp
+++ b/src/display/canvas-grid.cpp
@@ -469,7 +469,7 @@ static inline void attach_all(Gtk::Table &table, Gtk::Widget const *const arr[],
Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
#endif
} else {
- Gtk::HBox *space = manage (new Gtk::HBox);
+ Gtk::HBox *space = Gtk::manage (new Gtk::HBox);
space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y);
#if WITH_GTKMM_3_0
space->set_halign(Gtk::ALIGN_CENTER);
diff --git a/src/display/curve.cpp b/src/display/curve.cpp
index ae243853e..50f4c8954 100644
--- a/src/display/curve.cpp
+++ b/src/display/curve.cpp
@@ -34,7 +34,6 @@ SPCurve::SPCurve()
: _refcount(1),
_pathv()
{
- _pathv.clear();
}
SPCurve::SPCurve(Geom::PathVector const& pathv)
diff --git a/src/display/drawing-context.cpp b/src/display/drawing-context.cpp
index de5beb0f6..319136e06 100644
--- a/src/display/drawing-context.cpp
+++ b/src/display/drawing-context.cpp
@@ -25,27 +25,27 @@ using Geom::Y;
*/
DrawingContext::Save::Save()
- : _ct(NULL)
+ : _dc(NULL)
{}
-DrawingContext::Save::Save(DrawingContext &ct)
- : _ct(&ct)
+DrawingContext::Save::Save(DrawingContext &dc)
+ : _dc(&dc)
{
- _ct->save();
+ _dc->save();
}
DrawingContext::Save::~Save()
{
- if (_ct) {
- _ct->restore();
+ if (_dc) {
+ _dc->restore();
}
}
-void DrawingContext::Save::save(DrawingContext &ct)
+void DrawingContext::Save::save(DrawingContext &dc)
{
- if (_ct) {
+ if (_dc) {
// TODO: it might be better to treat this occurence as a bug
- _ct->restore();
+ _dc->restore();
}
- _ct = &ct;
- _ct->save();
+ _dc = &dc;
+ _dc->save();
}
/**
diff --git a/src/display/drawing-context.h b/src/display/drawing-context.h
index 35be9a86b..d990bcb73 100644
--- a/src/display/drawing-context.h
+++ b/src/display/drawing-context.h
@@ -31,11 +31,11 @@ public:
class Save {
public:
Save();
- Save(DrawingContext &ct);
+ Save(DrawingContext &dc);
~Save();
- void save(DrawingContext &ct);
+ void save(DrawingContext &dc);
private:
- DrawingContext *_ct;
+ DrawingContext *_dc;
};
DrawingContext(cairo_t *ct, Geom::Point const &origin);
diff --git a/src/display/drawing-group.cpp b/src/display/drawing-group.cpp
index b5ce18891..38ace001f 100644
--- a/src/display/drawing-group.cpp
+++ b/src/display/drawing-group.cpp
@@ -98,12 +98,12 @@ DrawingGroup::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, u
}
unsigned
-DrawingGroup::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+DrawingGroup::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
{
if (stop_at == NULL) {
// normal rendering
for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
- i->render(ct, area, flags, stop_at);
+ i->render(dc, area, flags, stop_at);
}
} else {
// background rendering
@@ -111,11 +111,11 @@ DrawingGroup::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigne
if (&*i == stop_at) return RENDER_OK; // do not render the stop_at item at all
if (i->isAncestorOf(stop_at)) {
// render its ancestors without masks, opacity or filters
- i->render(ct, area, flags | RENDER_FILTER_BACKGROUND, stop_at);
+ i->render(dc, area, flags | RENDER_FILTER_BACKGROUND, stop_at);
// stop further rendering
return RENDER_OK;
} else {
- i->render(ct, area, flags, stop_at);
+ i->render(dc, area, flags, stop_at);
}
}
}
@@ -123,10 +123,10 @@ DrawingGroup::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigne
}
void
-DrawingGroup::_clipItem(DrawingContext &ct, Geom::IntRect const &area)
+DrawingGroup::_clipItem(DrawingContext &dc, Geom::IntRect const &area)
{
for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
- i->clip(ct, area);
+ i->clip(dc, area);
}
}
diff --git a/src/display/drawing-group.h b/src/display/drawing-group.h
index 775fec8c4..651e9d8af 100644
--- a/src/display/drawing-group.h
+++ b/src/display/drawing-group.h
@@ -34,9 +34,9 @@ public:
protected:
virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
unsigned flags, unsigned reset);
- virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ virtual unsigned _renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags,
DrawingItem *stop_at);
- virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual void _clipItem(DrawingContext &dc, Geom::IntRect const &area);
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
virtual bool _canClip();
diff --git a/src/display/drawing-image.cpp b/src/display/drawing-image.cpp
index 1b9214c49..5844c8b08 100644
--- a/src/display/drawing-image.cpp
+++ b/src/display/drawing-image.cpp
@@ -102,22 +102,22 @@ DrawingImage::_updateItem(Geom::IntRect const &, UpdateContext const &, unsigned
return STATE_ALL;
}
-unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
+unsigned DrawingImage::_renderItem(DrawingContext &dc, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
{
bool outline = _drawing.outline();
if (!outline) {
if (!_pixbuf) return RENDER_OK;
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(_ctm);
- ct.newPath();
- ct.rectangle(_clipbox);
- ct.clip();
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+ dc.newPath();
+ dc.rectangle(_clipbox);
+ dc.clip();
- ct.translate(_origin);
- ct.scale(_scale);
- ct.setSource(_pixbuf->getSurfaceRaw(), 0, 0);
+ dc.translate(_origin);
+ dc.scale(_scale);
+ dc.setSource(_pixbuf->getSurfaceRaw(), 0, 0);
if (_style) {
// See: http://www.w3.org/TR/SVG/painting.html#ImageRenderingProperty
@@ -128,24 +128,25 @@ unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*ar
// Do nothing
break;
case SP_CSS_COLOR_RENDERING_OPTIMIZEQUALITY:
- ct.patternSetFilter( CAIRO_FILTER_BEST );
+ // In recent Cairo, BEST used Lanczos3, which is prohibitively slow
+ dc.patternSetFilter( CAIRO_FILTER_GOOD );
break;
case SP_CSS_COLOR_RENDERING_OPTIMIZESPEED:
default:
- ct.patternSetFilter( CAIRO_FILTER_NEAREST );
+ dc.patternSetFilter( CAIRO_FILTER_NEAREST );
break;
}
}
- ct.paint(_opacity);
+ dc.paint(_opacity);
} 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();
+ { Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+ dc.newPath();
Geom::Rect r = bounds();
Geom::Point c00 = r.corner(0);
@@ -153,21 +154,21 @@ unsigned DrawingImage::_renderItem(DrawingContext &ct, Geom::IntRect const &/*ar
Geom::Point c11 = r.corner(2);
Geom::Point c10 = r.corner(1);
- ct.moveTo(c00);
+ dc.moveTo(c00);
// the box
- ct.lineTo(c10);
- ct.lineTo(c11);
- ct.lineTo(c01);
- ct.lineTo(c00);
+ dc.lineTo(c10);
+ dc.lineTo(c11);
+ dc.lineTo(c01);
+ dc.lineTo(c00);
// the diagonals
- ct.lineTo(c11);
- ct.moveTo(c10);
- ct.lineTo(c01);
+ dc.lineTo(c11);
+ dc.moveTo(c10);
+ dc.lineTo(c01);
}
- ct.setLineWidth(0.5);
- ct.setSource(rgba);
- ct.stroke();
+ dc.setLineWidth(0.5);
+ dc.setSource(rgba);
+ dc.stroke();
}
return RENDER_OK;
}
diff --git a/src/display/drawing-image.h b/src/display/drawing-image.h
index cebaafc85..64e4517b0 100644
--- a/src/display/drawing-image.h
+++ b/src/display/drawing-image.h
@@ -38,7 +38,7 @@ public:
protected:
virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
unsigned flags, unsigned reset);
- virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ virtual unsigned _renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags,
DrawingItem *stop_at);
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
index a9b07bb6e..ccf905e81 100644
--- a/src/display/drawing-item.cpp
+++ b/src/display/drawing-item.cpp
@@ -24,60 +24,60 @@
namespace Inkscape {
#ifdef WITH_CSSBLEND
-void set_cairo_blend_operator( DrawingContext &ct, unsigned blend_mode ) {
+void set_cairo_blend_operator( DrawingContext &dc, unsigned blend_mode ) {
// All of the blend modes are implemented in Cairo as of 1.10.
// For a detailed description, see:
// http://cairographics.org/operators/
switch (blend_mode) {
case SP_CSS_BLEND_MULTIPLY:
- ct.setOperator(CAIRO_OPERATOR_MULTIPLY);
+ dc.setOperator(CAIRO_OPERATOR_MULTIPLY);
break;
case SP_CSS_BLEND_SCREEN:
- ct.setOperator(CAIRO_OPERATOR_SCREEN);
+ dc.setOperator(CAIRO_OPERATOR_SCREEN);
break;
case SP_CSS_BLEND_DARKEN:
- ct.setOperator(CAIRO_OPERATOR_DARKEN);
+ dc.setOperator(CAIRO_OPERATOR_DARKEN);
break;
case SP_CSS_BLEND_LIGHTEN:
- ct.setOperator(CAIRO_OPERATOR_LIGHTEN);
+ dc.setOperator(CAIRO_OPERATOR_LIGHTEN);
break;
case SP_CSS_BLEND_OVERLAY:
- ct.setOperator(CAIRO_OPERATOR_OVERLAY);
+ dc.setOperator(CAIRO_OPERATOR_OVERLAY);
break;
case SP_CSS_BLEND_COLORDODGE:
- ct.setOperator(CAIRO_OPERATOR_COLOR_DODGE);
+ dc.setOperator(CAIRO_OPERATOR_COLOR_DODGE);
break;
case SP_CSS_BLEND_COLORBURN:
- ct.setOperator(CAIRO_OPERATOR_COLOR_BURN);
+ dc.setOperator(CAIRO_OPERATOR_COLOR_BURN);
break;
case SP_CSS_BLEND_HARDLIGHT:
- ct.setOperator(CAIRO_OPERATOR_HARD_LIGHT);
+ dc.setOperator(CAIRO_OPERATOR_HARD_LIGHT);
break;
case SP_CSS_BLEND_SOFTLIGHT:
- ct.setOperator(CAIRO_OPERATOR_SOFT_LIGHT);
+ dc.setOperator(CAIRO_OPERATOR_SOFT_LIGHT);
break;
case SP_CSS_BLEND_DIFFERENCE:
- ct.setOperator(CAIRO_OPERATOR_DIFFERENCE);
+ dc.setOperator(CAIRO_OPERATOR_DIFFERENCE);
break;
case SP_CSS_BLEND_EXCLUSION:
- ct.setOperator(CAIRO_OPERATOR_EXCLUSION);
+ dc.setOperator(CAIRO_OPERATOR_EXCLUSION);
break;
case SP_CSS_BLEND_HUE:
- ct.setOperator(CAIRO_OPERATOR_HSL_HUE);
+ dc.setOperator(CAIRO_OPERATOR_HSL_HUE);
break;
case SP_CSS_BLEND_SATURATION:
- ct.setOperator(CAIRO_OPERATOR_HSL_SATURATION);
+ dc.setOperator(CAIRO_OPERATOR_HSL_SATURATION);
break;
case SP_CSS_BLEND_COLOR:
- ct.setOperator(CAIRO_OPERATOR_HSL_COLOR);
+ dc.setOperator(CAIRO_OPERATOR_HSL_COLOR);
break;
case SP_CSS_BLEND_LUMINOSITY:
- ct.setOperator(CAIRO_OPERATOR_HSL_LUMINOSITY);
+ dc.setOperator(CAIRO_OPERATOR_HSL_LUMINOSITY);
break;
case SP_CSS_BLEND_NORMAL:
default:
- ct.setOperator(CAIRO_OPERATOR_OVER);
+ dc.setOperator(CAIRO_OPERATOR_OVER);
break;
}
}
@@ -127,6 +127,7 @@ DrawingItem::DrawingItem(Drawing &drawing)
, _propagate(0)
// , _renders_opacity(0)
, _pick_children(0)
+ , _antialias(1)
, _isolation(SP_CSS_ISOLATION_AUTO)
, _blend_mode(SP_CSS_BLEND_NORMAL)
{}
@@ -229,6 +230,8 @@ DrawingItem::prependChild(DrawingItem *item)
void
DrawingItem::clearChildren()
{
+ if (_children.empty()) return;
+
_markForRendering();
// prevent children from referencing the parent during deletion
// this way, children won't try to remove themselves from a list
@@ -266,8 +269,19 @@ DrawingItem::setTransform(Geom::Affine const &new_trans)
void
DrawingItem::setOpacity(float opacity)
{
- _opacity = opacity;
- _markForRendering();
+ if (_opacity != opacity) {
+ _opacity = opacity;
+ _markForRendering();
+ }
+}
+
+void
+DrawingItem::setAntialiasing(bool a)
+{
+ if (_antialias != a) {
+ _antialias = a;
+ _markForRendering();
+ }
}
void
@@ -289,8 +303,10 @@ DrawingItem::setBlendMode(unsigned blend_mode)
void
DrawingItem::setVisible(bool v)
{
- _visible = v;
- _markForRendering();
+ if (_visible != v) {
+ _visible = v;
+ _markForRendering();
+ }
}
/// This is currently unused
@@ -545,7 +561,7 @@ struct MaskLuminanceToAlpha {
* @param flags Rendering options. This deals mainly with cache control.
*/
unsigned
-DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+DrawingItem::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
{
bool outline = _drawing.outline();
bool render_filters = _drawing.renderFilters();
@@ -560,7 +576,7 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag
// TODO convert outline rendering to a separate virtual function
if (outline) {
- _renderOutline(ct, area, flags);
+ _renderOutline(dc, area, flags);
return RENDER_OK;
}
@@ -568,14 +584,20 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag
Geom::OptIntRect carea = Geom::intersect(area, _drawbox);
if (!carea) return RENDER_OK;
+ if (_antialias) {
+ cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_DEFAULT);
+ } else {
+ cairo_set_antialias(dc.raw(), CAIRO_ANTIALIAS_NONE);
+ }
+
// render from cache if possible
if (_cached) {
if (_cache) {
_cache->prepare();
#ifdef WITH_CSSBLEND
- set_cairo_blend_operator( ct, _blend_mode );
+ set_cairo_blend_operator( dc, _blend_mode );
#endif
- _cache->paintFromCache(ct, carea);
+ _cache->paintFromCache(dc, carea);
if (!carea) return RENDER_OK;
} else {
// There is no cache. This could be because caching of this item
@@ -625,7 +647,7 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag
// filters and opacity do not apply when rendering the ancestors of the filtered
// element
if ((flags & RENDER_FILTER_BACKGROUND) || !needs_intermediate_rendering) {
- return _renderItem(ct, *carea, flags & ~RENDER_FILTER_BACKGROUND, stop_at);
+ return _renderItem(dc, *carea, flags & ~RENDER_FILTER_BACKGROUND, stop_at);
}
// iarea is the bounding box for intermediate rendering
@@ -688,9 +710,9 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag
}
if (bg_root) {
DrawingSurface bg(*iarea);
- DrawingContext bgct(bg);
- bg_root->render(bgct, *iarea, flags | RENDER_FILTER_BACKGROUND, this);
- _filter->render(this, ict, &bgct);
+ DrawingContext bgdc(bg);
+ bg_root->render(bgdc, *iarea, flags | RENDER_FILTER_BACKGROUND, this);
+ _filter->render(this, ict, &bgdc);
rendered = true;
}
}
@@ -716,20 +738,20 @@ DrawingItem::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flag
cachect.fill();
_cache->markClean(*carea);
}
- ct.rectangle(*carea);
- ct.setSource(&intermediate);
+ dc.rectangle(*carea);
+ dc.setSource(&intermediate);
#ifdef WITH_CSSBLEND
- set_cairo_blend_operator( ct, _blend_mode );
+ set_cairo_blend_operator( dc, _blend_mode );
#endif
- ct.fill();
- ct.setSource(0,0,0,0);
- // the call above is to clear a ref on the intermediate surface held by ct
+ dc.fill();
+ dc.setSource(0,0,0,0);
+ // the call above is to clear a ref on the intermediate surface held by dc
return render_result;
}
void
-DrawingItem::_renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+DrawingItem::_renderOutline(DrawingContext &dc, 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
@@ -738,7 +760,7 @@ DrawingItem::_renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsig
// just render everything: item, clip, mask
// First, render the object itself
- _renderItem(ct, *carea, flags, NULL);
+ _renderItem(dc, *carea, flags, NULL);
// render clip and mask, if any
guint32 saved_rgba = _drawing.outlinecolor; // save current outline color
@@ -746,12 +768,12 @@ DrawingItem::_renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsig
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
if (_clip) {
_drawing.outlinecolor = prefs->getInt("/options/wireframecolors/clips", 0x00ff00ff); // green clips
- _clip->render(ct, *carea, flags);
+ _clip->render(dc, *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);
+ _mask->render(dc, *carea, flags);
}
_drawing.outlinecolor = saved_rgba; // restore outline color
}
@@ -765,31 +787,31 @@ DrawingItem::_renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsig
* of render() for details.
*/
void
-DrawingItem::clip(Inkscape::DrawingContext &ct, Geom::IntRect const &area)
+DrawingItem::clip(Inkscape::DrawingContext &dc, 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;
- ct.setSource(0,0,0,1);
- ct.pushGroup();
+ dc.setSource(0,0,0,1);
+ dc.pushGroup();
// rasterize the clipping path
- _clipItem(ct, area);
+ _clipItem(dc, area);
if (_clip) {
// 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
- ct.pushGroup();
- _clip->clip(ct, area);
- ct.popGroupToSource();
- ct.setOperator(CAIRO_OPERATOR_IN);
- ct.paint();
+ dc.pushGroup();
+ _clip->clip(dc, area);
+ dc.popGroupToSource();
+ dc.setOperator(CAIRO_OPERATOR_IN);
+ dc.paint();
}
- ct.popGroupToSource();
- ct.setOperator(CAIRO_OPERATOR_OVER);
- ct.paint();
- ct.setSource(0,0,0,0);
+ dc.popGroupToSource();
+ dc.setOperator(CAIRO_OPERATOR_OVER);
+ dc.paint();
+ dc.setSource(0,0,0,0);
}
/**
diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h
index 1796d29d6..db803cf60 100644
--- a/src/display/drawing-item.h
+++ b/src/display/drawing-item.h
@@ -108,6 +108,7 @@ public:
void setCached(bool c, bool persistent = false);
void setOpacity(float opacity);
+ void setAntialiasing(bool a);
void setIsolation(unsigned isolation); // CSS Compositing and Blending
void setBlendMode(unsigned blend_mode);
void setTransform(Geom::Affine const &trans);
@@ -123,8 +124,8 @@ public:
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);
- unsigned render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags = 0, DrawingItem *stop_at = NULL);
- void clip(DrawingContext &ct, Geom::IntRect const &area);
+ unsigned render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags = 0, DrawingItem *stop_at = NULL);
+ void clip(DrawingContext &dc, Geom::IntRect const &area);
DrawingItem *pick(Geom::Point const &p, double delta, unsigned flags = 0);
protected:
@@ -141,7 +142,7 @@ protected:
RENDER_OK = 0,
RENDER_STOP = 1
};
- void _renderOutline(DrawingContext &ct, Geom::IntRect const &area, unsigned flags);
+ void _renderOutline(DrawingContext &dc, Geom::IntRect const &area, unsigned flags);
void _markForUpdate(unsigned state, bool propagate);
void _markForRendering();
void _invalidateFilterBackground(Geom::IntRect const &area);
@@ -150,9 +151,9 @@ protected:
Geom::OptIntRect _cacheRect();
virtual unsigned _updateItem(Geom::IntRect const &/*area*/, UpdateContext const &/*ctx*/,
unsigned /*flags*/, unsigned /*reset*/) { return 0; }
- virtual unsigned _renderItem(DrawingContext &/*ct*/, Geom::IntRect const &/*area*/, unsigned /*flags*/,
+ virtual unsigned _renderItem(DrawingContext &/*dc*/, Geom::IntRect const &/*area*/, unsigned /*flags*/,
DrawingItem * /*stop_at*/) { return RENDER_OK; }
- virtual void _clipItem(DrawingContext &/*ct*/, Geom::IntRect const &/*area*/) {}
+ virtual void _clipItem(DrawingContext &/*dc*/, Geom::IntRect const &/*area*/) {}
virtual DrawingItem *_pickItem(Geom::Point const &/*p*/, double /*delta*/, unsigned /*flags*/) { return NULL; }
virtual bool _canClip() { return false; }
@@ -205,6 +206,7 @@ protected:
//unsigned _renders_opacity : 1; ///< Whether object needs temporary surface for opacity
unsigned _pick_children : 1; ///< For groups: if true, children are returned from pick(),
/// otherwise the group is returned
+ unsigned _antialias : 1; ///< Whether to use antialiasing
unsigned _isolation : 1;
unsigned _blend_mode : 4;
diff --git a/src/display/drawing-shape.cpp b/src/display/drawing-shape.cpp
index e80f12486..92d71fad3 100644
--- a/src/display/drawing-shape.cpp
+++ b/src/display/drawing-shape.cpp
@@ -12,7 +12,7 @@
#include <glib.h>
#include <2geom/curves.h>
#include <2geom/pathvector.h>
-#include <2geom/svg-path.h>
+#include <2geom/path-sink.h>
#include <2geom/svg-path-parser.h>
#include "display/cairo-utils.h"
@@ -149,8 +149,53 @@ DrawingShape::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, u
return STATE_ALL;
}
+#ifdef WITH_SVG2
+void
+DrawingShape::_renderFill(DrawingContext &dc)
+{
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox);
+
+ if( has_fill ) {
+ dc.path(_curve->get_pathvector());
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ dc.newPath(); // clear path
+ }
+}
+
+void
+DrawingShape::_renderStroke(DrawingContext &dc)
+{
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ has_stroke &= (_nrstyle.stroke_width != 0);
+
+ if( has_stroke ) {
+ // TODO: remove segments outside of bbox when no dashes present
+ dc.path(_curve->get_pathvector());
+ _nrstyle.applyStroke(dc);
+ dc.strokePreserve();
+ dc.newPath(); // clear path
+ }
+}
+#endif
+
+void
+DrawingShape::_renderMarkers(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+{
+ // marker rendering
+ for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
+ i->render(dc, area, flags, stop_at);
+ }
+}
+
unsigned
-DrawingShape::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
+DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags, DrawingItem *stop_at)
{
if (!_curve || !_style) return RENDER_OK;
if (!area.intersects(_bbox)) return RENDER_OK; // skip if not within bounding box
@@ -160,67 +205,96 @@ DrawingShape::_renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigne
if (outline) {
guint32 rgba = _drawing.outlinecolor;
- { Inkscape::DrawingContext::Save save(ct);
- ct.transform(_ctm);
- ct.path(_curve->get_pathvector());
+ // paint-order doesn't matter
+ { Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+ dc.path(_curve->get_pathvector());
}
- { Inkscape::DrawingContext::Save save(ct);
- ct.setSource(rgba);
- ct.setLineWidth(0.5);
- ct.setTolerance(0.5);
- ct.stroke();
+ { Inkscape::DrawingContext::Save save(dc);
+ dc.setSource(rgba);
+ dc.setLineWidth(0.5);
+ dc.setTolerance(0.5);
+ dc.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, _item_bbox);
- has_stroke = _nrstyle.prepareStroke(ct, _item_bbox);
- 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
+
+ _renderMarkers(dc, area, flags, stop_at);
+ return RENDER_OK;
+
}
- // marker rendering
- for (ChildrenList::iterator i = _children.begin(); i != _children.end(); ++i) {
- i->render(ct, area, flags, stop_at);
+#ifdef WITH_SVG2
+ if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ) {
+ // This is the most common case, special case so we don't call get_pathvector(), etc. twice
+#endif
+ {
+ // we assume the context has no path
+ Inkscape::DrawingContext::Save save(dc);
+ dc.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
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox);
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ has_stroke &= (_nrstyle.stroke_width != 0);
+
+ if (has_fill || has_stroke) {
+ // TODO: remove segments outside of bbox when no dashes present
+ dc.path(_curve->get_pathvector());
+ if (has_fill) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
+ if (has_stroke) {
+ _nrstyle.applyStroke(dc);
+ dc.strokePreserve();
+ }
+ dc.newPath(); // clear path
+ } // has fill or stroke pattern
+ }
+ _renderMarkers(dc, area, flags, stop_at);
+ return RENDER_OK;
+
+#ifdef WITH_SVG2
+ }
+
+ // Handle different paint orders
+ for (unsigned i = 0; i < NRStyle::PAINT_ORDER_LAYERS; ++i) {
+ switch (_nrstyle.paint_order_layer[i]) {
+ case NRStyle::PAINT_ORDER_FILL:
+ _renderFill(dc);
+ break;
+ case NRStyle::PAINT_ORDER_STROKE:
+ _renderStroke(dc);
+ break;
+ case NRStyle::PAINT_ORDER_MARKER:
+ _renderMarkers(dc, area, flags, stop_at);
+ break;
+ default:
+ // PAINT_ORDER_AUTO Should not happen
+ break;
+ }
}
return RENDER_OK;
+#endif
}
-void DrawingShape::_clipItem(DrawingContext &ct, Geom::IntRect const & /*area*/)
+void DrawingShape::_clipItem(DrawingContext &dc, Geom::IntRect const & /*area*/)
{
if (!_curve) return;
- Inkscape::DrawingContext::Save save(ct);
+ Inkscape::DrawingContext::Save save(dc);
// handle clip-rule
if (_style) {
if (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
- ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
+ dc.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
} else {
- ct.setFillRule(CAIRO_FILL_RULE_WINDING);
+ dc.setFillRule(CAIRO_FILL_RULE_WINDING);
}
}
- ct.transform(_ctm);
- ct.path(_curve->get_pathvector());
- ct.fill();
+ dc.transform(_ctm);
+ dc.path(_curve->get_pathvector());
+ dc.fill();
}
DrawingItem *
diff --git a/src/display/drawing-shape.h b/src/display/drawing-shape.h
index 52496d86e..405c789e0 100644
--- a/src/display/drawing-shape.h
+++ b/src/display/drawing-shape.h
@@ -33,12 +33,19 @@ public:
protected:
virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
unsigned flags, unsigned reset);
- virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ virtual unsigned _renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags,
DrawingItem *stop_at);
- virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual void _clipItem(DrawingContext &dc, Geom::IntRect const &area);
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
virtual bool _canClip();
+#ifdef WITH_SVG2
+ void _renderFill(DrawingContext &dc);
+ void _renderStroke(DrawingContext &dc);
+#endif
+ void _renderMarkers(DrawingContext &dc, Geom::IntRect const &area, unsigned flags,
+ DrawingItem *stop_at);
+
SPCurve *_curve;
SPStyle *_style;
NRStyle _nrstyle;
diff --git a/src/display/drawing-surface.cpp b/src/display/drawing-surface.cpp
index bddccbd96..d2540de66 100644
--- a/src/display/drawing-surface.cpp
+++ b/src/display/drawing-surface.cpp
@@ -123,7 +123,7 @@ DrawingSurface::scale() const
Geom::Affine
DrawingSurface::drawingTransform() const
{
- Geom::Affine ret = _scale * Geom::Translate(-_origin);
+ Geom::Affine ret = Geom::Translate(-_origin) * _scale;
return ret;
}
@@ -215,7 +215,7 @@ DrawingCache::prepare()
bool is_identity = _pending_transform.isIdentity();
if (is_identity && _pending_area == old_area) return; // no change
- bool is_integer_translation = false;
+ bool is_integer_translation = is_identity;
if (!is_identity && _pending_transform.isTranslation()) {
Geom::IntPoint t = _pending_transform.translation().round();
if (Geom::are_near(Geom::Point(t), _pending_transform.translation())) {
@@ -224,6 +224,7 @@ DrawingCache::prepare()
if (old_area + t == _pending_area) {
// if the areas match, the only thing to do
// is to ensure that the clean area is not too large
+ // we can exit early
cairo_rectangle_int_t limit = _convertRect(_pending_area);
cairo_region_intersect_rectangle(_clean_region, &limit);
_origin += t;
@@ -232,33 +233,36 @@ DrawingCache::prepare()
}
}
}
- // otherwise, we need to transform the cache
+
+ // the area has changed, so the cache content needs to be copied
Geom::IntPoint old_origin = old_area.min();
cairo_surface_t *old_surface = _surface;
_surface = NULL;
_pixels = _pending_area.dimensions();
_origin = _pending_area.min();
- cairo_t *ct = createRawContext();
- if (!is_identity) {
- ink_cairo_transform(ct, _pending_transform);
- }
- cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]);
- cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
- cairo_paint(ct);
-
- cairo_surface_destroy(old_surface);
- cairo_destroy(ct);
+ if (is_integer_translation) {
+ // transform the cache only for integer translations and identities
+ cairo_t *ct = createRawContext();
+ if (!is_identity) {
+ ink_cairo_transform(ct, _pending_transform);
+ }
+ cairo_set_source_surface(ct, old_surface, old_origin[X], old_origin[Y]);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_pattern_set_filter(cairo_get_source(ct), CAIRO_FILTER_NEAREST);
+ cairo_paint(ct);
+ cairo_destroy(ct);
- if (!is_identity && !is_integer_translation) {
+ cairo_rectangle_int_t limit = _convertRect(_pending_area);
+ cairo_region_intersect_rectangle(_clean_region, &limit);
+ } else {
// dirty everything
cairo_region_destroy(_clean_region);
_clean_region = cairo_region_create();
- } else {
- cairo_rectangle_int_t limit = _convertRect(_pending_area);
- cairo_region_intersect_rectangle(_clean_region, &limit);
}
+
//std::cout << _pending_transform << old_area << _pending_area << std::endl;
+ cairo_surface_destroy(old_surface);
_pending_transform.setIdentity();
}
@@ -267,7 +271,7 @@ DrawingCache::prepare()
* parameter to the bounds of the region that must be repainted.
*/
void
-DrawingCache::paintFromCache(DrawingContext &ct, Geom::OptIntRect &area)
+DrawingCache::paintFromCache(DrawingContext &dc, Geom::OptIntRect &area)
{
if (!area) return;
@@ -296,10 +300,10 @@ DrawingCache::paintFromCache(DrawingContext &ct, Geom::OptIntRect &area)
cairo_rectangle_int_t tmp;
for (int i = 0; i < nr; ++i) {
cairo_region_get_rectangle(cache_region, i, &tmp);
- ct.rectangle(_convertRect(tmp));
+ dc.rectangle(_convertRect(tmp));
}
- ct.setSource(this);
- ct.fill();
+ dc.setSource(this);
+ dc.fill();
}
cairo_region_destroy(cache_region);
}
@@ -310,21 +314,21 @@ DrawingCache::_dumpCache(Geom::OptIntRect const &area)
{
static int dumpnr = 0;
cairo_surface_t *surface = ink_cairo_surface_copy(_surface);
- DrawingContext ct(surface, _origin);
+ DrawingContext dc(surface, _origin);
if (!cairo_region_is_empty(_clean_region)) {
- Inkscape::DrawingContext::Save save(ct);
+ Inkscape::DrawingContext::Save save(dc);
int nr = cairo_region_num_rectangles(_clean_region);
cairo_rectangle_int_t tmp;
for (int i = 0; i < nr; ++i) {
cairo_region_get_rectangle(_clean_region, i, &tmp);
- ct.rectangle(_convertRect(tmp));
+ dc.rectangle(_convertRect(tmp));
}
- ct.setSource(0,1,0,0.1);
- ct.fill();
+ dc.setSource(0,1,0,0.1);
+ dc.fill();
}
- ct.rectangle(*area);
- ct.setSource(1,0,0,0.1);
- ct.fill();
+ dc.rectangle(*area);
+ dc.setSource(1,0,0,0.1);
+ dc.fill();
char *fn = g_strdup_printf("dump%d.png", dumpnr++);
cairo_surface_write_to_png(surface, fn);
cairo_surface_destroy(surface);
diff --git a/src/display/drawing-surface.h b/src/display/drawing-surface.h
index 1ec848405..e937cca55 100644
--- a/src/display/drawing-surface.h
+++ b/src/display/drawing-surface.h
@@ -65,7 +65,7 @@ public:
void markClean(Geom::IntRect const &area = Geom::IntRect::infinite());
void scheduleTransform(Geom::IntRect const &new_area, Geom::Affine const &trans);
void prepare();
- void paintFromCache(DrawingContext &ct, Geom::OptIntRect &area);
+ void paintFromCache(DrawingContext &dc, Geom::OptIntRect &area);
protected:
cairo_region_t *_clean_region;
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
index f652a2970..a280e221a 100644
--- a/src/display/drawing-text.cpp
+++ b/src/display/drawing-text.cpp
@@ -195,7 +195,7 @@ DrawingText::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, un
return DrawingGroup::_updateItem(area, ctx, flags, reset);
}
-void DrawingText::decorateStyle(DrawingContext &ct, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2)
+void DrawingText::decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2)
{
double wave[16]={
0.000000, 0.382499, 0.706825, 0.923651, 1.000000, 0.923651, 0.706825, 0.382499,
@@ -235,12 +235,12 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
if(_nrstyle.text_decoration_style & TEXT_DECORATION_STYLE_ISDOUBLE){
ps -= Geom::Point(0, vextent/12.0);
pf -= Geom::Point(0, vextent/12.0);
- ct.moveTo(ps);
- ct.lineTo(pf);
+ dc.moveTo(ps);
+ dc.lineTo(pf);
ps += Geom::Point(0, vextent/6.0);
pf += Geom::Point(0, vextent/6.0);
- ct.moveTo(ps);
- ct.lineTo(pf);
+ dc.moveTo(ps);
+ dc.lineTo(pf);
}
/* The next three have a problem in that they are phase dependent. The bits of a line are not
necessarily passing through this routine in order, so we have to use the xphase information
@@ -251,14 +251,14 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
while(1){
if(dots[i]>0){
if(ps[Geom::X]> pf[Geom::X])break;
- ct.moveTo(ps);
+ dc.moveTo(ps);
ps += Geom::Point(step * (double)dots[i], 0.0);
if(ps[Geom::X]>= pf[Geom::X]){
- ct.lineTo(pf);
+ dc.lineTo(pf);
break;
}
else {
- ct.lineTo(ps);
+ dc.lineTo(ps);
}
ps += Geom::Point(step * 4.0, 0.0);
}
@@ -272,14 +272,14 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
while(1){
if(dashes[i]>0){
if(ps[Geom::X]> pf[Geom::X])break;
- ct.moveTo(ps);
+ dc.moveTo(ps);
ps += Geom::Point(step * (double)dashes[i], 0.0);
if(ps[Geom::X]>= pf[Geom::X]){
- ct.lineTo(pf);
+ dc.lineTo(pf);
break;
}
else {
- ct.lineTo(ps);
+ dc.lineTo(ps);
}
ps += Geom::Point(step * 8.0, 0.0);
}
@@ -293,23 +293,23 @@ pf = Geom::Point(step * round(p2[Geom::X]/step),p2[Geom::Y]);
double amp = vextent/10.0;
double x = ps[Geom::X];
double y = ps[Geom::Y];
- ct.moveTo(Geom::Point(x, y + amp * wave[i]));
+ dc.moveTo(Geom::Point(x, y + amp * wave[i]));
while(1){
i = ((i + 1) & 15);
x += step;
- ct.lineTo(Geom::Point(x, y + amp * wave[i]));
+ dc.lineTo(Geom::Point(x, y + amp * wave[i]));
if(x >= pf[Geom::X])break;
}
}
else { // TEXT_DECORATION_STYLE_SOLID, also default in case it was not set for some reason
- ct.moveTo(ps);
- ct.lineTo(pf);
-// ct.revrectangle(Geom::Rect(ps,pf));
+ dc.moveTo(ps);
+ dc.lineTo(pf);
+// dc.revrectangle(Geom::Rect(ps,pf));
}
}
/* returns scaled line thickness */
-double DrawingText::decorateItem(DrawingContext &ct, Geom::Affine const &aff, double phase_length)
+double DrawingText::decorateItem(DrawingContext &dc, Geom::Affine const &aff, double phase_length)
{
double tsp_width_adj = _nrstyle.tspan_width / _nrstyle.font_size;
double tsp_asc_adj = _nrstyle.ascender / _nrstyle.font_size;
@@ -321,8 +321,8 @@ double DrawingText::decorateItem(DrawingContext &ct, Geom::Affine const &aff, do
double scale = aff.descrim();
double xphase = phase_length/ _nrstyle.font_size; // used to figure out phase of patterns
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(aff); // must be leftmost affine in span
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(aff); // must be leftmost affine in span
Geom::Point p1;
Geom::Point p2;
@@ -331,52 +331,52 @@ double DrawingText::decorateItem(DrawingContext &ct, Geom::Affine const &aff, do
if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_UNDERLINE){
p1 = Geom::Point(0.0, -_nrstyle.underline_position);
p2 = Geom::Point(tsp_width_adj,-_nrstyle.underline_position);
- decorateStyle(ct, tsp_size_adj, xphase, p1, p2);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
}
if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_OVERLINE){
p1 = Geom::Point(0.0, tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
p2 = Geom::Point(tsp_width_adj,tsp_asc_adj -_nrstyle.underline_position + 1 * final_underline_thickness);
- decorateStyle(ct, tsp_size_adj, xphase, p1, p2);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
}
if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_LINETHROUGH){
thickness = final_line_through_thickness;
p1 = Geom::Point(0.0, _nrstyle.line_through_position);
p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position);
- decorateStyle(ct, tsp_size_adj, xphase, p1, p2);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
}
// Obviously this does not blink, but it does indicate which text has been set with that attribute
if(_nrstyle.text_decoration_line & TEXT_DECORATION_LINE_BLINK){
thickness = final_line_through_thickness;
p1 = Geom::Point(0.0, _nrstyle.line_through_position - 2*final_line_through_thickness);
p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position - 2*final_line_through_thickness);
- decorateStyle(ct, tsp_size_adj, xphase, p1, p2);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
p1 = Geom::Point(0.0, _nrstyle.line_through_position + 2*final_line_through_thickness);
p2 = Geom::Point(tsp_width_adj,_nrstyle.line_through_position + 2*final_line_through_thickness);
- decorateStyle(ct, tsp_size_adj, xphase, p1, p2);
+ decorateStyle(dc, tsp_size_adj, xphase, p1, p2);
}
thickness *= scale;
return(thickness);
}
-unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
+unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*area*/, unsigned /*flags*/, DrawingItem * /*stop_at*/)
{
if (_drawing.outline()) {
guint32 rgba = _drawing.outlinecolor;
- Inkscape::DrawingContext::Save save(ct);
- ct.setSource(rgba);
- ct.setTolerance(0.5); // low quality, but good enough for outline mode
+ Inkscape::DrawingContext::Save save(dc);
+ dc.setSource(rgba);
+ dc.setTolerance(0.5); // low quality, but good enough for outline mode
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);
+ Inkscape::DrawingContext::Save save(dc);
// skip glyphs with singular transforms
if (g->_ctm.isSingular()) continue;
- ct.transform(g->_ctm);
+ dc.transform(g->_ctm);
if(g->_drawable){
- ct.path(*g->_font->PathVector(g->_glyph));
- ct.fill();
+ dc.path(*g->_font->PathVector(g->_glyph));
+ dc.fill();
}
}
return RENDER_OK;
@@ -398,11 +398,11 @@ unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*are
// Therefore, only apply this ctm temporarily.
bool has_stroke, has_fill;
{
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(_ctm);
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
- has_fill = _nrstyle.prepareFill( ct, _item_bbox);
- has_stroke = _nrstyle.prepareStroke(ct, _item_bbox);
+ has_fill = _nrstyle.prepareFill( dc, _item_bbox);
+ has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
}
if (has_fill || has_stroke) {
@@ -418,11 +418,11 @@ unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*are
invset = true;
}
- Inkscape::DrawingContext::Save save(ct);
+ Inkscape::DrawingContext::Save save(dc);
if (g->_ctm.isSingular()) continue;
- ct.transform(g->_ctm);
+ dc.transform(g->_ctm);
if (g->_drawable) {
- ct.path(*g->_font->PathVector(g->_glyph));
+ dc.path(*g->_font->PathVector(g->_glyph));
}
// get the leftmost affine transform (leftmost defined with respect to the x axis of the first transform).
// That way the decoration will work no matter what mix of L->R, R->L text is in the span.
@@ -448,17 +448,36 @@ unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*are
// draw the text itself
// we need to apply this object's ctm again
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(_ctm);
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(_ctm);
+
+#ifdef WITH_SVG2
+ // Text doesn't have markers, we can do paint-order quick and dirty.
+ bool fill_first = false;
+ if( _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_NORMAL ||
+ _nrstyle.paint_order_layer[0] == NRStyle::PAINT_ORDER_FILL ||
+ _nrstyle.paint_order_layer[2] == NRStyle::PAINT_ORDER_STROKE ) {
+ fill_first = true;
+ } // Won't get "stroke fill stroke" but that isn't 'valid'
+
+ if (has_fill && fill_first) {
+#else
if (has_fill) {
- _nrstyle.applyFill(ct);
- ct.fillPreserve();
+#endif
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
}
if (has_stroke) {
- _nrstyle.applyStroke(ct);
- ct.strokePreserve();
+ _nrstyle.applyStroke(dc);
+ dc.strokePreserve();
}
- ct.newPath(); // clear path
+#ifdef WITH_SVG2
+ if (has_fill && !fill_first) {
+ _nrstyle.applyFill(dc);
+ dc.fillPreserve();
+ }
+#endif
+ dc.newPath(); // clear path
// draw text decoration
if (_nrstyle.text_decoration_line != TEXT_DECORATION_LINE_CLEAR && decorate) {
@@ -477,27 +496,27 @@ unsigned DrawingText::_renderItem(DrawingContext &ct, Geom::IntRect const &/*are
_nrstyle.fill.color.v.c[2],
1.0);
}
- ct.setSource(ergba);
- ct.setTolerance(0.5);
- double thickness = decorateItem(ct, aff, phase_length);
- ct.setLineWidth(thickness);
- ct.strokePreserve();
- ct.newPath(); // clear path
+ dc.setSource(ergba);
+ dc.setTolerance(0.5);
+ double thickness = decorateItem(dc, aff, phase_length);
+ dc.setLineWidth(thickness);
+ dc.strokePreserve();
+ dc.newPath(); // clear path
}
}
return RENDER_OK;
}
-void DrawingText::_clipItem(DrawingContext &ct, Geom::IntRect const &/*area*/)
+void DrawingText::_clipItem(DrawingContext &dc, Geom::IntRect const &/*area*/)
{
- Inkscape::DrawingContext::Save save(ct);
+ Inkscape::DrawingContext::Save save(dc);
// handle clip-rule
if (_style) {
if (_style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
- ct.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
+ dc.setFillRule(CAIRO_FILL_RULE_EVEN_ODD);
} else {
- ct.setFillRule(CAIRO_FILL_RULE_WINDING);
+ dc.setFillRule(CAIRO_FILL_RULE_WINDING);
}
}
@@ -507,13 +526,13 @@ void DrawingText::_clipItem(DrawingContext &ct, Geom::IntRect const &/*area*/)
throw InvalidItemException();
}
- Inkscape::DrawingContext::Save save(ct);
- ct.transform(g->_ctm);
+ Inkscape::DrawingContext::Save save(dc);
+ dc.transform(g->_ctm);
if(g->_drawable){
- ct.path(*g->_font->PathVector(g->_glyph));
+ dc.path(*g->_font->PathVector(g->_glyph));
}
}
- ct.fill();
+ dc.fill();
}
DrawingItem *
diff --git a/src/display/drawing-text.h b/src/display/drawing-text.h
index fd122b54b..b863ca2a4 100644
--- a/src/display/drawing-text.h
+++ b/src/display/drawing-text.h
@@ -62,14 +62,14 @@ public:
protected:
virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
unsigned flags, unsigned reset);
- virtual unsigned _renderItem(DrawingContext &ct, Geom::IntRect const &area, unsigned flags,
+ virtual unsigned _renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigned flags,
DrawingItem *stop_at);
- virtual void _clipItem(DrawingContext &ct, Geom::IntRect const &area);
+ virtual void _clipItem(DrawingContext &dc, Geom::IntRect const &area);
virtual DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags);
virtual bool _canClip();
- double decorateItem(DrawingContext &ct, Geom::Affine const &aff, double phase_length);
- void decorateStyle(DrawingContext &ct, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2);
+ double decorateItem(DrawingContext &dc, Geom::Affine const &aff, double phase_length);
+ void decorateStyle(DrawingContext &dc, double vextent, double xphase, Geom::Point const &p1, Geom::Point const &p2);
NRStyle _nrstyle;
friend class DrawingGlyphs;
diff --git a/src/display/drawing.cpp b/src/display/drawing.cpp
index c192e4565..6e728b03d 100644
--- a/src/display/drawing.cpp
+++ b/src/display/drawing.cpp
@@ -167,22 +167,22 @@ Drawing::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigned fl
}
void
-Drawing::render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags)
+Drawing::render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags)
{
if (_root) {
- _root->render(ct, area, flags);
+ _root->render(dc, area, flags);
}
if (colorMode() == COLORMODE_GRAYSCALE) {
// apply grayscale filter on top of everything
- cairo_surface_t *input = ct.rawTarget();
+ cairo_surface_t *input = dc.rawTarget();
cairo_surface_t *out = ink_cairo_surface_create_identical(input);
ink_cairo_surface_filter(input, out, _grayscale_colormatrix);
- Geom::Point origin = ct.targetLogicalBounds().min();
- ct.setSource(out, origin[Geom::X], origin[Geom::Y]);
- ct.setOperator(CAIRO_OPERATOR_SOURCE);
- ct.paint();
- ct.setOperator(CAIRO_OPERATOR_OVER);
+ Geom::Point origin = dc.targetLogicalBounds().min();
+ dc.setSource(out, origin[Geom::X], origin[Geom::Y]);
+ dc.setOperator(CAIRO_OPERATOR_SOURCE);
+ dc.paint();
+ dc.setOperator(CAIRO_OPERATOR_OVER);
cairo_surface_destroy(out);
}
diff --git a/src/display/drawing.h b/src/display/drawing.h
index 74ab57fae..cc74833ba 100644
--- a/src/display/drawing.h
+++ b/src/display/drawing.h
@@ -68,7 +68,7 @@ public:
void setGrayscaleMatrix(gdouble value_matrix[20]);
void update(Geom::IntRect const &area = Geom::IntRect::infinite(), UpdateContext const &ctx = UpdateContext(), unsigned flags = DrawingItem::STATE_ALL, unsigned reset = 0);
- void render(DrawingContext &ct, Geom::IntRect const &area, unsigned flags = 0);
+ void render(DrawingContext &dc, Geom::IntRect const &area, unsigned flags = 0);
DrawingItem *pick(Geom::Point const &p, double delta, unsigned flags);
sigc::signal<void, DrawingItem *> signal_request_update;
diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp
index 3bc00d2d7..dd90193fe 100644
--- a/src/display/nr-filter-component-transfer.cpp
+++ b/src/display/nr-filter-component-transfer.cpp
@@ -254,16 +254,21 @@ void FilterComponentTransfer::render_cairo(FilterSlot &slot)
// parameters: R = 0, G = 1, B = 2, A = 3
// Cairo: R = 2, G = 1, B = 0, A = 3
+ // If tableValues is empty, use identity.
for (unsigned i = 0; i < 3; ++i) {
guint32 color = 2 - i;
switch (type[i]) {
case COMPONENTTRANSFER_TYPE_TABLE:
- ink_cairo_surface_filter(out, out,
- ComponentTransferTable<false>(color, tableValues[i]));
+ if(!tableValues[i].empty()) {
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferTable<false>(color, tableValues[i]));
+ }
break;
case COMPONENTTRANSFER_TYPE_DISCRETE:
- ink_cairo_surface_filter(out, out,
- ComponentTransferDiscrete<false>(color, tableValues[i]));
+ if(!tableValues[i].empty()) {
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferDiscrete<false>(color, tableValues[i]));
+ }
break;
case COMPONENTTRANSFER_TYPE_LINEAR:
ink_cairo_surface_filter(out, out,
@@ -284,12 +289,16 @@ void FilterComponentTransfer::render_cairo(FilterSlot &slot)
// fast paths for alpha channel
switch (type[3]) {
case COMPONENTTRANSFER_TYPE_TABLE:
- ink_cairo_surface_filter(out, out,
- ComponentTransferTable<true>(tableValues[3]));
+ if(!tableValues[3].empty()) {
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferTable<true>(tableValues[3]));
+ }
break;
case COMPONENTTRANSFER_TYPE_DISCRETE:
- ink_cairo_surface_filter(out, out,
- ComponentTransferDiscrete<true>(tableValues[3]));
+ if(!tableValues[3].empty()) {
+ ink_cairo_surface_filter(out, out,
+ ComponentTransferDiscrete<true>(tableValues[3]));
+ }
break;
case COMPONENTTRANSFER_TYPE_LINEAR:
ink_cairo_surface_filter(out, out,
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index b96e24cbc..24960af78 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -568,12 +568,21 @@ void FilterGaussian::render_cairo(FilterSlot &slot)
return;
}
- Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
+ // Handle bounding box case.
+ double dx = _deviation_x;
+ double dy = _deviation_y;
+ if( slot.get_units().get_primitive_units() == SP_FILTER_UNITS_OBJECTBOUNDINGBOX ) {
+ Geom::OptRect const bbox = slot.get_units().get_item_bbox();
+ if( bbox ) {
+ dx *= (*bbox).width();
+ dy *= (*bbox).height();
+ }
+ }
- int w_orig = ink_cairo_surface_get_width(in);
- int h_orig = ink_cairo_surface_get_height(in);
- double deviation_x_orig = _deviation_x * trans.expansionX();
- double deviation_y_orig = _deviation_y * trans.expansionY();
+ Geom::Affine trans = slot.get_units().get_matrix_user2pb();
+
+ double deviation_x_orig = dx * trans.expansionX();
+ double deviation_y_orig = dy * trans.expansionY();
cairo_format_t fmt = cairo_image_surface_get_format(in);
int bytes_per_pixel = 0;
switch (fmt) {
@@ -595,6 +604,8 @@ void FilterGaussian::render_cairo(FilterSlot &slot)
int x_step = 1 << _effect_subsample_step_log2(deviation_x_orig, quality);
int y_step = 1 << _effect_subsample_step_log2(deviation_y_orig, quality);
bool resampling = x_step > 1 || y_step > 1;
+ int w_orig = ink_cairo_surface_get_width(in);
+ int h_orig = ink_cairo_surface_get_height(in);
int w_downsampled = resampling ? static_cast<int>(ceil(static_cast<double>(w_orig)/x_step))+1 : w_orig;
int h_downsampled = resampling ? static_cast<int>(ceil(static_cast<double>(h_orig)/y_step))+1 : h_orig;
double deviation_x = deviation_x_orig / x_step;
diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp
index 92bb9dcaa..179ba0e0a 100644
--- a/src/display/nr-filter-image.cpp
+++ b/src/display/nr-filter-image.cpp
@@ -108,17 +108,17 @@ void FilterImage::render_cairo(FilterSlot &slot)
Geom::Rect sa = slot.get_slot_area();
cairo_surface_t *out = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
sa.width(), sa.height());
- Inkscape::DrawingContext ct(out, sa.min());
- ct.transform(user2pb); // we are now in primitive units
- ct.translate(feImageX, feImageY);
-// ct.scale(scaleX, scaleY); No scaling should be done
+ Inkscape::DrawingContext dc(out, sa.min());
+ dc.transform(user2pb); // we are now in primitive units
+ dc.translate(feImageX, feImageY);
+// dc.scale(scaleX, scaleY); No scaling should be done
Geom::IntRect render_rect = area.roundOutwards();
- ct.translate(render_rect.min());
+// dc.translate(render_rect.min()); This seems incorrect
// Update to renderable state
drawing.update(render_rect);
- drawing.render(ct, render_rect);
+ drawing.render(dc, render_rect);
SVGElem->invoke_hide(key);
// For the moment, we'll assume that any image is in sRGB color space
@@ -174,7 +174,8 @@ void FilterImage::render_cairo(FilterSlot &slot)
sa.width(), sa.height());
// For the moment, we'll assume that any image is in sRGB color space
- set_cairo_surface_ci(out, SP_CSS_COLOR_INTERPOLATION_SRGB);
+ // set_cairo_surface_ci(out, SP_CSS_COLOR_INTERPOLATION_SRGB);
+ // This seemed like a sensible thing to do but it breaks filters-displace-01-f.svg
cairo_t *ct = cairo_create(out);
cairo_translate(ct, -sa.min()[Geom::X], -sa.min()[Geom::Y]);
diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp
index 01d6ffe56..af1081abe 100644
--- a/src/display/nr-filter-offset.cpp
+++ b/src/display/nr-filter-offset.cpp
@@ -40,8 +40,20 @@ void FilterOffset::render_cairo(FilterSlot &slot)
cairo_t *ct = cairo_create(out);
- Geom::Affine trans = slot.get_units().get_matrix_primitiveunits2pb();
- Geom::Point offset(dx, dy);
+ // Handle bounding box case
+ double x = dx;
+ double y = dy;
+ if( slot.get_units().get_primitive_units() == SP_FILTER_UNITS_OBJECTBOUNDINGBOX ) {
+ Geom::OptRect bbox = slot.get_units().get_item_bbox();
+ if( bbox ) {
+ x *= (*bbox).width();
+ y *= (*bbox).height();
+ }
+ }
+
+ Geom::Affine trans = slot.get_units().get_matrix_user2pb();
+
+ Geom::Point offset(x, y);
offset *= trans;
offset[X] -= trans[4];
offset[Y] -= trans[5];
diff --git a/src/display/nr-filter-primitive.cpp b/src/display/nr-filter-primitive.cpp
index 95d5d4b09..b065ac445 100644
--- a/src/display/nr-filter-primitive.cpp
+++ b/src/display/nr-filter-primitive.cpp
@@ -121,30 +121,10 @@ Geom::Rect FilterPrimitive::filter_primitive_area(FilterUnits const &units)
fa = *fa_opt;
}
- // This is definitely a hack... but what else to do?
- // Current viewport might not be document viewport... but how to find?
- SPDocument* document = inkscape_active_document();
- SPRoot* root = document->getRoot();
- Geom::Rect viewport;
- if( root->viewBox_set ) {
- viewport = root->viewBox;
- } else {
- // Pick some random values
- viewport = Geom::Rect::from_xywh(0,0,480,360);
- }
-
- /* Update computed values for ex, em, %. For %, assumes primitive unit is objectBoundingBox. */
- /* TODO: fetch somehow the object ex and em lengths; 12, 6 are just dummy values. */
- double len_x = bb.width();
- double len_y = bb.height();
- _subregion_x.update(12, 6, len_x);
- _subregion_y.update(12, 6, len_y);
- _subregion_width.update(12, 6, len_x);
- _subregion_height.update(12, 6, len_y);
// x, y, width, and height are independently defined (i.e. one can be defined, by default, to
- // the filter area while another is defined relative to the bounding box). It is better to keep
- // track of them separately and then compose the Rect at the end.
+ // the filter area (via default value ) while another is defined relative to the bounding
+ // box). It is better to keep track of them separately and then compose the Rect at the end.
double x = 0;
double y = 0;
double width = 0;
@@ -157,10 +137,21 @@ Geom::Rect FilterPrimitive::filter_primitive_area(FilterUnits const &units)
if( !_subregion_height._set ) height = fa.height();
if( units.get_primitive_units() == SP_FILTER_UNITS_OBJECTBOUNDINGBOX ) {
+
+ // Update computed values for ex, em, %.
+ // For %, assumes primitive unit is objectBoundingBox.
+ // TODO: fetch somehow the object ex and em lengths; 12, 6 are just dummy values.
+ double len_x = bb.width();
+ double len_y = bb.height();
+ _subregion_x.update(12, 6, len_x);
+ _subregion_y.update(12, 6, len_y);
+ _subregion_width.update(12, 6, len_x);
+ _subregion_height.update(12, 6, len_y);
+
// Values are in terms of fraction of bounding box.
if( _subregion_x._set && (_subregion_x.unit != SVGLength::PERCENT) ) x = bb.min()[X] + bb.width() * _subregion_x.value;
if( _subregion_y._set && (_subregion_y.unit != SVGLength::PERCENT) ) y = bb.min()[Y] + bb.height() * _subregion_y.value;
- if( _subregion_width._set && (_subregion_width.unit != SVGLength::PERCENT) ) width = bb.width() * _subregion_width.value;
+ if( _subregion_width._set && (_subregion_width.unit != SVGLength::PERCENT) ) width = bb.width() * _subregion_width.value;
if( _subregion_height._set && (_subregion_height.unit != SVGLength::PERCENT) ) height = bb.height() * _subregion_height.value;
// Values are in terms of percent
if( _subregion_x._set && (_subregion_x.unit == SVGLength::PERCENT) ) x = bb.min()[X] + _subregion_x.computed;
@@ -168,17 +159,11 @@ Geom::Rect FilterPrimitive::filter_primitive_area(FilterUnits const &units)
if( _subregion_width._set && (_subregion_width.unit == SVGLength::PERCENT) ) width = _subregion_width.computed;
if( _subregion_height._set && (_subregion_height.unit == SVGLength::PERCENT) ) height = _subregion_height.computed;
} else {
- // Values are in terms of user space coordinates or percent of viewbox (yuck!),
- // which is usually the size of SVG drawing. Default.
- if( _subregion_x._set && (_subregion_x.unit != SVGLength::PERCENT) ) x = _subregion_x.computed;
- if( _subregion_y._set && (_subregion_y.unit != SVGLength::PERCENT) ) y = _subregion_y.computed;
- if( _subregion_width._set && (_subregion_width.unit != SVGLength::PERCENT) ) width = _subregion_width.computed;
- if( _subregion_height._set && (_subregion_height.unit != SVGLength::PERCENT) ) height = _subregion_height.computed;
- // Percent of viewport
- if( _subregion_x._set && (_subregion_x.unit == SVGLength::PERCENT) ) x = _subregion_x.value * viewport.width();
- if( _subregion_y._set && (_subregion_y.unit == SVGLength::PERCENT) ) y = _subregion_y.value * viewport.height();
- if( _subregion_width._set && (_subregion_width.unit == SVGLength::PERCENT) ) width = _subregion_width.value * viewport.width();
- if( _subregion_height._set && (_subregion_height.unit == SVGLength::PERCENT) ) height = _subregion_height.value * viewport.height();
+ // Values are in terms of user space coordinates or percent of viewport (already calculated in sp-filter-primitive.cpp).
+ if( _subregion_x._set ) x = _subregion_x.computed;
+ if( _subregion_y._set ) y = _subregion_y.computed;
+ if( _subregion_width._set ) width = _subregion_width.computed;
+ if( _subregion_height._set ) height = _subregion_height.computed;
}
return Geom::Rect (Geom::Point(x,y), Geom::Point(x + width, y + height));
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index 755a30a74..e4c2f048e 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -25,13 +25,13 @@
namespace Inkscape {
namespace Filters {
-FilterSlot::FilterSlot(DrawingItem *item, DrawingContext *bgct,
+FilterSlot::FilterSlot(DrawingItem *item, DrawingContext *bgdc,
DrawingContext &graphic, FilterUnits const &u)
: _item(item)
, _source_graphic(graphic.rawTarget())
- , _background_ct(bgct ? bgct->raw() : NULL)
+ , _background_ct(bgdc ? bgdc->raw() : NULL)
, _source_graphic_area(graphic.targetLogicalBounds().roundOutwards()) // fixme
- , _background_area(bgct ? bgct->targetLogicalBounds().roundOutwards() : Geom::IntRect()) // fixme
+ , _background_area(bgdc ? bgdc->targetLogicalBounds().roundOutwards() : Geom::IntRect()) // fixme
, _units(u)
, _last_out(NR_FILTER_SOURCEGRAPHIC)
, filterquality(FILTER_QUALITY_BEST)
diff --git a/src/display/nr-filter-slot.h b/src/display/nr-filter-slot.h
index 805027bfe..f3c98b8d9 100644
--- a/src/display/nr-filter-slot.h
+++ b/src/display/nr-filter-slot.h
@@ -28,7 +28,7 @@ namespace Filters {
class FilterSlot {
public:
/** Creates a new FilterSlot object. */
- FilterSlot(DrawingItem *item, DrawingContext *bgct,
+ FilterSlot(DrawingItem *item, DrawingContext *bgdc,
DrawingContext &graphic, FilterUnits const &u);
/** Destroys the FilterSlot object and all its contents */
virtual ~FilterSlot();
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index e63b335d2..a2a8c5756 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -288,7 +288,7 @@ private:
static double constexpr PerlinOffset = 4096.0;
#else
#if (__cplusplus < 201103L)
- static double const PerlinOffset = 4096.0;
+ static double const PerlinOffset;
#else
static double constexpr PerlinOffset = 4096.0;
#endif
@@ -309,6 +309,10 @@ private:
bool _fractalnoise;
};
+#if !defined(CPP11) && __cplusplus < 201103L
+ double const TurbulenceGenerator::PerlinOffset = 4096.0;
+#endif
+
FilterTurbulence::FilterTurbulence()
: gen(new TurbulenceGenerator())
, XbaseFrequency(0)
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index af9c15cd8..90b233fbc 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -98,7 +98,7 @@ Filter::~Filter()
}
-int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &graphic, DrawingContext *bgct)
+int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &graphic, DrawingContext *bgdc)
{
if (_primitive.empty()) {
// when no primitives are defined, clear source graphic
@@ -150,7 +150,7 @@ int Filter::render(Inkscape::DrawingItem const *item, DrawingContext &graphic, D
}
}
- FilterSlot slot(const_cast<Inkscape::DrawingItem*>(item), bgct, graphic, units);
+ FilterSlot slot(const_cast<Inkscape::DrawingItem*>(item), bgdc, graphic, units);
slot.set_quality(filterquality);
slot.set_blurquality(blurquality);
@@ -222,14 +222,19 @@ void Filter::area_enlarge(Geom::IntRect &bbox, Inkscape::DrawingItem const *item
Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
{
Geom::Point minp, maxp;
- double len_x = bbox ? bbox->width() : 0;
- double len_y = bbox ? bbox->height() : 0;
- /* TODO: fetch somehow the object ex and em lengths */
- _region_x.update(12, 6, len_x);
- _region_y.update(12, 6, len_y);
- _region_width.update(12, 6, len_x);
- _region_height.update(12, 6, len_y);
+
if (_filter_units == SP_FILTER_UNITS_OBJECTBOUNDINGBOX) {
+
+ double len_x = bbox ? bbox->width() : 0;
+ double len_y = bbox ? bbox->height() : 0;
+ /* TODO: fetch somehow the object ex and em lengths */
+
+ // Update for em, ex, and % values
+ _region_x.update(12, 6, len_x);
+ _region_y.update(12, 6, len_y);
+ _region_width.update(12, 6, len_x);
+ _region_height.update(12, 6, len_y);
+
if (!bbox) return Geom::OptRect();
if (_region_x.unit == SVGLength::PERCENT) {
@@ -254,7 +259,7 @@ Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
maxp[Y] = minp[Y] + _region_height.computed * len_y;
}
} else if (_filter_units == SP_FILTER_UNITS_USERSPACEONUSE) {
- /* TODO: make sure bbox and fe region are in same coordinate system */
+ // Region already set in sp-filter.cpp
minp[X] = _region_x.computed;
maxp[X] = minp[X] + _region_width.computed;
minp[Y] = _region_y.computed;
@@ -262,7 +267,9 @@ Geom::OptRect Filter::filter_effect_area(Geom::OptRect const &bbox)
} else {
g_warning("Error in Inkscape::Filters::Filter::filter_effect_area: unrecognized value of _filter_units");
}
+
Geom::OptRect area(minp, maxp);
+ // std::cout << "Filter::filter_effect_area: area: " << *area << std::endl;
return area;
}
diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h
index 5df38ffe9..f9dcf1d84 100644
--- a/src/display/nr-filter.h
+++ b/src/display/nr-filter.h
@@ -28,12 +28,12 @@ namespace Filters {
class Filter {
public:
- /** Given background state from @a bgct and an intermediate rendering from the surface
+ /** Given background state from @a bgdc 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(Inkscape::DrawingItem const *item, DrawingContext &graphic, DrawingContext *bgct);
+ int render(Inkscape::DrawingItem const *item, DrawingContext &graphic, DrawingContext *bgdc);
/**
* Creates a new filter primitive under this filter object.
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
index 317f38635..125d0c6d6 100644
--- a/src/display/nr-style.cpp
+++ b/src/display/nr-style.cpp
@@ -68,7 +68,11 @@ NRStyle::NRStyle()
, line_through_thickness(0)
, line_through_position(0)
, font_size(0)
-{}
+{
+#ifdef WITH_SVG2
+ paint_order_layer[0] = PAINT_ORDER_NORMAL;
+#endif
+}
NRStyle::~NRStyle()
{
@@ -148,18 +152,38 @@ void NRStyle::set(SPStyle *style)
delete [] dash;
}
- n_dash = style->stroke_dash.n_dash;
+ n_dash = style->stroke_dasharray.values.size();
if (n_dash != 0) {
- dash_offset = style->stroke_dash.offset;
+ dash_offset = style->stroke_dashoffset.value;
dash = new double[n_dash];
for (unsigned int i = 0; i < n_dash; ++i) {
- dash[i] = style->stroke_dash.dash[i];
+ dash[i] = style->stroke_dasharray.values[i];
}
} else {
dash_offset = 0.0;
dash = NULL;
}
+
+#ifdef WITH_SVG2
+ for( unsigned i = 0; i < PAINT_ORDER_LAYERS; ++i) {
+ switch (style->paint_order.layer[i]) {
+ case SP_CSS_PAINT_ORDER_NORMAL:
+ paint_order_layer[i]=PAINT_ORDER_NORMAL;
+ break;
+ case SP_CSS_PAINT_ORDER_FILL:
+ paint_order_layer[i]=PAINT_ORDER_FILL;
+ break;
+ case SP_CSS_PAINT_ORDER_STROKE:
+ paint_order_layer[i]=PAINT_ORDER_STROKE;
+ break;
+ case SP_CSS_PAINT_ORDER_MARKER:
+ paint_order_layer[i]=PAINT_ORDER_MARKER;
+ break;
+ }
+ }
+#endif
+
text_decoration_line = TEXT_DECORATION_LINE_CLEAR;
if(style->text_decoration_line.inherit ){ text_decoration_line |= TEXT_DECORATION_LINE_INHERIT; }
if(style->text_decoration_line.underline ){ text_decoration_line |= TEXT_DECORATION_LINE_UNDERLINE + TEXT_DECORATION_LINE_SET; }
@@ -207,14 +231,14 @@ void NRStyle::set(SPStyle *style)
update();
}
-bool NRStyle::prepareFill(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox)
+bool NRStyle::prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
{
// update fill pattern
if (!fill_pattern) {
switch (fill.type) {
case PAINT_SERVER: {
- //fill_pattern = sp_paint_server_create_pattern(fill.server, ct.raw(), paintbox, fill.opacity);
- fill_pattern = fill.server->pattern_new(ct.raw(), paintbox, fill.opacity);
+ //fill_pattern = sp_paint_server_create_pattern(fill.server, dc.raw(), paintbox, fill.opacity);
+ fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity);
} break;
case PAINT_COLOR: {
@@ -229,19 +253,19 @@ bool NRStyle::prepareFill(Inkscape::DrawingContext &ct, Geom::OptRect const &pai
return true;
}
-void NRStyle::applyFill(Inkscape::DrawingContext &ct)
+void NRStyle::applyFill(Inkscape::DrawingContext &dc)
{
- ct.setSource(fill_pattern);
- ct.setFillRule(fill_rule);
+ dc.setSource(fill_pattern);
+ dc.setFillRule(fill_rule);
}
-bool NRStyle::prepareStroke(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox)
+bool NRStyle::prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
{
if (!stroke_pattern) {
switch (stroke.type) {
case PAINT_SERVER: {
- //stroke_pattern = sp_paint_server_create_pattern(stroke.server, ct.raw(), paintbox, stroke.opacity);
- stroke_pattern = stroke.server->pattern_new(ct.raw(), paintbox, stroke.opacity);
+ //stroke_pattern = sp_paint_server_create_pattern(stroke.server, dc.raw(), paintbox, stroke.opacity);
+ stroke_pattern = stroke.server->pattern_new(dc.raw(), paintbox, stroke.opacity);
} break;
case PAINT_COLOR: {
@@ -256,14 +280,14 @@ bool NRStyle::prepareStroke(Inkscape::DrawingContext &ct, Geom::OptRect const &p
return true;
}
-void NRStyle::applyStroke(Inkscape::DrawingContext &ct)
+void NRStyle::applyStroke(Inkscape::DrawingContext &dc)
{
- ct.setSource(stroke_pattern);
- ct.setLineWidth(stroke_width);
- ct.setLineCap(line_cap);
- ct.setLineJoin(line_join);
- ct.setMiterLimit(miter_limit);
- cairo_set_dash(ct.raw(), dash, n_dash, dash_offset); // fixme
+ dc.setSource(stroke_pattern);
+ dc.setLineWidth(stroke_width);
+ dc.setLineCap(line_cap);
+ dc.setLineJoin(line_join);
+ dc.setMiterLimit(miter_limit);
+ cairo_set_dash(dc.raw(), dash, n_dash, dash_offset); // fixme
}
void NRStyle::update()
diff --git a/src/display/nr-style.h b/src/display/nr-style.h
index 8fd736cc3..717cda899 100644
--- a/src/display/nr-style.h
+++ b/src/display/nr-style.h
@@ -28,10 +28,10 @@ struct NRStyle {
~NRStyle();
void set(SPStyle *);
- bool prepareFill(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox);
- bool prepareStroke(Inkscape::DrawingContext &ct, Geom::OptRect const &paintbox);
- void applyFill(Inkscape::DrawingContext &ct);
- void applyStroke(Inkscape::DrawingContext &ct);
+ bool prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
+ bool prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
+ void applyFill(Inkscape::DrawingContext &dc);
+ void applyStroke(Inkscape::DrawingContext &dc);
void update();
enum PaintType {
@@ -68,6 +68,18 @@ struct NRStyle {
cairo_pattern_t *fill_pattern;
cairo_pattern_t *stroke_pattern;
+#ifdef WITH_SVG2
+ enum PaintOrderType {
+ PAINT_ORDER_NORMAL,
+ PAINT_ORDER_FILL,
+ PAINT_ORDER_STROKE,
+ PAINT_ORDER_MARKER
+ };
+
+ static const size_t PAINT_ORDER_LAYERS = 3;
+ PaintOrderType paint_order_layer[PAINT_ORDER_LAYERS];
+#endif
+
#define TEXT_DECORATION_LINE_CLEAR 0x00
#define TEXT_DECORATION_LINE_SET 0x01
#define TEXT_DECORATION_LINE_INHERIT 0x02
diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp
index c350e4614..e6e427047 100644
--- a/src/display/sodipodi-ctrlrect.cpp
+++ b/src/display/sodipodi-ctrlrect.cpp
@@ -142,7 +142,18 @@ void CtrlRect::render(SPCanvasBuf *buf)
ink_cairo_set_source_rgba32(buf->ct, _border_color);
cairo_stroke(buf->ct);
- if (_shadow_size > 0) {
+ if (_shadow_size == 1) { // highlight the border by drawing it in _shadow_color
+ if (_dashed) {
+ cairo_set_dash(buf->ct, dashes, 2, 4);
+ cairo_rectangle(buf->ct, 0.5 + area[X].min(), 0.5 + area[Y].min(),
+ area[X].max() - area[X].min(), area[Y].max() - area[Y].min());
+ } else {
+ cairo_rectangle(buf->ct, -0.5 + area[X].min(), -0.5 + area[Y].min(),
+ area[X].max() - area[X].min(), area[Y].max() - area[Y].min());
+ }
+ ink_cairo_set_source_rgba32(buf->ct, _shadow_color);
+ cairo_stroke(buf->ct);
+ } else if (_shadow_size > 1) { // fill the shadow
ink_cairo_set_source_rgba32(buf->ct, _shadow_color);
cairo_rectangle(buf->ct, 1 + area[X].max(), area[Y].min() + _shadow_size,
_shadow_size, area[Y].max() - area[Y].min() + 1); // right shadow
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 455f628bc..6d903867b 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -35,7 +35,6 @@
#include "display/cairo-utils.h"
#include "debug/gdk-event-latency-tracker.h"
#include "desktop.h"
-#include "sp-namedview.h"
using Inkscape::Debug::GdkEventLatencyTracker;
@@ -1387,8 +1386,13 @@ void SPCanvasImpl::realize(GtkWidget *widget)
gdk_window_set_user_data (window, widget);
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- if ( prefs->getBool("/options/useextinput/value", true) )
+ if (prefs->getBool("/options/useextinput/value", true)) {
gtk_widget_set_events(widget, attributes.event_mask);
+#if !GTK_CHECK_VERSION(3,0,0)
+ gtk_widget_set_extension_events(widget, GDK_EXTENSION_EVENTS_ALL);
+ // TODO: Extension event stuff has been deprecated in GTK+ 3
+#endif
+ }
#if !GTK_CHECK_VERSION(3,0,0)
// This does nothing in GTK+ 3
@@ -1524,27 +1528,31 @@ int SPCanvasImpl::emitEvent(SPCanvas *canvas, GdkEvent *event)
// Convert to world coordinates -- we have two cases because of different
// offsets of the fields in the event structures.
- //
- GdkEvent ev = *event;
+ GdkEvent *ev = gdk_event_copy(event);
- switch (ev.type) {
+ switch (ev->type) {
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
- ev.crossing.x += canvas->x0;
- ev.crossing.y += canvas->y0;
+ ev->crossing.x += canvas->x0;
+ ev->crossing.y += canvas->y0;
break;
case GDK_MOTION_NOTIFY:
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
- ev.motion.x += canvas->x0;
- ev.motion.y += canvas->y0;
+ ev->motion.x += canvas->x0;
+ ev->motion.y += canvas->y0;
break;
default:
break;
}
+ // Block Undo and Redo while we drag /anything/
+ if(event->type == GDK_BUTTON_PRESS && event->button.button == 1)
+ canvas->is_dragging = true;
+ else if(event->type == GDK_BUTTON_RELEASE)
+ canvas->is_dragging = false;
// Choose where we send the event
@@ -1588,12 +1596,14 @@ int SPCanvasImpl::emitEvent(SPCanvas *canvas, GdkEvent *event)
while (item && !finished) {
g_object_ref (item);
- g_signal_emit (G_OBJECT (item), item_signals[ITEM_EVENT], 0, &ev, &finished);
+ g_signal_emit (G_OBJECT (item), item_signals[ITEM_EVENT], 0, ev, &finished);
SPCanvasItem *parent = item->parent;
g_object_unref (item);
item = parent;
}
+ gdk_event_free(ev);
+
return finished;
}
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index b570b739e..72ae4b6bc 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -124,6 +124,7 @@ struct SPCanvas {
SPCanvasItem *root;
+ bool is_dragging;
double dx0;
double dy0;
int x0;
diff --git a/src/display/sp-ctrlquadr.h b/src/display/sp-ctrlquadr.h
index 9fdfd29b3..1dfb06456 100644
--- a/src/display/sp-ctrlquadr.h
+++ b/src/display/sp-ctrlquadr.h
@@ -12,9 +12,7 @@
* Released under GNU GPL
*/
-#include "sp-canvas.h"
-
-
+#include <2geom/geom.h>
#define SP_TYPE_CTRLQUADR (sp_ctrlquadr_get_type ())
#define SP_CTRLQUADR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_CTRLQUADR, SPCtrlQuadr))