diff options
Diffstat (limited to 'src/pattern-manipulation.cpp')
-rw-r--r-- | src/pattern-manipulation.cpp | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/src/pattern-manipulation.cpp b/src/pattern-manipulation.cpp new file mode 100644 index 0000000..910a449 --- /dev/null +++ b/src/pattern-manipulation.cpp @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <glibmm/fileutils.h> +#include <glibmm/i18n.h> +#include "pattern-manipulation.h" +#include "document.h" +#include "color.h" +#include "helper/stock-items.h" +#include "object/sp-pattern.h" +#include "io/resource.h" +#include "xml/repr.h" + + +std::vector<std::shared_ptr<SPDocument>> sp_get_stock_patterns() { + auto patterns = sp_get_paint_documents([](SPDocument* doc){ + return !sp_get_pattern_list(doc).empty(); + }); + if (patterns.empty()) { + g_warning("No stock patterns!"); + } + return patterns; +} + +std::vector<SPPattern*> sp_get_pattern_list(SPDocument* source) { + std::vector<SPPattern*> list; + if (!source) return list; + + std::vector<SPObject*> patterns = source->getResourceList("pattern"); + for (auto pattern : patterns) { + auto p = cast<SPPattern>(pattern); + if (p && p == p->rootPattern() && p->hasChildren()) { // only if this is a vali root pattern + list.push_back(cast<SPPattern>(pattern)); + } + } + + return list; +} + +void sp_pattern_set_color(SPPattern* pattern, unsigned int color) { + if (!pattern) return; + + SPColor c(color); + SPCSSAttr* css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, "fill", c.toString().c_str()); + pattern->changeCSS(css, "style"); + sp_repr_css_attr_unref(css); +} + +void sp_pattern_set_transform(SPPattern* pattern, const Geom::Affine& transform) { + if (!pattern) return; + + // for now, this is that simple + pattern->transform_multiply(transform, true); +} + +void sp_pattern_set_offset(SPPattern* pattern, const Geom::Point& offset) { + if (!pattern) return; + + // TODO: verify + pattern->setAttributeDouble("x", offset.x()); + pattern->setAttributeDouble("y", offset.y()); +} + +void sp_pattern_set_uniform_scale(SPPattern* pattern, bool uniform) { + if (!pattern) return; + + //TODO: make smarter to keep existing value when possible + pattern->setAttribute("preserveAspectRatio", uniform ? "xMidYMid" : "none"); +} + +void sp_pattern_set_gap(SPPattern* link_pattern, Geom::Scale gap_percent) { + if (!link_pattern) return; + auto root = link_pattern->rootPattern(); + if (!root || root == link_pattern) { + g_assert(false && "Setting pattern gap requires link and root patterns objects"); + return; + } + + auto set_gap = [=](double size, double percent, const char* attr) { + if (percent == 0.0 || size <= 0.0) { + // no gap + link_pattern->removeAttribute(attr); + } + else if (percent > 0.0) { + // positive gap + link_pattern->setAttributeDouble(attr, size + size * percent / 100.0); + } + else if (percent < 0.0 && percent > -100.0) { + // negative gap - overlap + percent = -percent; + link_pattern->setAttributeDouble(attr, size - size * percent / 100.0); + } + }; + + set_gap(root->width(), gap_percent[Geom::X], "width"); + set_gap(root->height(), gap_percent[Geom::Y], "height"); +} + +Geom::Scale sp_pattern_get_gap(SPPattern* link_pattern) { + Geom::Scale gap(0, 0); + + if (!link_pattern) return gap; + auto root = link_pattern->rootPattern(); + if (!root || root == link_pattern) { + g_assert(false && "Reading pattern gap requires link and root patterns objects"); + return gap; + } + + auto get_gap = [=](double root_size, double link_size) { + if (root_size > 0.0 && link_size > 0.0) { + if (link_size > root_size) { + return (link_size - root_size) / root_size; + } + else if (link_size < root_size) { + return -link_size / root_size; + } + } + return 0.0; + }; + + return Geom::Scale( + get_gap(root->width(), link_pattern->width()) * 100.0, + get_gap(root->height(), link_pattern->height()) * 100.0 + ); +} + + +std::string sp_get_pattern_label(SPPattern* pattern) { + if (!pattern) return std::string(); + + Inkscape::XML::Node* repr = pattern->getRepr(); + if (auto label = pattern->getAttribute("inkscape:label")) { + if (*label) { + return std::string(gettext(label)); + } + } + const char* stock_id = _(repr->attribute("inkscape:stockid")); + const char* pat_id = stock_id ? stock_id : _(repr->attribute("id")); + return std::string(pat_id ? pat_id : ""); +} |