summaryrefslogtreecommitdiffstats
path: root/src/sp-item.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/sp-item.cpp')
-rw-r--r--src/sp-item.cpp456
1 files changed, 281 insertions, 175 deletions
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index b10aae1c6..73347fc4e 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -1,6 +1,3 @@
-/** \file
- * Base class for visual SVG elements
- */
/*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
@@ -15,12 +12,6 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-/** \class SPItem
- *
- * SPItem is an abstract base class for all graphic (visible) SVG nodes. It
- * is a subclass of SPObject, with great deal of specific functionality.
- */
-
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
@@ -44,6 +35,7 @@
#include "sp-rect.h"
#include "sp-use.h"
#include "sp-text.h"
+#include "sp-textpath.h"
#include "sp-item-rm-unsatisfied-cns.h"
#include "sp-pattern.h"
#include "sp-paint-server.h"
@@ -99,6 +91,8 @@ SPItem::SPItem() : SPObject() {
sensitive = TRUE;
bbox_valid = FALSE;
+ _highlightColor = NULL;
+
transform_center_x = 0;
transform_center_y = 0;
@@ -117,11 +111,10 @@ SPItem::SPItem() : SPObject() {
mask_ref = new SPMaskReference(this);
mask_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(mask_ref_changed), this));
- avoidRef = new SPAvoidRef(this);
-
- //new (&constraints) std::vector<SPGuideConstraint>();
+ style->signal_fill_ps_changed.connect(sigc::bind(sigc::ptr_fun(fill_ps_ref_changed), this));
+ style->signal_stroke_ps_changed.connect(sigc::bind(sigc::ptr_fun(stroke_ps_ref_changed), this));
- //new (&_transformed_signal) sigc::signal<void, Geom::Affine const *, SPItem *>();
+ avoidRef = new SPAvoidRef(this);
}
SPItem::~SPItem() {
@@ -137,7 +130,8 @@ bool SPItem::isVisibleAndUnlocked(unsigned display_key) const {
bool SPItem::isLocked() const {
for (SPObject const *o = this; o != NULL; o = o->parent) {
- if (SP_IS_ITEM(o) && !(SP_ITEM(o)->sensitive)) {
+ SPItem const *item = dynamic_cast<SPItem const *>(o);
+ if (item && !(item->sensitive)) {
return true;
}
}
@@ -183,6 +177,29 @@ bool SPItem::isHidden(unsigned display_key) const {
return true;
}
+bool SPItem::isHighlightSet() const {
+ return _highlightColor != NULL;
+}
+
+guint32 SPItem::highlight_color() const {
+ if (_highlightColor)
+ {
+ return atoi(_highlightColor) | 0x00000000;
+ }
+ else {
+ SPItem const *item = dynamic_cast<SPItem const *>(parent);
+ if (parent && (parent != this) && item)
+ {
+ return item->highlight_color();
+ }
+ else
+ {
+ static Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ return prefs->getInt("/tools/nodes/highlight_color", 0xff0000ff) | 0x00000000;
+ }
+ }
+}
+
void SPItem::setEvaluated(bool evaluated) {
_is_evaluated = evaluated;
_evaluated_status = StatusSet;
@@ -196,8 +213,9 @@ void SPItem::resetEvaluated() {
requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
}
} if ( StatusSet == _evaluated_status ) {
- if (SP_IS_SWITCH(parent)) {
- SP_SWITCH(parent)->resetChildEvaluated();
+ SPSwitch *switchItem = dynamic_cast<SPSwitch *>(parent);
+ if (switchItem) {
+ switchItem->resetChildEvaluated();
}
}
}
@@ -210,20 +228,12 @@ bool SPItem::isEvaluated() const {
return _is_evaluated;
}
-/**
- * Returns something suitable for the `Hide' checkbox in the Object Properties dialog box.
- * Corresponds to setExplicitlyHidden.
- */
bool SPItem::isExplicitlyHidden() const
{
return (style->display.set
&& style->display.value == SP_CSS_DISPLAY_NONE);
}
-/**
- * Sets the display CSS property to `hidden' if \a val is true,
- * otherwise makes it unset
- */
void SPItem::setExplicitlyHidden(bool val) {
style->display.set = val;
style->display.value = ( val ? SP_CSS_DISPLAY_NONE : SP_CSS_DISPLAY_INLINE );
@@ -231,19 +241,27 @@ void SPItem::setExplicitlyHidden(bool val) {
updateRepr();
}
-/**
- * Sets the transform_center_x and transform_center_y properties to retain the rotation centre
- */
void SPItem::setCenter(Geom::Point const &object_centre) {
document->ensureUpToDate();
+ // Copied from DocumentProperties::onDocUnitChange()
+ gdouble viewscale = 1.0;
+ Geom::Rect vb = this->document->getRoot()->viewBox;
+ if ( !vb.hasZeroArea() ) {
+ gdouble viewscale_w = this->document->getWidth().value("px") / vb.width();
+ gdouble viewscale_h = this->document->getHeight().value("px")/ vb.height();
+ viewscale = std::min(viewscale_h, viewscale_w);
+ }
+
// FIXME this is seriously wrong
Geom::OptRect bbox = desktopGeometricBounds();
if (bbox) {
- transform_center_x = object_centre[Geom::X] - bbox->midpoint()[Geom::X];
+ // object centre is document coordinates (i.e. in pixels), so we need to consider the viewbox
+ // to translate to user units; transform_center_x/y is in user units
+ transform_center_x = (object_centre[Geom::X] - bbox->midpoint()[Geom::X])/viewscale;
if (Geom::are_near(transform_center_x, 0)) // rounding error
transform_center_x = 0;
- transform_center_y = object_centre[Geom::Y] - bbox->midpoint()[Geom::Y];
+ transform_center_y = (object_centre[Geom::Y] - bbox->midpoint()[Geom::Y])/viewscale;
if (Geom::are_near(transform_center_y, 0)) // rounding error
transform_center_y = 0;
}
@@ -259,23 +277,41 @@ bool SPItem::isCenterSet() const {
return (transform_center_x != 0 || transform_center_y != 0);
}
+// Get the item's transformation center in document coordinates (i.e. in pixels)
Geom::Point SPItem::getCenter() const {
document->ensureUpToDate();
+ // Copied from DocumentProperties::onDocUnitChange()
+ gdouble viewscale = 1.0;
+ Geom::Rect vb = this->document->getRoot()->viewBox;
+ if ( !vb.hasZeroArea() ) {
+ gdouble viewscale_w = this->document->getWidth().value("px") / vb.width();
+ gdouble viewscale_h = this->document->getHeight().value("px")/ vb.height();
+ viewscale = std::min(viewscale_h, viewscale_w);
+ }
+
// FIXME this is seriously wrong
Geom::OptRect bbox = desktopGeometricBounds();
if (bbox) {
- return bbox->midpoint() + Geom::Point (transform_center_x, transform_center_y);
+ // transform_center_x/y are stored in user units, so we have to take the viewbox into account to translate to document coordinates
+ return bbox->midpoint() + Geom::Point (transform_center_x*viewscale, transform_center_y*viewscale);
+
} else {
return Geom::Point(0, 0); // something's wrong!
}
+
}
+void
+SPItem::scaleCenter(Geom::Scale const &sc) {
+ transform_center_x *= sc[Geom::X];
+ transform_center_y *= sc[Geom::Y];
+}
namespace {
bool is_item(SPObject const &object) {
- return SP_IS_ITEM(&object);
+ return dynamic_cast<SPItem const *>(&object) != NULL;
}
}
@@ -338,12 +374,7 @@ void SPItem::lowerToBottom() {
}
}
-/*
- * Move this SPItem into or after another SPItem in the doc
- * \param target - the SPItem to move into or after
- * \param intoafter - move to after the target (false), move inside (sublayer) of the target (true)
- */
-void SPItem::moveTo(SPItem *target, gboolean intoafter) {
+void SPItem::moveTo(SPItem *target, bool intoafter) {
Inkscape::XML::Node *target_ref = ( target ? target->getRepr() : NULL );
Inkscape::XML::Node *our_ref = getRepr();
@@ -396,6 +427,7 @@ void SPItem::build(SPDocument *document, Inkscape::XML::Node *repr) {
object->readAttr( "inkscape:transform-center-y" );
object->readAttr( "inkscape:connector-avoid" );
object->readAttr( "inkscape:connection-points" );
+ object->readAttr( "inkscape:highlight-color" );
SPObject::build(document, repr);
}
@@ -416,7 +448,15 @@ void SPItem::release() {
SPObject::release();
+ SPPaintServer *fill_ps = style->getFillPaintServer();
+ SPPaintServer *stroke_ps = style->getStrokePaintServer();
while (item->display) {
+ if (fill_ps) {
+ fill_ps->hide(item->display->arenaitem->key());
+ }
+ if (stroke_ps) {
+ stroke_ps->hide(item->display->arenaitem->key());
+ }
item->display = sp_item_view_list_remove(item->display, item->display);
}
@@ -470,11 +510,23 @@ void SPItem::set(unsigned int key, gchar const* value) {
break;
}
case SP_ATTR_SODIPODI_INSENSITIVE:
+ {
item->sensitive = !value;
for (SPItemView *v = item->display; v != NULL; v = v->next) {
v->arenaitem->setSensitive(item->sensitive);
}
break;
+ }
+ case SP_ATTR_INKSCAPE_HIGHLIGHT_COLOR:
+ {
+ g_free(item->_highlightColor);
+ if (value) {
+ item->_highlightColor = g_strdup(value);
+ } else {
+ item->_highlightColor = NULL;
+ }
+ break;
+ }
case SP_ATTR_CONNECTOR_AVOID:
item->avoidRef->setAvoid(value);
break;
@@ -519,20 +571,23 @@ void SPItem::clip_ref_changed(SPObject *old_clip, SPObject *clip, SPItem *item)
SPItemView *v;
/* Hide clippath */
for (v = item->display; v != NULL; v = v->next) {
- SP_CLIPPATH(old_clip)->hide(v->arenaitem->key());
+ SPClipPath *oldPath = dynamic_cast<SPClipPath *>(old_clip);
+ g_assert(oldPath != NULL);
+ oldPath->hide(v->arenaitem->key());
}
}
- if (SP_IS_CLIPPATH(clip)) {
+ SPClipPath *clipPath = dynamic_cast<SPClipPath *>(clip);
+ if (clipPath) {
Geom::OptRect bbox = item->geometricBounds();
for (SPItemView *v = item->display; v != NULL; v = v->next) {
if (!v->arenaitem->key()) {
v->arenaitem->setKey(SPItem::display_key_new(3));
}
- Inkscape::DrawingItem *ai = SP_CLIPPATH(clip)->show(
+ Inkscape::DrawingItem *ai = clipPath->show(
v->arenaitem->drawing(),
v->arenaitem->key());
v->arenaitem->setClip(ai);
- SP_CLIPPATH(clip)->setBBox(v->arenaitem->key(), bbox);
+ clipPath->setBBox(v->arenaitem->key(), bbox);
clip->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
@@ -543,25 +598,78 @@ void SPItem::mask_ref_changed(SPObject *old_mask, SPObject *mask, SPItem *item)
if (old_mask) {
/* Hide mask */
for (SPItemView *v = item->display; v != NULL; v = v->next) {
- SP_MASK(old_mask)->sp_mask_hide(v->arenaitem->key());
+ SPMask *maskItem = dynamic_cast<SPMask *>(old_mask);
+ g_assert(maskItem != NULL);
+ maskItem->sp_mask_hide(v->arenaitem->key());
}
}
- if (SP_IS_MASK(mask)) {
+ SPMask *maskItem = dynamic_cast<SPMask *>(mask);
+ if (maskItem) {
Geom::OptRect bbox = item->geometricBounds();
for (SPItemView *v = item->display; v != NULL; v = v->next) {
if (!v->arenaitem->key()) {
v->arenaitem->setKey(SPItem::display_key_new(3));
}
- Inkscape::DrawingItem *ai = SP_MASK(mask)->sp_mask_show(
+ Inkscape::DrawingItem *ai = maskItem->sp_mask_show(
v->arenaitem->drawing(),
v->arenaitem->key());
v->arenaitem->setMask(ai);
- SP_MASK(mask)->sp_mask_set_bbox(v->arenaitem->key(), bbox);
+ maskItem->sp_mask_set_bbox(v->arenaitem->key(), bbox);
mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
}
+void SPItem::fill_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item) {
+ SPPaintServer *old_fill_ps = dynamic_cast<SPPaintServer *>(old_ps);
+ if (old_fill_ps) {
+ for (SPItemView *v =item->display; v != NULL; v = v->next) {
+ old_fill_ps->hide(v->arenaitem->key());
+ }
+ }
+
+ SPPaintServer *new_fill_ps = dynamic_cast<SPPaintServer *>(ps);
+ if (new_fill_ps) {
+ Geom::OptRect bbox = item->geometricBounds();
+ for (SPItemView *v = item->display; v != NULL; v = v->next) {
+ if (!v->arenaitem->key()) {
+ v->arenaitem->setKey(SPItem::display_key_new(3));
+ }
+ Inkscape::DrawingPattern *pi = new_fill_ps->show(
+ v->arenaitem->drawing(), v->arenaitem->key(), bbox);
+ v->arenaitem->setFillPattern(pi);
+ if (pi) {
+ new_fill_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
+ }
+}
+
+void SPItem::stroke_ps_ref_changed(SPObject *old_ps, SPObject *ps, SPItem *item) {
+ SPPaintServer *old_stroke_ps = dynamic_cast<SPPaintServer *>(old_ps);
+ if (old_stroke_ps) {
+ for (SPItemView *v =item->display; v != NULL; v = v->next) {
+ old_stroke_ps->hide(v->arenaitem->key());
+ }
+ }
+
+ SPPaintServer *new_stroke_ps = dynamic_cast<SPPaintServer *>(ps);
+ if (new_stroke_ps) {
+ Geom::OptRect bbox = item->geometricBounds();
+ for (SPItemView *v = item->display; v != NULL; v = v->next) {
+ if (!v->arenaitem->key()) {
+ v->arenaitem->setKey(SPItem::display_key_new(3));
+ }
+ Inkscape::DrawingPattern *pi = new_stroke_ps->show(
+ v->arenaitem->drawing(), v->arenaitem->key(), bbox);
+ v->arenaitem->setStrokePattern(pi);
+ if (pi) {
+ new_stroke_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
+ }
+}
+
void SPItem::update(SPCtx* /*ctx*/, guint flags) {
SPItem *item = this;
SPItem* object = item;
@@ -601,7 +709,7 @@ void SPItem::update(SPCtx* /*ctx*/, guint flags) {
v->arenaitem->setOpacity(SP_SCALE24_TO_FLOAT(object->style->opacity.value));
v->arenaitem->setAntialiasing(object->style->shape_rendering.computed != SP_CSS_SHAPE_RENDERING_CRISPEDGES);
v->arenaitem->setIsolation( object->style->isolation.value );
- v->arenaitem->setBlendMode( object->style->blend_mode.value );
+ v->arenaitem->setBlendMode( object->style->mix_blend_mode.value );
v->arenaitem->setVisible(!item->isHidden());
}
}
@@ -621,6 +729,10 @@ void SPItem::update(SPCtx* /*ctx*/, guint flags) {
item->avoidRef->handleSettingChange();
}
+void SPItem::modified(unsigned int /*flags*/)
+{
+}
+
Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
SPItem *item = this;
SPItem* object = item;
@@ -630,7 +742,7 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X
if (flags & SP_OBJECT_WRITE_BUILD) {
GSList *l = NULL;
for (SPObject *child = object->firstChild(); child != NULL; child = child->next ) {
- if (SP_IS_TITLE(child) || SP_IS_DESC(child)) {
+ if (dynamic_cast<SPTitle *>(child) || dynamic_cast<SPDesc *>(child)) {
Inkscape::XML::Node *crepr = child->updateRepr(xml_doc, NULL, flags);
if (crepr) {
l = g_slist_prepend (l, crepr);
@@ -644,7 +756,7 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X
}
} else {
for (SPObject *child = object->firstChild() ; child != NULL; child = child->next ) {
- if (SP_IS_TITLE(child) || SP_IS_DESC(child)) {
+ if (dynamic_cast<SPTitle *>(child) || dynamic_cast<SPDesc *>(child)) {
child->updateRepr(flags);
}
}
@@ -684,6 +796,11 @@ Inkscape::XML::Node* SPItem::write(Inkscape::XML::Document *xml_doc, Inkscape::X
g_free ((void *) uri);
}
}
+ if (item->_highlightColor){
+ repr->setAttribute("inkscape:highlight-color", item->_highlightColor);
+ } else {
+ repr->setAttribute("inkscape:highlight-color", NULL);
+ }
SPObject::write(xml_doc, repr, flags);
@@ -695,11 +812,7 @@ Geom::OptRect SPItem::bbox(Geom::Affine const & /*transform*/, SPItem::BBoxType
//throw;
return Geom::OptRect();
}
-/**
- * Get item's geometric bounding box in this item's coordinate system.
- *
- * The geometric bounding box includes only the path, disregarding all style attributes.
- */
+
Geom::OptRect SPItem::geometricBounds(Geom::Affine const &transform) const
{
Geom::OptRect bbox;
@@ -712,11 +825,6 @@ Geom::OptRect SPItem::geometricBounds(Geom::Affine const &transform) const
return bbox;
}
-/**
- * Get item's visual bounding box in this item's coordinate system.
- *
- * The visual bounding box includes the stroke and the filter region.
- */
Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const
{
using Geom::X;
@@ -724,13 +832,14 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const
Geom::OptRect bbox;
- if ( style && style->filter.href && style->getFilter() && SP_IS_FILTER(style->getFilter())) {
+
+ SPFilter *filter = (style && style->filter.href) ? dynamic_cast<SPFilter *>(style->getFilter()) : NULL;
+ if ( filter ) {
// call the subclass method
// CPPIFY
//bbox = this->bbox(Geom::identity(), SPItem::VISUAL_BBOX);
bbox = const_cast<SPItem*>(this)->bbox(Geom::identity(), SPItem::GEOMETRIC_BBOX); // see LP Bug 1229971
- SPFilter *filter = SP_FILTER(style->getFilter());
// default filer area per the SVG spec:
SVGLength x, y, w, h;
Geom::Point minp, maxp;
@@ -777,7 +886,10 @@ Geom::OptRect SPItem::visualBounds(Geom::Affine const &transform) const
bbox = const_cast<SPItem*>(this)->bbox(transform, SPItem::VISUAL_BBOX);
}
if (clip_ref->getObject()) {
- bbox.intersectWith(SP_CLIPPATH(clip_ref->getObject())->geometricBounds(transform));
+ SPItem *ownerItem = dynamic_cast<SPItem *>(clip_ref->getOwner());
+ g_assert(ownerItem != NULL);
+ ownerItem->bbox_valid = FALSE; // LP Bug 1349018
+ bbox.intersectWith(clip_ref->getObject()->geometricBounds(transform));
}
return bbox;
@@ -792,14 +904,11 @@ Geom::OptRect SPItem::bounds(BBoxType type, Geom::Affine const &transform) const
}
}
-/** Get item's geometric bbox in document coordinate system.
- * Document coordinates are the default coordinates of the root element:
- * the origin is at the top left, X grows to the right and Y grows downwards. */
Geom::OptRect SPItem::documentGeometricBounds() const
{
return geometricBounds(i2doc_affine());
}
-/// Get item's visual bbox in document coordinate system.
+
Geom::OptRect SPItem::documentVisualBounds() const
{
if (!bbox_valid) {
@@ -816,14 +925,12 @@ Geom::OptRect SPItem::documentBounds(BBoxType type) const
return documentVisualBounds();
}
}
-/** Get item's geometric bbox in desktop coordinate system.
- * Desktop coordinates should be user defined. Currently they are hardcoded:
- * origin is at bottom left, X grows to the right and Y grows upwards. */
+
Geom::OptRect SPItem::desktopGeometricBounds() const
{
return geometricBounds(i2dt_affine());
}
-/// Get item's visual bbox in desktop coordinate system.
+
Geom::OptRect SPItem::desktopVisualBounds() const
{
/// @fixme hardcoded desktop transform
@@ -862,7 +969,7 @@ unsigned int SPItem::pos_in_parent() const {
return pos;
}
- if (SP_IS_ITEM(iter)) {
+ if (dynamic_cast<SPItem *>(iter)) {
pos++;
}
}
@@ -904,10 +1011,11 @@ void SPItem::getSnappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscap
if (*o) {
// obj is a group object, the children are the actual clippers
for (SPObject *child = (*o)->children ; child ; child = child->next) {
- if (SP_IS_ITEM(child)) {
+ SPItem *item = dynamic_cast<SPItem *>(child);
+ if (item) {
std::vector<Inkscape::SnapCandidatePoint> p_clip_or_mask;
// Please note the recursive call here!
- SP_ITEM(child)->getSnappoints(p_clip_or_mask, snapprefs);
+ item->getSnappoints(p_clip_or_mask, snapprefs);
// Take into account the transformation of the item being clipped or masked
for (std::vector<Inkscape::SnapCandidatePoint>::const_iterator p_orig = p_clip_or_mask.begin(); p_orig != p_clip_or_mask.end(); ++p_orig) {
// All snappoints are in desktop coordinates, but the item's transformation is
@@ -947,11 +1055,6 @@ gchar* SPItem::description() const {
return g_strdup("");
}
-/**
- * Returns a string suitable for status bar, formatted in pango markup language.
- *
- * Must be freed by caller.
- */
gchar *SPItem::detailedDescription() const {
gchar* s = g_strdup_printf("<b>%s</b> %s",
this->displayName(), this->description());
@@ -985,20 +1088,10 @@ gchar *SPItem::detailedDescription() const {
return s;
}
-/**
- * Returns true if the item is filtered, false otherwise. Used with groups/lists to determine how many, or if any, are filtered
- *
- */
bool SPItem::isFiltered() const {
return (style && style->filter.href && style->filter.href->getObject());
}
-/**
- * Allocates unique integer keys.
- * \param numkeys Number of keys required.
- * \return First allocated key; hence if the returned key is n
- * you can use n, n + 1, ..., n + (numkeys - 1)
- */
unsigned SPItem::display_key_new(unsigned numkeys)
{
static unsigned dkey = 0;
@@ -1027,7 +1120,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned
ai->setTransform(transform);
ai->setOpacity(SP_SCALE24_TO_FLOAT(style->opacity.value));
ai->setIsolation( style->isolation.value );
- ai->setBlendMode( style->blend_mode.value );
+ ai->setBlendMode( style->mix_blend_mode.value );
//ai->setCompositeOperator( style->composite_op.value );
ai->setVisible(!isHidden());
ai->setSensitive(sensitive);
@@ -1044,7 +1137,7 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned
ai->setClip(ac);
// Update bbox, in case the clip uses bbox units
- SP_CLIPPATH(cp)->setBBox(clip_key, item_bbox);
+ cp->setBBox(clip_key, item_bbox);
cp->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
if (mask_ref->getObject()) {
@@ -1060,9 +1153,36 @@ Inkscape::DrawingItem *SPItem::invoke_show(Inkscape::Drawing &drawing, unsigned
ai->setMask(ac);
// Update bbox, in case the mask uses bbox units
- SP_MASK(mask)->sp_mask_set_bbox(mask_key, item_bbox);
+ mask->sp_mask_set_bbox(mask_key, item_bbox);
mask->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
+
+ SPPaintServer *fill_ps = style->getFillPaintServer();
+ if (fill_ps) {
+ if (!display->arenaitem->key()) {
+ display->arenaitem->setKey(display_key_new(3));
+ }
+ int fill_key = display->arenaitem->key();
+
+ Inkscape::DrawingPattern *ap = fill_ps->show(drawing, fill_key, item_bbox);
+ ai->setFillPattern(ap);
+ if (ap) {
+ fill_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
+ SPPaintServer *stroke_ps = style->getStrokePaintServer();
+ if (stroke_ps) {
+ if (!display->arenaitem->key()) {
+ display->arenaitem->setKey(display_key_new(3));
+ }
+ int stroke_key = display->arenaitem->key();
+
+ Inkscape::DrawingPattern *ap = stroke_ps->show(drawing, stroke_key, item_bbox);
+ ai->setStrokePattern(ap);
+ if (ap) {
+ stroke_ps->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+ }
ai->setData(this);
ai->setItemBounds(geometricBounds());
}
@@ -1092,6 +1212,14 @@ void SPItem::invoke_hide(unsigned key)
mask_ref->getObject()->sp_mask_hide(v->arenaitem->key());
v->arenaitem->setMask(NULL);
}
+ SPPaintServer *fill_ps = style->getFillPaintServer();
+ if (fill_ps) {
+ fill_ps->hide(v->arenaitem->key());
+ }
+ SPPaintServer *stroke_ps = style->getStrokePaintServer();
+ if (stroke_ps) {
+ stroke_ps->hide(v->arenaitem->key());
+ }
if (!ref) {
display = v->next;
} else {
@@ -1108,20 +1236,24 @@ void SPItem::invoke_hide(unsigned key)
// Adjusters
-void SPItem::adjust_pattern (Geom::Affine const &postmul, bool set)
+void SPItem::adjust_pattern(Geom::Affine const &postmul, bool set, PatternTransform pt)
{
- if (style && (style->fill.isPaintserver())) {
+ bool fill = (pt == TRANSFORM_FILL || pt == TRANSFORM_BOTH);
+ if (fill && style && (style->fill.isPaintserver())) {
SPObject *server = style->getFillPaintServer();
- if ( SP_IS_PATTERN(server) ) {
- SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "fill");
+ SPPattern *serverPatt = dynamic_cast<SPPattern *>(server);
+ if ( serverPatt ) {
+ SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "fill");
sp_pattern_transform_multiply(pattern, postmul, set);
}
}
- if (style && (style->stroke.isPaintserver())) {
+ bool stroke = (pt == TRANSFORM_STROKE || pt == TRANSFORM_BOTH);
+ if (stroke && style && (style->stroke.isPaintserver())) {
SPObject *server = style->getStrokePaintServer();
- if ( SP_IS_PATTERN(server) ) {
- SPPattern *pattern = sp_pattern_clone_if_necessary(this, SP_PATTERN(server), "stroke");
+ SPPattern *serverPatt = dynamic_cast<SPPattern *>(server);
+ if ( serverPatt ) {
+ SPPattern *pattern = sp_pattern_clone_if_necessary(this, serverPatt, "stroke");
sp_pattern_transform_multiply(pattern, postmul, set);
}
}
@@ -1131,7 +1263,8 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
{
if ( style && style->fill.isPaintserver() ) {
SPPaintServer *server = style->getFillPaintServer();
- if ( SP_IS_GRADIENT(server) ) {
+ SPGradient *serverGrad = dynamic_cast<SPGradient *>(server);
+ if ( serverGrad ) {
/**
* \note Bbox units for a gradient are generally a bad idea because
@@ -1142,7 +1275,7 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
* \todo FIXME: convert back to bbox units after transforming with
* the item, so as to preserve the original units.
*/
- SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), this, "fill" );
+ SPGradient *gradient = sp_gradient_convert_to_userspace( serverGrad, this, "fill" );
sp_gradient_transform_multiply( gradient, postmul, set );
}
@@ -1150,8 +1283,9 @@ void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set )
if ( style && style->stroke.isPaintserver() ) {
SPPaintServer *server = style->getStrokePaintServer();
- if ( SP_IS_GRADIENT(server) ) {
- SPGradient *gradient = sp_gradient_convert_to_userspace( SP_GRADIENT(server), this, "stroke");
+ SPGradient *serverGrad = dynamic_cast<SPGradient *>(server);
+ if ( serverGrad ) {
+ SPGradient *gradient = sp_gradient_convert_to_userspace( serverGrad, this, "stroke");
sp_gradient_transform_multiply( gradient, postmul, set );
}
}
@@ -1198,18 +1332,16 @@ static Geom::Affine sp_item_transform_repr (SPItem *item)
}
-/**
- * Recursively scale stroke width in \a item and its children by \a expansion.
- */
void SPItem::adjust_stroke_width_recursive(double expansion)
{
adjust_stroke (expansion);
// A clone's child is the ghost of its original - we must not touch it, skip recursion
- if ( !SP_IS_USE(this) ) {
+ if ( !dynamic_cast<SPUse *>(this) ) {
for ( SPObject *o = children; o; o = o->getNext() ) {
- if (SP_IS_ITEM(o)) {
- SP_ITEM(o)->adjust_stroke_width_recursive(expansion);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ item->adjust_stroke_width_recursive(expansion);
}
}
}
@@ -1220,10 +1352,11 @@ void SPItem::freeze_stroke_width_recursive(bool freeze)
freeze_stroke_width = freeze;
// A clone's child is the ghost of its original - we must not touch it, skip recursion
- if ( !SP_IS_USE(this) ) {
+ if ( !dynamic_cast<SPUse *>(this) ) {
for ( SPObject *o = children; o; o = o->getNext() ) {
- if (SP_IS_ITEM(o)) {
- SP_ITEM(o)->freeze_stroke_width_recursive(freeze);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ item->freeze_stroke_width_recursive(freeze);
}
}
}
@@ -1235,19 +1368,19 @@ void SPItem::freeze_stroke_width_recursive(bool freeze)
static void
sp_item_adjust_rects_recursive(SPItem *item, Geom::Affine advertized_transform)
{
- if (SP_IS_RECT (item)) {
- SP_RECT(item)->compensateRxRy(advertized_transform);
+ SPRect *rect = dynamic_cast<SPRect *>(item);
+ if (rect) {
+ rect->compensateRxRy(advertized_transform);
}
for (SPObject *o = item->children; o != NULL; o = o->next) {
- if (SP_IS_ITEM(o))
- sp_item_adjust_rects_recursive(SP_ITEM(o), advertized_transform);
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
+ sp_item_adjust_rects_recursive(item, advertized_transform);
+ }
}
}
-/**
- * Recursively compensate pattern or gradient transform.
- */
void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern)
{
// _Before_ full pattern/gradient transform: t_paint * t_item * t_ancestors
@@ -1259,12 +1392,13 @@ void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Af
// Within text, we do not fork gradients, and so must not recurse to avoid double compensation;
// also we do not recurse into clones, because a clone's child is the ghost of its original -
// we must not touch it
- if (!(this && (SP_IS_TEXT(this) || SP_IS_USE(this)))) {
+ if (!(this && (dynamic_cast<SPText *>(this) || dynamic_cast<SPUse *>(this)))) {
for (SPObject *o = children; o != NULL; o = o->next) {
- if (SP_IS_ITEM(o)) {
+ SPItem *item = dynamic_cast<SPItem *>(o);
+ if (item) {
// At the level of the transformed item, t_ancestors is identity;
// below it, it is the accmmulated chain of transforms from this level to the top level
- SP_ITEM(o)->adjust_paint_recursive (advertized_transform, t_item * t_ancestors, is_pattern);
+ item->adjust_paint_recursive (advertized_transform, t_item * t_ancestors, is_pattern);
}
}
}
@@ -1283,20 +1417,18 @@ void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Af
void SPItem::adjust_livepatheffect (Geom::Affine const &postmul, bool set)
{
- if ( SP_IS_LPE_ITEM(this) ) {
- SPLPEItem *lpeitem = SP_LPE_ITEM (this);
- if ( lpeitem->hasPathEffect() ) {
- lpeitem->forkPathEffectsIfNecessary();
-
- // now that all LPEs are forked_if_necessary, we can apply the transform
- PathEffectList effect_list = lpeitem->getEffectList();
- for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); ++it)
- {
- LivePathEffectObject *lpeobj = (*it)->lpeobject;
- if (lpeobj && lpeobj->get_lpe()) {
- Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe();
- effect->transform_multiply(postmul, set);
- }
+ SPLPEItem *lpeitem = dynamic_cast<SPLPEItem *>(this);
+ if ( lpeitem && lpeitem->hasPathEffect() ) {
+ lpeitem->forkPathEffectsIfNecessary();
+
+ // now that all LPEs are forked_if_necessary, we can apply the transform
+ PathEffectList effect_list = lpeitem->getEffectList();
+ for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); ++it)
+ {
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+ if (lpeobj && lpeobj->get_lpe()) {
+ Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe();
+ effect->transform_multiply(postmul, set);
}
}
}
@@ -1309,14 +1441,6 @@ Geom::Affine SPItem::set_transform(Geom::Affine const &transform) {
return transform;
}
-/**
- * Set a new transform on an object.
- *
- * Compensate for stroke scaling and gradient/pattern fill transform, if
- * necessary. Call the object's set_transform method if transforms are
- * stored optimized. Send _transformed_signal. Invoke _write method so that
- * the repr is updated with the new transform.
- */
void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv, bool compensate)
{
g_return_if_fail(repr != NULL);
@@ -1379,10 +1503,11 @@ void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &tra
// onSetTransform cannot be pure due to the fact that not all visible Items are transformable.
if ( // run the object's set_transform (i.e. embed transform) only if:
- !preserve && // user did not chose to preserve all transforms
+ (dynamic_cast<SPText *>(this) && firstChild() && dynamic_cast<SPTextPath *>(firstChild())) ||
+ (!preserve && // user did not chose to preserve all transforms
(!clip_ref || !clip_ref->getObject()) && // the object does not have a clippath
(!mask_ref || !mask_ref->getObject()) && // the object does not have a mask
- !(!transform.isTranslation() && style && style->getFilter()) // the object does not have a filter, or the transform is translation (which is supposed to not affect filters)
+ !(!transform.isTranslation() && style && style->getFilter())) // the object does not have a filter, or the transform is translation (which is supposed to not affect filters)
)
{
transform_attr = this->set_transform(transform);
@@ -1427,10 +1552,6 @@ gint SPItem::emitEvent(SPEvent &event)
return this->event(&event);
}
-/**
- * Sets item private transform (not propagated to repr), without compensating stroke widths,
- * gradients, patterns as sp_item_write_transform does.
- */
void SPItem::set_item_transform(Geom::Affine const &transform_matrix)
{
if (!Geom::are_near(transform_matrix, transform, 1e-18)) {
@@ -1448,21 +1569,19 @@ void SPItem::set_item_transform(Geom::Affine const &transform_matrix)
//}
-/**
- * \pre \a ancestor really is an ancestor (\>=) of \a object, or NULL.
- * ("Ancestor (\>=)" here includes as far as \a object itself.)
- */
-Geom::Affine
-i2anc_affine(SPObject const *object, SPObject const *const ancestor) {
+Geom::Affine i2anc_affine(SPObject const *object, SPObject const *const ancestor) {
Geom::Affine ret(Geom::identity());
g_return_val_if_fail(object != NULL, ret);
/* stop at first non-renderable ancestor */
- while ( object != ancestor && SP_IS_ITEM(object) ) {
- if (SP_IS_ROOT(object)) {
- ret *= SP_ROOT(object)->c2p;
+ while ( object != ancestor && dynamic_cast<SPItem const *>(object) ) {
+ SPRoot const *root = dynamic_cast<SPRoot const *>(object);
+ if (root) {
+ ret *= root->c2p;
} else {
- ret *= SP_ITEM(object)->transform;
+ SPItem const *item = dynamic_cast<SPItem const *>(object);
+ g_assert(item != NULL);
+ ret *= item->transform;
}
object = object->parent;
}
@@ -1480,18 +1599,11 @@ Geom::Affine SPItem::getRelativeTransform(SPObject const *dest) const {
return i2i_affine(this, dest);
}
-/**
- * Returns the accumulated transformation of the item and all its ancestors, including root's viewport.
- * \pre (item != NULL) and SP_IS_ITEM(item).
- */
Geom::Affine SPItem::i2doc_affine() const
{
return i2anc_affine(this, NULL);
}
-/**
- * Returns the transformation from item to desktop coords
- */
Geom::Affine SPItem::i2dt_affine() const
{
Geom::Affine ret;
@@ -1522,9 +1634,6 @@ void SPItem::set_i2d_affine(Geom::Affine const &i2dt)
}
-/**
- * should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa)
- */
Geom::Affine SPItem::dt2i_affine() const
{
/* fixme: Implement the right way (Lauris) */
@@ -1536,7 +1645,7 @@ Geom::Affine SPItem::dt2i_affine() const
SPItemView *SPItem::sp_item_view_new_prepend(SPItemView *list, SPItem *item, unsigned flags, unsigned key, Inkscape::DrawingItem *drawing_item)
{
g_assert(item != NULL);
- g_assert(SP_IS_ITEM(item));
+ g_assert(dynamic_cast<SPItem *>(item) != NULL);
g_assert(drawing_item != NULL);
SPItemView *new_view = g_new(SPItemView, 1);
@@ -1568,10 +1677,6 @@ sp_item_view_list_remove(SPItemView *list, SPItemView *view)
return ret;
}
-/**
- * Return the arenaitem corresponding to the given item in the display
- * with the given key
- */
Inkscape::DrawingItem *SPItem::get_arenaitem(unsigned key)
{
for ( SPItemView *iv = display ; iv ; iv = iv->next ) {
@@ -1598,8 +1703,9 @@ SPItem *sp_item_first_item_child(SPObject *obj)
{
SPItem *child = 0;
for ( SPObject *iter = obj->firstChild() ; iter ; iter = iter->next ) {
- if ( SP_IS_ITEM(iter) ) {
- child = SP_ITEM(iter);
+ SPItem *tmp = dynamic_cast<SPItem *>(iter);
+ if ( tmp ) {
+ child = tmp;
break;
}
}