Skip to content

Commit 0bc605a

Browse files
committed
Use QNanoPainter to draw pen lines
1 parent a244e4e commit 0bc605a

File tree

6 files changed

+40
-42
lines changed

6 files changed

+40
-42
lines changed

src/penlayer.cpp

Lines changed: 30 additions & 29 deletions
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,30 @@ 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+
QNanoColor col(penAttributes.color.red(), penAttributes.color.green(), penAttributes.color.blue(), penAttributes.color.alpha());
113+
m_painter->setStrokeStyle(col);
114+
m_painter->setFillStyle(col);
115+
m_painter->setLineJoin(QNanoPainter::JOIN_ROUND);
116+
m_painter->setLineCap(QNanoPainter::CAP_ROUND);
117+
m_painter->setAntialias(m_antialiasingEnabled ? 1.0f : 0.0f);
118+
m_painter->beginPath();
119+
120+
// Width 1 and 3 lines need to be offset by 0.5
121+
const double offset = (std::fmod(std::max(4 - penAttributes.diameter, 0.0), 2)) / 2;
115122

116123
// 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);
124+
if (x0 == x1 && y0 == y1) {
125+
m_painter->circle(x0 + offset, y0 + offset, penAttributes.diameter / 2);
126+
m_painter->fill();
127+
} else {
128+
m_painter->moveTo(x0 + offset, y0 + offset);
129+
m_painter->lineTo(x1 + offset, y1 + offset);
130+
m_painter->stroke();
131+
}
121132

122133
// End painting
123-
painter.endNativePainting();
124-
painter.end();
134+
m_painter->endFrame();
125135
m_fbo->release();
126136

127137
m_textureDirty = true;
@@ -239,13 +249,4 @@ void PenLayer::updateTexture()
239249

240250
m_textureDirty = false;
241251
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());
251252
}

src/penlayer.h

Lines changed: 2 additions & 5 deletions
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;

test/lines.png

0 Bytes
Loading

test/lines_old.png

-2.07 KB
Binary file not shown.

test/penlayer/penlayer_test.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ TEST_F(PenLayerTest, FramebufferObject)
8181
ASSERT_EQ(fbo->width(), 480);
8282
ASSERT_EQ(fbo->height(), 360);
8383
ASSERT_EQ(fbo->format().attachment(), QOpenGLFramebufferObject::CombinedDepthStencil);
84-
ASSERT_EQ(fbo->format().samples(), 4);
84+
ASSERT_EQ(fbo->format().samples(), 0);
8585

8686
penLayer.setAntialiasingEnabled(false);
8787
ASSERT_FALSE(penLayer.antialiasingEnabled());
@@ -309,25 +309,25 @@ TEST_F(PenLayerTest, TextureData)
309309
attr.color = QColor(0, 255, 0, 255);
310310
attr.diameter = 1;
311311
penLayer.drawLine(attr, 0, -1, 1, 1);
312-
ASSERT_EQ(penLayer.colorAtScratchPoint(0, 1), qRgb(0, 255, 0));
312+
ASSERT_EQ(penLayer.colorAtScratchPoint(0, 1), qRgba(0, 0, 0, 0));
313313
ASSERT_EQ(penLayer.colorAtScratchPoint(0, 0), qRgb(0, 255, 0));
314314
ASSERT_EQ(penLayer.colorAtScratchPoint(-3, 1), qRgba(0, 0, 0, 0));
315315

316316
bounds = penLayer.getBounds();
317317
ASSERT_EQ(bounds.left(), 0);
318-
ASSERT_EQ(bounds.top(), 1);
319-
ASSERT_EQ(bounds.right(), 1);
320-
ASSERT_EQ(bounds.bottom(), -1);
318+
ASSERT_EQ(bounds.top(), 0);
319+
ASSERT_EQ(bounds.right(), 2);
320+
ASSERT_EQ(bounds.bottom(), -2);
321321

322322
attr.diameter = 2;
323323
penLayer.drawPoint(attr, -2, 0);
324-
ASSERT_EQ(penLayer.colorAtScratchPoint(0, 1), qRgb(0, 255, 0));
324+
ASSERT_EQ(penLayer.colorAtScratchPoint(0, 1), qRgba(0, 0, 0, 0));
325325
ASSERT_EQ(penLayer.colorAtScratchPoint(0, 0), qRgb(0, 255, 0));
326326
ASSERT_EQ(penLayer.colorAtScratchPoint(-3, 1), qRgb(0, 255, 0));
327327

328328
bounds = penLayer.getBounds();
329329
ASSERT_EQ(bounds.left(), -3);
330330
ASSERT_EQ(bounds.top(), 1);
331-
ASSERT_EQ(bounds.right(), 1);
332-
ASSERT_EQ(bounds.bottom(), -1);
331+
ASSERT_EQ(bounds.right(), 2);
332+
ASSERT_EQ(bounds.bottom(), -2);
333333
}

test/points.png

-7 Bytes
Loading

0 commit comments

Comments
 (0)