summaryrefslogtreecommitdiffstats
path: root/src/pattern-manipulation.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:50:49 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 11:50:49 +0000
commitc853ffb5b2f75f5a889ed2e3ef89b818a736e87a (patch)
tree7d13a0883bb7936b84d6ecdd7bc332b41ed04bee /src/pattern-manipulation.cpp
parentInitial commit. (diff)
downloadinkscape-c853ffb5b2f75f5a889ed2e3ef89b818a736e87a.tar.xz
inkscape-c853ffb5b2f75f5a889ed2e3ef89b818a736e87a.zip
Adding upstream version 1.3+ds.upstream/1.3+dsupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/pattern-manipulation.cpp')
-rw-r--r--src/pattern-manipulation.cpp140
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 : "");
+}