From 1eb1d82bb52720d1379a4ed8f78c0e700251956d Mon Sep 17 00:00:00 2001 From: kiirala Date: Tue, 29 May 2007 10:47:04 +0000 Subject: [PATCH] Added support for in-parameter in filter primitives --- src/attributes.cpp | 3 ++ src/attributes.h | 3 ++ src/display/nr-filter-blend.cpp | 8 ---- src/display/nr-filter-slot.cpp | 23 ++++++++-- src/display/nr-filter-types.h | 2 +- src/display/nr-filter.cpp | 2 - src/sp-feblend.cpp | 28 +++++++----- src/sp-feblend.h | 1 + src/sp-filter-primitive.cpp | 80 +++++++++++++++++++++++++++++++++ src/sp-filter-primitive.h | 5 +++ src/sp-filter.cpp | 30 +++++++++++++ src/sp-filter.h | 12 +++++ 12 files changed, 170 insertions(+), 27 deletions(-) diff --git a/src/attributes.cpp b/src/attributes.cpp index 39f6a04f9..a8cd2e83d 100644 --- a/src/attributes.cpp +++ b/src/attributes.cpp @@ -165,6 +165,9 @@ static SPStyleProp const props[] = { {SP_ATTR_FILTERUNITS, "filterUnits"}, {SP_ATTR_PRIMITIVEUNITS, "primitiveUnits"}, {SP_ATTR_FILTERRES, "filterRes"}, + /* Filter primitives common */ + {SP_ATTR_IN, "in"}, + {SP_ATTR_RESULT, "result"}, /*feBlend*/ {SP_ATTR_MODE, "mode"}, {SP_ATTR_IN2, "in2"}, diff --git a/src/attributes.h b/src/attributes.h index 85eb00e38..fa492d978 100644 --- a/src/attributes.h +++ b/src/attributes.h @@ -165,6 +165,9 @@ enum SPAttributeEnum { SP_ATTR_FILTERUNITS, SP_ATTR_PRIMITIVEUNITS, SP_ATTR_FILTERRES, + /* Filter primitives common */ + SP_ATTR_IN, + SP_ATTR_RESULT, /*feBlend*/ SP_ATTR_MODE, SP_ATTR_IN2, diff --git a/src/display/nr-filter-blend.cpp b/src/display/nr-filter-blend.cpp index 1468eb61b..0e2f965b7 100644 --- a/src/display/nr-filter-blend.cpp +++ b/src/display/nr-filter-blend.cpp @@ -23,14 +23,6 @@ #include "libnr/nr-blit.h" #include "libnr/nr-pixops.h" -/* -static inline int clamp(const int val, const int min, const int max) { - if (val < min) return min; - if (val > max) return max; - return val; -} -*/ - template static void _render(NRPixBlock &out, NRPixBlock &in1, NRPixBlock &in2) { unsigned char *in1_data = NR_PIXBLOCK_PX(&in1); diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp index 3a2895ec6..673754f18 100644 --- a/src/display/nr-filter-slot.cpp +++ b/src/display/nr-filter-slot.cpp @@ -62,7 +62,7 @@ NRPixBlock *FilterSlot::get(int slot_nr) || slot_nr == NR_FILTER_BACKGROUNDIMAGE || slot_nr == NR_FILTER_BACKGROUNDALPHA || slot_nr == NR_FILTER_FILLPAINT - || slot_nr == NR_FILTER_SOURCEPAINT)) + || slot_nr == NR_FILTER_STROKEPAINT)) { /* If needed, fetch background */ if (slot_nr == NR_FILTER_BACKGROUNDIMAGE @@ -70,7 +70,22 @@ NRPixBlock *FilterSlot::get(int slot_nr) { NRPixBlock *pb; pb = nr_arena_item_get_background(_arena_item); - this->set(NR_FILTER_BACKGROUNDIMAGE, pb); + if (pb) { + this->set(NR_FILTER_BACKGROUNDIMAGE, pb); + } else { + NRPixBlock *source = this->get(NR_FILTER_SOURCEGRAPHIC); + pb = new NRPixBlock(); + if (!pb) return NULL; // Allocation failed + nr_pixblock_setup_fast(pb, source->mode, + source->area.x0, source->area.y0, + source->area.x1, source->area.y1, true); + if (pb->size != NR_PIXBLOCK_SIZE_TINY && pb->data.px == NULL) { + // allocation failed + delete pb; + return NULL; + } + this->set(NR_FILTER_BACKGROUNDIMAGE, pb); + } } /* If only a alpha channel is needed, strip it from full image */ if (slot_nr == NR_FILTER_SOURCEALPHA) { @@ -83,7 +98,7 @@ NRPixBlock *FilterSlot::get(int slot_nr) if (slot_nr == NR_FILTER_FILLPAINT) { // TODO } - if (slot_nr == NR_FILTER_SOURCEPAINT) { + if (slot_nr == NR_FILTER_STROKEPAINT) { // TODO } } @@ -125,7 +140,7 @@ int FilterSlot::_get_index(int slot_nr) slot_nr == NR_FILTER_BACKGROUNDIMAGE || slot_nr == NR_FILTER_BACKGROUNDALPHA || slot_nr == NR_FILTER_FILLPAINT || - slot_nr == NR_FILTER_SOURCEPAINT); + slot_nr == NR_FILTER_STROKEPAINT); int index = -1; if (slot_nr == NR_FILTER_SLOT_NOT_SET) { diff --git a/src/display/nr-filter-types.h b/src/display/nr-filter-types.h index 3eebe3731..6f28c6257 100644 --- a/src/display/nr-filter-types.h +++ b/src/display/nr-filter-types.h @@ -31,7 +31,7 @@ enum { NR_FILTER_BACKGROUNDIMAGE = -4, NR_FILTER_BACKGROUNDALPHA = -5, NR_FILTER_FILLPAINT = -6, - NR_FILTER_SOURCEPAINT = -7 + NR_FILTER_STROKEPAINT = -7 }; } /* namespace NR */ diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index 515d5961f..d8cfb2ecf 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -35,8 +35,6 @@ using Inkscape::round; #endif -//#include "display/nr-arena-shape.h" - __attribute__ ((const)) inline static int _max4(const double a, const double b, const double c, const double d) { diff --git a/src/sp-feblend.cpp b/src/sp-feblend.cpp index 49ab18a25..bedbf4f61 100644 --- a/src/sp-feblend.cpp +++ b/src/sp-feblend.cpp @@ -43,7 +43,6 @@ static Inkscape::XML::Node *sp_feBlend_write(SPObject *object, Inkscape::XML::No static void sp_feBlend_build_renderer(SPFilterPrimitive *sp_prim, NR::Filter *filter); static SPFilterPrimitiveClass *feBlend_parent_class; -static int renderer; GType sp_feBlend_get_type() @@ -86,7 +85,7 @@ sp_feBlend_class_init(SPFeBlendClass *klass) static void sp_feBlend_init(SPFeBlend *feBlend) { - renderer = -1; + feBlend->in2 = NR::NR_FILTER_SLOT_NOT_SET; } /** @@ -103,6 +102,7 @@ sp_feBlend_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *re /*LOAD ATTRIBUTES FROM REPR HERE*/ sp_object_read_attr(object, "mode"); + sp_object_read_attr(object, "in2"); } /** @@ -155,18 +155,23 @@ sp_feBlend_set(SPObject *object, unsigned int key, gchar const *value) SPFeBlend *feBlend = SP_FEBLEND(object); (void)feBlend; + NR::FilterBlendMode mode; + int input; switch(key) { /*DEAL WITH SETTING ATTRIBUTES HERE*/ case SP_ATTR_MODE: - feBlend->blend_mode = sp_feBlend_readmode(value); -/* - if (renderer >= 0) { - NR::Filter *filter = SP_FILTER(object->parent)->_renderer; - NR::FilterBlend *blend = dynamic_cast(filter->get_primitive(renderer)); - blend->set_mode(feBlend->blend_mode); + mode = sp_feBlend_readmode(value); + if (mode != feBlend->blend_mode) { + feBlend->blend_mode = mode; + object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + break; + case SP_ATTR_IN2: + input = sp_filter_primitive_read_in(feBlend, value); + if (input != feBlend->in2) { + feBlend->in2 = input; + object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); } -*/ - object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); break; default: if (((SPObjectClass *) feBlend_parent_class)->set) @@ -228,8 +233,7 @@ static void sp_feBlend_build_renderer(SPFilterPrimitive *primitive, NR::Filter * sp_filter_primitive_renderer_common(primitive, nr_primitive); nr_blend->set_mode(sp_blend->blend_mode); - - renderer = primitive_n; + nr_blend->set_input(1, sp_blend->in2); } /* diff --git a/src/sp-feblend.h b/src/sp-feblend.h index 90ab8967f..f6f71b892 100644 --- a/src/sp-feblend.h +++ b/src/sp-feblend.h @@ -25,6 +25,7 @@ class SPFeBlendClass; struct SPFeBlend : public SPFilterPrimitive { /** BLEND ATTRIBUTES HERE */ NR::FilterBlendMode blend_mode; + int in2; }; struct SPFeBlendClass { diff --git a/src/sp-filter-primitive.cpp b/src/sp-filter-primitive.cpp index f799dbe54..cd8c53c65 100644 --- a/src/sp-filter-primitive.cpp +++ b/src/sp-filter-primitive.cpp @@ -23,6 +23,7 @@ #include "xml/repr.h" #include "sp-filter.h" #include "display/nr-filter-primitive.h" +#include "display/nr-filter-types.h" /* FilterPrimitive base class */ @@ -80,6 +81,8 @@ sp_filter_primitive_class_init(SPFilterPrimitiveClass *klass) static void sp_filter_primitive_init(SPFilterPrimitive *filter_primitive) { + filter_primitive->image_in = NR::NR_FILTER_SLOT_NOT_SET; + filter_primitive->image_out = NR::NR_FILTER_SLOT_NOT_SET; } /** @@ -94,6 +97,9 @@ sp_filter_primitive_build(SPObject *object, SPDocument *document, Inkscape::XML: ((SPObjectClass *) filter_primitive_parent_class)->build(object, document, repr); } + sp_object_read_attr(object, "in"); + sp_object_read_attr(object, "result"); + if (object->parent) add_primitive((SPFilter*)object->parent, (SPFilterPrimitive*)object); } @@ -118,6 +124,32 @@ sp_filter_primitive_set(SPObject *object, unsigned int key, gchar const *value) SPFilterPrimitive *filter_primitive = SP_FILTER_PRIMITIVE(object); (void)filter_primitive; + int image_nr; + switch (key) { + case SP_ATTR_IN: + if (value) { + image_nr = sp_filter_primitive_read_in(filter_primitive, value); + } else { + image_nr = NR::NR_FILTER_SLOT_NOT_SET; + } + if (image_nr != filter_primitive->image_in) { + filter_primitive->image_in = image_nr; + object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + break; + case SP_ATTR_RESULT: + if (value) { + image_nr = sp_filter_primitive_read_result(filter_primitive, value); + } else { + image_nr = NR::NR_FILTER_SLOT_NOT_SET; + } + if (image_nr != filter_primitive->image_out) { + filter_primitive->image_out = image_nr; + object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + break; + } + /* See if any parents need this value. */ if (((SPObjectClass *) filter_primitive_parent_class)->set) { ((SPObjectClass *) filter_primitive_parent_class)->set(object, key, value); @@ -169,12 +201,60 @@ sp_filter_primitive_write(SPObject *object, Inkscape::XML::Node *repr, guint fla return repr; } +int sp_filter_primitive_read_in(SPFilterPrimitive *prim, gchar const *name) +{ + if (!name) return NR::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 NR::NR_FILTER_SOURCEGRAPHIC; + if (strcmp(name, "SourceAlpha") == 0) + return NR::NR_FILTER_SOURCEALPHA; + if (strcmp(name, "StrokePaint") == 0) + return NR::NR_FILTER_STROKEPAINT; + break; + case 'B': + if (strcmp(name, "BackgroundImage") == 0) + return NR::NR_FILTER_BACKGROUNDIMAGE; + if (strcmp(name, "BackgroundAlpha") == 0) + return NR::NR_FILTER_BACKGROUNDALPHA; + break; + case 'F': + if (strcmp(name, "FillPaint") == 0) + return NR::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 NR::NR_FILTER_SLOT_NOT_SET; +} + +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 NR::NR_FILTER_SLOT_NOT_SET; +} + /* Common initialization for filter primitives */ void sp_filter_primitive_renderer_common(SPFilterPrimitive *sp_prim, NR::FilterPrimitive *nr_prim) { g_assert(sp_prim != NULL); g_assert(nr_prim != NULL); + + nr_prim->set_input(sp_prim->image_in); + nr_prim->set_output(sp_prim->image_out); + /* TODO: place here code to handle input images, filter area etc. */ } diff --git a/src/sp-filter-primitive.h b/src/sp-filter-primitive.h index 96268dbfe..6f6558c5c 100644 --- a/src/sp-filter-primitive.h +++ b/src/sp-filter-primitive.h @@ -17,6 +17,7 @@ #include "sp-object.h" #include "display/nr-filter.h" #include "display/nr-filter-primitive.h" +#include "display/nr-filter-types.h" #define SP_TYPE_FILTER_PRIMITIVE (sp_filter_primitive_get_type ()) #define SP_FILTER_PRIMITIVE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_FILTER_PRIMITIVE, SPFilterPrimitive)) @@ -28,6 +29,7 @@ class SPFilterPrimitive; class SPFilterPrimitiveClass; struct SPFilterPrimitive : public SPObject { + int image_in, image_out; }; struct SPFilterPrimitiveClass { @@ -40,6 +42,9 @@ GType sp_filter_primitive_get_type (void); /* Common initialization for filter primitives */ void sp_filter_primitive_renderer_common(SPFilterPrimitive *sp_prim, NR::FilterPrimitive *nr_prim); +int sp_filter_primitive_read_in(SPFilterPrimitive *prim, gchar const *name); +int sp_filter_primitive_read_result(SPFilterPrimitive *prim, gchar const *name); + #endif /* Local Variables: diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp index ac0d3d29e..43f2dc9d2 100644 --- a/src/sp-filter.cpp +++ b/src/sp-filter.cpp @@ -17,6 +17,11 @@ # include "config.h" #endif +#include +#include +using std::map; +using std::pair; + #include "attributes.h" #include "document.h" #include "sp-filter.h" @@ -454,6 +459,31 @@ int sp_filter_primitive_count(SPFilter *filter) { return filter->_primitive_count; } +int sp_filter_get_image_name(SPFilter *filter, gchar const *name) { + gchar *name_copy = strdup(name); + map::iterator result = filter->_image_name.find(name_copy); + free(name_copy); + if (result == filter->_image_name.end()) return -1; + else return (*result).second; +} + +int sp_filter_set_image_name(SPFilter *filter, gchar const *name) { + int value = filter->_image_number_next; + filter->_image_number_next++; + gchar *name_copy = strdup(name); + pair::iterator,bool> ret = filter->_image_name.insert(pair(name_copy, value)); + if (ret.second == false) { + return (*ret.first).second; + } + return value; +} + +bool ltstr::operator()(const char* s1, const char* s2) const +{ + return strcmp(s1, s2) < 0; +} + + /* Local Variables: mode:c++ diff --git a/src/sp-filter.h b/src/sp-filter.h index 06b46ecc6..55e3eaa0a 100644 --- a/src/sp-filter.h +++ b/src/sp-filter.h @@ -14,6 +14,8 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include + #include "number-opt-number.h" #include "sp-object.h" #include "sp-filter-units.h" @@ -30,6 +32,10 @@ struct SPFilterReference; class SPFilter; class SPFilterClass; +struct ltstr { + bool operator()(const char* s1, const char* s2) const; +}; + struct SPFilter : public SPObject { /** filterUnits attribute */ @@ -55,6 +61,9 @@ struct SPFilter : public SPObject { int _primitive_table_size; SPFilterPrimitive ** _primitives; NR::Filter *_renderer; + + std::map _image_name; + int _image_number_next; }; struct SPFilterClass { @@ -72,6 +81,9 @@ void sp_filter_build_renderer(SPFilter *sp_filter, NR::Filter *nr_filter); */ int sp_filter_primitive_count(SPFilter *filter); +int sp_filter_get_image_name(SPFilter *filter, gchar const *name); +int sp_filter_set_image_name(SPFilter *filter, gchar const *name); + #endif /* !SP_FILTER_H_SEEN */ /* -- 2.30.2