summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/display/CMakeLists.txt2
-rw-r--r--src/display/Makefile_insert2
-rw-r--r--src/display/drawing-item.cpp45
-rw-r--r--src/display/drawing-item.h9
-rw-r--r--src/display/drawing-pattern.cpp195
-rw-r--r--src/display/drawing-pattern.h88
-rw-r--r--src/display/drawing-shape.cpp8
-rw-r--r--src/display/drawing-text.cpp8
-rw-r--r--src/display/nr-style.cpp78
-rw-r--r--src/display/nr-style.h9
-rw-r--r--src/sp-paint-server.cpp5
-rw-r--r--src/sp-paint-server.h1
12 files changed, 415 insertions, 35 deletions
diff --git a/src/display/CMakeLists.txt b/src/display/CMakeLists.txt
index 20424c845..800c4d0d4 100644
--- a/src/display/CMakeLists.txt
+++ b/src/display/CMakeLists.txt
@@ -13,6 +13,7 @@ set(display_SRC
drawing-group.cpp
drawing-image.cpp
drawing-item.cpp
+ drawing-pattern.cpp
drawing-shape.cpp
drawing-surface.cpp
drawing-text.cpp
@@ -75,6 +76,7 @@ set(display_SRC
drawing-group.h
drawing-image.h
drawing-item.h
+ drawing-pattern.h
drawing-shape.h
drawing-surface.h
drawing-text.h
diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert
index abbd89a68..2355c3653 100644
--- a/src/display/Makefile_insert
+++ b/src/display/Makefile_insert
@@ -33,6 +33,8 @@ ink_common_sources += \
display/drawing-image.h \
display/drawing-item.cpp \
display/drawing-item.h \
+ display/drawing-pattern.cpp \
+ display/drawing-pattern.h \
display/drawing-shape.cpp \
display/drawing-shape.h \
display/drawing-surface.cpp \
diff --git a/src/display/drawing-item.cpp b/src/display/drawing-item.cpp
index 2ea3641dc..5226edda3 100644
--- a/src/display/drawing-item.cpp
+++ b/src/display/drawing-item.cpp
@@ -16,6 +16,7 @@
#include "display/drawing-context.h"
#include "display/drawing-item.h"
#include "display/drawing-group.h"
+#include "display/drawing-pattern.h"
#include "display/drawing-surface.h"
#include "nr-filter.h"
#include "preferences.h"
@@ -110,6 +111,8 @@ DrawingItem::DrawingItem(Drawing &drawing)
, _transform(NULL)
, _clip(NULL)
, _mask(NULL)
+ , _fill_pattern(NULL)
+ , _stroke_pattern(NULL)
, _filter(NULL)
, _user_data(NULL)
, _cache(NULL)
@@ -164,6 +167,12 @@ DrawingItem::~DrawingItem()
case CHILD_ROOT:
_drawing._root = NULL;
break;
+ case CHILD_FILL_PATTERN:
+ _parent->_fill_pattern = NULL;
+ break;
+ case CHILD_STROKE_PATTERN:
+ _parent->_stroke_pattern = NULL;
+ break;
default: ;
}
@@ -172,6 +181,8 @@ DrawingItem::~DrawingItem()
}
clearChildren();
delete _transform;
+ delete _stroke_pattern;
+ delete _fill_pattern;
delete _clip;
delete _mask;
delete _filter;
@@ -366,6 +377,34 @@ DrawingItem::setMask(DrawingItem *item)
_markForUpdate(STATE_ALL, true);
}
+void
+DrawingItem::setFillPattern(DrawingPattern *pattern)
+{
+ _markForRendering();
+ delete _fill_pattern;
+ _fill_pattern = pattern;
+ if (pattern) {
+ pattern->_parent = this;
+ assert(pattern->_child_type == CHILD_ORPHAN);
+ pattern->_child_type = CHILD_FILL_PATTERN;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
+void
+DrawingItem::setStrokePattern(DrawingPattern *pattern)
+{
+ _markForRendering();
+ delete _stroke_pattern;
+ _stroke_pattern = pattern;
+ if (pattern) {
+ pattern->_parent = this;
+ assert(pattern->_child_type == CHILD_ORPHAN);
+ pattern->_child_type = CHILD_STROKE_PATTERN;
+ }
+ _markForUpdate(STATE_ALL, true);
+}
+
/// Move this item to the given place in the Z order of siblings.
/// Does nothing if the item has no parent.
void
@@ -530,6 +569,12 @@ DrawingItem::update(Geom::IntRect const &area, UpdateContext const &ctx, unsigne
if (to_update & STATE_RENDER) {
// 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 (_fill_pattern) {
+ _fill_pattern->update(area, child_ctx, flags, reset);
+ }
+ if (_stroke_pattern) {
+ _stroke_pattern->update(area, child_ctx, flags, reset);
+ }
if (!is_drawing_group(this) || (_filter && render_filters)) {
_markForRendering();
}
diff --git a/src/display/drawing-item.h b/src/display/drawing-item.h
index 925bcbddb..c0c6e321e 100644
--- a/src/display/drawing-item.h
+++ b/src/display/drawing-item.h
@@ -28,6 +28,7 @@ class Drawing;
class DrawingCache;
class DrawingContext;
class DrawingItem;
+class DrawingPattern;
namespace Filters {
@@ -114,6 +115,8 @@ public:
void setTransform(Geom::Affine const &trans);
void setClip(DrawingItem *item);
void setMask(DrawingItem *item);
+ void setFillPattern(DrawingPattern *pattern);
+ void setStrokePattern(DrawingPattern *pattern);
void setZOrder(unsigned z);
void setItemBounds(Geom::OptRect const &bounds);
void setFilterBounds(Geom::OptRect const &bounds);
@@ -135,8 +138,8 @@ protected:
CHILD_CLIP = 2, // referenced by _clip member of parent
CHILD_MASK = 3, // referenced by _mask member of parent
CHILD_ROOT = 4, // root item of _drawing
- CHILD_FILL_PATTERN = 5, // not yet implemented: referenced by fill pattern of parent
- CHILD_STROKE_PATTERN = 6 // not yet implemented: referenced by stroke pattern of parent
+ CHILD_FILL_PATTERN = 5, // referenced by fill pattern of parent
+ CHILD_STROKE_PATTERN = 6 // referenced by stroke pattern of parent
};
enum RenderResult {
RENDER_OK = 0,
@@ -185,6 +188,8 @@ protected:
DrawingItem *_clip;
DrawingItem *_mask;
+ DrawingPattern *_fill_pattern;
+ DrawingPattern *_stroke_pattern;
Inkscape::Filters::Filter *_filter;
void *_user_data; ///< Used to associate DrawingItems with SPItems that created them
DrawingCache *_cache;
diff --git a/src/display/drawing-pattern.cpp b/src/display/drawing-pattern.cpp
new file mode 100644
index 000000000..77752bce3
--- /dev/null
+++ b/src/display/drawing-pattern.cpp
@@ -0,0 +1,195 @@
+/**
+ * @file
+ * Canvas belonging to SVG pattern.
+ *//*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 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-pattern.h"
+#include "display/drawing-surface.h"
+
+namespace Inkscape {
+
+DrawingPattern::DrawingPattern(Drawing &drawing, bool debug)
+ : DrawingGroup(drawing)
+ , _pattern_to_user(NULL)
+ , _overflow_steps(1)
+ , _debug(debug)
+{
+}
+
+DrawingPattern::~DrawingPattern()
+{
+ delete _pattern_to_user; // delete NULL; is safe
+}
+
+void
+DrawingPattern::setPatternToUserTransform(Geom::Affine const &new_trans) {
+ Geom::Affine current;
+ if (_pattern_to_user) {
+ current = *_pattern_to_user;
+ }
+
+ if (!Geom::are_near(current, new_trans, 1e-18)) {
+ // mark the area where the object was for redraw.
+ _markForRendering();
+ if (new_trans.isIdentity()) {
+ delete _pattern_to_user; // delete NULL; is safe
+ _pattern_to_user = NULL;
+ } else {
+ _pattern_to_user = new Geom::Affine(new_trans);
+ }
+ _markForUpdate(STATE_ALL, true);
+ }
+}
+
+void
+DrawingPattern::setTileRect(Geom::Rect const &tile_rect) {
+ _tile_rect = tile_rect;
+}
+
+void
+DrawingPattern::setOverflow(Geom::Affine initial_transform, int steps, Geom::Affine step_transform) {
+ _overflow_initial_transform = initial_transform;
+ _overflow_steps = steps;
+ _overflow_step_transform = step_transform;
+}
+
+cairo_pattern_t *
+DrawingPattern::renderPattern(float opacity) {
+ bool needs_opacity = (1.0 - opacity) >= 1e-3;
+ bool visible = opacity >= 1e-3;
+
+ if (!visible) {
+ return NULL;
+ }
+
+ if (!_tile_rect || (_tile_rect->area() == 0)) {
+ return NULL;
+ }
+ Geom::Rect pattern_tile = *_tile_rect;
+
+ //TODO: If pattern_to_user set it to identity transform
+
+ // The DrawingSurface class handles the mapping from "logical space"
+ // (coordinates in the rendering) to "physical space" (surface pixels).
+ // An oversampling is done as the pattern may not pixel align with the final surface.
+ // The cairo surface is created when the DrawingContext is declared.
+ // Create drawing surface with size of pattern tile (in pattern space) but with number of pixels
+ // based on required resolution (c).
+ Inkscape::DrawingSurface pattern_surface(pattern_tile, _pattern_resolution);
+ Inkscape::DrawingContext dc(pattern_surface);
+ dc.transform( pattern_surface.drawingTransform().inverse() );
+
+ pattern_tile *= pattern_surface.drawingTransform();
+ Geom::IntRect one_tile = pattern_tile.roundOutwards();
+
+ // Render pattern.
+ if (needs_opacity) {
+ dc.pushGroup(); // this group is for pattern + opacity
+ }
+
+ if (_debug) {
+ dc.setSource(0.8, 0.0, 0.8);
+ dc.paint();
+ }
+
+ //FIXME: What flags to choose?
+ if (_overflow_steps == 1) {
+ render(dc, one_tile, RENDER_DEFAULT);
+ } else {
+ //Overflow transforms need to be transformed to the new coordinate system
+ //introduced by dc.transform( pattern_surface.drawingTransform().inverse() );
+ Geom::Affine dt = pattern_surface.drawingTransform();
+ Geom::Affine idt = pattern_surface.drawingTransform().inverse();
+ Geom::Affine initial_transform = idt * _overflow_initial_transform * dt;
+ Geom::Affine step_transform = idt * _overflow_step_transform * dt;
+
+ dc.transform(initial_transform);
+ for (int i = 0; i < _overflow_steps; i++) {
+ render(dc, one_tile, RENDER_DEFAULT);
+ dc.transform(step_transform);
+ }
+ }
+
+ //Uncomment to debug
+ // cairo_surface_t* raw = pattern_surface.raw();
+ // std::cout << " cairo_surface (sp-pattern): "
+ // << " width: " << cairo_image_surface_get_width( raw )
+ // << " height: " << cairo_image_surface_get_height( raw )
+ // << std::endl;
+ // std::string filename = "drawing-pattern.png";
+ // cairo_surface_write_to_png( pattern_surface.raw(), filename.c_str() );
+
+ if (needs_opacity) {
+ dc.popGroupToSource(); // pop raw pattern
+ dc.paint(opacity); // apply opacity
+ }
+
+ cairo_pattern_t *cp = cairo_pattern_create_for_surface(pattern_surface.raw());
+ // Apply transformation to user space. Also compensate for oversampling.
+ if (_pattern_to_user) {
+ ink_cairo_pattern_set_matrix(cp, _pattern_to_user->inverse() * pattern_surface.drawingTransform());
+ } else {
+ ink_cairo_pattern_set_matrix(cp, pattern_surface.drawingTransform());
+ }
+
+ if (_debug) {
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_NONE);
+ } else {
+ cairo_pattern_set_extend(cp, CAIRO_EXTEND_REPEAT);
+ }
+
+ return cp;
+}
+
+unsigned
+DrawingPattern::_updateItem(Geom::IntRect const &area, UpdateContext const &ctx, unsigned flags, unsigned reset)
+{
+ UpdateContext pattern_ctx;
+
+ if (!_tile_rect || (_tile_rect->area() == 0)) {
+ return STATE_NONE;
+ }
+
+ Geom::Rect pattern_tile = *_tile_rect;
+
+ Geom::Coord det_ctm = ctx.ctm.descrim();
+ Geom::Coord det_ps2user = _pattern_to_user ? _pattern_to_user->descrim() : 1.0;
+ Geom::Coord det_child_transform = _child_transform ? _child_transform->descrim() : 1.0;
+ const double oversampling = 2.0;
+ double scale = det_ctm*det_ps2user*det_child_transform * oversampling;
+ //FIXME: When scale is too big (zooming in a hatch), cairo doesn't render the pattern
+ //More precisely it fails when seting pattern matrix in DrawingPattern::renderPattern
+ //Fully correct solution should make use of visible area bbox and change hach tile rect
+ //accordingly
+ if (scale > 25) {
+ scale = 25;
+ }
+ Geom::Point c(pattern_tile.dimensions()*scale*oversampling);
+ _pattern_resolution = c.ceil();
+
+ Inkscape::DrawingSurface pattern_surface(pattern_tile, _pattern_resolution);
+
+ pattern_ctx.ctm = pattern_surface.drawingTransform();
+ return DrawingGroup::_updateItem(Geom::IntRect::infinite(), pattern_ctx, flags, reset);
+}
+
+} // 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-pattern.h b/src/display/drawing-pattern.h
new file mode 100644
index 000000000..487da51b7
--- /dev/null
+++ b/src/display/drawing-pattern.h
@@ -0,0 +1,88 @@
+/**
+ * @file
+ * Canvas belonging to SVG pattern.
+ *//*
+ * Authors:
+ * Tomasz Boczkowski <penginsbacon@gmail.com>
+ *
+ * Copyright (C) 2014 Authors
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifndef SEEN_INKSCAPE_DISPLAY_DRAWING_PATTERN_H
+#define SEEN_INKSCAPE_DISPLAY_DRAWING_PATTERN_H
+
+#include "display/drawing-group.h"
+
+typedef struct _cairo_pattern cairo_pattern_t;
+class SPStyle;
+
+namespace Inkscape {
+
+/**
+ * @brief Drawing tree node used for rendering paints.
+ *
+ * DrawingPattern is used for rendering patterns and hatches.
+ *
+ * It renders it's children to a cairo_pattern_t structure that can be
+ * applied as source for fill or stroke operations.
+ */
+class DrawingPattern
+ : public DrawingGroup
+{
+public:
+ DrawingPattern(Drawing &drawing, bool debug = false);
+ ~DrawingPattern();
+
+ /**
+ * Set the transformation from pattern to user coordinate systems.
+ * @see SPPattern description for explanation of coordinate systems.
+ */
+ void setPatternToUserTransform(Geom::Affine const &new_trans);
+ /**
+ * Set the tile rect position and dimentions in content coordinate system
+ */
+ void setTileRect(Geom::Rect const &tile_rect);
+ /**
+ * Turn on overflow rendering.
+ *
+ * Overflow is implemented as repeated rendering of pattern contents. In every step
+ * a translation transform is applied.
+ */
+ void setOverflow(Geom::Affine initial_transform, int steps, Geom::Affine step_transform);
+ /**
+ * Render the pattern.
+ *
+ * Returns caito_pattern_t structure that can be set as source surface.
+ */
+ cairo_pattern_t *renderPattern(float opacity);
+protected:
+ virtual unsigned _updateItem(Geom::IntRect const &area, UpdateContext const &ctx,
+ unsigned flags, unsigned reset);
+
+ Geom::Affine *_pattern_to_user;
+ Geom::Affine _overflow_initial_transform;
+ Geom::Affine _overflow_step_transform;
+ int _overflow_steps;
+ Geom::OptRect _tile_rect;
+ bool _debug;
+
+ Geom::IntPoint _pattern_resolution;
+};
+
+bool is_drawing_group(DrawingItem *item);
+
+} // end namespace Inkscape
+
+#endif // !SEEN_INKSCAPE_DISPLAY_DRAWING_PATTERN_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
index 1a41bdb3a..fe525b1a5 100644
--- a/src/display/drawing-shape.cpp
+++ b/src/display/drawing-shape.cpp
@@ -155,7 +155,7 @@ DrawingShape::_renderFill(DrawingContext &dc)
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
- bool has_fill = _nrstyle.prepareFill(dc, _item_bbox);
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox, _fill_pattern);
if( has_fill ) {
dc.path(_curve->get_pathvector());
@@ -171,7 +171,7 @@ DrawingShape::_renderStroke(DrawingContext &dc)
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
- bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox);
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern);
has_stroke &= (_nrstyle.stroke_width != 0);
if( has_stroke ) {
@@ -231,8 +231,8 @@ DrawingShape::_renderItem(DrawingContext &dc, Geom::IntRect const &area, unsigne
// 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);
+ bool has_fill = _nrstyle.prepareFill(dc, _item_bbox, _fill_pattern);
+ bool has_stroke = _nrstyle.prepareStroke(dc, _item_bbox, _stroke_pattern);
has_stroke &= (_nrstyle.stroke_width != 0);
if (has_fill || has_stroke) {
diff --git a/src/display/drawing-text.cpp b/src/display/drawing-text.cpp
index 9f3b447df..cb6520bcd 100644
--- a/src/display/drawing-text.cpp
+++ b/src/display/drawing-text.cpp
@@ -445,13 +445,13 @@ unsigned DrawingText::_renderItem(DrawingContext &dc, Geom::IntRect const &/*are
Inkscape::DrawingContext::Save save(dc);
dc.transform(_ctm);
- has_fill = _nrstyle.prepareFill( dc, _item_bbox);
- has_stroke = _nrstyle.prepareStroke( dc, _item_bbox);
+ has_fill = _nrstyle.prepareFill( dc, _item_bbox, _fill_pattern);
+ has_stroke = _nrstyle.prepareStroke( dc, _item_bbox, _stroke_pattern);
// Avoid creating patterns if not needed
if( decorate ) {
- has_td_fill = _nrstyle.prepareTextDecorationFill( dc, _item_bbox);
- has_td_stroke = _nrstyle.prepareTextDecorationStroke(dc, _item_bbox);
+ has_td_fill = _nrstyle.prepareTextDecorationFill( dc, _item_bbox, _fill_pattern);
+ has_td_stroke = _nrstyle.prepareTextDecorationStroke(dc, _item_bbox, _stroke_pattern);
}
}
diff --git a/src/display/nr-style.cpp b/src/display/nr-style.cpp
index ec3117079..96d16bf06 100644
--- a/src/display/nr-style.cpp
+++ b/src/display/nr-style.cpp
@@ -14,6 +14,7 @@
#include "sp-paint-server.h"
#include "display/canvas-bpath.h" // contains SPStrokeJoinType, SPStrokeCapType etc. (WTF!)
#include "display/drawing-context.h"
+#include "display/drawing-pattern.h"
void NRStyle::Paint::clear()
{
@@ -95,7 +96,14 @@ NRStyle::~NRStyle()
void NRStyle::set(SPStyle *style)
{
if ( style->fill.isPaintserver() ) {
- fill.set(style->getFillPaintServer());
+ SPPaintServer* server = style->getFillPaintServer();
+ if ( server && server->isValid() ) {
+ fill.set(server);
+ } else if ( style->fill.colorSet ) {
+ fill.set(style->fill.value.color);
+ } else {
+ fill.clear();
+ }
} else if ( style->fill.isColor() ) {
fill.set(style->fill.value.color);
} else if ( style->fill.isNone() ) {
@@ -117,7 +125,14 @@ void NRStyle::set(SPStyle *style)
}
if ( style->stroke.isPaintserver() ) {
- stroke.set(style->getStrokePaintServer());
+ SPPaintServer* server = style->getStrokePaintServer();
+ if ( server && server->isValid() ) {
+ stroke.set(server);
+ } else if ( style->stroke.isColor() ) {
+ stroke.set(style->stroke.colorSet);
+ } else {
+ stroke.clear();
+ }
} else if ( style->stroke.isColor() ) {
stroke.set(style->stroke.value.color);
} else if ( style->stroke.isNone() ) {
@@ -285,13 +300,16 @@ void NRStyle::set(SPStyle *style)
update();
}
-bool NRStyle::prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+bool NRStyle::prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
{
// update fill pattern
if (!fill_pattern) {
switch (fill.type) {
- case PAINT_SERVER: {
- fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity);
+ case PAINT_SERVER:
+ if (pattern) {
+ fill_pattern = pattern->renderPattern(fill.opacity);
+ } else {
+ fill_pattern = fill.server->pattern_new(dc.raw(), paintbox, fill.opacity);
} break;
case PAINT_COLOR: {
SPColor const &c = fill.color;
@@ -311,14 +329,20 @@ void NRStyle::applyFill(Inkscape::DrawingContext &dc)
dc.setFillRule(fill_rule);
}
-bool NRStyle::prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+bool NRStyle::prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
{
// update text decoration pattern
if (!text_decoration_fill_pattern) {
switch (text_decoration_fill.type) {
- case PAINT_SERVER: {
- text_decoration_fill_pattern = text_decoration_fill.server->pattern_new(dc.raw(), paintbox, text_decoration_fill.opacity);
- } break;
+ case PAINT_SERVER:
+ if (pattern) {
+ text_decoration_fill_pattern = pattern->renderPattern(
+ text_decoration_fill.opacity);
+ } else {
+ text_decoration_fill_pattern = text_decoration_fill.server->pattern_new(dc.raw(),
+ paintbox, text_decoration_fill.opacity);
+ }
+ break;
case PAINT_COLOR: {
SPColor const &c = text_decoration_fill.color;
text_decoration_fill_pattern = cairo_pattern_create_rgba(
@@ -337,19 +361,25 @@ void NRStyle::applyTextDecorationFill(Inkscape::DrawingContext &dc)
// Fill rule does not matter, no intersections.
}
-bool NRStyle::prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+bool NRStyle::prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
{
if (!stroke_pattern) {
switch (stroke.type) {
- case PAINT_SERVER: {
- stroke_pattern = stroke.server->pattern_new(dc.raw(), paintbox, stroke.opacity);
- } break;
+ case PAINT_SERVER:
+ if (pattern) {
+ stroke_pattern = pattern->renderPattern(stroke.opacity);
+ } else {
+ stroke_pattern = stroke.server->pattern_new(dc.raw(), paintbox, stroke.opacity);
+ }
+ break;
case PAINT_COLOR: {
SPColor const &c = stroke.color;
- stroke_pattern = cairo_pattern_create_rgba(
- c.v.c[0], c.v.c[1], c.v.c[2], stroke.opacity);
- } break;
- default: break;
+ stroke_pattern = cairo_pattern_create_rgba(c.v.c[0], c.v.c[1], c.v.c[2],
+ stroke.opacity);
+ }
+ break;
+ default:
+ break;
}
}
if (!stroke_pattern) return false;
@@ -366,13 +396,19 @@ void NRStyle::applyStroke(Inkscape::DrawingContext &dc)
cairo_set_dash(dc.raw(), dash, n_dash, dash_offset); // fixme
}
-bool NRStyle::prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox)
+bool NRStyle::prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern)
{
if (!text_decoration_stroke_pattern) {
switch (text_decoration_stroke.type) {
- case PAINT_SERVER: {
- text_decoration_stroke_pattern = text_decoration_stroke.server->pattern_new(dc.raw(), paintbox, text_decoration_stroke.opacity);
- } break;
+ case PAINT_SERVER:
+ if (pattern) {
+ text_decoration_stroke_pattern = pattern->renderPattern(
+ text_decoration_stroke.opacity);
+ } else {
+ text_decoration_stroke_pattern = text_decoration_stroke.server->pattern_new(
+ dc.raw(), paintbox, text_decoration_stroke.opacity);
+ }
+ break;
case PAINT_COLOR: {
SPColor const &c = text_decoration_stroke.color;
text_decoration_stroke_pattern = cairo_pattern_create_rgba(
diff --git a/src/display/nr-style.h b/src/display/nr-style.h
index 83bcb1ab7..f324fdb56 100644
--- a/src/display/nr-style.h
+++ b/src/display/nr-style.h
@@ -21,6 +21,7 @@ class SPStyle;
namespace Inkscape {
class DrawingContext;
+class DrawingPattern;
}
struct NRStyle {
@@ -28,10 +29,10 @@ struct NRStyle {
~NRStyle();
void set(SPStyle *);
- bool prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
- bool prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
- bool prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
- bool prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox);
+ bool prepareFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
+ bool prepareStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
+ bool prepareTextDecorationFill(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
+ bool prepareTextDecorationStroke(Inkscape::DrawingContext &dc, Geom::OptRect const &paintbox, Inkscape::DrawingPattern *pattern);
void applyFill(Inkscape::DrawingContext &dc);
void applyStroke(Inkscape::DrawingContext &dc);
void applyTextDecorationFill(Inkscape::DrawingContext &dc);
diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp
index 692265bd8..d692fc611 100644
--- a/src/sp-paint-server.cpp
+++ b/src/sp-paint-server.cpp
@@ -58,6 +58,11 @@ bool SPPaintServer::isSolid() const
return solid;
}
+bool SPPaintServer::isValid() const
+{
+ return true;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h
index 02e2f10ec..c1c8d651e 100644
--- a/src/sp-paint-server.h
+++ b/src/sp-paint-server.h
@@ -29,6 +29,7 @@ public:
bool isSwatch() const;
bool isSolid() const;
+ virtual bool isValid() const;
virtual cairo_pattern_t* pattern_new(cairo_t *ct, Geom::OptRect const &bbox, double opacity) = 0;