QSkinny 0.8.0
C++/Qt UI toolkit
Loading...
Searching...
No Matches
QskGraphicIO.cpp
1/******************************************************************************
2 * QSkinny - Copyright (C) The authors
3 * SPDX-License-Identifier: BSD-3-Clause
4 *****************************************************************************/
5
6#include "QskGraphicIO.h"
7#include "QskGraphic.h"
8#include "QskPainterCommand.h"
9
10#include <qbuffer.h>
11#include <qdatastream.h>
12#include <qfile.h>
13#include <qvector.h>
14
15#include <cstring>
16
17static const char qskMagicNumber[] = "QSKG";
18
19/*
20 To avoid crashes ( fonts ), when svg2qvg was running with a different Qt
21 version, than the one of the application we hardcode
22 the datastream format.
23 */
24static const int qskDataStreamVersion = QDataStream::Qt_5_15;
25
26static inline void qskWritePathData(
27 const QPainterPath& path, QDataStream& s )
28{
29 s << path;
30}
31
32static inline void qskReadPathData(
33 QDataStream& s, QVector< QskPainterCommand >& commands )
34{
35 QPainterPath path;
36 s >> path;
37
38 commands += QskPainterCommand( path );
39}
40
41static inline void qskWritePixmapData(
42 const QskPainterCommand::PixmapData& data, QDataStream& s )
43{
44 s << data.rect << data.pixmap << data.subRect;
45}
46
47static inline void qskReadPixmapData(
48 QDataStream& s, QVector< QskPainterCommand >& commands )
49{
50 QskPainterCommand::PixmapData data;
51
52 s >> data.rect;
53 s >> data.pixmap;
54 s >> data.subRect;
55
56 commands += QskPainterCommand( data.rect, data.pixmap, data.subRect );
57}
58
59static inline void qskWriteImageData(
60 const QskPainterCommand::ImageData& data, QDataStream& s )
61{
62 s << data.rect << data.image << data.subRect;
63}
64
65static inline void qskReadImageData(
66 QDataStream& s, QVector< QskPainterCommand >& commands )
67{
68 QskPainterCommand::ImageData data;
69
70 s >> data.rect;
71 s >> data.image;
72 s >> data.subRect;
73
74 quint8 flags;
75 s >> flags;
76 data.flags = static_cast< Qt::ImageConversionFlags >( flags );
77
78 commands += QskPainterCommand( data.rect, data.image, data.subRect, data.flags );
79}
80
81static inline void qskWriteStateData(
82 const QskPainterCommand::StateData& data, QDataStream& s )
83{
84 s << static_cast< quint16 >( data.flags );
85
86 if ( data.flags & QPaintEngine::DirtyPen )
87 s << data.pen;
88
89 if ( data.flags & QPaintEngine::DirtyBrush )
90 s << data.brush;
91
92 if ( data.flags & QPaintEngine::DirtyBrushOrigin )
93 s << data.brushOrigin;
94
95 if ( data.flags & QPaintEngine::DirtyFont )
96 s << data.font;
97
98 if ( data.flags & QPaintEngine::DirtyBackground )
99 {
100 s << static_cast< quint8 >( data.backgroundMode );
101 s << data.backgroundBrush;
102 }
103
104 if ( data.flags & QPaintEngine::DirtyTransform )
105 s << data.transform;
106
107 if ( data.flags & QPaintEngine::DirtyClipEnabled )
108 s << data.isClipEnabled;
109
110 if ( data.flags & QPaintEngine::DirtyClipRegion )
111 {
112 s << data.clipRegion;
113 s << static_cast< quint8 >( data.clipOperation );
114 }
115
116 if ( data.flags & QPaintEngine::DirtyClipPath )
117 {
118 s << data.clipPath;
119 s << static_cast< quint8 >( data.clipOperation );
120 }
121
122 if ( data.flags & QPaintEngine::DirtyHints )
123 s << static_cast< qint32 >( data.renderHints );
124
125 if ( data.flags & QPaintEngine::DirtyCompositionMode )
126 s << static_cast< qint16 >( data.compositionMode );
127
128 if ( data.flags & QPaintEngine::DirtyOpacity )
129 s << data.opacity;
130}
131
132static inline void qskReadStateData(
133 QDataStream& s, QVector< QskPainterCommand >& commands )
134{
135 QskPainterCommand::StateData data;
136
137 quint16 flags;
138 s >> flags;
139
140 data.flags = static_cast< QPaintEngine::DirtyFlags >( flags );
141
142 if ( data.flags & QPaintEngine::DirtyPen )
143 s >> data.pen;
144
145 if ( data.flags & QPaintEngine::DirtyBrush )
146 s >> data.brush;
147
148 if ( data.flags & QPaintEngine::DirtyBrushOrigin )
149 s >> data.brushOrigin;
150
151 if ( data.flags & QPaintEngine::DirtyFont )
152 s >> data.font;
153
154 if ( data.flags & QPaintEngine::DirtyBackground )
155 {
156 quint8 bgMode = data.backgroundMode;
157 s >> bgMode >> data.backgroundBrush;
158 data.backgroundMode = static_cast< Qt::BGMode >( bgMode );
159 }
160
161 if ( data.flags & QPaintEngine::DirtyTransform )
162 s >> data.transform;
163
164 if ( data.flags & QPaintEngine::DirtyClipEnabled )
165 s >> data.isClipEnabled;
166
167 if ( data.flags & QPaintEngine::DirtyClipRegion )
168 {
169 s >> data.clipRegion;
170
171 quint8 clipOperation;
172 s >> clipOperation;
173 data.clipOperation = static_cast< Qt::ClipOperation >( clipOperation );
174 }
175
176 if ( data.flags & QPaintEngine::DirtyClipPath )
177 {
178 s >> data.clipPath;
179
180 quint8 clipOperation;
181 s >> clipOperation;
182 data.clipOperation = static_cast< Qt::ClipOperation >( clipOperation );
183 }
184
185 if ( data.flags & QPaintEngine::DirtyHints )
186 {
187 qint32 renderHints;
188 s >> renderHints;
189 data.renderHints = static_cast< QPainter::RenderHints >( renderHints );
190 }
191
192 if ( data.flags & QPaintEngine::DirtyCompositionMode )
193 {
194 qint16 compositionMode;
195 s >> compositionMode;
196 data.compositionMode = static_cast< QPainter::CompositionMode >( compositionMode );
197 }
198
199 if ( data.flags & QPaintEngine::DirtyOpacity )
200 s >> data.opacity;
201
202 commands += QskPainterCommand( data );
203}
204
205QskGraphic QskGraphicIO::read( const QString& fileName )
206{
207 QFile file( fileName );
208 if ( file.open( QIODevice::ReadOnly ) == false )
209 {
210 qWarning( "QskGraphicIO::read can't open %s", qPrintable( fileName ) );
211 return QskGraphic();
212 }
213
214 return read( &file );
215}
216
217QskGraphic QskGraphicIO::read( const QByteArray& data )
218{
219 QBuffer buffer;
220 buffer.setData( data );
221
222 return read( &buffer );
223}
224
225QskGraphic QskGraphicIO::read( QIODevice* dev )
226{
227 if ( dev == nullptr )
228 return QskGraphic();
229
230 QDataStream stream( dev );
231#if 1
232 stream.setVersion( qskDataStreamVersion );
233#endif
234 stream.setByteOrder( QDataStream::BigEndian );
235
236 char magicNumber[ 4 ];
237 stream.readRawData( magicNumber, 4 );
238 if ( memcmp( magicNumber, qskMagicNumber, 4 ) != 0 )
239 {
240 qWarning( "QskGraphicIO::read: bad magic number" );
241 return QskGraphic();
242 }
243
244 QRectF viewBox;
245 stream >> viewBox;
246
247 quint32 numCommands;
248 stream >> numCommands;
249
250 QVector< QskPainterCommand > commands;
251 commands.reserve( numCommands );
252
253 for ( uint i = 0; i < numCommands; i++ )
254 {
255 quint8 type;
256 stream >> type;
257
258 switch ( type )
259 {
261 {
262 qskReadPathData( stream, commands );
263 break;
264 }
266 {
267 qskReadPixmapData( stream, commands );
268 break;
269 }
271 {
272 qskReadImageData( stream, commands );
273 break;
274 }
276 {
277 qskReadStateData( stream, commands );
278 break;
279 }
280 default:
281 return QskGraphic();
282 }
283 }
284
285 QskGraphic graphic;
286 graphic.setViewBox( viewBox );
287 graphic.setCommands( commands );
288
289 return graphic;
290}
291
292bool QskGraphicIO::write( const QskGraphic& graphic, const QString& fileName )
293{
294 QFile file( fileName );
295 if ( file.open( QIODevice::WriteOnly | QIODevice::Truncate ) == false )
296 {
297 qWarning( "QskGraphicIO::write can't open %s", qPrintable( fileName ) );
298 return false;
299 }
300
301 return write( graphic, &file );
302}
303
304bool QskGraphicIO::write( const QskGraphic& graphic, QByteArray& data )
305{
306 QBuffer buffer( &data );
307 return write( graphic, &buffer );
308}
309
310bool QskGraphicIO::write( const QskGraphic& graphic, QIODevice* dev )
311{
312 if ( dev == nullptr )
313 return false;
314
315 QDataStream stream( dev );
316#if 1
317 stream.setVersion( qskDataStreamVersion );
318#endif
319 stream.setByteOrder( QDataStream::BigEndian );
320 stream.writeRawData( qskMagicNumber, 4 );
321
322 stream << graphic.viewBox();
323
324 const auto numCommands = graphic.commands().size();
325 const QskPainterCommand* cmds = graphic.commands().constData();
326
327 stream << static_cast< quint32 >( numCommands );
328
329 for ( int i = 0; i < numCommands; i++ )
330 {
331 stream << static_cast< quint8 >( cmds[ i ].type() );
332
333 switch ( cmds[ i ].type() )
334 {
336 {
337 qskWritePathData( *cmds[ i ].path(), stream );
338 break;
339 }
341 {
342 qskWritePixmapData( *cmds[ i ].pixmapData(), stream );
343 break;
344 }
346 {
347 qskWriteImageData( *cmds[ i ].imageData(), stream );
348 break;
349 }
351 {
352 qskWriteStateData( *cmds[ i ].stateData(), stream );
353 break;
354 }
355 default:
356 {
357 // cleanup ???
358 return false;
359 }
360 }
361 }
362
363 return true;
364}
A paint device for scalable graphics.
Definition QskGraphic.h:28
@ Path
Draw a QPainterPath.
@ Image
Draw a QImage.
@ Pixmap
Draw a QPixmap.
@ State
QPainter state change.