Skip to content

Commit 8bad035

Browse files
committed
Refactor costume loading
1 parent dbe3f54 commit 8bad035

File tree

7 files changed

+56
-187
lines changed

7 files changed

+56
-187
lines changed

ScratchCPPGui/irenderedtarget.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,6 @@ class IRenderedTarget : public QNanoQuickItem
5252
virtual qreal height() const = 0;
5353
virtual void setHeight(qreal width) = 0;
5454

55-
virtual double costumeWidth() const = 0;
56-
virtual void setCostumeWidth(double width) = 0;
57-
58-
virtual double costumeHeight() const = 0;
59-
virtual void setCostumeHeight(double width) = 0;
60-
61-
virtual unsigned char *svgBitmap() const = 0;
6255
virtual QBuffer *bitmapBuffer() = 0;
6356
virtual const QString &bitmapUniqueKey() const = 0;
6457

ScratchCPPGui/renderedtarget.cpp

Lines changed: 33 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,6 @@ RenderedTarget::RenderedTarget(QNanoQuickItem *parent) :
1616
{
1717
}
1818

19-
RenderedTarget::~RenderedTarget()
20-
{
21-
if (m_svgBitmap)
22-
free(m_svgBitmap);
23-
}
24-
2519
void RenderedTarget::loadProperties()
2620
{
2721
Q_ASSERT(!(m_spriteModel && m_stageModel));
@@ -83,30 +77,12 @@ void RenderedTarget::loadCostume(Costume *costume)
8377
return;
8478

8579
m_costumeMutex.lock();
86-
Target *target = scratchTarget();
87-
m_costume = costume;
8880
m_imageChanged = true;
8981

9082
if (costume->dataFormat() == "svg") {
91-
// TODO: Load SVG here
92-
// In case of rasterizing, write the bitmap to m_svgBitmap
93-
} else {
94-
if (m_svgBitmap) {
95-
free(m_svgBitmap);
96-
m_svgBitmap = nullptr;
97-
}
98-
99-
m_bitmapBuffer.open(QBuffer::WriteOnly);
100-
m_bitmapBuffer.write(static_cast<const char *>(costume->data()), costume->dataSize());
101-
m_bitmapBuffer.close();
102-
m_bitmapUniqueKey = QString::fromStdString(costume->id());
103-
104-
QImageReader reader(&m_bitmapBuffer);
105-
QSize size = reader.size();
106-
calculateSize(target, size.width(), size.height());
107-
m_bitmapBuffer.close();
10883
}
10984

85+
m_costume = costume;
11086
m_costumeMutex.unlock();
11187
}
11288

@@ -116,8 +92,12 @@ void RenderedTarget::updateProperties()
11692
setVisible(m_visible);
11793

11894
if (m_visible) {
119-
setWidth(m_width);
120-
setHeight(m_height);
95+
if (m_imageChanged) {
96+
doLoadCostume();
97+
update();
98+
m_imageChanged = false;
99+
}
100+
121101
setX(m_x);
122102
setY(m_y);
123103
setZ(m_z);
@@ -128,11 +108,6 @@ void RenderedTarget::updateProperties()
128108
m_mirrorHorizontally = m_newMirrorHorizontally;
129109
emit mirrorHorizontallyChanged();
130110
}
131-
132-
if (m_imageChanged) {
133-
update();
134-
m_imageChanged = false;
135-
}
136111
}
137112

138113
mutex.unlock();
@@ -210,38 +185,36 @@ void RenderedTarget::setHeight(qreal height)
210185
QNanoQuickItem::setHeight(height);
211186
}
212187

213-
double RenderedTarget::costumeWidth() const
188+
QNanoQuickItemPainter *RenderedTarget::createItemPainter() const
214189
{
215-
return m_width;
190+
return new TargetPainter();
216191
}
217192

218-
void RenderedTarget::setCostumeWidth(double width)
193+
void RenderedTarget::doLoadCostume()
219194
{
220-
mutex.lock();
221-
m_width = width;
222-
mutex.unlock();
223-
}
195+
m_costumeMutex.lock();
224196

225-
double RenderedTarget::costumeHeight() const
226-
{
227-
return m_height;
228-
}
197+
if (!m_costume) {
198+
m_costumeMutex.unlock();
199+
return;
200+
}
229201

230-
void RenderedTarget::setCostumeHeight(double height)
231-
{
232-
mutex.lock();
233-
m_height = height;
234-
mutex.unlock();
235-
}
202+
Target *target = scratchTarget();
236203

237-
unsigned char *RenderedTarget::svgBitmap() const
238-
{
239-
return m_svgBitmap;
240-
}
204+
if (m_costume->dataFormat() == "svg") {
205+
} else {
206+
m_bitmapBuffer.open(QBuffer::WriteOnly);
207+
m_bitmapBuffer.write(static_cast<const char *>(m_costume->data()), m_costume->dataSize());
208+
m_bitmapBuffer.close();
209+
m_bitmapUniqueKey = QString::fromStdString(m_costume->id());
241210

242-
QNanoQuickItemPainter *RenderedTarget::createItemPainter() const
243-
{
244-
return new TargetPainter();
211+
QImageReader reader(&m_bitmapBuffer);
212+
QSize size = reader.size();
213+
calculateSize(target, size.width(), size.height());
214+
m_bitmapBuffer.close();
215+
}
216+
217+
m_costumeMutex.unlock();
245218
}
246219

247220
void RenderedTarget::calculateSize(Target *target, double costumeWidth, double costumeHeight)
@@ -252,11 +225,11 @@ void RenderedTarget::calculateSize(Target *target, double costumeWidth, double c
252225

253226
if (sprite) {
254227
double size = sprite->size();
255-
m_width = costumeWidth * size / 100 / bitmapRes;
256-
m_height = costumeHeight * size / 100 / bitmapRes;
228+
setWidth(costumeWidth * size / 100 / bitmapRes);
229+
setHeight(costumeHeight * size / 100 / bitmapRes);
257230
} else {
258-
m_width = costumeWidth / bitmapRes;
259-
m_height = costumeHeight / bitmapRes;
231+
setWidth(costumeWidth / bitmapRes);
232+
setHeight(costumeHeight / bitmapRes);
260233
}
261234
}
262235
}

ScratchCPPGui/renderedtarget.h

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ class RenderedTarget : public IRenderedTarget
2525

2626
public:
2727
RenderedTarget(QNanoQuickItem *parent = nullptr);
28-
~RenderedTarget();
2928

3029
Q_INVOKABLE void loadProperties() override;
3130
void loadCostume(libscratchcpp::Costume *costume) override;
@@ -48,13 +47,6 @@ class RenderedTarget : public IRenderedTarget
4847
qreal height() const override;
4948
void setHeight(qreal height) override;
5049

51-
double costumeWidth() const override;
52-
void setCostumeWidth(double width) override;
53-
54-
double costumeHeight() const override;
55-
void setCostumeHeight(double height) override;
56-
57-
unsigned char *svgBitmap() const override;
5850
QBuffer *bitmapBuffer() override;
5951
const QString &bitmapUniqueKey() const override;
6052

@@ -74,21 +66,19 @@ class RenderedTarget : public IRenderedTarget
7466
QNanoQuickItemPainter *createItemPainter() const override;
7567

7668
private:
69+
void doLoadCostume();
7770
void calculateSize(libscratchcpp::Target *target, double costumeWidth, double costumeHeight);
7871

7972
libscratchcpp::IEngine *m_engine = nullptr;
8073
libscratchcpp::Costume *m_costume = nullptr;
8174
StageModel *m_stageModel = nullptr;
8275
SpriteModel *m_spriteModel = nullptr;
83-
unsigned char *m_svgBitmap = nullptr;
8476
QBuffer m_bitmapBuffer;
8577
QString m_bitmapUniqueKey;
8678
QMutex m_costumeMutex;
8779
QMutex mutex;
8880
bool m_imageChanged = false;
8981
bool m_visible = true;
90-
double m_width = 0;
91-
double m_height = 0;
9282
double m_x = 0;
9383
double m_y = 0;
9484
double m_z = 0;

ScratchCPPGui/targetpainter.cpp

Lines changed: 2 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,30 +20,11 @@ TargetPainter::~TargetPainter()
2020
void TargetPainter::paint(QNanoPainter *painter)
2121
{
2222
m_target->lockCostume();
23-
unsigned char *svgBitmap = m_target->svgBitmap();
2423
double width = m_target->width();
2524
double height = m_target->height();
2625

27-
if (svgBitmap) {
28-
// TODO: Paint shapes from SVG directly instead of painting rasterized SVG
29-
for (int i = 0; i < width * height; ++i) {
30-
int pixelIndex = i * 4; // Each pixel has four values (R, G, B, A)
31-
32-
uchar red = svgBitmap[pixelIndex];
33-
uchar green = svgBitmap[pixelIndex + 1];
34-
uchar blue = svgBitmap[pixelIndex + 2];
35-
uchar alpha = svgBitmap[pixelIndex + 3];
36-
37-
int x = i % static_cast<int>(width);
38-
int y = i / static_cast<int>(width);
39-
40-
painter->setFillStyle(QNanoColor(red, green, blue, alpha));
41-
painter->fillRect(x, y, 1, 1);
42-
}
43-
} else {
44-
QNanoImage image = QNanoImage::fromCache(painter, m_target->bitmapBuffer(), m_target->bitmapUniqueKey());
45-
painter->drawImage(image, 0, 0, width, height);
46-
}
26+
QNanoImage image = QNanoImage::fromCache(painter, m_target->bitmapBuffer(), m_target->bitmapUniqueKey());
27+
painter->drawImage(image, 0, 0, width, height);
4728

4829
m_target->unlockCostume();
4930
}

test/mocks/renderedtargetmock.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,6 @@ class RenderedTargetMock : public IRenderedTarget
3333
MOCK_METHOD(qreal, height, (), (const, override));
3434
MOCK_METHOD(void, setHeight, (qreal), (override));
3535

36-
MOCK_METHOD(double, costumeWidth, (), (const, override));
37-
MOCK_METHOD(void, setCostumeWidth, (double), (override));
38-
39-
MOCK_METHOD(double, costumeHeight, (), (const, override));
40-
MOCK_METHOD(void, setCostumeHeight, (double), (override));
41-
42-
MOCK_METHOD(unsigned char *, svgBitmap, (), (const, override));
4336
MOCK_METHOD(QBuffer *, bitmapBuffer, (), (override));
4437
MOCK_METHOD(const QString &, bitmapUniqueKey, (), (const, override));
4538

test/renderedtarget/renderedtarget_test.cpp

Lines changed: 20 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ TEST(RenderedTargetTest, LoadAndUpdateProperties)
3333
stage.setInterface(&stageModel);
3434
target.setStageModel(&stageModel);
3535
Costume costume("", "", "");
36+
std::string costumeData = readFileStr("image.png");
37+
costume.setData(costumeData.size(), static_cast<void *>(costumeData.data()));
3638
costume.setRotationCenterX(-23);
3739
costume.setRotationCenterY(72);
3840
EngineMock engine;
3941
target.loadCostume(&costume);
4042
target.setEngine(&engine);
41-
target.setCostumeWidth(102.3);
42-
target.setCostumeHeight(80.7);
4343

4444
target.setWidth(14.3);
4545
target.setHeight(5.8);
@@ -61,8 +61,8 @@ TEST(RenderedTargetTest, LoadAndUpdateProperties)
6161
ASSERT_EQ(target.transformOriginPoint(), QPointF(3.4, 9.7));
6262

6363
target.updateProperties();
64-
ASSERT_EQ(target.width(), 102.3);
65-
ASSERT_EQ(target.height(), 80.7);
64+
ASSERT_EQ(target.width(), 4);
65+
ASSERT_EQ(target.height(), 6);
6666
ASSERT_EQ(target.x(), 283.5);
6767
ASSERT_EQ(target.y(), 88.5);
6868
ASSERT_EQ(target.z(), 0);
@@ -105,8 +105,8 @@ TEST(RenderedTargetTest, LoadAndUpdateProperties)
105105
ASSERT_EQ(target.transformOriginPoint(), QPointF(3.4, 9.7));
106106

107107
target.updateProperties();
108-
ASSERT_EQ(target.width(), 102.3);
109-
ASSERT_EQ(target.height(), 80.7);
108+
ASSERT_EQ(target.width(), 14.3);
109+
ASSERT_EQ(target.height(), 5.8);
110110
ASSERT_EQ(std::round(target.x() * 100) / 100, 220.62);
111111
ASSERT_EQ(std::round(target.y() * 100) / 100, -49.09);
112112
ASSERT_EQ(target.z(), 3);
@@ -163,17 +163,19 @@ TEST(RenderedTargetTest, LoadJpegCostume)
163163
costume.setId("abc");
164164

165165
RenderedTarget target;
166-
ASSERT_EQ(target.costumeWidth(), 0);
167-
ASSERT_EQ(target.costumeHeight(), 0);
168166

169167
target.loadCostume(&costume);
170-
ASSERT_EQ(target.costumeWidth(), 4 / 3.0);
171-
ASSERT_EQ(target.costumeHeight(), 2);
168+
ASSERT_FALSE(target.bitmapBuffer()->isOpen());
169+
target.bitmapBuffer()->open(QBuffer::ReadOnly);
170+
ASSERT_TRUE(target.bitmapBuffer()->readAll().toStdString().empty());
171+
ASSERT_TRUE(target.bitmapUniqueKey().toStdString().empty());
172+
target.bitmapBuffer()->close();
173+
174+
target.updateProperties();
172175
ASSERT_FALSE(target.bitmapBuffer()->isOpen());
173176
target.bitmapBuffer()->open(QBuffer::ReadOnly);
174177
ASSERT_EQ(target.bitmapBuffer()->readAll().toStdString(), str);
175178
ASSERT_EQ(target.bitmapUniqueKey().toStdString(), costume.id());
176-
ASSERT_EQ(target.svgBitmap(), nullptr);
177179
}
178180

179181
TEST(RenderedTargetTest, LoadPngCostume)
@@ -185,17 +187,19 @@ TEST(RenderedTargetTest, LoadPngCostume)
185187
costume.setId("abc");
186188

187189
RenderedTarget target;
188-
ASSERT_EQ(target.costumeWidth(), 0);
189-
ASSERT_EQ(target.costumeHeight(), 0);
190190

191191
target.loadCostume(&costume);
192-
ASSERT_EQ(target.costumeWidth(), 4 / 3.0);
193-
ASSERT_EQ(target.costumeHeight(), 2);
192+
ASSERT_FALSE(target.bitmapBuffer()->isOpen());
193+
target.bitmapBuffer()->open(QBuffer::ReadOnly);
194+
ASSERT_TRUE(target.bitmapBuffer()->readAll().toStdString().empty());
195+
ASSERT_TRUE(target.bitmapUniqueKey().toStdString().empty());
196+
target.bitmapBuffer()->close();
197+
198+
target.updateProperties();
194199
ASSERT_FALSE(target.bitmapBuffer()->isOpen());
195200
target.bitmapBuffer()->open(QBuffer::ReadOnly);
196201
ASSERT_EQ(target.bitmapBuffer()->readAll().toStdString(), str);
197202
ASSERT_EQ(target.bitmapUniqueKey().toStdString(), costume.id());
198-
ASSERT_EQ(target.svgBitmap(), nullptr);
199203
}
200204

201205
TEST(RenderedTargetTest, Engine)
@@ -246,21 +250,3 @@ TEST(RenderedTargetTest, ScratchTarget)
246250
target.setSpriteModel(&spriteModel);
247251
ASSERT_EQ(target.scratchTarget(), &sprite);
248252
}
249-
250-
TEST(RenderedTargetTest, CostumeWidth)
251-
{
252-
RenderedTarget target;
253-
ASSERT_EQ(target.costumeWidth(), 0);
254-
255-
target.setCostumeWidth(64.15);
256-
ASSERT_EQ(target.costumeWidth(), 64.15);
257-
}
258-
259-
TEST(RenderedTargetTest, CostumeHeight)
260-
{
261-
RenderedTarget target;
262-
ASSERT_EQ(target.costumeHeight(), 0);
263-
264-
target.setCostumeHeight(46.48);
265-
ASSERT_EQ(target.costumeHeight(), 46.48);
266-
}

0 commit comments

Comments
 (0)