Skip to content

Commit

Permalink
Add SVG support
Browse files Browse the repository at this point in the history
  • Loading branch information
adazem009 committed Dec 11, 2023
1 parent 5655f81 commit 4fff9c9
Show file tree
Hide file tree
Showing 10 changed files with 264 additions and 14 deletions.
4 changes: 4 additions & 0 deletions ScratchCPPGui/irenderedtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <qnanoquickitem.h>

class QBuffer;
class QNanoPainter;

namespace libscratchcpp
{
Expand Down Expand Up @@ -59,6 +60,9 @@ class IRenderedTarget : public QNanoQuickItem
virtual void unlockCostume() = 0;

virtual bool mirrorHorizontally() const = 0;

virtual bool isSvg() const = 0;
virtual void paintSvg(QNanoPainter *painter) = 0;
};

} // namespace scratchcppgui
49 changes: 49 additions & 0 deletions ScratchCPPGui/renderedtarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <scratchcpp/iengine.h>
#include <scratchcpp/costume.h>
#include <QtSvg/QSvgRenderer>
#include <qnanopainter.h>

#include "renderedtarget.h"
#include "targetpainter.h"
Expand Down Expand Up @@ -80,6 +82,8 @@ void RenderedTarget::loadCostume(Costume *costume)
m_imageChanged = true;

if (costume->dataFormat() == "svg") {
if (costume != m_costume)
m_svgRenderer.load(QByteArray::fromRawData(static_cast<const char *>(costume->data()), costume->dataSize()));
}

m_costume = costume;
Expand Down Expand Up @@ -202,6 +206,8 @@ void RenderedTarget::doLoadCostume()
Target *target = scratchTarget();

if (m_costume->dataFormat() == "svg") {
QRectF rect = m_svgRenderer.viewBoxF();
calculateSize(target, rect.width(), rect.height());
} else {
m_bitmapBuffer.open(QBuffer::WriteOnly);
m_bitmapBuffer.write(static_cast<const char *>(m_costume->data()), m_costume->dataSize());
Expand All @@ -217,6 +223,41 @@ void RenderedTarget::doLoadCostume()
m_costumeMutex.unlock();
}

void RenderedTarget::paintSvg(QNanoPainter *painter)
{
Q_ASSERT(painter);
QOpenGLContext *context = QOpenGLContext::currentContext();
Q_ASSERT(context);

if (!context)
return;

QOffscreenSurface surface;
surface.setFormat(context->format());
surface.create();
Q_ASSERT(surface.isValid());

QSurface *oldSurface = context->surface();
context->makeCurrent(&surface);

const QRectF drawRect(0, 0, width(), height());
const QSize drawRectSize = drawRect.size().toSize();

/*QOpenGLFramebufferObjectFormat fboFormat;
fboFormat.setSamples(16);
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);*/

QOpenGLPaintDevice device(drawRectSize);
QPainter qPainter;
qPainter.begin(&device);
qPainter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
m_svgRenderer.render(&qPainter, drawRect);
qPainter.end();

context->doneCurrent();
context->makeCurrent(oldSurface);
}

void RenderedTarget::calculateSize(Target *target, double costumeWidth, double costumeHeight)
{
if (m_costume) {
Expand Down Expand Up @@ -258,3 +299,11 @@ bool RenderedTarget::mirrorHorizontally() const
{
return m_mirrorHorizontally;
}

bool RenderedTarget::isSvg() const
{
if (!m_costume)
return false;

return (m_costume->dataFormat() == "svg");
}
5 changes: 5 additions & 0 deletions ScratchCPPGui/renderedtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <qnanoquickitem.h>
#include <QBuffer>
#include <QMutex>
#include <QtSvg/QSvgRenderer>

#include "irenderedtarget.h"

Expand Down Expand Up @@ -55,6 +56,9 @@ class RenderedTarget : public IRenderedTarget

bool mirrorHorizontally() const override;

bool isSvg() const override;
void paintSvg(QNanoPainter *painter) override;

signals:
void engineChanged();
void stageModelChanged();
Expand All @@ -73,6 +77,7 @@ class RenderedTarget : public IRenderedTarget
libscratchcpp::Costume *m_costume = nullptr;
StageModel *m_stageModel = nullptr;
SpriteModel *m_spriteModel = nullptr;
QSvgRenderer m_svgRenderer;
QBuffer m_bitmapBuffer;
QString m_bitmapUniqueKey;
QMutex m_costumeMutex;
Expand Down
8 changes: 6 additions & 2 deletions ScratchCPPGui/targetpainter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,12 @@ void TargetPainter::paint(QNanoPainter *painter)
double width = m_target->width();
double height = m_target->height();

QNanoImage image = QNanoImage::fromCache(painter, m_target->bitmapBuffer(), m_target->bitmapUniqueKey());
painter->drawImage(image, 0, 0, width, height);
if (m_target->isSvg())
m_target->paintSvg(painter);
else {
QNanoImage image = QNanoImage::fromCache(painter, m_target->bitmapBuffer(), m_target->bitmapUniqueKey());
painter->drawImage(image, 0, 0, width, height);
}

m_target->unlockCostume();
}
Expand Down
56 changes: 56 additions & 0 deletions test/image.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions test/mocks/renderedtargetmock.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class RenderedTargetMock : public IRenderedTarget

MOCK_METHOD(bool, mirrorHorizontally, (), (const, override));

MOCK_METHOD(bool, isSvg, (), (const, override));
MOCK_METHOD(void, paintSvg, (QNanoPainter *), (override));

MOCK_METHOD(QNanoQuickItemPainter *, createItemPainter, (), (const, override));
};

Expand Down
Loading

0 comments on commit 4fff9c9

Please sign in to comment.