Ejemplo n.º 1
0
void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style)
{
    g_return_if_fail(group != NULL);
    g_return_if_fail(NR_IS_ARENA_GROUP(group));

    if (style) sp_style_ref(style);
    if (group->style) sp_style_unref(group->style);
    group->style = style;

    //if group has a filter
    if (style->filter.set && style->getFilter()) {
        if (!group->filter) {
            int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
            group->filter = new Inkscape::Filters::Filter(primitives);
        }
        sp_filter_build_renderer(SP_FILTER(style->getFilter()), group->filter);
    } else {
        //no filter set for this group
        delete group->filter;
        group->filter = NULL;
    }

    if (style && style->enable_background.set
        && style->enable_background.value == SP_CSS_BACKGROUND_NEW) {
        group->background_new = true;
    }
}
Ejemplo n.º 2
0
int sp_filter_primitive_read_in(SPFilterPrimitive *prim, gchar const *name)
{
    if (!name) return Inkscape::Filters::NR_FILTER_SLOT_NOT_SET;
    // TODO: are these case sensitive or not? (assumed yes)
    switch (name[0]) {
        case 'S':
            if (strcmp(name, "SourceGraphic") == 0)
                return Inkscape::Filters::NR_FILTER_SOURCEGRAPHIC;
            if (strcmp(name, "SourceAlpha") == 0)
                return Inkscape::Filters::NR_FILTER_SOURCEALPHA;
            if (strcmp(name, "StrokePaint") == 0)
                return Inkscape::Filters::NR_FILTER_STROKEPAINT;
            break;
        case 'B':
            if (strcmp(name, "BackgroundImage") == 0)
                return Inkscape::Filters::NR_FILTER_BACKGROUNDIMAGE;
            if (strcmp(name, "BackgroundAlpha") == 0)
                return Inkscape::Filters::NR_FILTER_BACKGROUNDALPHA;
            break;
        case 'F':
            if (strcmp(name, "FillPaint") == 0)
                return Inkscape::Filters::NR_FILTER_FILLPAINT;
            break;
    }

    SPFilter *parent = SP_FILTER(prim->parent);
    int ret = sp_filter_get_image_name(parent, name);
    if (ret >= 0) return ret;

    return Inkscape::Filters::NR_FILTER_SLOT_NOT_SET;
}
Ejemplo n.º 3
0
/**
 * Receives update notifications.
 */
void SPFilterPrimitive::update(SPCtx *ctx, guint flags) {

    SPItemCtx *ictx = (SPItemCtx *) ctx;

    // Do here since we know viewport (Bounding box case handled during rendering)
    SPFilter *parent = SP_FILTER(this->parent);

    if( parent->primitiveUnits == SP_FILTER_UNITS_USERSPACEONUSE ) {
        if (this->x.unit == SVGLength::PERCENT) {
            this->x._set = true;
            this->x.computed = this->x.value * ictx->viewport.width();
        }

        if (this->y.unit == SVGLength::PERCENT) {
            this->y._set = true;
            this->y.computed = this->y.value * ictx->viewport.height();
        }

        if (this->width.unit == SVGLength::PERCENT) {
            this->width._set = true;
            this->width.computed = this->width.value * ictx->viewport.width();
        }

        if (this->height.unit == SVGLength::PERCENT) {
            this->height._set = true;
            this->height.computed = this->height.value * ictx->viewport.height();
        }
    }

    SPObject::update(ctx, flags);
}
Ejemplo n.º 4
0
/**
 * Receives update notifications.
 */
static void
sp_feComposite_update(SPObject *object, SPCtx *ctx, guint flags)
{
    SPFeComposite *comp = SP_FECOMPOSITE(object);

    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
                 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {

        /* do something to trigger redisplay, updates? */

    }

    /* Unlike normal in, in2 is required attribute. Make sure, we can call
     * it by some name. */
    if (comp->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
        comp->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
    {
        SPFilter *parent = SP_FILTER(object->parent);
        comp->in2 = sp_filter_primitive_name_previous_out(comp);
        object->repr->setAttribute("in2", sp_filter_name_for_image(parent, comp->in2));
    }

    if (((SPObjectClass *) feComposite_parent_class)->update) {
        ((SPObjectClass *) feComposite_parent_class)->update(object, ctx, flags);
    }
}
Ejemplo n.º 5
0
/**
 * Reads the Inkscape::XML::Node, and initializes SPFeComposite variables.  For this to get called,
 * our name must be associated with a repr via "sp_object_type_register".  Best done through
 * sp-object-repr.cpp's repr_name_entries array.
 */
static void
sp_feComposite_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
{
    if (((SPObjectClass *) feComposite_parent_class)->build) {
        ((SPObjectClass *) feComposite_parent_class)->build(object, document, repr);
    }

    SPFeComposite *comp = SP_FECOMPOSITE(object);

    sp_object_read_attr(object, "operator");
    if (comp->composite_operator == COMPOSITE_ARITHMETIC) {
        sp_object_read_attr(object, "k1");
        sp_object_read_attr(object, "k2");
        sp_object_read_attr(object, "k3");
        sp_object_read_attr(object, "k4");
    }
    sp_object_read_attr(object, "in2");

    /* Unlike normal in, in2 is required attribute. Make sure, we can call
     * it by some name. */
    if (comp->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
        comp->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
    {
        SPFilter *parent = SP_FILTER(object->parent);
        comp->in2 = sp_filter_primitive_name_previous_out(comp);
        repr->setAttribute("in2", sp_filter_name_for_image(parent, comp->in2));
    }
}
Ejemplo n.º 6
0
/**
 * Process information related to the new style.
 *
 * Note: _style is not used by DrawingGlyphs which uses its parent style.
 */
void
DrawingItem::setStyle(SPStyle *style, SPStyle *context_style)
{
    // std::cout << "DrawingItem::setStyle: " << name() << " " << style
    //           << " " << context_style << std::endl;

    if( style != _style ) {
        if (style) sp_style_ref(style);
        if (_style) sp_style_unref(_style);
        _style = style;
    }
    
    if (style && style->filter.set && style->getFilter()) {
        if (!_filter) {
            int primitives = sp_filter_primitive_count(SP_FILTER(style->getFilter()));
            _filter = new Inkscape::Filters::Filter(primitives);
        }
        sp_filter_build_renderer(SP_FILTER(style->getFilter()), _filter);
    } else {
        // no filter set for this group
        delete _filter;
        _filter = NULL;
    }

    if (style && style->enable_background.set) {
        if (style->enable_background.value == SP_CSS_BACKGROUND_NEW && !_background_new) {
            _background_new = true;
            _markForUpdate(STATE_BACKGROUND, true);
        } else if (style->enable_background.value == SP_CSS_BACKGROUND_ACCUMULATE && _background_new) {
            _background_new = false;
            _markForUpdate(STATE_BACKGROUND, true);
        }
    }

    if (context_style != NULL) {
        _context_style = context_style;
    } else if (_parent != NULL) {
        _context_style = _parent->_context_style;
    }

    _markForUpdate(STATE_ALL, false);
}
Ejemplo n.º 7
0
int sp_filter_primitive_read_result(SPFilterPrimitive *prim, gchar const *name)
{
    SPFilter *parent = SP_FILTER(prim->parent);
    int ret = sp_filter_get_image_name(parent, name);
    if (ret >= 0) return ret;

    ret = sp_filter_set_image_name(parent, name);
    if (ret >= 0) return ret;

    return Inkscape::Filters::NR_FILTER_SLOT_NOT_SET;
}
Ejemplo n.º 8
0
/**
 * Writes its settings to an incoming repr object, if any.
 */
static Inkscape::XML::Node *
sp_feBlend_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags)
{
    SPFeBlend *blend = SP_FEBLEND(object);
    SPFilter *parent = SP_FILTER(object->parent);

    if (!repr) {
        repr = doc->createElement("svg:feBlend");
    }

    gchar const *out_name = sp_filter_name_for_image(parent, blend->in2);
    if (out_name) {
        repr->setAttribute("in2", out_name);
    } else {
        SPObject *i = parent->children;
        while (i && i->next != object) i = i->next;
        SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
        out_name = sp_filter_name_for_image(parent, i_prim->image_out);
        repr->setAttribute("in2", out_name);
        if (!out_name) {
            g_warning("Unable to set in2 for feBlend");
        }
    }

    char const *mode;
    switch(blend->blend_mode) {
        case Inkscape::Filters::BLEND_NORMAL:
            mode = "normal"; break;
        case Inkscape::Filters::BLEND_MULTIPLY:
            mode = "multiply"; break;
        case Inkscape::Filters::BLEND_SCREEN:
            mode = "screen"; break;
        case Inkscape::Filters::BLEND_DARKEN:
            mode = "darken"; break;
        case Inkscape::Filters::BLEND_LIGHTEN:
            mode = "lighten"; break;
        default:
            mode = 0;
    }
    repr->setAttribute("mode", mode);

    if (((SPObjectClass *) feBlend_parent_class)->write) {
        ((SPObjectClass *) feBlend_parent_class)->write(object, doc, repr, flags);
    }

    return repr;
}
Ejemplo n.º 9
0
/**
 * Reads the Inkscape::XML::Node, and initializes SPFeBlend variables.  For this to get called,
 * our name must be associated with a repr via "sp_object_type_register".  Best done through
 * sp-object-repr.cpp's repr_name_entries array.
 */
void SPFeBlend::build(SPDocument *document, Inkscape::XML::Node *repr) {
    SPFilterPrimitive::build(document, repr);

    /*LOAD ATTRIBUTES FROM REPR HERE*/
    this->readAttr( "mode" );
    this->readAttr( "in2" );

    /* Unlike normal in, in2 is required attribute. Make sure, we can call
     * it by some name. */
    if (this->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
        this->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
    {
        SPFilter *parent = SP_FILTER(this->parent);
        this->in2 = sp_filter_primitive_name_previous_out(this);
        repr->setAttribute("in2", sp_filter_name_for_image(parent, this->in2));
    }
}
Ejemplo n.º 10
0
/**
 * Gives name for output of previous filter. Makes things clearer when prim
 * is a filter with two or more inputs. Returns the slot number of result
 * of previous primitive, or NR_FILTER_SOURCEGRAPHIC if this is the first
 * primitive.
 */
int sp_filter_primitive_name_previous_out(SPFilterPrimitive *prim) {
    SPFilter *parent = SP_FILTER(prim->parent);
    SPObject *i = parent->children;
    while (i && i->next != prim) i = i->next;
    if (i) {
        SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
        if (i_prim->image_out < 0) {
            Glib::ustring name = sp_filter_get_new_result_name(parent);
            int slot = sp_filter_set_image_name(parent, name.c_str());
            i_prim->image_out = slot;
            //XML Tree is being directly used while it shouldn't be.
            i_prim->getRepr()->setAttribute("result", name.c_str());
            return slot;
        } else {
            return i_prim->image_out;
        }
    }
    return Inkscape::Filters::NR_FILTER_SOURCEGRAPHIC;
}
Ejemplo n.º 11
0
/**
 * Receives update notifications.
 */
void SPFeBlend::update(SPCtx *ctx, guint flags) {
    if (flags & SP_OBJECT_MODIFIED_FLAG) {
        this->readAttr( "mode" );
        this->readAttr( "in2" );
    }

    /* Unlike normal in, in2 is required attribute. Make sure, we can call
     * it by some name. */
    if (this->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
        this->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
    {
        SPFilter *parent = SP_FILTER(this->parent);
        this->in2 = sp_filter_primitive_name_previous_out(this);

        // TODO: XML Tree being used directly here while it shouldn't be.
        this->getRepr()->setAttribute("in2", sp_filter_name_for_image(parent, this->in2));
    }

    SPFilterPrimitive::update(ctx, flags);
}
Ejemplo n.º 12
0
/**
 * Writes its settings to an incoming repr object, if any.
 */
Inkscape::XML::Node* SPFeDisplacementMap::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) {
    SPFilter *parent = SP_FILTER(this->parent);

    if (!repr) {
        repr = doc->createElement("svg:feDisplacementMap");
    }

    gchar const *in2_name = sp_filter_name_for_image(parent, this->in2);

    if( !in2_name ) {

        // This code is very similar to sp_filter_primtive_name_previous_out()
        SPObject *i = parent->children;

        // Find previous filter primitive
        while (i && i->next != this) {
        	i = i->next;
        }

        if( i ) {
            SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
            in2_name = sp_filter_name_for_image(parent, i_prim->image_out);
        }
    }

    if (in2_name) {
        repr->setAttribute("in2", in2_name);
    } else {
        g_warning("Unable to set in2 for feDisplacementMap");
    }

    sp_repr_set_svg_double(repr, "scale", this->scale);
    repr->setAttribute("xChannelSelector",
                       get_channelselector_name(this->xChannelSelector));
    repr->setAttribute("yChannelSelector",
                       get_channelselector_name(this->yChannelSelector));

    SPFilterPrimitive::write(doc, repr, flags);

    return repr;
}
Ejemplo n.º 13
0
/**
 * Writes its settings to an incoming repr object, if any.
 */
Inkscape::XML::Node* SPFilterPrimitive::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) {
    SPFilterPrimitive* object = this;

    SPFilterPrimitive *prim = SP_FILTER_PRIMITIVE(object);
    SPFilter *parent = SP_FILTER(object->parent);

    if (!repr) {
        repr = object->getRepr()->duplicate(doc);
    }

    gchar const *in_name = sp_filter_name_for_image(parent, prim->image_in);
    repr->setAttribute("in", in_name);

    gchar const *out_name = sp_filter_name_for_image(parent, prim->image_out);
    repr->setAttribute("result", out_name);

    /* Do we need to add x,y,width,height? */
    SPObject::write(doc, repr, flags);

    return repr;
}
Ejemplo n.º 14
0
/**
 * Receives update notifications.
 */
void SPFeDisplacementMap::update(SPCtx *ctx, guint flags) {
    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG |
                 SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {

        /* do something to trigger redisplay, updates? */

    }

    /* Unlike normal in, in2 is required attribute. Make sure, we can call
     * it by some name. */
    if (this->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
        this->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
    {
        SPFilter *parent = SP_FILTER(this->parent);
        this->in2 = sp_filter_primitive_name_previous_out(this);

        //XML Tree being used directly here while it shouldn't be.
        this->getRepr()->setAttribute("in2", sp_filter_name_for_image(parent, this->in2));
    }

    SPFilterPrimitive::update(ctx, flags);
}
Ejemplo n.º 15
0
/**
 * Reads the Inkscape::XML::Node, and initializes SPFeBlend variables.  For this to get called,
 * our name must be associated with a repr via "sp_object_type_register".  Best done through
 * sp-object-repr.cpp's repr_name_entries array.
 */
static void
sp_feBlend_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
{
    SPFeBlend *blend = SP_FEBLEND(object);

    if (((SPObjectClass *) feBlend_parent_class)->build) {
        ((SPObjectClass *) feBlend_parent_class)->build(object, document, repr);
    }

    /*LOAD ATTRIBUTES FROM REPR HERE*/
    sp_object_read_attr(object, "mode");
    sp_object_read_attr(object, "in2");

    /* Unlike normal in, in2 is required attribute. Make sure, we can call
     * it by some name. */
    if (blend->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
        blend->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
    {
        SPFilter *parent = SP_FILTER(object->parent);
        blend->in2 = sp_filter_primitive_name_previous_out(blend);
        repr->setAttribute("in2", sp_filter_name_for_image(parent, blend->in2));
    }
}
Ejemplo n.º 16
0
/**
 * Receives update notifications.
 */
static void
sp_feBlend_update(SPObject *object, SPCtx *ctx, guint flags)
{
    SPFeBlend *blend = SP_FEBLEND(object);

    if (flags & SP_OBJECT_MODIFIED_FLAG) {
        sp_object_read_attr(object, "mode");
        sp_object_read_attr(object, "in2");
    }

    /* Unlike normal in, in2 is required attribute. Make sure, we can call
     * it by some name. */
    if (blend->in2 == Inkscape::Filters::NR_FILTER_SLOT_NOT_SET ||
        blend->in2 == Inkscape::Filters::NR_FILTER_UNNAMED_SLOT)
    {
        SPFilter *parent = SP_FILTER(object->parent);
        blend->in2 = sp_filter_primitive_name_previous_out(blend);
        object->repr->setAttribute("in2", sp_filter_name_for_image(parent, blend->in2));
    }

    if (((SPObjectClass *) feBlend_parent_class)->update) {
        ((SPObjectClass *) feBlend_parent_class)->update(object, ctx, flags);
    }
}
Ejemplo n.º 17
0
/**
 * Writes its settings to an incoming repr object, if any.
 */
static Inkscape::XML::Node *
sp_feComposite_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags)
{
    SPFeComposite *comp = SP_FECOMPOSITE(object);
    SPFilter *parent = SP_FILTER(object->parent);

    if (!repr) {
        repr = doc->createElement("svg:feComposite");
    }

    gchar const *out_name = sp_filter_name_for_image(parent, comp->in2);
    if (out_name) {
        repr->setAttribute("in2", out_name);
    } else {
        SPObject *i = parent->children;
        while (i && i->next != object) i = i->next;
        SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
        out_name = sp_filter_name_for_image(parent, i_prim->image_out);
        repr->setAttribute("in2", out_name);
        if (!out_name) {
            g_warning("Unable to set in2 for feComposite");
        }
    }

    char const *comp_op;
    switch (comp->composite_operator) {
        case COMPOSITE_OVER:
            comp_op = "over"; break;
        case COMPOSITE_IN:
            comp_op = "in"; break;
        case COMPOSITE_OUT:
            comp_op = "out"; break;
        case COMPOSITE_ATOP:
            comp_op = "atop"; break;
        case COMPOSITE_XOR:
            comp_op = "xor"; break;
        case COMPOSITE_ARITHMETIC:
            comp_op = "arithmetic"; break;
        default:
            comp_op = 0;
    }
    repr->setAttribute("operator", comp_op);

    if (comp->composite_operator == COMPOSITE_ARITHMETIC) {
        sp_repr_set_svg_double(repr, "k1", comp->k1);
        sp_repr_set_svg_double(repr, "k2", comp->k2);
        sp_repr_set_svg_double(repr, "k3", comp->k3);
        sp_repr_set_svg_double(repr, "k4", comp->k4);
    } else {
        repr->setAttribute("k1", 0);
        repr->setAttribute("k2", 0);
        repr->setAttribute("k3", 0);
        repr->setAttribute("k4", 0);
    }

    if (((SPObjectClass *) feComposite_parent_class)->write) {
        ((SPObjectClass *) feComposite_parent_class)->write(object, doc, repr, flags);
    }

    return repr;
}
Ejemplo n.º 18
0
/**
 * Writes its settings to an incoming repr object, if any.
 */
Inkscape::XML::Node* SPFeBlend::write(Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) {
    SPFilter *parent = SP_FILTER(this->parent);

    if (!repr) {
        repr = doc->createElement("svg:feBlend");
    }

    gchar const *out_name = sp_filter_name_for_image(parent, this->in2);

    if (out_name) {
        repr->setAttribute("in2", out_name);
    } else {
        SPObject *i = parent->children;

        while (i && i->next != this) {
        	i = i->next;
        }

        SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i);
        out_name = sp_filter_name_for_image(parent, i_prim->image_out);
        repr->setAttribute("in2", out_name);

        if (!out_name) {
            g_warning("Unable to set in2 for feBlend");
        }
    }

    char const *mode;
    switch(this->blend_mode) {
        case Inkscape::Filters::BLEND_NORMAL:
            mode = "normal";      break;
        case Inkscape::Filters::BLEND_MULTIPLY:
            mode = "multiply";    break;
        case Inkscape::Filters::BLEND_SCREEN:
            mode = "screen";      break;
        case Inkscape::Filters::BLEND_DARKEN:
            mode = "darken";      break;
        case Inkscape::Filters::BLEND_LIGHTEN:
            mode = "lighten";     break;
        // New
        case Inkscape::Filters::BLEND_OVERLAY:
            mode = "overlay";     break;
        case Inkscape::Filters::BLEND_COLORDODGE:
            mode = "color-dodge"; break;
        case Inkscape::Filters::BLEND_COLORBURN:
            mode = "color-burn";  break;
        case Inkscape::Filters::BLEND_HARDLIGHT:
            mode = "hard-light";  break;
        case Inkscape::Filters::BLEND_SOFTLIGHT:
            mode = "soft-light";  break;
        case Inkscape::Filters::BLEND_DIFFERENCE:
            mode = "difference";  break;
        case Inkscape::Filters::BLEND_EXCLUSION:
            mode = "exclusion";   break;
        case Inkscape::Filters::BLEND_HUE:
            mode = "hue";         break;
        case Inkscape::Filters::BLEND_SATURATION:
            mode = "saturation";  break;
        case Inkscape::Filters::BLEND_COLOR:
            mode = "color";       break;
        case Inkscape::Filters::BLEND_LUMINOSITY:
            mode = "luminosity";  break;
        default:
            mode = 0;
    }

    repr->setAttribute("mode", mode);

    SPFilterPrimitive::write(doc, repr, flags);

    return repr;
}
Ejemplo n.º 19
0
void
ObjectCompositeSettings::_blendBlurValueChanged()
{
    if (!_subject) {
        return;
    }

    SPDesktop *desktop = _subject->getDesktop();
    if (!desktop) {
        return;
    }
    SPDocument *document = sp_desktop_document (desktop);

    if (_blocked)
        return;
    _blocked = true;

    // FIXME: fix for GTK breakage, see comment in SelectedStyle::on_opacity_changed; here it results in crash 1580903
    //sp_canvas_force_full_redraw_after_interruptions(sp_desktop_canvas(desktop), 0);

    Geom::OptRect bbox = _subject->getBounds(SPItem::GEOMETRIC_BBOX);
    double radius;
    if (bbox) {
        double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y];   // fixme: this is only half the perimeter, is that correct?
        radius = _fe_cb.get_blur_value() * perimeter / 400;
    } else {
        radius = 0;
    }

    const Glib::ustring blendmode = _fe_cb.get_blend_mode();

    //apply created filter to every selected item
    for (StyleSubject::iterator i = _subject->begin() ; i != _subject->end() ; ++i ) {
        if (!SP_IS_ITEM(*i)) {
            continue;
        }

        SPItem * item = SP_ITEM(*i);
        SPStyle *style = item->style;
        g_assert(style != NULL);

        if (blendmode != "normal") {
            SPFilter *filter = new_filter_simple_from_item(document, item, blendmode.c_str(), radius);
            sp_style_set_property_url(item, "filter", filter, false);
        } else {
            sp_style_set_property_url(item, "filter", NULL, false);
        }

        if (radius == 0 && item->style->filter.set
            && filter_is_single_gaussian_blur(SP_FILTER(item->style->getFilter()))) {
            remove_filter(item, false);
        }
        else if (radius != 0) {
            SPFilter *filter = modify_filter_gaussian_blur_from_item(document, item, radius);
            sp_style_set_property_url(item, "filter", filter, false);
        }

        //request update
        item->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG |
                                     SP_OBJECT_STYLE_MODIFIED_FLAG ));
    }

    DocumentUndo::maybeDone(document, _blur_tag.c_str(), _verb_code,
                            _("Change blur"));

    // resume interruptibility
    //sp_canvas_end_forced_full_redraws(sp_desktop_canvas(desktop));

    _blocked = false;
}