qskinny/src/graphic/QskGraphicIO.cpp
2017-07-21 18:21:34 +02:00

344 lines
8.6 KiB
C++

/******************************************************************************
* QSkinny - Copyright (C) 2016 Uwe Rathmann
* This file may be used under the terms of the QSkinny License, Version 1.0
*****************************************************************************/
#include "QskGraphicIO.h"
#include "QskGraphic.h"
#include "QskPainterCommand.h"
#include <QFile>
#include <QBuffer>
#include <QDataStream>
#include <QVector>
#include <cstring>
static const char qskMagicNumber[] = "QSKG";
static inline void qskWritePathData(
const QPainterPath& path, QDataStream& s )
{
s << path;
}
static inline void qskReadPathData(
QDataStream& s, QVector< QskPainterCommand >& commands )
{
QPainterPath path;
s >> path;
commands += QskPainterCommand( path );
}
static inline void qskWritePixmapData(
const QskPainterCommand::PixmapData& data, QDataStream& s )
{
s << data.rect << data.pixmap << data.subRect;
}
static inline void qskReadPixmapData(
QDataStream& s, QVector< QskPainterCommand >& commands )
{
QskPainterCommand::PixmapData data;
s >> data.rect;
s >> data.pixmap;
s >> data.subRect;
commands += QskPainterCommand( data.rect, data.pixmap, data.subRect );
}
static inline void qskWriteImageData(
const QskPainterCommand::ImageData& data, QDataStream& s )
{
s << data.rect << data.image << data.subRect;
}
static inline void qskReadImageData(
QDataStream& s, QVector< QskPainterCommand >& commands )
{
QskPainterCommand::ImageData data;
s >> data.rect;
s >> data.image;
s >> data.subRect;
quint8 flags;
s >> flags;
data.flags = static_cast< Qt::ImageConversionFlags >( flags );
commands += QskPainterCommand( data.rect, data.image, data.subRect, data.flags );
}
static inline void qskWriteStateData(
const QskPainterCommand::StateData& data, QDataStream& s )
{
s << static_cast< quint16 >( data.flags );
if ( data.flags & QPaintEngine::DirtyPen )
s << data.pen;
if ( data.flags & QPaintEngine::DirtyBrush )
s << data.brush;
if ( data.flags & QPaintEngine::DirtyBrushOrigin )
s << data.brushOrigin;
if ( data.flags & QPaintEngine::DirtyFont )
s << data.font;
if ( data.flags & QPaintEngine::DirtyBackground )
{
s << static_cast< quint8 >( data.backgroundMode );
s << data.backgroundBrush;
}
if ( data.flags & QPaintEngine::DirtyTransform )
s << data.transform;
if ( data.flags & QPaintEngine::DirtyClipEnabled )
s << data.isClipEnabled;
if ( data.flags & QPaintEngine::DirtyClipRegion )
{
s << data.clipRegion;
s << static_cast< quint8 >( data.clipOperation );
}
if ( data.flags & QPaintEngine::DirtyClipPath )
{
s << data.clipPath;
s << static_cast< quint8 >( data.clipOperation );
}
if ( data.flags & QPaintEngine::DirtyHints )
s << static_cast< qint32 >( data.renderHints );
if ( data.flags & QPaintEngine::DirtyCompositionMode )
s << static_cast< qint16 >( data.compositionMode );
if ( data.flags & QPaintEngine::DirtyOpacity )
s << data.opacity;
}
static inline void qskReadStateData(
QDataStream& s, QVector< QskPainterCommand >& commands )
{
QskPainterCommand::StateData data;
quint16 flags;
s >> flags;
data.flags = ( QPaintEngine::DirtyFlags ) flags;
if ( data.flags & QPaintEngine::DirtyPen )
s >> data.pen;
if ( data.flags & QPaintEngine::DirtyBrush )
s >> data.brush;
if ( data.flags & QPaintEngine::DirtyBrushOrigin )
s >> data.brushOrigin;
if ( data.flags & QPaintEngine::DirtyFont )
s >> data.font;
if ( data.flags & QPaintEngine::DirtyBackground )
{
quint8 bgMode = data.backgroundMode;
s >> bgMode >> data.backgroundBrush;
data.backgroundMode = static_cast< Qt::BGMode >( bgMode );
}
if ( data.flags & QPaintEngine::DirtyTransform )
s >> data.transform;
if ( data.flags & QPaintEngine::DirtyClipEnabled )
s >> data.isClipEnabled;
if ( data.flags & QPaintEngine::DirtyClipRegion )
{
s >> data.clipRegion;
quint8 clipOperation;
s >> clipOperation;
data.clipOperation = static_cast< Qt::ClipOperation >( clipOperation );
}
if ( data.flags & QPaintEngine::DirtyClipPath )
{
s >> data.clipPath;
quint8 clipOperation;
s >> clipOperation;
data.clipOperation = static_cast< Qt::ClipOperation >( clipOperation );
}
if ( data.flags & QPaintEngine::DirtyHints )
{
qint32 renderHints;
s >> renderHints;
data.renderHints = static_cast< QPainter::RenderHints >( renderHints );
}
if ( data.flags & QPaintEngine::DirtyCompositionMode )
{
qint16 compositionMode;
s >> compositionMode;
data.compositionMode = static_cast< QPainter::CompositionMode >( compositionMode );
}
if ( data.flags & QPaintEngine::DirtyOpacity )
s >> data.opacity;
commands += QskPainterCommand( data );
}
QskGraphic QskGraphicIO::read( const QString& fileName )
{
QFile file( fileName );
if ( file.open( QIODevice::ReadOnly ) == false )
{
qWarning( "QskGraphicIO::read can't open %s", qPrintable( fileName ) );
return QskGraphic();
}
return read( &file );
}
QskGraphic QskGraphicIO::read( const QByteArray& data )
{
QBuffer buffer;
buffer.setData( data );
return read( &buffer );
}
QskGraphic QskGraphicIO::read( QIODevice* dev )
{
if ( dev == nullptr )
return QskGraphic();
QDataStream stream( dev );
stream.setByteOrder( QDataStream::BigEndian );
char magicNumber[4];
stream.readRawData( magicNumber, 4 );
if ( memcmp( magicNumber, qskMagicNumber, 4 ) != 0 )
{
qWarning( "QskGraphicIO::read: bad magic number" );
return QskGraphic();
}
quint32 numCommands;
stream >> numCommands;
QVector< QskPainterCommand > commands;
commands.reserve( numCommands );
for ( uint i = 0; i < numCommands; i++ )
{
quint8 type;
stream >> type;
switch( type )
{
case QskPainterCommand::Path:
{
qskReadPathData( stream, commands );
break;
}
case QskPainterCommand::Pixmap:
{
qskReadPixmapData( stream, commands );
break;
}
case QskPainterCommand::Image:
{
qskReadImageData( stream, commands );
break;
}
case QskPainterCommand::State:
{
qskReadStateData( stream, commands );
break;
}
default:
return QskGraphic();
}
}
QskGraphic graphic;
graphic.setCommands( commands );
return graphic;
}
bool QskGraphicIO::write( const QskGraphic& graphic, const QString& fileName )
{
QFile file( fileName );
if ( file.open( QIODevice::WriteOnly | QIODevice::Truncate ) == false )
{
qWarning( "QskGraphicIO::write can't open %s", qPrintable( fileName ) );
return false;
}
return write( graphic, &file );
}
bool QskGraphicIO::write( const QskGraphic& graphic, QByteArray& data )
{
QBuffer buffer( &data );
return write( graphic, &buffer );
}
bool QskGraphicIO::write( const QskGraphic& graphic, QIODevice* dev )
{
if ( dev == nullptr )
return false;
QDataStream stream( dev );
stream.setByteOrder( QDataStream::BigEndian ),
stream.writeRawData( qskMagicNumber, 4 );
const int numCommands = graphic.commands().size();
const QskPainterCommand* cmds = graphic.commands().constData();
stream << static_cast< quint32 >( numCommands );
for ( int i = 0; i < numCommands; i++ )
{
stream << static_cast< quint8 > ( cmds[i].type() );
switch( cmds[i].type() )
{
case QskPainterCommand::Path:
{
qskWritePathData( *cmds[i].path(), stream );
break;
}
case QskPainterCommand::Pixmap:
{
qskWritePixmapData( *cmds[i].pixmapData(), stream );
break;
}
case QskPainterCommand::Image:
{
qskWriteImageData( *cmds[i].imageData(), stream );
break;
}
case QskPainterCommand::State:
{
qskWriteStateData( *cmds[i].stateData(), stream );
break;
}
default:
{
// cleanup ???
return false;
}
}
}
return true;
}