@@ -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