From cca66b9ec4e494c1d919bff0f71a820d8afab1fa Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 20:24:48 +0200 Subject: Adding upstream version 1.2.2. Signed-off-by: Daniel Baumann --- src/object/filters/displacementmap.cpp | 256 +++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 src/object/filters/displacementmap.cpp (limited to 'src/object/filters/displacementmap.cpp') diff --git a/src/object/filters/displacementmap.cpp b/src/object/filters/displacementmap.cpp new file mode 100644 index 0000000..41ce4d1 --- /dev/null +++ b/src/object/filters/displacementmap.cpp @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** \file + * SVG implementation. + * + */ +/* + * Authors: + * hugo Rodrigues + * Abhishek Sharma + * + * Copyright (C) 2006 Hugo Rodrigues + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include "displacementmap.h" + +#include "attributes.h" +#include "helper-fns.h" + +#include "display/nr-filter-displacement-map.h" +#include "display/nr-filter.h" + +#include "object/sp-filter.h" + +#include "svg/svg.h" + +#include "xml/repr.h" + +SPFeDisplacementMap::SPFeDisplacementMap() : SPFilterPrimitive() { + this->scale=0; + this->xChannelSelector = DISPLACEMENTMAP_CHANNEL_ALPHA; + this->yChannelSelector = DISPLACEMENTMAP_CHANNEL_ALPHA; + this->in2 = Inkscape::Filters::NR_FILTER_SLOT_NOT_SET; +} + +SPFeDisplacementMap::~SPFeDisplacementMap() = default; + +/** + * Reads the Inkscape::XML::Node, and initializes SPFeDisplacementMap 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 SPFeDisplacementMap::build(SPDocument *document, Inkscape::XML::Node *repr) { + SPFilterPrimitive::build(document, repr); + + /*LOAD ATTRIBUTES FROM REPR HERE*/ + this->readAttr(SPAttr::SCALE); + this->readAttr(SPAttr::IN2); + this->readAttr(SPAttr::XCHANNELSELECTOR); + this->readAttr(SPAttr::YCHANNELSELECTOR); + + /* 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 = this->name_previous_out(); + repr->setAttribute("in2", parent->name_for_image(this->in2)); + } +} + +/** + * Drops any allocated memory. + */ +void SPFeDisplacementMap::release() { + SPFilterPrimitive::release(); +} + +static FilterDisplacementMapChannelSelector sp_feDisplacementMap_readChannelSelector(gchar const *value) +{ + if (!value) return DISPLACEMENTMAP_CHANNEL_ALPHA; + + switch (value[0]) { + case 'R': + return DISPLACEMENTMAP_CHANNEL_RED; + break; + case 'G': + return DISPLACEMENTMAP_CHANNEL_GREEN; + break; + case 'B': + return DISPLACEMENTMAP_CHANNEL_BLUE; + break; + case 'A': + return DISPLACEMENTMAP_CHANNEL_ALPHA; + break; + default: + // error + g_warning("Invalid attribute for Channel Selector. Valid modes are 'R', 'G', 'B' or 'A'"); + break; + } + + return DISPLACEMENTMAP_CHANNEL_ALPHA; //default is Alpha Channel +} + +/** + * Sets a specific value in the SPFeDisplacementMap. + */ +void SPFeDisplacementMap::set(SPAttr key, gchar const *value) { + int input; + double read_num; + FilterDisplacementMapChannelSelector read_selector; + + switch(key) { + /*DEAL WITH SETTING ATTRIBUTES HERE*/ + case SPAttr::XCHANNELSELECTOR: + read_selector = sp_feDisplacementMap_readChannelSelector(value); + + if (read_selector != this->xChannelSelector){ + this->xChannelSelector = read_selector; + this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + break; + case SPAttr::YCHANNELSELECTOR: + read_selector = sp_feDisplacementMap_readChannelSelector(value); + + if (read_selector != this->yChannelSelector){ + this->yChannelSelector = read_selector; + this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + break; + case SPAttr::SCALE: + read_num = value ? helperfns_read_number(value) : 0; + + if (read_num != this->scale) { + this->scale = read_num; + this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + break; + case SPAttr::IN2: + input = this->read_in(value); + + if (input != this->in2) { + this->in2 = input; + this->parent->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + break; + default: + SPFilterPrimitive::set(key, value); + break; + } +} + +/** + * 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 = this->name_previous_out(); + + //XML Tree being used directly here while it shouldn't be. + this->setAttribute("in2", parent->name_for_image(this->in2)); + } + + SPFilterPrimitive::update(ctx, flags); +} + +static char const * get_channelselector_name(FilterDisplacementMapChannelSelector selector) { + switch(selector) { + case DISPLACEMENTMAP_CHANNEL_RED: + return "R"; + case DISPLACEMENTMAP_CHANNEL_GREEN: + return "G"; + case DISPLACEMENTMAP_CHANNEL_BLUE: + return "B"; + case DISPLACEMENTMAP_CHANNEL_ALPHA: + return "A"; + default: + return nullptr; + } +} + +/** + * 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 = parent->name_for_image(this->in2); + + if( !in2_name ) { + + // This code is very similar to name_previous_out() + SPObject *i = parent->firstChild(); + + // Find previous filter primitive + while (i && i->getNext() != this) { + i = i->getNext(); + } + + if( i ) { + SPFilterPrimitive *i_prim = SP_FILTER_PRIMITIVE(i); + in2_name = parent->name_for_image(i_prim->image_out); + } + } + + if (in2_name) { + repr->setAttribute("in2", in2_name); + } else { + g_warning("Unable to set in2 for feDisplacementMap"); + } + + repr->setAttributeSvgDouble("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; +} + +void SPFeDisplacementMap::build_renderer(Inkscape::Filters::Filter* filter) { + g_assert(filter != nullptr); + + int primitive_n = filter->add_primitive(Inkscape::Filters::NR_FILTER_DISPLACEMENTMAP); + Inkscape::Filters::FilterPrimitive *nr_primitive = filter->get_primitive(primitive_n); + Inkscape::Filters::FilterDisplacementMap *nr_displacement_map = dynamic_cast(nr_primitive); + g_assert(nr_displacement_map != nullptr); + + this->renderer_common(nr_primitive); + + nr_displacement_map->set_input(1, this->in2); + nr_displacement_map->set_scale(this->scale); + nr_displacement_map->set_channel_selector(0, this->xChannelSelector); + nr_displacement_map->set_channel_selector(1, this->yChannelSelector); +} + +/* + 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:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3