@@ -58,11 +58,7 @@ void PenLayer::setEngine(libscratchcpp::IEngine *newEngine)
5858
5959 if (m_engine && QOpenGLContext::currentContext()) {
6060 m_projectPenLayers[m_engine] = this;
61- QOpenGLFramebufferObjectFormat fboFormat;
62- fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
63- m_fbo = std::make_unique<QOpenGLFramebufferObject>(m_engine->stageWidth(), m_engine->stageHeight(), fboFormat);
64- Q_ASSERT(m_fbo->isValid());
65- m_texture = Texture(m_fbo->texture(), m_fbo->size());
61+ createFbo();
6662
6763 if (!m_painter)
6864 m_painter = std::make_unique<QNanoPainter>();
@@ -106,6 +102,21 @@ void PenLayer::setEngine(libscratchcpp::IEngine *newEngine)
106102 emit engineChanged();
107103}
108104
105+ bool PenLayer::hqPen() const
106+ {
107+ return m_hqPen;
108+ }
109+
110+ void PenLayer::setHqPen(bool newHqPen)
111+ {
112+ if (m_hqPen == newHqPen)
113+ return;
114+
115+ m_hqPen = newHqPen;
116+ createFbo();
117+ emit hqPenChanged();
118+ }
119+
109120void scratchcpprender::PenLayer::clear()
110121{
111122 if (!m_fbo)
@@ -138,16 +149,23 @@ void scratchcpprender::PenLayer::drawLine(const PenAttributes &penAttributes, do
138149
139150 m_painter->beginFrame(m_fbo->width(), m_fbo->height());
140151
152+ // Apply scale (HQ pen)
153+ x0 *= m_scale;
154+ y0 *= m_scale;
155+ x1 *= m_scale;
156+ y1 *= m_scale;
157+
141158 // Translate to Scratch coordinate system
142- double stageWidthHalf = m_engine->stageWidth () / 2;
143- double stageHeightHalf = m_engine->stageHeight () / 2;
159+ double stageWidthHalf = width () / 2;
160+ double stageHeightHalf = height () / 2;
144161 x0 += stageWidthHalf;
145162 y0 = stageHeightHalf - y0;
146163 x1 += stageWidthHalf;
147164 y1 = stageHeightHalf - y1;
148165
149166 // Set pen attributes
150- m_painter->setLineWidth(penAttributes.diameter);
167+ const double diameter = penAttributes.diameter * m_scale;
168+ m_painter->setLineWidth(diameter);
151169 m_painter->setStrokeStyle(penAttributes.color);
152170 m_painter->setFillStyle(penAttributes.color);
153171 m_painter->setLineJoin(QNanoPainter::JOIN_ROUND);
@@ -156,11 +174,11 @@ void scratchcpprender::PenLayer::drawLine(const PenAttributes &penAttributes, do
156174 m_painter->beginPath();
157175
158176 // Width 1 and 3 lines need to be offset by 0.5
159- const double offset = (std::fmod(std::max(4 - penAttributes. diameter, 0.0), 2)) / 2;
177+ const double offset = (std::fmod(std::max(4 - diameter, 0.0), 2)) / 2;
160178
161179 // If the start and end coordinates are the same, draw a point, otherwise draw a line
162180 if (x0 == x1 && y0 == y1) {
163- m_painter->circle(x0 + offset, y0 + offset, penAttributes. diameter / 2);
181+ m_painter->circle(x0 + offset, y0 + offset, diameter / 2);
164182 m_painter->fill();
165183 } else {
166184 m_painter->moveTo(x0 + offset, y0 + offset);
@@ -223,6 +241,9 @@ void PenLayer::stamp(IRenderedTarget *target)
223241 } else
224242 costume = target->stageModel()->stage()->currentCostume();
225243
244+ // Apply scale (HQ pen)
245+ scale *= m_scale;
246+
226247 const double bitmapRes = costume->bitmapResolution();
227248 const double centerX = costume->rotationCenterX() / bitmapRes;
228249 const double centerY = costume->rotationCenterY() / bitmapRes;
@@ -234,8 +255,11 @@ void PenLayer::stamp(IRenderedTarget *target)
234255
235256 const double textureScale = texture.width() / static_cast<double>(target->costumeWidth());
236257
258+ // Apply scale (HQ pen)
259+ x *= m_scale;
260+ y *= m_scale;
261+
237262 // Translate the coordinates
238- // TODO: Apply scale (HQ pen)
239263 x = std::floor(x + m_texture.width() / 2.0);
240264 y = std::floor(-y + m_texture.height() / 2.0);
241265
@@ -352,8 +376,11 @@ QRgb PenLayer::colorAtScratchPoint(double x, double y) const
352376 const double width = m_texture.width();
353377 const double height = m_texture.height();
354378
379+ // Apply scale (HQ pen)
380+ x *= m_scale;
381+ y *= m_scale;
382+
355383 // Translate the coordinates
356- // TODO: Apply scale
357384 x = std::floor(x + width / 2.0);
358385 y = std::floor(-y + height / 2.0);
359386
@@ -393,7 +420,6 @@ const libscratchcpp::Rect &PenLayer::getBounds() const
393420 }
394421
395422 for (const QPointF &point : points) {
396- // TODO: Apply scale
397423 double x = point.x() - width / 2;
398424 double y = -point.y() + height / 2;
399425
@@ -410,10 +436,10 @@ const libscratchcpp::Rect &PenLayer::getBounds() const
410436 bottom = y;
411437 }
412438
413- m_bounds.setLeft(left);
414- m_bounds.setTop(top);
415- m_bounds.setRight(right + 1);
416- m_bounds.setBottom(bottom - 1);
439+ m_bounds.setLeft(left / m_scale );
440+ m_bounds.setTop(top / m_scale );
441+ m_bounds.setRight(right / m_scale + 1);
442+ m_bounds.setBottom(bottom / m_scale - 1);
417443 }
418444
419445 return m_bounds;
@@ -439,6 +465,33 @@ QNanoQuickItemPainter *PenLayer::createItemPainter() const
439465 return new PenLayerPainter;
440466}
441467
468+ void PenLayer::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
469+ {
470+ if (m_hqPen && newGeometry != oldGeometry)
471+ createFbo();
472+
473+ QNanoQuickItem::geometryChange(newGeometry, oldGeometry);
474+ }
475+
476+ void PenLayer::createFbo()
477+ {
478+ if (!QOpenGLContext::currentContext() || !m_engine)
479+ return;
480+
481+ QOpenGLFramebufferObjectFormat fboFormat;
482+ fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
483+
484+ QOpenGLFramebufferObject *newFbo = new QOpenGLFramebufferObject(width(), height(), fboFormat);
485+ Q_ASSERT(newFbo->isValid());
486+
487+ if (m_fbo)
488+ QOpenGLFramebufferObject::blitFramebuffer(newFbo, m_fbo.get());
489+
490+ m_fbo.reset(newFbo);
491+ m_texture = Texture(m_fbo->texture(), m_fbo->size());
492+ m_scale = width() / m_engine->stageWidth();
493+ }
494+
442495void PenLayer::updateTexture()
443496{
444497 if (!m_fbo)
0 commit comments