1 | // Copyright (C) 2020 The Qt Company Ltd. |
---|---|
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #ifndef QQUICKKEYFRAMEDATAUTILS_H |
5 | #define QQUICKKEYFRAMEDATAUTILS_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include <QtCore/QCborStreamReader> |
19 | #include <QtCore/QCborStreamWriter> |
20 | #include <QtCore/QVariant> |
21 | #include <QtCore/QMetaType> |
22 | |
23 | #include <QtCore/QRect> |
24 | #include <QtGui/QVector2D> |
25 | #include <QtGui/QVector3D> |
26 | #include <QtGui/QVector4D> |
27 | #include <QtGui/QQuaternion> |
28 | #include <QtGui/QColor> |
29 | #include <QtCore/private/qglobal_p.h> |
30 | |
31 | // This file contains useful methods to read & write keyframes |
32 | // CBOR binary files and understand the format. |
33 | |
34 | // Read property 'type' value from CBOR and return it as QVariant. |
35 | QVariant readValue(QCborStreamReader &reader, QMetaType::Type type) |
36 | { |
37 | switch (type) { |
38 | case QMetaType::Bool: { |
39 | bool b = reader.toBool(); |
40 | reader.next(); |
41 | return QVariant(b); |
42 | break; |
43 | } |
44 | case QMetaType::Int: { |
45 | int i = reader.toInteger(); |
46 | reader.next(); |
47 | return QVariant(i); |
48 | break; |
49 | } |
50 | case QMetaType::Float: { |
51 | float f = reader.toFloat(); |
52 | reader.next(); |
53 | return QVariant(f); |
54 | break; |
55 | } |
56 | case QMetaType::Double: { |
57 | double d = reader.toDouble(); |
58 | reader.next(); |
59 | return QVariant(d); |
60 | break; |
61 | } |
62 | case QMetaType::QString: { |
63 | QString s = reader.readString().data; |
64 | return QVariant(s); |
65 | break; |
66 | } |
67 | case QMetaType::QVector2D: { |
68 | QVector2D v; |
69 | v.setX(reader.toFloat()); |
70 | reader.next(); |
71 | v.setY(reader.toFloat()); |
72 | reader.next(); |
73 | return QVariant(v); |
74 | break; |
75 | } |
76 | case QMetaType::QVector3D: { |
77 | QVector3D v; |
78 | v.setX(reader.toFloat()); |
79 | reader.next(); |
80 | v.setY(reader.toFloat()); |
81 | reader.next(); |
82 | v.setZ(reader.toFloat()); |
83 | reader.next(); |
84 | return QVariant(v); |
85 | break; |
86 | } |
87 | case QMetaType::QVector4D: { |
88 | QVector4D v; |
89 | v.setX(reader.toFloat()); |
90 | reader.next(); |
91 | v.setY(reader.toFloat()); |
92 | reader.next(); |
93 | v.setZ(reader.toFloat()); |
94 | reader.next(); |
95 | v.setW(reader.toFloat()); |
96 | reader.next(); |
97 | return QVariant(v); |
98 | break; |
99 | } |
100 | case QMetaType::QQuaternion: { |
101 | QQuaternion q; |
102 | q.setScalar(reader.toFloat()); |
103 | reader.next(); |
104 | q.setX(reader.toFloat()); |
105 | reader.next(); |
106 | q.setY(reader.toFloat()); |
107 | reader.next(); |
108 | q.setZ(reader.toFloat()); |
109 | reader.next(); |
110 | return QVariant(q); |
111 | break; |
112 | } |
113 | case QMetaType::QColor: { |
114 | QColor c; |
115 | c.setRed(reader.toInteger()); |
116 | reader.next(); |
117 | c.setGreen(reader.toInteger()); |
118 | reader.next(); |
119 | c.setBlue(reader.toInteger()); |
120 | reader.next(); |
121 | c.setAlpha(reader.toInteger()); |
122 | reader.next(); |
123 | return QVariant(c); |
124 | break; |
125 | } |
126 | case QMetaType::QRect: { |
127 | QRect r; |
128 | r.setX(reader.toInteger()); |
129 | reader.next(); |
130 | r.setY(reader.toInteger()); |
131 | reader.next(); |
132 | r.setWidth(reader.toInteger()); |
133 | reader.next(); |
134 | r.setHeight(reader.toInteger()); |
135 | reader.next(); |
136 | return QVariant(r); |
137 | break; |
138 | } |
139 | default: { |
140 | qWarning() << "Keyframe property type not handled:"<< type; |
141 | } |
142 | } |
143 | |
144 | return QVariant(); |
145 | } |
146 | |
147 | // Read a string from COB. |
148 | QString readString(QCborStreamReader &reader) |
149 | { |
150 | QString result; |
151 | auto r = reader.readString(); |
152 | while (r.status == QCborStreamReader::Ok) { |
153 | result += r.data; |
154 | r = reader.readString(); |
155 | } |
156 | |
157 | if (r.status == QCborStreamReader::Error) { |
158 | // handle error condition |
159 | result.clear(); |
160 | } |
161 | return result; |
162 | } |
163 | |
164 | // Read a real (double or float) from CBOR. |
165 | double readReal(QCborStreamReader &reader) |
166 | { |
167 | double result = 0.0; |
168 | if (reader.isDouble()) { |
169 | result = reader.toDouble(); |
170 | reader.next(); |
171 | } else if (reader.isFloat()) { |
172 | result = reader.toFloat(); |
173 | reader.next(); |
174 | } |
175 | return result; |
176 | } |
177 | |
178 | // Read keyframes file header and return version. |
179 | // If header is not valid, -1 is returned. |
180 | int readKeyframesHeader(QCborStreamReader &reader) |
181 | { |
182 | int version = -1; |
183 | if (reader.lastError() == QCborError::NoError && reader.isArray()) { |
184 | // Start root array |
185 | reader.enterContainer(); |
186 | if (reader.isString()) { |
187 | QString header = readString(reader); |
188 | if (header == QStringLiteral("QTimelineKeyframes")) { |
189 | if (reader.isInteger()) { |
190 | version = reader.toInteger(); |
191 | reader.next(); |
192 | } else { |
193 | qWarning() << "Invalid keyframeSource version"; |
194 | } |
195 | } else { |
196 | qWarning() << "Invalid keyframeSource header"; |
197 | } |
198 | } else { |
199 | qWarning() << "Invalid keyframeSource container"; |
200 | } |
201 | } |
202 | return version; |
203 | } |
204 | |
205 | void writeKeyframesHeader(QCborStreamWriter &writer, QMetaType::Type type, int version = 1) |
206 | { |
207 | // Root array |
208 | writer.startArray(); |
209 | // header name |
210 | writer.append(str: "QTimelineKeyframes"); |
211 | // file version |
212 | writer.append(i: version); |
213 | // property type |
214 | writer.append(i: type); |
215 | } |
216 | |
217 | // Write QVariant value into CBOR in correct type. |
218 | void writeValue(QCborStreamWriter &writer, const QVariant &value) |
219 | { |
220 | const QMetaType type = value.metaType(); |
221 | switch (type.id()) { |
222 | case QMetaType::Bool: { |
223 | bool b = value.toBool(); |
224 | writer.append(b); |
225 | break; |
226 | } |
227 | case QMetaType::Int: { |
228 | int i = value.toInt(); |
229 | writer.append(i); |
230 | break; |
231 | } |
232 | case QMetaType::Float: { |
233 | float f = value.toFloat(); |
234 | writer.append(f); |
235 | break; |
236 | } |
237 | case QMetaType::Double: { |
238 | double d = value.toDouble(); |
239 | writer.append(d); |
240 | break; |
241 | } |
242 | case QMetaType::QVector2D: { |
243 | QVector2D v = value.value<QVector2D>(); |
244 | writer.append(f: v.x()); |
245 | writer.append(f: v.y()); |
246 | break; |
247 | } |
248 | case QMetaType::QVector3D: { |
249 | QVector3D v = value.value<QVector3D>(); |
250 | writer.append(f: v.x()); |
251 | writer.append(f: v.y()); |
252 | writer.append(f: v.z()); |
253 | break; |
254 | } |
255 | case QMetaType::QVector4D: { |
256 | QVector4D v = value.value<QVector4D>(); |
257 | writer.append(f: v.x()); |
258 | writer.append(f: v.y()); |
259 | writer.append(f: v.z()); |
260 | writer.append(f: v.w()); |
261 | break; |
262 | } |
263 | case QMetaType::QQuaternion: { |
264 | QQuaternion q = value.value<QQuaternion>(); |
265 | writer.append(f: q.scalar()); |
266 | writer.append(f: q.x()); |
267 | writer.append(f: q.y()); |
268 | writer.append(f: q.z()); |
269 | break; |
270 | } |
271 | case QMetaType::QColor: { |
272 | QColor c = value.value<QColor>(); |
273 | writer.append(i: c.red()); |
274 | writer.append(i: c.green()); |
275 | writer.append(i: c.blue()); |
276 | writer.append(i: c.alpha()); |
277 | break; |
278 | } |
279 | case QMetaType::QRect: { |
280 | QRect r = value.value<QRect>(); |
281 | writer.append(i: r.x()); |
282 | writer.append(i: r.y()); |
283 | writer.append(i: r.width()); |
284 | writer.append(i: r.height()); |
285 | break; |
286 | } |
287 | default: { |
288 | qDebug() << "Not able to add:"<< value << "of type:"<< type.name(); |
289 | qDebug() << "Please add support for this type into generator."; |
290 | break; |
291 | } |
292 | } |
293 | } |
294 | |
295 | #endif // QQUICKKEYFRAMEDATAUTILS_H |
296 |