Skip to content

Commit 9bf9f6b

Browse files
authored
Merge pull request #127 from scratchcpp/refactor_pen_rendering
Refactor pen rendering
2 parents a244e4e + bcbe09b commit 9bf9f6b

12 files changed

+127
-133
lines changed

src/penattributes.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22

33
#pragma once
44

5-
#include <QColor>
5+
#include <qnanocolor.h>
66

77
namespace scratchcpprender
88
{
99

1010
struct PenAttributes
1111
{
12-
QColor color = QColor(0, 0, 255);
12+
QNanoColor color = QNanoColor(0, 0, 255);
1313
double diameter = 1;
1414
};
1515

src/penlayer.cpp

+29-29
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ std::unordered_map<libscratchcpp::IEngine *, IPenLayer *> PenLayer::m_projectPen
1111
PenLayer::PenLayer(QNanoQuickItem *parent) :
1212
IPenLayer(parent)
1313
{
14-
m_fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
15-
m_fboFormat.setSamples(m_antialiasingEnabled ? 4 : 0);
1614
setSmooth(false);
1715
}
1816

@@ -30,7 +28,6 @@ bool PenLayer::antialiasingEnabled() const
3028
void PenLayer::setAntialiasingEnabled(bool enabled)
3129
{
3230
m_antialiasingEnabled = enabled;
33-
m_fboFormat.setSamples(enabled ? 4 : 0);
3431
}
3532

3633
libscratchcpp::IEngine *PenLayer::engine() const
@@ -50,10 +47,15 @@ void PenLayer::setEngine(libscratchcpp::IEngine *newEngine)
5047

5148
if (m_engine && QOpenGLContext::currentContext()) {
5249
m_projectPenLayers[m_engine] = this;
53-
m_fbo = std::make_unique<QOpenGLFramebufferObject>(m_engine->stageWidth(), m_engine->stageHeight(), m_fboFormat);
50+
QOpenGLFramebufferObjectFormat fboFormat;
51+
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
52+
m_fbo = std::make_unique<QOpenGLFramebufferObject>(m_engine->stageWidth(), m_engine->stageHeight(), fboFormat);
5453
Q_ASSERT(m_fbo->isValid());
54+
m_texture = Texture(m_fbo->texture(), m_fbo->size());
55+
56+
if (!m_painter)
57+
m_painter = std::make_unique<QNanoPainter>();
5558

56-
m_paintDevice = std::make_unique<QOpenGLPaintDevice>(m_fbo->size());
5759
clear();
5860
}
5961

@@ -89,15 +91,13 @@ void scratchcpprender::PenLayer::drawPoint(const PenAttributes &penAttributes, d
8991

9092
void scratchcpprender::PenLayer::drawLine(const PenAttributes &penAttributes, double x0, double y0, double x1, double y1)
9193
{
92-
if (!m_fbo || !m_paintDevice || !m_engine)
94+
if (!m_fbo || !m_painter || !m_engine)
9395
return;
9496

9597
// Begin painting
9698
m_fbo->bind();
97-
QPainter painter(m_paintDevice.get());
98-
painter.beginNativePainting();
99-
painter.setRenderHint(QPainter::Antialiasing, m_antialiasingEnabled);
100-
painter.setRenderHint(QPainter::SmoothPixmapTransform, false);
99+
100+
m_painter->beginFrame(m_fbo->width(), m_fbo->height());
101101

102102
// Translate to Scratch coordinate system
103103
double stageWidthHalf = m_engine->stageWidth() / 2;
@@ -108,20 +108,29 @@ void scratchcpprender::PenLayer::drawLine(const PenAttributes &penAttributes, do
108108
y1 = stageHeightHalf - y1;
109109

110110
// Set pen attributes
111-
QPen pen(penAttributes.color);
112-
pen.setWidthF(penAttributes.diameter);
113-
pen.setCapStyle(Qt::RoundCap);
114-
painter.setPen(pen);
111+
m_painter->setLineWidth(penAttributes.diameter);
112+
m_painter->setStrokeStyle(penAttributes.color);
113+
m_painter->setFillStyle(penAttributes.color);
114+
m_painter->setLineJoin(QNanoPainter::JOIN_ROUND);
115+
m_painter->setLineCap(QNanoPainter::CAP_ROUND);
116+
m_painter->setAntialias(m_antialiasingEnabled ? 1.0f : 0.0f);
117+
m_painter->beginPath();
118+
119+
// Width 1 and 3 lines need to be offset by 0.5
120+
const double offset = (std::fmod(std::max(4 - penAttributes.diameter, 0.0), 2)) / 2;
115121

116122
// If the start and end coordinates are the same, draw a point, otherwise draw a line
117-
if (x0 == x1 && y0 == y1)
118-
painter.drawPoint(x0, y0);
119-
else
120-
painter.drawLine(x0, y0, x1, y1);
123+
if (x0 == x1 && y0 == y1) {
124+
m_painter->circle(x0 + offset, y0 + offset, penAttributes.diameter / 2);
125+
m_painter->fill();
126+
} else {
127+
m_painter->moveTo(x0 + offset, y0 + offset);
128+
m_painter->lineTo(x1 + offset, y1 + offset);
129+
m_painter->stroke();
130+
}
121131

122132
// End painting
123-
painter.endNativePainting();
124-
painter.end();
133+
m_painter->endFrame();
125134
m_fbo->release();
126135

127136
m_textureDirty = true;
@@ -239,13 +248,4 @@ void PenLayer::updateTexture()
239248

240249
m_textureDirty = false;
241250
m_textureManager.removeTexture(m_texture);
242-
243-
if (!m_resolvedFbo || m_resolvedFbo->size() != m_fbo->size()) {
244-
QOpenGLFramebufferObjectFormat format;
245-
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
246-
m_resolvedFbo = std::make_unique<QOpenGLFramebufferObject>(m_fbo->size(), format);
247-
}
248-
249-
QOpenGLFramebufferObject::blitFramebuffer(m_resolvedFbo.get(), m_fbo.get());
250-
m_texture = Texture(m_resolvedFbo->texture(), m_resolvedFbo->size());
251251
}

src/penlayer.h

+2-5
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
#pragma once
44

55
#include <QOpenGLFramebufferObject>
6-
#include <QOpenGLPaintDevice>
76
#include <QOpenGLFunctions>
8-
#include <QPainter>
7+
#include <qnanopainter.h>
98
#include <scratchcpp/iengine.h>
109

1110
#include "ipenlayer.h"
@@ -56,9 +55,7 @@ class PenLayer : public IPenLayer
5655
bool m_antialiasingEnabled = true;
5756
libscratchcpp::IEngine *m_engine = nullptr;
5857
std::unique_ptr<QOpenGLFramebufferObject> m_fbo;
59-
std::unique_ptr<QOpenGLFramebufferObject> m_resolvedFbo;
60-
std::unique_ptr<QOpenGLPaintDevice> m_paintDevice;
61-
QOpenGLFramebufferObjectFormat m_fboFormat;
58+
std::unique_ptr<QNanoPainter> m_painter;
6259
std::unique_ptr<QOpenGLFunctions> m_glF;
6360
Texture m_texture;
6461
bool m_textureDirty = true;

src/penlayerpainter.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ void PenLayerPainter::paint(QNanoPainter *painter)
2424
// Custom FBO - only used for testing
2525
QOpenGLFramebufferObject *targetFbo = m_targetFbo ? m_targetFbo : framebufferObject();
2626

27-
QOpenGLFramebufferObjectFormat format;
28-
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
29-
3027
// Blit the FBO to the item FBO
3128
QOpenGLFramebufferObject::blitFramebuffer(targetFbo, m_fbo);
3229
}

src/penstate.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ struct PenState
3131
const int v = brightness * 255 / 100;
3232
const int a = 255 - transparency * 255 / 100;
3333

34-
penAttributes.color = QColor::fromHsv(h, s, v, a);
34+
penAttributes.color = QNanoColor::fromQColor(QColor::fromHsv(h, s, v, a));
3535
}
3636
};
3737

0 commit comments

Comments
 (0)