1 /*
2  *  Copyright (c) 2014 Dmitry Kazakov <dimula73@gmail.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include "kis_dom_utils.h"
20 
21 #include <QTransform>
22 
23 #include "kis_debug.h"
24 
25 namespace KisDomUtils {
26 
saveValue(QDomElement * parent,const QString & tag,const QSize & size)27 void saveValue(QDomElement *parent, const QString &tag, const QSize &size)
28 {
29     QDomDocument doc = parent->ownerDocument();
30     QDomElement e = doc.createElement(tag);
31     parent->appendChild(e);
32 
33     e.setAttribute("type", "size");
34 
35     e.setAttribute("w", toString(size.width()));
36     e.setAttribute("h", toString(size.height()));
37 }
38 
saveValue(QDomElement * parent,const QString & tag,const QRect & rc)39 void saveValue(QDomElement *parent, const QString &tag, const QRect &rc)
40 {
41     QDomDocument doc = parent->ownerDocument();
42     QDomElement e = doc.createElement(tag);
43     parent->appendChild(e);
44 
45     e.setAttribute("type", "rect");
46 
47     e.setAttribute("x", toString(rc.x()));
48     e.setAttribute("y", toString(rc.y()));
49     e.setAttribute("w", toString(rc.width()));
50     e.setAttribute("h", toString(rc.height()));
51 }
52 
saveValue(QDomElement * parent,const QString & tag,const QRectF & rc)53 void saveValue(QDomElement *parent, const QString &tag, const QRectF &rc)
54 {
55     QDomDocument doc = parent->ownerDocument();
56     QDomElement e = doc.createElement(tag);
57     parent->appendChild(e);
58 
59     e.setAttribute("type", "rectf");
60 
61     e.setAttribute("x", toString(rc.x()));
62     e.setAttribute("y", toString(rc.y()));
63     e.setAttribute("w", toString(rc.width()));
64     e.setAttribute("h", toString(rc.height()));
65 }
66 
saveValue(QDomElement * parent,const QString & tag,const QPoint & pt)67 void saveValue(QDomElement *parent, const QString &tag, const QPoint &pt)
68 {
69     QDomDocument doc = parent->ownerDocument();
70     QDomElement e = doc.createElement(tag);
71     parent->appendChild(e);
72 
73     e.setAttribute("type", "point");
74 
75     e.setAttribute("x", toString(pt.x()));
76     e.setAttribute("y", toString(pt.y()));
77 }
78 
saveValue(QDomElement * parent,const QString & tag,const QPointF & pt)79 void saveValue(QDomElement *parent, const QString &tag, const QPointF &pt)
80 {
81     QDomDocument doc = parent->ownerDocument();
82     QDomElement e = doc.createElement(tag);
83     parent->appendChild(e);
84 
85     e.setAttribute("type", "pointf");
86 
87     e.setAttribute("x", toString(pt.x()));
88     e.setAttribute("y", toString(pt.y()));
89 }
90 
saveValue(QDomElement * parent,const QString & tag,const QVector3D & pt)91 void saveValue(QDomElement *parent, const QString &tag, const QVector3D &pt)
92 {
93     QDomDocument doc = parent->ownerDocument();
94     QDomElement e = doc.createElement(tag);
95     parent->appendChild(e);
96 
97     e.setAttribute("type", "vector3d");
98 
99     e.setAttribute("x", toString(pt.x()));
100     e.setAttribute("y", toString(pt.y()));
101     e.setAttribute("z", toString(pt.z()));
102 }
103 
saveValue(QDomElement * parent,const QString & tag,const QTransform & t)104 void saveValue(QDomElement *parent, const QString &tag, const QTransform &t)
105 {
106     QDomDocument doc = parent->ownerDocument();
107     QDomElement e = doc.createElement(tag);
108     parent->appendChild(e);
109 
110     e.setAttribute("type", "transform");
111 
112     e.setAttribute("m11", toString(t.m11()));
113     e.setAttribute("m12", toString(t.m12()));
114     e.setAttribute("m13", toString(t.m13()));
115 
116     e.setAttribute("m21", toString(t.m21()));
117     e.setAttribute("m22", toString(t.m22()));
118     e.setAttribute("m23", toString(t.m23()));
119 
120     e.setAttribute("m31", toString(t.m31()));
121     e.setAttribute("m32", toString(t.m32()));
122     e.setAttribute("m33", toString(t.m33()));
123 }
124 
saveValue(QDomElement * parent,const QString & tag,const QColor & c)125 void saveValue(QDomElement *parent, const QString &tag, const QColor &c)
126 {
127     QDomDocument doc = parent->ownerDocument();
128     QDomElement e = doc.createElement(tag);
129     parent->appendChild(e);
130 
131     e.setAttribute("type", "qcolor");
132     e.setAttribute("value", c.name(QColor::HexArgb));
133 }
134 
findOnlyElement(const QDomElement & parent,const QString & tag,QDomElement * el,QStringList * errorMessages)135 bool findOnlyElement(const QDomElement &parent, const QString &tag, QDomElement *el, QStringList *errorMessages)
136 {
137     QDomNodeList list = parent.elementsByTagName(tag);
138     if (list.size() != 1 || !list.at(0).isElement()) {
139         QString msg = i18n("Could not find \"%1\" XML tag in \"%2\"", tag, parent.tagName());
140         if (errorMessages) {
141             *errorMessages << msg;
142         } else {
143             warnKrita << msg;
144         }
145 
146         return false;
147     }
148 
149     *el = list.at(0).toElement();
150     return true;
151 }
152 
removeElements(QDomElement & parent,const QString & tag)153 bool removeElements(QDomElement &parent, const QString &tag) {
154     QDomNodeList list = parent.elementsByTagName(tag);
155     KIS_SAFE_ASSERT_RECOVER_NOOP(list.size() <= 1);
156 
157     for (int i = 0; i < list.size(); i++) {
158         parent.removeChild(list.at(i));
159     }
160 
161     return list.size() > 0;
162 }
163 
164 namespace Private {
checkType(const QDomElement & e,const QString & expectedType)165     bool checkType(const QDomElement &e, const QString &expectedType)
166     {
167         QString type = e.attribute("type", "unknown-type");
168         if (type != expectedType) {
169             warnKrita << i18n("Error: incorrect type (%2) for value %1. Expected %3", e.tagName(), type, expectedType);
170             return false;
171         }
172 
173         return true;
174     }
175 }
176 
loadValue(const QDomElement & e,float * v)177 bool loadValue(const QDomElement &e, float *v)
178 {
179     if (!Private::checkType(e, "value")) return false;
180     *v = toDouble(e.attribute("value", "0"));
181     return true;
182 }
183 
loadValue(const QDomElement & e,double * v)184 bool loadValue(const QDomElement &e, double *v)
185 {
186     if (!Private::checkType(e, "value")) return false;
187     *v = toDouble(e.attribute("value", "0"));
188     return true;
189 }
190 
loadValue(const QDomElement & e,QSize * size)191 bool loadValue(const QDomElement &e, QSize *size)
192 {
193     if (!Private::checkType(e, "size")) return false;
194 
195     size->setWidth(toInt(e.attribute("w", "0")));
196     size->setHeight(toInt(e.attribute("h", "0")));
197 
198     return true;
199 }
200 
loadValue(const QDomElement & e,QRect * rc)201 bool loadValue(const QDomElement &e, QRect *rc)
202 {
203     if (!Private::checkType(e, "rect")) return false;
204 
205     rc->setX(toInt(e.attribute("x", "0")));
206     rc->setY(toInt(e.attribute("y", "0")));
207     rc->setWidth(toInt(e.attribute("w", "0")));
208     rc->setHeight(toInt(e.attribute("h", "0")));
209 
210     return true;
211 }
212 
loadValue(const QDomElement & e,QRectF * rc)213 bool loadValue(const QDomElement &e, QRectF *rc)
214 {
215     if (!Private::checkType(e, "rectf")) return false;
216 
217     rc->setX(toInt(e.attribute("x", "0")));
218     rc->setY(toInt(e.attribute("y", "0")));
219     rc->setWidth(toInt(e.attribute("w", "0")));
220     rc->setHeight(toInt(e.attribute("h", "0")));
221 
222     return true;
223 }
224 
loadValue(const QDomElement & e,QPoint * pt)225 bool loadValue(const QDomElement &e, QPoint *pt)
226 {
227     if (!Private::checkType(e, "point")) return false;
228 
229     pt->setX(toInt(e.attribute("x", "0")));
230     pt->setY(toInt(e.attribute("y", "0")));
231 
232     return true;
233 }
234 
loadValue(const QDomElement & e,QPointF * pt)235 bool loadValue(const QDomElement &e, QPointF *pt)
236 {
237     if (!Private::checkType(e, "pointf")) return false;
238 
239     pt->setX(toDouble(e.attribute("x", "0")));
240     pt->setY(toDouble(e.attribute("y", "0")));
241 
242     return true;
243 }
244 
loadValue(const QDomElement & e,QVector3D * pt)245 bool loadValue(const QDomElement &e, QVector3D *pt)
246 {
247     if (!Private::checkType(e, "vector3d")) return false;
248 
249     pt->setX(toDouble(e.attribute("x", "0")));
250     pt->setY(toDouble(e.attribute("y", "0")));
251     pt->setZ(toDouble(e.attribute("z", "0")));
252 
253     return true;
254 }
255 
loadValue(const QDomElement & e,QTransform * t)256 bool loadValue(const QDomElement &e, QTransform *t)
257 {
258     if (!Private::checkType(e, "transform")) return false;
259 
260     qreal m11 = toDouble(e.attribute("m11", "1.0"));
261     qreal m12 = toDouble(e.attribute("m12", "0.0"));
262     qreal m13 = toDouble(e.attribute("m13", "0.0"));
263 
264     qreal m21 = toDouble(e.attribute("m21", "0.0"));
265     qreal m22 = toDouble(e.attribute("m22", "1.0"));
266     qreal m23 = toDouble(e.attribute("m23", "0.0"));
267 
268     qreal m31 = toDouble(e.attribute("m31", "0.0"));
269     qreal m32 = toDouble(e.attribute("m32", "0.0"));
270     qreal m33 = toDouble(e.attribute("m33", "1.0"));
271 
272     t->setMatrix(
273         m11, m12, m13,
274         m21, m22, m23,
275         m31, m32, m33);
276 
277     return true;
278 }
279 
loadValue(const QDomElement & e,QString * value)280 bool loadValue(const QDomElement &e, QString *value)
281 {
282     if (!Private::checkType(e, "value")) return false;
283     *value = e.attribute("value", "no-value");
284     return true;
285 }
286 
loadValue(const QDomElement & e,QColor * value)287 bool loadValue(const QDomElement &e, QColor *value)
288 {
289     if (!Private::checkType(e, "qcolor")) return false;
290     value->setNamedColor(e.attribute("value", "#FFFF0000"));
291     return true;
292 }
293 
findElementByAttibute(QDomNode parent,const QString & tag,const QString & attribute,const QString & key)294 QDomElement findElementByAttibute(QDomNode parent,
295                                   const QString &tag,
296                                   const QString &attribute,
297                                   const QString &key)
298 {
299     QDomNode node = parent.firstChild();
300 
301     while (!node.isNull()) {
302         QDomElement el = node.toElement();
303 
304         if (!el.isNull() && el.tagName() == tag) {
305             QString value = el.attribute(attribute, "<undefined>");
306             if (value == key) return el;
307         }
308 
309         node = node.nextSibling();
310     }
311 
312     return QDomElement();
313 }
314 
315 
316 }
317