From 9a5352f6231f55c96d746cb1e674e6cfecdaa4bf Mon Sep 17 00:00:00 2001 From: kiirala Date: Thu, 7 Jun 2007 15:26:34 +0000 Subject: [PATCH] First version of feOffset support. Contains some rendering glitches. --- src/display/Makefile_insert | 2 + src/display/nr-arena-item.cpp | 5 +- src/display/nr-filter-offset.cpp | 92 ++++++++++++++++++++++++++++++ src/display/nr-filter-offset.h | 50 ++++++++++++++++ src/display/nr-filter-skeleton.cpp | 64 +++++++++++++++++++++ src/display/nr-filter-skeleton.h | 57 ++++++++++++++++++ src/display/nr-filter-slot.cpp | 1 + src/display/nr-filter.cpp | 4 +- src/sp-feoffset.cpp | 56 ++++++++++++++++-- src/sp-feoffset.h | 2 +- 10 files changed, 324 insertions(+), 9 deletions(-) create mode 100644 src/display/nr-filter-offset.cpp create mode 100644 src/display/nr-filter-offset.h create mode 100644 src/display/nr-filter-skeleton.cpp create mode 100644 src/display/nr-filter-skeleton.h diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index 95502170a..a4d747001 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -71,6 +71,8 @@ display_libspdisplay_a_SOURCES = \ display/nr-filter-gaussian.h \ display/nr-filter-blend.cpp \ display/nr-filter-blend.h \ + display/nr-filter-offset.cpp \ + display/nr-filter-offset.h \ display/nr-filter-slot.cpp \ display/nr-filter-slot.h \ display/nr-filter-types.h \ diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index b7ff825d2..a4fdcf5bc 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -414,9 +414,10 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area /* If background access is used, save the pixblock address. * This address is set to NULL at the end of this block */ - if (item->background_new - || (item->parent && item->parent->background_pb)) { + if (item->background_new) { item->background_pb = &ipb; + } else if (item->parent && item->parent->background_pb) { + item->background_pb = item->parent->background_pb; } ipb.visible_area = pb->visible_area; unsigned int state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, &ipb, flags); diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp new file mode 100644 index 000000000..ee6741d20 --- /dev/null +++ b/src/display/nr-filter-offset.cpp @@ -0,0 +1,92 @@ +/* + * feOffset filter primitive renderer + * + * Authors: + * Niko Kiirala + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "display/nr-filter-offset.h" +#include "display/nr-filter-slot.h" +#include "libnr/nr-blit.h" +#include "libnr/nr-matrix.h" +#include "libnr/nr-pixblock.h" +#include "libnr/nr-point.h" +#include "libnr/nr-point-matrix-ops.h" +#include "libnr/nr-rect-l.h" + +namespace NR { + +FilterOffset::FilterOffset() : + dx(0), dy(0) +{} + +FilterPrimitive * FilterOffset::create() { + return new FilterOffset(); +} + +FilterOffset::~FilterOffset() +{} + +int FilterOffset::render(FilterSlot &slot, Matrix const &trans) { + NRPixBlock *in = slot.get(_input); + NRPixBlock *out = new NRPixBlock; + + Point offset(dx, dy); + offset *= trans; + offset[X] -= trans[4]; + offset[Y] -= trans[5]; + + nr_pixblock_setup_fast(out, in->mode, + in->area.x0, in->area.y0, in->area.x1, in->area.y1, + true); + nr_blit_pixblock_pixblock(out, in); + + out->area.x0 += static_cast(offset[X]); + out->area.y0 += static_cast(offset[Y]); + out->area.x1 += static_cast(offset[X]); + out->area.y1 += static_cast(offset[Y]); + out->visible_area = out->area; + + out->empty = FALSE; + slot.set(_output, out); + + return 0; +} + +void FilterOffset::set_dx(double amount) { + dx = amount; +} + +void FilterOffset::set_dy(double amount) { + dy = amount; +} + +void FilterOffset::area_enlarge(NRRectL &area, Matrix const &trans) +{ + Point offset(dx, dy); + offset *= trans; + offset[X] -= trans[4]; + offset[Y] -= trans[5]; + + area.x0 -= static_cast(offset[X]); + area.x1 -= static_cast(offset[X]); + area.y0 -= static_cast(offset[Y]); + area.y1 -= static_cast(offset[Y]); +} + +} /* namespace NR */ + +/* + 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:encoding=utf-8:textwidth=99 : diff --git a/src/display/nr-filter-offset.h b/src/display/nr-filter-offset.h new file mode 100644 index 000000000..7c39b0ecc --- /dev/null +++ b/src/display/nr-filter-offset.h @@ -0,0 +1,50 @@ +#ifndef __NR_FILTER_OFFSET_H__ +#define __NR_FILTER_OFFSET_H__ + +/* + * feOffset filter primitive renderer + * + * Authors: + * Niko Kiirala + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "display/nr-filter-primitive.h" +#include "display/nr-filter-slot.h" +#include "libnr/nr-matrix.h" +#include "libnr/nr-rect-l.h" + +namespace NR { + +class FilterOffset : public FilterPrimitive { +public: + FilterOffset(); + static FilterPrimitive *create(); + virtual ~FilterOffset(); + + virtual int render(FilterSlot &slot, Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Matrix const &trans); + + void set_dx(double amount); + void set_dy(double amount); + +private: + double dx, dy; +}; + +} /* namespace NR */ + +#endif /* __NR_FILTER_OFFSET_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:encoding=utf-8:textwidth=99 : diff --git a/src/display/nr-filter-skeleton.cpp b/src/display/nr-filter-skeleton.cpp new file mode 100644 index 000000000..f595f13f1 --- /dev/null +++ b/src/display/nr-filter-skeleton.cpp @@ -0,0 +1,64 @@ +/* + * Filter primitive renderer skeleton class + * You can create your new filter primitive renderer by replacing + * all occurences of Skeleton, skeleton and SKELETON with your filter + * type, like gaussian or blend in respective case. + * + * This can be accomplished with the following sed command: + * sed -e "s/Skeleton/Name/g" -e "s/skeleton/name" -e "s/SKELETON/NAME" + * nr-filter-skeleton.cpp >nr-filter-name.cpp + * + * (on one line, replace occurences of 'name' with your filter name) + * + * Remember to convert the .h file too. The sed command is same for both + * files. + * + * Authors: + * Niko Kiirala + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "display/nr-filter-skeleton.h" +#include "display/nr-filter-slot.h" +#include "libnr/nr-pixblock.h" +#include "libnr/nr-matrix.h" + +namespace NR { + +FilterSkeleton::FilterSkeleton() +{} + +FilterPrimitive * FilterSkeleton::create() { + return new FilterSkeleton(); +} + +FilterSkeleton::~FilterSkeleton() +{} + +int FilterSkeleton::render(FilterSlot &slot, Matrix const &trans) { + NRPixBlock *in = slot.get(_input); + NRPixBlock *out; + + /* Insert rendering code here */ + + out->empty = FALSE; + slot.set(_output, out); + + return 0; +} + +} /* namespace NR */ + +/* + 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:encoding=utf-8:textwidth=99 : diff --git a/src/display/nr-filter-skeleton.h b/src/display/nr-filter-skeleton.h new file mode 100644 index 000000000..ae3a08046 --- /dev/null +++ b/src/display/nr-filter-skeleton.h @@ -0,0 +1,57 @@ +#ifndef __NR_FILTER_SKELETON_H__ +#define __NR_FILTER_SKELETON_H__ + +/* + * Filter primitive renderer skeleton class + * You can create your new filter primitive renderer by replacing + * all occurences of Skeleton, skeleton and SKELETON with your filter + * type, like gaussian or blend in respective case. + * + * This can be accomplished with the following sed command: + * sed -e "s/Skeleton/Name/g" -e "s/skeleton/name" -e "s/SKELETON/NAME" + * nr-filter-skeleton.h >nr-filter-name.h + * + * (on one line, replace occurences of 'name' with your filter name) + * + * Remember to convert the .cpp file too. The sed command is same for both + * files. + * + * Authors: + * Niko Kiirala + * + * Copyright (C) 2007 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "display/nr-filter-primitive.h" +#include "display/nr-filter-slot.h" +#include "libnr/nr-matrix.h" + +namespace NR { + +class FilterSkeleton : public FilterPrimitive { +public: + FilterSkeleton(); + static FilterPrimitive *create(); + virtual ~FilterSkeleton(); + + virtual int render(FilterSlot &slot, Matrix const &trans); + +private: + +}; + +} /* namespace NR */ + +#endif /* __NR_FILTER_SKELETON_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:encoding=utf-8:textwidth=99 : diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp index 673754f18..250aee10b 100644 --- a/src/display/nr-filter-slot.cpp +++ b/src/display/nr-filter-slot.cpp @@ -84,6 +84,7 @@ NRPixBlock *FilterSlot::get(int slot_nr) delete pb; return NULL; } + pb->empty = FALSE; this->set(NR_FILTER_BACKGROUNDIMAGE, pb); } } diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index 38ed3938a..33e89ac3e 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -22,6 +22,7 @@ #include "display/pixblock-transform.h" #include "display/nr-filter-gaussian.h" #include "display/nr-filter-blend.h" +#include "display/nr-filter-offset.h" #include "display/nr-arena-item.h" #include "libnr/nr-pixblock.h" @@ -209,6 +210,7 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb) return 0; nr_blit_pixblock_pixblock(in, pb); } + in->empty = FALSE; slot.set(NR_FILTER_SOURCEGRAPHIC, in); in = NULL; // in is now handled by FilterSlot, we should not touch it @@ -316,7 +318,7 @@ void Filter::_create_constructor_table() _constructor[NR_FILTER_IMAGE] = NULL; _constructor[NR_FILTER_MERGE] = NULL; _constructor[NR_FILTER_MORPHOLOGY] = NULL; - _constructor[NR_FILTER_OFFSET] = NULL; + _constructor[NR_FILTER_OFFSET] = &FilterOffset::create; _constructor[NR_FILTER_SPECULARLIGHTING] = NULL; _constructor[NR_FILTER_TILE] = NULL; _constructor[NR_FILTER_TURBULENCE] = NULL; diff --git a/src/sp-feoffset.cpp b/src/sp-feoffset.cpp index 2980f9ef8..298d3e495 100644 --- a/src/sp-feoffset.cpp +++ b/src/sp-feoffset.cpp @@ -7,8 +7,9 @@ /* * Authors: * hugo Rodrigues + * Niko Kiirala * - * Copyright (C) 2006 Hugo Rodrigues + * Copyright (C) 2006,2007 authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -21,7 +22,7 @@ #include "svg/svg.h" #include "sp-feoffset.h" #include "xml/repr.h" - +#include "display/nr-filter-offset.h" /* FeOffset base class */ @@ -33,6 +34,7 @@ static void sp_feOffset_release(SPObject *object); static void sp_feOffset_set(SPObject *object, unsigned int key, gchar const *value); static void sp_feOffset_update(SPObject *object, SPCtx *ctx, guint flags); static Inkscape::XML::Node *sp_feOffset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags); +static void sp_feOffset_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter); static SPFilterPrimitiveClass *feOffset_parent_class; @@ -61,6 +63,7 @@ static void sp_feOffset_class_init(SPFeOffsetClass *klass) { SPObjectClass *sp_object_class = (SPObjectClass *)klass; + SPFilterPrimitiveClass *sp_primitive_class = (SPFilterPrimitiveClass *)klass; feOffset_parent_class = (SPFilterPrimitiveClass*)g_type_class_peek_parent(klass); @@ -69,11 +72,15 @@ sp_feOffset_class_init(SPFeOffsetClass *klass) sp_object_class->write = sp_feOffset_write; sp_object_class->set = sp_feOffset_set; sp_object_class->update = sp_feOffset_update; + + sp_primitive_class->build_renderer = sp_feOffset_build_renderer; } static void sp_feOffset_init(SPFeOffset *feOffset) { + feOffset->dx = 0; + feOffset->dy = 0; } /** @@ -88,7 +95,8 @@ sp_feOffset_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *r ((SPObjectClass *) feOffset_parent_class)->build(object, document, repr); } - /*LOAD ATTRIBUTES FROM REPR HERE*/ + sp_object_read_attr(object, "dx"); + sp_object_read_attr(object, "dy"); } /** @@ -101,6 +109,18 @@ sp_feOffset_release(SPObject *object) ((SPObjectClass *) feOffset_parent_class)->release(object); } +double sp_feOffset_read_number(gchar const *value) { + char *end; + double ret = g_ascii_strtod(value, &end); + if (*end) { + g_warning("Unable to convert \"%s\" to number", value); + // We could leave this out, too. If strtod can't convert + // anything, it will return zero. + ret = 0; + } + return ret; +} + /** * Sets a specific value in the SPFeOffset. */ @@ -108,9 +128,17 @@ static void sp_feOffset_set(SPObject *object, unsigned int key, gchar const *value) { SPFeOffset *feOffset = SP_FEOFFSET(object); - (void)feOffset; switch(key) { + case SP_ATTR_DX: + feOffset->dx = sp_feOffset_read_number(value); + object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + case SP_ATTR_DY: + feOffset->dy = sp_feOffset_read_number(value); + object->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + break; + /*DEAL WITH SETTING ATTRIBUTES HERE*/ default: if (((SPObjectClass *) feOffset_parent_class)->set) @@ -148,7 +176,8 @@ sp_feOffset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) if (flags & SP_OBJECT_WRITE_EXT) { if (repr) { // is this sane? - repr->mergeFrom(SP_OBJECT_REPR(object), "id"); + // Not. Causes coredumps. + // repr->mergeFrom(SP_OBJECT_REPR(object), "id"); } else { repr = SP_OBJECT_REPR(object)->duplicate(NULL); // FIXME } @@ -161,6 +190,23 @@ sp_feOffset_write(SPObject *object, Inkscape::XML::Node *repr, guint flags) return repr; } +static void sp_feOffset_build_renderer(SPFilterPrimitive *primitive, NR::Filter *filter) { + g_assert(primitive != NULL); + g_assert(filter != NULL); + + SPFeOffset *sp_offset = SP_FEOFFSET(primitive); + + int primitive_n = filter->add_primitive(NR::NR_FILTER_OFFSET); + NR::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n); + NR::FilterOffset *nr_offset = dynamic_cast(nr_primitive); + g_assert(nr_offset != NULL); + + sp_filter_primitive_renderer_common(primitive, nr_primitive); + + nr_offset->set_dx(sp_offset->dx); + nr_offset->set_dy(sp_offset->dy); +} + /* Local Variables: diff --git a/src/sp-feoffset.h b/src/sp-feoffset.h index 2eda946c2..042711495 100644 --- a/src/sp-feoffset.h +++ b/src/sp-feoffset.h @@ -21,7 +21,7 @@ class SPFeOffsetClass; struct SPFeOffset : public SPFilterPrimitive { /** OFFSET ATTRIBUTES HERE */ - + double dx, dy; }; struct SPFeOffsetClass { -- 2.30.2