Enhance save as template and new from template dialogs
[inkscape.git] / testfiles / src / actions-svg-processing.cpp
blobd9da10e4e977e03660b730bb4fffbd8863d08411
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3 * Unit tests migrated from cxxtest
5 * Authors:
6 * Martin Owens
8 * Copyright (C) 2024 Authors
10 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
13 #include <gtest/gtest.h>
15 #include <src/document.h>
16 #include <src/inkscape.h>
17 #include <src/object/sp-root.h>
18 #include <src/object/sp-object.h>
20 using namespace Inkscape;
21 using namespace Inkscape::XML;
22 using namespace std::literals;
24 class ObjectLinksTest : public ::testing::Test {
25 public:
26 static void SetUpTestCase() {
27 Inkscape::Application::create(false);
30 void SetUp() override {
31 constexpr auto docString = R"A(<?xml version="1.0" encoding="UTF-8" standalone="no"?>
32 <svg width="62.256149mm" height="55.27673mm" viewBox="0 0 62.256149 55.27673" version="1.1" id="svg1" inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)" sodipodi:docname="g.svg" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
33 <sodipodi:namedview id="namedview1" pagecolor="#ffffff" bordercolor="#000000" borderopacity="0.25" inkscape:showpageshadow="2" inkscape:pageopacity="0.0" inkscape:pagecheckerboard="0" inkscape:deskcolor="#d1d1d1" inkscape:document-units="mm" inkscape:zoom="2.7086912" inkscape:cx="246.79816" inkscape:cy="174.62308" inkscape:window-width="2560" inkscape:window-height="1295" inkscape:window-x="0" inkscape:window-y="32" inkscape:window-maximized="1" inkscape:current-layer="layer1" />
34 <defs id="defs1">
35 <clipPath clipPathUnits="userSpaceOnUse" id="clipPath2">
36 <rect style="fill:#241f31;stroke-width:0.7;stroke-linejoin:round" id="rect3" width="61.610233" height="54.703255" x="16.41909" y="45.084824" transform="rotate(-18.396241)" />
37 </clipPath>
38 <clipPath clipPathUnits="userSpaceOnUse" id="clipPath5">
39 <rect style="fill:#241f31;stroke-width:0.7;stroke-linejoin:round" id="rect6" width="61.610233" height="54.703255" x="16.41909" y="45.084824" transform="rotate(-18.396241)" />
40 </clipPath>
41 </defs>
42 <g inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" transform="translate(-31.562698,-31.792045)">
43 <path id="rect1" clip-path="url(#clipPath2)" style="fill:#a51d2d;stroke-width:0.7;stroke-linejoin:round" transform="rotate(5.1388646)" d="M 36.865765,26.479748 H 98.475998 V 81.183002 H 36.865765 Z" />
44 <path id="rect4" clip-path="url(#clipPath5)" style="fill:#a51d2d;stroke-width:0.7;stroke-linejoin:round" transform="rotate(-5.1388646)" d="M 36.865765,26.479748 H 98.475998 V 81.183002 H 36.865765 Z" />
45 <path d="m 88.414007,34.281815 -27.684619,-2.48977 -27.05571,6.37429 -2.11098,23.47298 5.40432,22.93969 27.68461,2.48977 27.056229,-6.37429 2.11099,-23.47299 z" style="mix-blend-mode:difference;fill:#a51d2d;fill-opacity:1;stroke-width:0.7;stroke-linejoin:round" id="path5" />
46 <g id="g14" transform="translate(-69.610709,-8.3331963)" style="fill:#f6f5f4">
47 <g id="g9" transform="translate(-3.2234202,-4.2002143)" style="fill:#f6f5f4">
48 <g id="g6" style="fill:#f6f5f4">
49 <path id="path6" style="stroke-width:0.7;stroke-linejoin:round" d="m 128.36298,61.92614 a 3.9560158,4.1513743 0 0 1 -3.95601,4.151374 3.9560158,4.1513743 0 0 1 -3.95602,-4.151374 3.9560158,4.1513743 0 0 1 3.95602,-4.151375 3.9560158,4.1513743 0 0 1 3.95601,4.151375 z" />
50 <path id="ellipse6" style="stroke-width:0.7;stroke-linejoin:round" d="m 150.73156,62.512215 a 3.9560158,4.1513743 0 0 1 -3.95602,4.151374 3.9560158,4.1513743 0 0 1 -3.95601,-4.151374 3.9560158,4.1513743 0 0 1 3.95601,-4.151375 3.9560158,4.1513743 0 0 1 3.95602,4.151375 z" />
51 </g>
52 <g id="g8" transform="translate(0.0976794,20.610354)" style="fill:#f6f5f4">
53 <path id="ellipse7" style="stroke-width:0.7;stroke-linejoin:round" transform="scale(0.9)" d="m 128.36298,61.92614 a 3.9560158,4.1513743 0 0 1 -3.95601,4.151374 3.9560158,4.1513743 0 0 1 -3.95602,-4.151374 3.9560158,4.1513743 0 0 1 3.95602,-4.151375 3.9560158,4.1513743 0 0 1 3.95601,4.151375 z" />
54 <path id="ellipse8" style="stroke-width:0.7;stroke-linejoin:round" transform="scale(1.1)" d="m 150.73156,62.512215 a 3.9560158,4.1513743 0 0 1 -3.95602,4.151374 3.9560158,4.1513743 0 0 1 -3.95601,-4.151374 3.9560158,4.1513743 0 0 1 3.95601,-4.151375 3.9560158,4.1513743 0 0 1 3.95602,4.151375 z" />
55 </g>
56 </g>
57 </g>
58 </g>
59 </svg>)A"sv;
60 doc = SPDocument::createNewDocFromMem(docString, false);
62 ASSERT_TRUE(doc);
63 ASSERT_TRUE(doc->getRoot());
66 std::vector<SPObject *> getObjects(std::vector<std::string> const &lst) {
67 std::vector<SPObject *> ret;
68 for (auto &id : lst) {
69 ret.push_back(doc->getObjectById(id));
71 return ret;
74 std::unique_ptr<SPDocument> doc;
77 ::testing::AssertionResult RectNear(std::string expr1,
78 std::string expr2,
79 Geom::Rect val1,
80 Geom::Rect val2,
81 double abs_error = 0.01) {
83 double diff = 0;
84 for (auto x = 0; x < 2; x++) {
85 for (auto y = 0; y < 2; y++) {
86 diff += fabs(val1[x][y] - val2[x][y]);
90 if (diff <= abs_error)
91 return ::testing::AssertionSuccess();
93 return ::testing::AssertionFailure()
94 << "The difference between " << expr1 << " and " << expr2
95 << " is " << diff << ", which exceeds " << abs_error << ", where\n"
96 << expr1 << " evaluates to " << val1 << ",\n"
97 << expr2 << " evaluates to " << val2 << ".\n";
100 TEST_F(ObjectLinksTest, removeTransforms)
102 doc->ensureUpToDate();
104 std::vector<std::string> watch = {"rect1", "rect4", "path5", "g14", "g9", "g6", "path6", "ellipse7", "g8"};
105 std::map<std::string, Geom::Rect> boxes;
107 for (auto id : watch) {
108 auto item = cast<SPItem>(doc->getObjectById(id));
109 ASSERT_TRUE(item) << " item by id '" << id << "'";
110 auto obox = item->documentGeometricBounds();
111 ASSERT_TRUE(obox) << " item bounds '" << id << "'";
112 boxes[id] = *obox;
115 doc->getActionGroup()->activate_action("remove-all-transforms");
116 doc->ensureUpToDate();
118 for (auto id : watch) {
119 auto item = cast<SPItem>(doc->getObjectById(id));
120 ASSERT_TRUE(item) << " item by id '" << id << "'";
121 ASSERT_FALSE(item->getAttribute("transform")) << " item transform '" << id << "'";
122 auto old_box = boxes[id];
123 auto new_box = item->documentGeometricBounds();
124 ASSERT_TRUE(new_box) << " item bounds '" << id << "'";
125 EXPECT_TRUE(RectNear(id + ".old_box", id + ".new_box", old_box, *new_box, 0.01));