summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBent Bisballe Nyeng <deva@aasimon.org>2020-11-14 09:46:34 +0100
committerBent Bisballe Nyeng <deva@aasimon.org>2020-11-14 12:08:50 +0100
commita8eea6e9c1f32d5562594656c68dc4b9f985b790 (patch)
treefd44df99b9ff3bd4b4a19003653dbfa814e29f0c
parentacc285b59b264c6d8b1e724a883c56e7f24d22b0 (diff)
Add x_offset to drawable::line to be able to have drawImage render images outside the parent area.
-rw-r--r--plugingui/drawable.h3
-rw-r--r--plugingui/image.cc4
-rw-r--r--plugingui/image.h5
-rw-r--r--plugingui/painter.cc12
-rw-r--r--plugingui/texture.cc4
-rw-r--r--plugingui/texture.h3
-rw-r--r--plugingui/texturedbox.cc2
-rw-r--r--plugingui/texturedbox.h3
-rw-r--r--test/paintertest.cc92
9 files changed, 112 insertions, 16 deletions
diff --git a/plugingui/drawable.h b/plugingui/drawable.h
index e793a27..95492d6 100644
--- a/plugingui/drawable.h
+++ b/plugingui/drawable.h
@@ -43,7 +43,8 @@ public:
virtual std::size_t height() const = 0;
virtual const Colour& getPixel(std::size_t x, std::size_t y) const = 0;
- virtual const std::uint8_t* line(std::size_t y) const = 0;
+ virtual const std::uint8_t* line(std::size_t y,
+ std::size_t x_offset = 0) const = 0;
virtual bool hasAlpha() const = 0;
};
diff --git a/plugingui/image.cc b/plugingui/image.cc
index 1b858ad..118203e 100644
--- a/plugingui/image.cc
+++ b/plugingui/image.cc
@@ -198,9 +198,9 @@ const Colour& Image::getPixel(size_t x, size_t y) const
return image_data[x + y * _width];
}
-const std::uint8_t* Image::line(std::size_t y) const
+const std::uint8_t* Image::line(std::size_t y, std::size_t x_offset) const
{
- return image_data_raw.data() + y * _width * 4;
+ return image_data_raw.data() + y * _width * 4 + x_offset * 4;
}
bool Image::hasAlpha() const
diff --git a/plugingui/image.h b/plugingui/image.h
index 4d140ab..d162a75 100644
--- a/plugingui/image.h
+++ b/plugingui/image.h
@@ -50,13 +50,14 @@ public:
size_t height() const override;
const Colour& getPixel(size_t x, size_t y) const override;
- const std::uint8_t* line(std::size_t y) const override;
+ const std::uint8_t* line(std::size_t y,
+ std::size_t x_offset = 0) const override;
bool hasAlpha() const override;
bool isValid() const;
-private:
+protected:
void setError();
bool valid{false};
diff --git a/plugingui/painter.cc b/plugingui/painter.cc
index f2fc66a..f746f83 100644
--- a/plugingui/painter.cc
+++ b/plugingui/painter.cc
@@ -437,21 +437,21 @@ void Painter::drawImage(int x0, int y0, const Drawable& image)
}
else
{
- std::size_t x = -1 * std::min(0, x0);
+ std::size_t x_offset = -1 * std::min(0, x0);
for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y)
{
- pixbuf.blendLine(x + x0, y + y0, image.line(y),
- std::min((int)image.width(), fw - (int)x));
+ pixbuf.blendLine(x_offset + x0, y + y0, image.line(y, x_offset),
+ std::min((int)image.width(), fw - (int)x_offset));
}
}
}
else
{
- std::size_t x = -1 * std::min(0, x0);
+ std::size_t x_offset = -1 * std::min(0, x0);
for(std::size_t y = -1 * std::min(0, y0); y < (std::size_t)fh; ++y)
{
- pixbuf.writeLine(x + x0, y + y0, image.line(y),
- std::min((int)image.width(), fw - (int)x));
+ pixbuf.writeLine(x_offset + x0, y + y0, image.line(y, x_offset),
+ std::min((int)image.width(), fw - (int)x_offset));
}
}
}
diff --git a/plugingui/texture.cc b/plugingui/texture.cc
index a5908cb..8cd7040 100644
--- a/plugingui/texture.cc
+++ b/plugingui/texture.cc
@@ -59,9 +59,9 @@ const Colour& Texture::getPixel(size_t x, size_t y) const
return image.getPixel(x + _x, y + _y);
}
-const std::uint8_t* Texture::line(std::size_t y) const
+const std::uint8_t* Texture::line(std::size_t y, std::size_t x_offset) const
{
- return image.line(y + _y) + _x * 4;
+ return image.line(y + _y) + _x * 4 + x_offset * 4;
}
bool Texture::hasAlpha() const
diff --git a/plugingui/texture.h b/plugingui/texture.h
index e5b0472..c751ed4 100644
--- a/plugingui/texture.h
+++ b/plugingui/texture.h
@@ -49,7 +49,8 @@ public:
size_t height() const override;
const Colour& getPixel(size_t x, size_t y) const override;
- const std::uint8_t* line(std::size_t y) const override;
+ const std::uint8_t* line(std::size_t y,
+ std::size_t x_offset = 0) const override;
bool hasAlpha() const override;
private:
diff --git a/plugingui/texturedbox.cc b/plugingui/texturedbox.cc
index 21bf946..e48353a 100644
--- a/plugingui/texturedbox.cc
+++ b/plugingui/texturedbox.cc
@@ -133,7 +133,7 @@ const Colour& TexturedBox::getPixel(std::size_t x, std::size_t y) const
return outOfRange;
}
-const std::uint8_t* TexturedBox::line(std::size_t y) const
+const std::uint8_t* TexturedBox::line(std::size_t y, std::size_t x_offset) const
{
// TODO: Gather line into temporary buffer?
return nullptr;
diff --git a/plugingui/texturedbox.h b/plugingui/texturedbox.h
index 0ff0490..7aa3967 100644
--- a/plugingui/texturedbox.h
+++ b/plugingui/texturedbox.h
@@ -89,7 +89,8 @@ public:
void setSize(std::size_t width, std::size_t height);
const Colour& getPixel(std::size_t x, std::size_t y) const override;
- const std::uint8_t* line(std::size_t y) const override;
+ const std::uint8_t* line(std::size_t y,
+ std::size_t x_offset = 0) const override;
bool hasAlpha() const override;
private:
diff --git a/test/paintertest.cc b/test/paintertest.cc
index f471313..fb17a91 100644
--- a/test/paintertest.cc
+++ b/test/paintertest.cc
@@ -31,6 +31,37 @@
#include "../plugingui/image.h"
#include "../plugingui/font.h"
+class TestColour
+{
+public:
+ TestColour(std::uint8_t r, std::uint8_t g, std::uint8_t b, std::uint8_t a)
+ : colour(r, g, b, a) {}
+ TestColour(const GUI::Colour& colour)
+ : colour(colour) {}
+
+ bool operator!=(const TestColour& other) const
+ {
+ return
+ colour.red() != other.colour.red() ||
+ colour.green() != other.colour.green() ||
+ colour.blue() != other.colour.blue() ||
+ colour.alpha() != other.colour.alpha()
+ ;
+ }
+
+ const GUI::Colour colour;
+};
+
+std::ostream& operator<<(std::ostream& stream, const TestColour& col)
+{
+ stream << "(" <<
+ static_cast<int>(col.colour.red()) << ", " <<
+ static_cast<int>(col.colour.green()) << ", " <<
+ static_cast<int>(col.colour.blue()) << ", " <<
+ static_cast<int>(col.colour.alpha()) << ")";
+ return stream;
+}
+
class TestableCanvas
: public GUI::Canvas
{
@@ -48,6 +79,37 @@ private:
GUI::PixelBufferAlpha pixbuf;
};
+class TestImage
+ : public GUI::Image
+{
+public:
+ TestImage(std::uint8_t width, std::uint8_t height, bool alpha)
+ : GUI::Image(":resources/logo.png") // just load some default image
+ {
+ _width = width;
+ _height = height;
+ has_alpha = alpha;
+
+ image_data.resize(_width * _height);
+ image_data_raw.resize(_width * _height);
+
+ // Store x and y coordinates as red and green colour components
+ for(std::uint8_t x = 0; x < _width; ++x)
+ {
+ for(std::uint8_t y = 0; y < _height; ++y)
+ {
+ image_data[x + _width * y] = GUI::Colour(x, y, 0, alpha ? 128 : 255);
+ image_data_raw[4 * (x + _width * y) + 0] = x;
+ image_data_raw[4 * (x + _width * y) + 1] = y;
+ image_data_raw[4 * (x + _width * y) + 2] = 0;
+ image_data_raw[4 * (x + _width * y) + 3] = alpha ? 128 : 255;
+ }
+ }
+
+ valid = true;
+ }
+};
+
class PainterTest
: public uUnit
{
@@ -56,6 +118,7 @@ public:
{
uUNIT_TEST(PainterTest::testDrawImage);
uUNIT_TEST(PainterTest::testDrawText);
+ uUNIT_TEST(PainterTest::testClipping);
}
void testDrawImage()
@@ -153,6 +216,35 @@ public:
font, someText);
}
}
+
+ // Test rendering images outside the container is being clipped correctly.
+ void testClipping()
+ {
+ TestableCanvas canvas(100, 100);
+ GUI::Painter painter(canvas);
+
+ { // Without alpha
+ TestImage image(16, 16, false);
+ painter.clear();
+ painter.drawImage(-10, -10, image);
+ auto& pixbuf = canvas.getPixelBuffer();
+
+ // Top left corner pixel should have the RGBA value (10, 10, 0, 255)
+ uUNIT_ASSERT_EQUAL(TestColour(10, 10, 0, 255),
+ TestColour(pixbuf.pixel(0, 0)));
+ }
+
+ { // With alpha (different pipeline)
+ TestImage image(16, 16, true);
+ painter.clear();
+ painter.drawImage(-10, -10, image);
+ auto& pixbuf = canvas.getPixelBuffer();
+
+ // Top left corner pixel should have the RGBA value (10, 10, 0, 128)
+ uUNIT_ASSERT_EQUAL(TestColour(10, 10, 0, 128),
+ TestColour(pixbuf.pixel(0, 0)));
+ }
+ }
};
// Registers the fixture into the 'registry'