Skip to content

Commit 449d736

Browse files
committed
CpuTextureManager: Refactor point color methods
1 parent bf71a0e commit 449d736

File tree

4 files changed

+105
-34
lines changed

4 files changed

+105
-34
lines changed

src/cputexturemanager.cpp

+29-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "cputexturemanager.h"
44
#include "texture.h"
5+
#include "effecttransform.h"
56

67
using namespace scratchcpprender;
78

@@ -51,10 +52,36 @@ const std::vector<QPoint> &CpuTextureManager::getTextureConvexHullPoints(const T
5152
return it->second;
5253
}
5354

54-
bool CpuTextureManager::textureContainsPoint(const Texture &texture, const QPointF &localPoint)
55+
QRgb CpuTextureManager::getPointColor(const Texture &texture, int x, int y, const std::unordered_map<ShaderManager::Effect, double> &effects)
56+
{
57+
const int width = texture.width();
58+
const int height = texture.height();
59+
60+
if (!effects.empty()) {
61+
// Get local position with effect transform
62+
QVector2D transformedCoords;
63+
const QVector2D localCoords(x / static_cast<float>(width), y / static_cast<float>(height));
64+
EffectTransform::transformPoint(effects, localCoords, transformedCoords);
65+
x = transformedCoords.x() * width;
66+
y = transformedCoords.y() * height;
67+
}
68+
69+
if ((x < 0 || x >= width) || (y < 0 || y >= height))
70+
return qRgba(0, 0, 0, 0);
71+
72+
GLubyte *pixels = getTextureData(texture);
73+
QRgb color = qRgba(pixels[(y * width + x) * 4], pixels[(y * width + x) * 4 + 1], pixels[(y * width + x) * 4 + 2], pixels[(y * width + x) * 4 + 3]);
74+
75+
if (effects.empty())
76+
return color;
77+
else
78+
return EffectTransform::transformColor(effects, color);
79+
}
80+
81+
bool CpuTextureManager::textureContainsPoint(const Texture &texture, const QPointF &localPoint, const std::unordered_map<ShaderManager::Effect, double> &effects)
5582
{
5683
// https://github.com/scratchfoundation/scratch-render/blob/7b823985bc6fe92f572cc3276a8915e550f7c5e6/src/Silhouette.js#L219-L226
57-
return getPointAlpha(texture, localPoint.x(), localPoint.y()) > 0;
84+
return qAlpha(getPointColor(texture, localPoint.x(), localPoint.y(), effects)) > 0;
5885
}
5986

6087
void CpuTextureManager::removeTexture(const Texture &texture)
@@ -137,12 +164,3 @@ bool CpuTextureManager::addTexture(const Texture &texture)
137164

138165
return true;
139166
}
140-
141-
int CpuTextureManager::getPointAlpha(const Texture &texture, int x, int y)
142-
{
143-
if ((x < 0 || x >= texture.width()) || (y < 0 || y >= texture.height()))
144-
return 0;
145-
146-
GLubyte *pixels = getTextureData(texture);
147-
return pixels[(y * texture.width() + x) * 4 + 3];
148-
}

src/cputexturemanager.h

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
#include <QtOpenGL>
77
#include <unordered_map>
88

9+
#include "shadermanager.h"
10+
911
namespace scratchcpprender
1012
{
1113

@@ -20,13 +22,13 @@ class CpuTextureManager
2022
GLubyte *getTextureData(const Texture &texture);
2123
const std::vector<QPoint> &getTextureConvexHullPoints(const Texture &texture);
2224

23-
bool textureContainsPoint(const Texture &texture, const QPointF &localPoint);
25+
QRgb getPointColor(const Texture &texture, int x, int y, const std::unordered_map<ShaderManager::Effect, double> &effects);
26+
bool textureContainsPoint(const Texture &texture, const QPointF &localPoint, const std::unordered_map<ShaderManager::Effect, double> &effects);
2427

2528
void removeTexture(const Texture &texture);
2629

2730
private:
2831
bool addTexture(const Texture &texture);
29-
int getPointAlpha(const Texture &texture, int x, int y);
3032

3133
std::unordered_map<GLuint, GLubyte *> m_textureData;
3234
std::unordered_map<GLuint, std::vector<QPoint>> m_convexHullPoints;

src/renderedtarget.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ void RenderedTarget::updateHullPoints()
817817

818818
bool RenderedTarget::containsLocalPoint(const QPointF &point) const
819819
{
820-
return textureManager()->textureContainsPoint(m_cpuTexture, point);
820+
return textureManager()->textureContainsPoint(m_cpuTexture, point, m_graphicEffects);
821821
}
822822

823823
QPointF RenderedTarget::transformPoint(double scratchX, double scratchY, double originX, double originY, double rot) const

test/texture/cputexturemanager_test.cpp

+71-20
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,49 @@ TEST_F(CpuTextureManagerTest, TextureDataAndHullPoints)
129129
context.doneCurrent();
130130
}
131131

132+
TEST_F(CpuTextureManagerTest, GetPointColor)
133+
{
134+
// Create OpenGL context
135+
QOpenGLContext context;
136+
QOffscreenSurface surface;
137+
createContextAndSurface(&context, &surface);
138+
139+
// Paint
140+
QNanoPainter painter;
141+
ImagePainter imgPainter(&painter, "image.png");
142+
143+
// Read texture data
144+
Texture texture(imgPainter.fbo()->texture(), imgPainter.fbo()->size());
145+
146+
// Test
147+
CpuTextureManager manager;
148+
ASSERT_EQ(manager.getPointColor(texture, 0, 0, {}), qRgba(0, 0, 0, 0));
149+
ASSERT_EQ(manager.getPointColor(texture, 1, 0, {}), qRgba(0, 0, 0, 0));
150+
ASSERT_EQ(manager.getPointColor(texture, 2, 0, {}), qRgba(0, 0, 0, 0));
151+
ASSERT_EQ(manager.getPointColor(texture, 3, 0, {}), qRgba(0, 0, 0, 0));
152+
153+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 0, 1 }, {}));
154+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 1 }, {}));
155+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1.4, 1.25 }, {}));
156+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 2, 1 }, {}));
157+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 1 }, {}));
158+
159+
ASSERT_EQ(manager.getPointColor(texture, 0, 1, {}), qRgba(0, 0, 0, 0));
160+
ASSERT_EQ(manager.getPointColor(texture, 1, 1, {}), qRgb(0, 0, 255));
161+
ASSERT_EQ(manager.getPointColor(texture, 2, 1, {}), qRgb(255, 0, 255));
162+
ASSERT_EQ(manager.getPointColor(texture, 3, 1, {}), qRgb(255, 128, 128));
163+
164+
std::unordered_map<ShaderManager::Effect, double> effects = { { ShaderManager::Effect::Color, 50 } };
165+
ASSERT_EQ(manager.getPointColor(texture, 1, 1, effects), qRgb(255, 0, 128));
166+
ASSERT_EQ(manager.getPointColor(texture, 2, 1, effects), qRgb(255, 128, 0));
167+
ASSERT_EQ(manager.getPointColor(texture, 3, 1, effects), qRgb(192, 255, 128));
168+
169+
// TODO: Test point transform (graphic effects that change shape)
170+
171+
// Cleanup
172+
context.doneCurrent();
173+
}
174+
132175
TEST_F(CpuTextureManagerTest, TextureContainsPoint)
133176
{
134177
// Create OpenGL context
@@ -145,26 +188,34 @@ TEST_F(CpuTextureManagerTest, TextureContainsPoint)
145188

146189
// Test
147190
CpuTextureManager manager;
148-
ASSERT_FALSE(manager.textureContainsPoint(texture, { 0, 0 }));
149-
ASSERT_FALSE(manager.textureContainsPoint(texture, { 1, 0 }));
150-
ASSERT_FALSE(manager.textureContainsPoint(texture, { 2, 0 }));
151-
ASSERT_FALSE(manager.textureContainsPoint(texture, { 3, 0 }));
152-
153-
ASSERT_FALSE(manager.textureContainsPoint(texture, { 0, 1 }));
154-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 1 }));
155-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1.4, 1.25 }));
156-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 2, 1 }));
157-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 1 }));
158-
159-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 2 }));
160-
ASSERT_FALSE(manager.textureContainsPoint(texture, { 2, 2 }));
161-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 2 }));
162-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3.5, 2.1 }));
163-
164-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 3 }));
165-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 2, 3 }));
166-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 3 }));
167-
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3.3, 3.5 }));
191+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 0, 0 }, {}));
192+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 1, 0 }, {}));
193+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 2, 0 }, {}));
194+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 3, 0 }, {}));
195+
196+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 0, 1 }, {}));
197+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 1 }, {}));
198+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1.4, 1.25 }, {}));
199+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 2, 1 }, {}));
200+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 1 }, {}));
201+
202+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 2 }, {}));
203+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 2, 2 }, {}));
204+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 2 }, {}));
205+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3.5, 2.1 }, {}));
206+
207+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 1, 3 }, {}));
208+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 2, 3 }, {}));
209+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3, 3 }, {}));
210+
ASSERT_TRUE(manager.textureContainsPoint(texture, { 3.3, 3.5 }, {}));
211+
212+
std::unordered_map<ShaderManager::Effect, double> effects = { { ShaderManager::Effect::Ghost, 100 } };
213+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 1, 3 }, effects));
214+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 2, 3 }, effects));
215+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 3, 3 }, effects));
216+
ASSERT_FALSE(manager.textureContainsPoint(texture, { 3.3, 3.5 }, effects));
217+
218+
// TODO: Test point transform (graphic effects that change shape)
168219

169220
// Cleanup
170221
context.doneCurrent();

0 commit comments

Comments
 (0)