graphic/QskGraphicIO.cpp

Functions

  Name
void qskWritePathData(const QPainterPath & path, QDataStream & s)
void qskReadPathData(QDataStream & s, QVector< QskPainterCommand > & commands)
void qskWritePixmapData(const QskPainterCommand::PixmapData & data, QDataStream & s)
void qskReadPixmapData(QDataStream & s, QVector< QskPainterCommand > & commands)
void qskWriteImageData(const QskPainterCommand::ImageData & data, QDataStream & s)
void qskReadImageData(QDataStream & s, QVector< QskPainterCommand > & commands)
void qskWriteStateData(const QskPainterCommand::StateData & data, QDataStream & s)
void qskReadStateData(QDataStream & s, QVector< QskPainterCommand > & commands)

Attributes

  Name
const char qskMagicNumber
const int qskDataStreamVersion

Functions Documentation

function qskWritePathData

static inline void qskWritePathData(
    const QPainterPath & path,
    QDataStream & s
)

function qskReadPathData

static inline void qskReadPathData(
    QDataStream & s,
    QVector< QskPainterCommand > & commands
)

function qskWritePixmapData

static inline void qskWritePixmapData(
    const QskPainterCommand::PixmapData & data,
    QDataStream & s
)

function qskReadPixmapData

static inline void qskReadPixmapData(
    QDataStream & s,
    QVector< QskPainterCommand > & commands
)

function qskWriteImageData

static inline void qskWriteImageData(
    const QskPainterCommand::ImageData & data,
    QDataStream & s
)

function qskReadImageData

static inline void qskReadImageData(
    QDataStream & s,
    QVector< QskPainterCommand > & commands
)

function qskWriteStateData

static inline void qskWriteStateData(
    const QskPainterCommand::StateData & data,
    QDataStream & s
)

function qskReadStateData

static inline void qskReadStateData(
    QDataStream & s,
    QVector< QskPainterCommand > & commands
)

Attributes Documentation

variable qskMagicNumber

static const char qskMagicNumber = "QSKG";

variable qskDataStreamVersion

static const int qskDataStreamVersion = QDataStream::Qt_5_6;

Source code

/******************************************************************************
 * 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 <qbuffer.h>
#include <qdatastream.h>
#include <qfile.h>
#include <qvector.h>

#include <cstring>

static const char qskMagicNumber[] = "QSKG";

/*
    To avoid crashes ( fonts ), when svg2qvg was running with a different Qt
    version, than the one of the application we hardcode
    the datastream format to Qt 5.6. Once everything is running with
    Qt 5.15 we can increase the version. TODO ...
 */
static const int qskDataStreamVersion = QDataStream::Qt_5_6;

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 );
#if 1
    stream.setVersion( qskDataStreamVersion );
#endif
    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 );
#if 1
    stream.setVersion( qskDataStreamVersion );
#endif
    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;
}

Updated on 28 July 2023 at 14:02:30 CEST