Line data Source code
1 : /*
2 : * SPDX-License-Identifier: GPL-3.0-only
3 : * MuseScore-Studio-CLA-applies
4 : *
5 : * MuseScore Studio
6 : * Music Composition & Notation
7 : *
8 : * Copyright (C) 2021 MuseScore Limited and others
9 : *
10 : * This program is free software: you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License version 3 as
12 : * published by the Free Software Foundation.
13 : *
14 : * This program is distributed in the hope that it will be useful,
15 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 : * GNU General Public License for more details.
18 : *
19 : * You should have received a copy of the GNU General Public License
20 : * along with this program. If not, see <https://www.gnu.org/licenses/>.
21 : */
22 :
23 : #include "xmlreader.h"
24 :
25 : #include "log.h"
26 :
27 : using namespace mu;
28 : using namespace muse::draw;
29 :
30 : namespace mu::engraving {
31 3968 : XmlReader::~XmlReader()
32 : {
33 3968 : }
34 :
35 999 : PointF XmlReader::readPoint()
36 : {
37 999 : assert(tokenType() == XmlStreamReader::StartElement);
38 : #ifndef NDEBUG
39 999 : if (!hasAttribute("x")) {
40 0 : LOGD("XmlReader::readPoint: x attribute missing: %s", name().ascii());
41 0 : unknown();
42 : }
43 999 : if (!hasAttribute("y")) {
44 0 : LOGD("XmlReader::readPoint: y attribute missing: %s", name().ascii());
45 0 : unknown();
46 : }
47 : #endif
48 999 : double x = doubleAttribute("x", 0.0);
49 999 : double y = doubleAttribute("y", 0.0);
50 999 : readNext();
51 999 : return PointF(x, y);
52 : }
53 :
54 : //---------------------------------------------------------
55 : // readColor
56 : //---------------------------------------------------------
57 :
58 306 : Color XmlReader::readColor()
59 : {
60 306 : assert(tokenType() == XmlStreamReader::StartElement);
61 306 : Color c;
62 306 : c.setRed(intAttribute("r"));
63 306 : c.setGreen(intAttribute("g"));
64 306 : c.setBlue(intAttribute("b"));
65 306 : c.setAlpha(intAttribute("a", 255));
66 306 : skipCurrentElement();
67 306 : return c;
68 : }
69 :
70 : //---------------------------------------------------------
71 : // readSize
72 : //---------------------------------------------------------
73 :
74 14 : SizeF XmlReader::readSize()
75 : {
76 14 : assert(tokenType() == XmlStreamReader::StartElement);
77 14 : SizeF p;
78 14 : p.setWidth(doubleAttribute("w", 0.0));
79 14 : p.setHeight(doubleAttribute("h", 0.0));
80 14 : skipCurrentElement();
81 14 : return p;
82 : }
83 :
84 0 : ScaleF XmlReader::readScale()
85 : {
86 0 : assert(tokenType() == XmlStreamReader::StartElement);
87 0 : ScaleF p;
88 0 : p.setWidth(doubleAttribute("w", 0.0));
89 0 : p.setHeight(doubleAttribute("h", 0.0));
90 0 : skipCurrentElement();
91 0 : return p;
92 : }
93 :
94 : //---------------------------------------------------------
95 : // readRect
96 : //---------------------------------------------------------
97 :
98 0 : RectF XmlReader::readRect()
99 : {
100 0 : assert(tokenType() == XmlStreamReader::StartElement);
101 0 : RectF p;
102 0 : p.setLeft(doubleAttribute("x", 0.0));
103 0 : p.setTop(doubleAttribute("y", 0.0));
104 0 : p.setWidth(doubleAttribute("w", 0.0));
105 0 : p.setHeight(doubleAttribute("h", 0.0));
106 0 : skipCurrentElement();
107 0 : return p;
108 : }
109 :
110 : //---------------------------------------------------------
111 : // readFraction
112 : // recognizes this two styles:
113 : // <move z="2" n="4"/> (old style)
114 : // <move>2/4</move> (new style)
115 : //---------------------------------------------------------
116 :
117 14368 : Fraction XmlReader::readFraction()
118 : {
119 14368 : assert(tokenType() == XmlStreamReader::StartElement);
120 14368 : int z = intAttribute("z", 0);
121 14368 : int n = intAttribute("n", 1);
122 14368 : AsciiStringView s = readAsciiText();
123 14368 : if (!s.empty()) {
124 14181 : size_t i = s.indexOf('/');
125 14181 : if (i == muse::nidx) {
126 62 : return Fraction::fromTicks(s.toInt());
127 : } else {
128 14119 : String str = String::fromAscii(s.ascii());
129 14119 : z = str.left(i).toInt();
130 14119 : n = str.mid(i + 1).toInt();
131 14119 : }
132 : }
133 14306 : return Fraction(z, n);
134 : }
135 :
136 : //---------------------------------------------------------
137 : // unknown
138 : // unknown tag read
139 : //---------------------------------------------------------
140 :
141 2722 : void XmlReader::unknown()
142 : {
143 2722 : if (XmlStreamReader::error()) {
144 0 : LOGD("%s ", muPrintable(errorString()));
145 : }
146 2722 : if (!m_docName.isEmpty()) {
147 2587 : LOGD() << "tag in <" << m_docName << "> byte offset " << byteOffset() + m_byteOffsetAdjustment << ": " << name();
148 : } else {
149 135 : LOGD() << "byte offset " << byteOffset() + m_byteOffsetAdjustment << ": " << name();
150 : }
151 2722 : skipCurrentElement();
152 2722 : }
153 :
154 1 : double XmlReader::readDouble(double min, double max)
155 : {
156 1 : double val = readDouble();
157 1 : if (val < min) {
158 0 : val = min;
159 1 : } else if (val > max) {
160 0 : val = max;
161 : }
162 1 : return val;
163 : }
164 :
165 : //---------------------------------------------------------
166 : // htmlToString
167 : //---------------------------------------------------------
168 :
169 1572 : void XmlReader::htmlToString(int level, String* s)
170 : {
171 1572 : bool selfClosing = noChildren();
172 1572 : *s += u'<' + String::fromAscii(name().ascii());
173 2445 : for (const Attribute& a : attributes()) {
174 873 : *s += u' ' + String::fromAscii(a.name.ascii()) + u"=\"" + a.value + u'\"';
175 1572 : }
176 1572 : *s += selfClosing ? u"/>" : u">";
177 1572 : ++level;
178 : for (;;) {
179 2864 : XmlStreamReader::TokenType t = readNext();
180 2864 : switch (t) {
181 533 : case XmlStreamReader::StartElement:
182 533 : htmlToString(level, s);
183 533 : break;
184 1572 : case XmlStreamReader::EndElement:
185 1572 : if (!selfClosing) {
186 1002 : *s += u"</" + String::fromAscii(name().ascii()) + u'>';
187 : }
188 1572 : --level;
189 1572 : return;
190 759 : case XmlStreamReader::Characters:
191 759 : if (!s->empty() || !isWhitespace()) {
192 759 : *s += text().toXmlEscaped();
193 : } else {
194 0 : LOGD() << "ignoring whitespace";
195 : }
196 759 : break;
197 0 : case XmlStreamReader::Comment:
198 0 : break;
199 :
200 0 : default:
201 0 : LOGD() << "htmlToString: read token: " << tokenString();
202 0 : return;
203 : }
204 1292 : }
205 : }
206 :
207 : //-------------------------------------------------------------------
208 : // readXml
209 : // read verbatim until end tag of current level is reached
210 : //-------------------------------------------------------------------
211 :
212 7376 : String XmlReader::readXml()
213 : {
214 7376 : String s;
215 7376 : int level = 1;
216 15471 : for (XmlStreamReader::TokenType t = readNext(); t != XmlStreamReader::EndElement; t = readNext()) {
217 8095 : switch (t) {
218 1039 : case XmlStreamReader::StartElement:
219 1039 : htmlToString(level, &s);
220 1039 : break;
221 0 : case XmlStreamReader::EndElement:
222 0 : break;
223 7056 : case XmlStreamReader::Characters:
224 7056 : if (!isWhitespace()) {
225 7056 : s += text().toXmlEscaped();
226 : }
227 7056 : break;
228 0 : case XmlStreamReader::Comment:
229 0 : break;
230 :
231 0 : default:
232 0 : LOGD() << "read token: " << tokenString();
233 0 : return s;
234 : }
235 : }
236 7376 : return s;
237 0 : }
238 : }
|