From 2f02157f365415636c515d4cfdc503f044c483de Mon Sep 17 00:00:00 2001 From: haa_rodrigues Date: Sun, 20 Aug 2006 12:13:40 +0000 Subject: [PATCH] Object groups can be blurred. Blur slider updates when selection changes. Comments added/fixed. --- src/desktop-style.cpp | 79 ++++++++++++++++++++++++++++--- src/desktop-style.h | 2 +- src/dialogs/object-properties.cpp | 73 +++++++++++++++++++--------- src/display/nr-arena-group.cpp | 40 +++++++++++++++- src/display/nr-arena-shape.cpp | 10 ++-- src/display/nr-filter.cpp | 3 +- src/sp-filter-primitive.cpp | 28 +---------- 7 files changed, 172 insertions(+), 63 deletions(-) diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index ff96f7e8e..66953aae7 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -24,6 +24,8 @@ #include "style.h" #include "prefs-utils.h" #include "sp-use.h" +#include "sp-filter.h" +#include "sp-gaussian-blur.h" #include "sp-flowtext.h" #include "sp-flowregion.h" #include "sp-flowdiv.h" @@ -1010,15 +1012,77 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res) } /** - * Write to style_res the average opacity of a list of objects. + * Write to style_res the average blurring of a list of objects. */ int objects_query_blur (GSList *objects, SPStyle *style_res) { - /*************temporary**********/ - //style_res->opacity.value = SP_SCALE24_FROM_FLOAT(0.5); - return QUERY_STYLE_MULTIPLE_SAME; - /*************temporary**********/ + if (g_slist_length(objects) == 0) { + /* No objects, set empty */ + return QUERY_STYLE_NOTHING; + } + + float blur_sum = 0; + float blur_prev = -1; + bool same_blur = true; + guint blur_items = 0; + + for (GSList const *i = objects; i != NULL; i = i->next) { + SPObject *obj = SP_OBJECT (i->data); + SPStyle *style = SP_OBJECT_STYLE (obj); + if (!style) continue; + + //if object has a filter + if (style->filter.set && style->filter.filter) { + //cycle through filter primitives + for(int i=0; ifilter.filter->_primitive_count; i++) + { + SPFilterPrimitive *primitive = style->filter.filter->_primitives[i]; + //if primitive is gaussianblur + // if(SP_IS_GAUSSIANBLUR(primitive)) + { + SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive); + float num = spblur->stdDeviation.getNumber(); + blur_sum += num; + if (blur_prev != -1 && num != blur_prev) + same_blur = false; + blur_prev = num; + //TODO: deal with opt number, for the moment it's not necessary to the ui. + blur_items ++; + } + } + } + + } + if (blur_items > 0) + { + blur_sum /= blur_items; + style_res->filter.set = true; + style_res->filter.filter = new SPFilter(); + //TODO: this SPFilter attributes should be set on sp-filter.cpp + // when a new SPFilter is created, not here + style_res->filter.filter->_primitive_count=0; + style_res->filter.filter->_primitive_table_size = 1; + style_res->filter.filter->_primitives = new SPFilterPrimitive*[1]; + style_res->filter.filter->_primitives[0] = NULL; + + SPGaussianBlur * b = new SPGaussianBlur(); + add_primitive(style_res->filter.filter, b); + sp_gaussianBlur_setDeviation(b, blur_sum); + } + + + + if (blur_items == 0) { + return QUERY_STYLE_NOTHING; + } else if (blur_items == 1) { + return QUERY_STYLE_SINGLE; + } else { + if (same_blur) + return QUERY_STYLE_MULTIPLE_SAME; + else + return QUERY_STYLE_MULTIPLE_AVERAGED; + } } /** @@ -1092,8 +1156,9 @@ sp_desktop_query_style_all (SPDesktop *desktop, SPStyle *query) int result_strokecap = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_STROKECAP); int result_strokejoin = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_STROKEJOIN); int result_opacity = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_MASTEROPACITY); - - return (result_family != QUERY_STYLE_NOTHING && result_fstyle != QUERY_STYLE_NOTHING && result_fnumbers != QUERY_STYLE_NOTHING && result_fill != QUERY_STYLE_NOTHING && result_stroke != QUERY_STYLE_NOTHING && result_opacity != QUERY_STYLE_NOTHING && result_strokewidth != QUERY_STYLE_NOTHING && result_strokemiterlimit != QUERY_STYLE_NOTHING && result_strokecap != QUERY_STYLE_NOTHING && result_strokejoin != QUERY_STYLE_NOTHING); + int result_blur = sp_desktop_query_style (desktop, query, QUERY_STYLE_PROPERTY_BLUR); + + return (result_family != QUERY_STYLE_NOTHING && result_fstyle != QUERY_STYLE_NOTHING && result_fnumbers != QUERY_STYLE_NOTHING && result_fill != QUERY_STYLE_NOTHING && result_stroke != QUERY_STYLE_NOTHING && result_opacity != QUERY_STYLE_NOTHING && result_strokewidth != QUERY_STYLE_NOTHING && result_strokemiterlimit != QUERY_STYLE_NOTHING && result_strokecap != QUERY_STYLE_NOTHING && result_strokejoin != QUERY_STYLE_NOTHING && result_blur != QUERY_STYLE_NOTHING); } diff --git a/src/desktop-style.h b/src/desktop-style.h index a1fd8a4ff..112fe1372 100644 --- a/src/desktop-style.h +++ b/src/desktop-style.h @@ -47,7 +47,7 @@ enum { // which property was queried (add when you need more) QUERY_STYLE_PROPERTY_FONTSTYLE, // font style QUERY_STYLE_PROPERTY_FONTNUMBERS, // size, spacings QUERY_STYLE_PROPERTY_MASTEROPACITY, // opacity - QUERY_STYLE_PROPERTY_BLUR // opacity + QUERY_STYLE_PROPERTY_BLUR // blur }; void sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines); diff --git a/src/dialogs/object-properties.cpp b/src/dialogs/object-properties.cpp index 4d6298b05..a4dd49aeb 100644 --- a/src/dialogs/object-properties.cpp +++ b/src/dialogs/object-properties.cpp @@ -13,7 +13,9 @@ * * Released under GNU GPL, read the file 'COPYING' for more information */ - +//uncomment to display blur slider +//#define WITH_BLUR + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -218,10 +220,10 @@ sp_object_properties_dialog (void) g_signal_connect ( G_OBJECT (INKSCAPE), "modify_selection", G_CALLBACK (sp_fillstroke_selection_modified), dlg ); g_signal_connect ( G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_fillstroke_selection_changed), dlg ); - + +#ifdef WITH_BLUR /* Blur */ -/* uncomment to display blur slider*/ -/* GtkWidget *b_vb = gtk_vbox_new (FALSE, 0); + GtkWidget *b_vb = gtk_vbox_new (FALSE, 0); gtk_box_pack_start (GTK_BOX (vb), b_vb, FALSE, FALSE, 2); gtk_object_set_data (GTK_OBJECT (dlg), "blur", b_vb); @@ -250,7 +252,7 @@ sp_object_properties_dialog (void) dlg ); gtk_widget_show_all (b_vb); -*/ +#endif sp_fillstroke_selection_changed(NULL, NULL, NULL); gtk_widget_show (dlg); @@ -323,6 +325,32 @@ sp_fillstroke_selection_changed ( Inkscape::Application *inkscape, break; } + + GtkWidget *b = GTK_WIDGET (gtk_object_get_data (GTK_OBJECT (dlg), "blur")); + GtkAdjustment *bluradjustment = GTK_ADJUSTMENT(gtk_object_get_data(GTK_OBJECT(dlg), "blur_adjustment")); + +#ifdef WITH_BLUR + //query now for current average blurring of selection + int blur_result = sp_desktop_query_style (SP_ACTIVE_DESKTOP, query, QUERY_STYLE_PROPERTY_BLUR); + + switch (blur_result) { + case QUERY_STYLE_NOTHING: //no blurring +// gtk_widget_set_sensitive (b, FALSE); + break; + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + gtk_widget_set_sensitive (b, TRUE); + //update blur widget value + SPGaussianBlur * spblur = SP_GAUSSIANBLUR(query->filter.filter->_primitives[0]); + gtk_adjustment_set_value(bluradjustment, spblur->stdDeviation.getNumber()); + break; + } +#endif + + + + g_free (query); gtk_object_set_data (GTK_OBJECT (dlg), "blocked", GUINT_TO_POINTER (FALSE)); } @@ -353,43 +381,44 @@ sp_fillstroke_opacity_changed (GtkAdjustment *a, SPWidget *dlg) /** - * Creates new private filter for the given vector + * Creates a filter with blur primitive of specified stdDeviation */ - static SPFilter * -sp_filter_get(SPDocument *document, gdouble stdDeviation) +sp_fillstroke_get_new_filter(SPDocument *document, gdouble stdDeviation) { g_return_val_if_fail(document != NULL, NULL); SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS(document); - // create a new private filter of the requested type + // create a new private filter Inkscape::XML::Node *repr; repr = sp_repr_new("svg:filter"); - // privates are garbage-collectable repr->setAttribute("inkscape:collect", "always"); + //create feGaussianBlur node Inkscape::XML::Node *b_repr; b_repr = sp_repr_new("svg:feGaussianBlur"); - // privates are garbage-collectable - //b_repr->setAttribute("inkscape:collect", "always"); - + b_repr->setAttribute("inkscape:collect", "always"); + //set stdDeviation attribute Inkscape::CSSOStringStream os; os << stdDeviation; b_repr->setAttribute("stdDeviation", os.str().c_str()); + //set feGaussianBlur as child of filter node repr->appendChild(b_repr); Inkscape::GC::release(b_repr); - /* Append the new private filter to defs */ + // Append the new filter node to defs SP_OBJECT_REPR(defs)->appendChild(repr); Inkscape::GC::release(repr); // get corresponding object SPFilter *f = SP_FILTER( document->getObjectByRepr(repr) ); SPGaussianBlur *b = SP_GAUSSIANBLUR( document->getObjectByRepr(b_repr) ); - add_primitive(f, /*(SPFilterPrimitive * )*/ b); + //add blur primitive to SPFilter object + add_primitive(f, b); //TODO: this should be triggered in SPFilter.cpp, when a child is added, not here... + g_assert(f != NULL); g_assert(SP_IS_FILTER(f)); g_assert(b != NULL); @@ -398,9 +427,7 @@ sp_filter_get(SPDocument *document, gdouble stdDeviation) return f; } -/* - * TODO: check if selection has a filter applied and change its parameters instead of creating a new one - */ + static void sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *dlg) { @@ -426,10 +453,9 @@ sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *dlg) //create new filter with feGaussianBlur primitive - SPFilter *constructed = sp_filter_get(document, a->value); + SPFilter *constructed = sp_fillstroke_get_new_filter(document, a->value); - - //apply created filter to every selected item + //apply created filter to every selected item for (GSList const *i = items; i != NULL; i = i->next) { SPItem * item = SP_ITEM(i->data); @@ -441,7 +467,8 @@ sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *dlg) //if there is a filter attached, remove it SPCSSAttr *css = sp_repr_css_attr_new (); sp_repr_css_unset_property (css, "filter"); - sp_desktop_set_style (desktop, css); + sp_repr_css_change_recursive(SP_OBJECT_REPR(item), css, "style"); + sp_desktop_set_style (SP_ACTIVE_DESKTOP, css); sp_repr_css_attr_unref (css); }/* else if( style->filter.filter ) { //item has a filter assigned Inkscape::XML::Node *repr = SP_OBJECT_REPR ( style->filter.filter ); @@ -449,6 +476,7 @@ sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *dlg) os << a->value; repr->firstChild()->setAttribute("stdDeviation", os.str().c_str()); }*/ else { + //add new filter attribute to object style gchar *val = g_strdup_printf("url(#%s)", SP_OBJECT_ID(constructed)); SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "filter", val); @@ -457,6 +485,7 @@ sp_fillstroke_blur_changed (GtkAdjustment *a, SPWidget *dlg) sp_desktop_set_style (SP_ACTIVE_DESKTOP, css); sp_repr_css_attr_unref(css); } + //request update SP_OBJECT(item)->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG )); } diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp index b4cc3930b..8df045332 100644 --- a/src/display/nr-arena-group.cpp +++ b/src/display/nr-arena-group.cpp @@ -14,7 +14,11 @@ #include "display/nr-arena-group.h" #include "display/nr-filter.h" +#include "display/nr-filter-gaussian.h" +#include "display/nr-filter-types.h" #include "style.h" +#include "sp-filter.h" +#include "sp-gaussian-blur.h" static void nr_arena_group_class_init (NRArenaGroupClass *klass); static void nr_arena_group_init (NRArenaGroup *group); @@ -193,9 +197,41 @@ void nr_arena_group_set_style (NRArenaGroup *group, SPStyle *style) if (group->style) sp_style_unref(group->style); group->style = style; + //if there is a filter set for this group if (style && style->filter.set && style->filter.filter) { - group->filter = new NR::Filter(); - } + + group->filter = new NR::Filter(); + group->filter->set_x(style->filter.filter->x); + group->filter->set_y(style->filter.filter->y); + group->filter->set_width(style->filter.filter->width); + group->filter->set_height(style->filter.filter->height); + + //go through all SP filter primitives + for(int i=0; ifilter.filter->_primitive_count; i++) + { + SPFilterPrimitive *primitive = style->filter.filter->_primitives[i]; + //if primitive is gaussianblur +// if(SP_IS_GAUSSIANBLUR(primitive)) + { + NR::FilterGaussian * gaussian = (NR::FilterGaussian *) group->filter->add_primitive(NR::NR_FILTER_GAUSSIANBLUR); + SPGaussianBlur * spblur = SP_GAUSSIANBLUR(primitive); + float num = spblur->stdDeviation.getNumber(); + if( num>=0.0 ) + { + float optnum = spblur->stdDeviation.getOptNumber(); + if( optnum>=0.0 ) + gaussian->set_deviation((double) num, (double) optnum); + else + gaussian->set_deviation((double) num); + } + } + } + } + else + { + //no filter set for this group + group->filter = NULL; + } if (style && style->enable_background.set && style->enable_background.value == SP_CSS_BACKGROUND_NEW) { diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index f9c203187..2f278b3de 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -1089,9 +1089,8 @@ nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style) } shape->setMitreLimit(style->stroke_miterlimit.value); - /* TODO: after SPStyle handles filters, get the correct filter - * from there. */ - if (style->filter.set && style->filter.filter) + //if shape has a filter + if (style->filter.set && style->filter.filter) { shape->filter = new NR::Filter(); shape->filter->set_x(style->filter.filter->x); @@ -1120,6 +1119,11 @@ nr_arena_shape_set_style(NRArenaShape *shape, SPStyle *style) } } } + else + { + //no filter set for this shape + shape->filter = NULL; + } nr_arena_item_request_update(shape, NR_ARENA_ITEM_STATE_ALL, FALSE); } diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index a96b02a62..35d8804e7 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -131,7 +131,8 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb) in = NULL; // in is now handled by FilterSlot, we should not touch it // TODO: loop through the primitives and render them one at a time - _primitive[0]->render(slot, trans); + if(_primitive[0]) + _primitive[0]->render(slot, trans); NRPixBlock *out = slot.get(_output_slot); diff --git a/src/sp-filter-primitive.cpp b/src/sp-filter-primitive.cpp index 6b208f1be..a0c09a4ce 100644 --- a/src/sp-filter-primitive.cpp +++ b/src/sp-filter-primitive.cpp @@ -1,15 +1,8 @@ #define __SP_FILTER_PRIMITIVE_CPP__ /** \file - * SVG implementation, used as an example for a base starting class - * when implementing new sp-objects. + * Superclass for all the filter primitives * - * In vi, three global search-and-replaces will let you rename everything - * in this and the .h file: - * - * :%s/FILTER_PRIMITIVE/YOURNAME/g - * :%s/FilterPrimitive/Yourname/g - * :%s/filter_primitive/yourname/g */ /* * Authors: @@ -95,22 +88,6 @@ sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML: ((SPObjectClass *) filter_primitive_parent_class)->build(object, document, repr); } - /* - Pay attention to certain settings here - - sp_object_read_attr(object, "xlink:href"); - sp_object_read_attr(object, "attributeName"); - sp_object_read_attr(object, "attributeType"); - sp_object_read_attr(object, "begin"); - sp_object_read_attr(object, "dur"); - sp_object_read_attr(object, "end"); - sp_object_read_attr(object, "min"); - sp_object_read_attr(object, "max"); - sp_object_read_attr(object, "restart"); - sp_object_read_attr(object, "repeatCount"); - sp_object_read_attr(object, "repeatDur"); - sp_object_read_attr(object, "fill"); - */ } /** @@ -119,9 +96,7 @@ sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML: static void sp_filter_primitive_release(SPObject *object) { - /* deal with our children and our selves here */ - if (((SPObjectClass *) filter_primitive_parent_class)->release) ((SPObjectClass *) filter_primitive_parent_class)->release(object); } @@ -152,7 +127,6 @@ sp_filter_primitive_update(SPObject *object, SPCtx *ctx, guint flags) SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { /* do something to trigger redisplay, updates? */ - } if (((SPObjectClass *) filter_primitive_parent_class)->update) { -- 2.30.2