From dc3584cefced7f59fa1960b7983194ea7f75f276 Mon Sep 17 00:00:00 2001 From: Michael Lemaire Date: Tue, 19 Aug 2014 11:25:27 +0200 Subject: [PATCH] Check canvas preview coordinates to avoid segfault --- src/interface/desktop/WidgetPreviewCanvas.cpp | 2 +- src/render/software/Canvas.cpp | 2 +- src/render/software/CanvasPreview.cpp | 22 ++++++-- src/render/software/CanvasPreview.h | 2 + src/tests/CanvasPortion_Test.cpp | 6 +++ src/tests/CanvasPreview_Test.cpp | 50 +++++++++++++++++++ src/tests/tests.pro | 3 +- 7 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 src/tests/CanvasPreview_Test.cpp diff --git a/src/interface/desktop/WidgetPreviewCanvas.cpp b/src/interface/desktop/WidgetPreviewCanvas.cpp index e1463f9..36ade57 100644 --- a/src/interface/desktop/WidgetPreviewCanvas.cpp +++ b/src/interface/desktop/WidgetPreviewCanvas.cpp @@ -25,7 +25,7 @@ void WidgetPreviewCanvas::setCanvas(const Canvas *canvas) this->canvas = canvas; } -void WidgetPreviewCanvas::paintEvent(QPaintEvent *event) +void WidgetPreviewCanvas::paintEvent(QPaintEvent *) { QPainter painter(this); painter.drawImage(0, 0, *pixbuf); diff --git a/src/render/software/Canvas.cpp b/src/render/software/Canvas.cpp index 4e4e746..7cf1439 100644 --- a/src/render/software/Canvas.cpp +++ b/src/render/software/Canvas.cpp @@ -70,7 +70,7 @@ void Canvas::setSize(int width, int height) this->height = height; // Smaller preview - while (width > 800 and height > 800) + while (width > 1000 or height > 700) { width = width / 2; height = height / 2; diff --git a/src/render/software/CanvasPreview.cpp b/src/render/software/CanvasPreview.cpp index f7cf1fc..5012911 100644 --- a/src/render/software/CanvasPreview.cpp +++ b/src/render/software/CanvasPreview.cpp @@ -7,6 +7,12 @@ #include +#define CHECK_COORDINATES(_x_, _y_) \ + assert(_x_ >= 0); \ + assert(_y_ >= 0); \ + assert(_x_ < this->width); \ + assert(_y_ < this->height) \ + CanvasPreview::CanvasPreview() { width = 1; @@ -34,6 +40,13 @@ CanvasPreview::~CanvasPreview() delete profile; } +const Color &CanvasPreview::getFinalPixel(int x, int y) const +{ + CHECK_COORDINATES(x, y); + + return pixels[y * width + x]; +} + void CanvasPreview::setSize(int real_width, int real_height, int preview_width, int preview_height) { lock->acquire(); @@ -110,8 +123,11 @@ void CanvasPreview::pushPixel(int real_x, int real_y, const Color &old_color, co if (scaled) { - x = round(real_x / factor_x); - y = round(real_y / factor_y); + x = int(real_x / factor_x); + y = int(real_y / factor_y); + + x = (x >= width) ? width - 1 : x; + y = (y >= height) ? height - 1 : y; } else { @@ -119,7 +135,7 @@ void CanvasPreview::pushPixel(int real_x, int real_y, const Color &old_color, co y = real_y; } - // TODO Assert-check on x and y + CHECK_COORDINATES(x, y); Color* pixel = pixels + (y * width + x); pixel->r = pixel->r - old_color.r / factor + new_color.r / factor; diff --git a/src/render/software/CanvasPreview.h b/src/render/software/CanvasPreview.h index f67cc39..dbcc0e4 100644 --- a/src/render/software/CanvasPreview.h +++ b/src/render/software/CanvasPreview.h @@ -18,6 +18,8 @@ public: inline int getWidth() const {return width;} inline int getHeight() const {return height;} + const Color &getFinalPixel(int x, int y) const; + void setSize(int real_width, int real_height, int preview_width, int preview_height); void reset(); diff --git a/src/tests/CanvasPortion_Test.cpp b/src/tests/CanvasPortion_Test.cpp index b88137c..c3e8cd2 100644 --- a/src/tests/CanvasPortion_Test.cpp +++ b/src/tests/CanvasPortion_Test.cpp @@ -21,6 +21,8 @@ TEST(CanvasPortion, pushFragment) int count; portion.setSize(50, 50); + portion.preparePixels(); + portion.pushFragment(10, 15, pushed); count = portion.getFragmentCount(10, 14); @@ -40,6 +42,7 @@ TEST(CanvasPortion, pushFragment_opaque) CanvasFragment pushed; portion.setSize(10, 10); + portion.preparePixels(); pushed = CanvasFragment(2.0, VECTOR_ZERO, 0); portion.pushFragment(2, 2, pushed); @@ -66,6 +69,7 @@ TEST(CanvasPortion, pushFragment_transparent) CanvasFragment pushed; portion.setSize(10, 10); + portion.preparePixels(); pushed = CanvasFragment(2.0, VECTOR_ZERO, 0, false); portion.pushFragment(2, 2, pushed); @@ -92,6 +96,8 @@ TEST(CanvasPortion, clear) CanvasFragment fragment; portion.setSize(10, 10); + portion.preparePixels(); + portion.pushFragment(5, 5, fragment); EXPECT_EQ(0, portion.getFragmentCount(4, 5)); diff --git a/src/tests/CanvasPreview_Test.cpp b/src/tests/CanvasPreview_Test.cpp new file mode 100644 index 0000000..e754267 --- /dev/null +++ b/src/tests/CanvasPreview_Test.cpp @@ -0,0 +1,50 @@ +#include "BaseTestCase.h" + +#include "CanvasPreview.h" +#include "Color.h" + +TEST(CanvasPreview, setSize) +{ + CanvasPreview preview; + + preview.setSize(800, 600, 400, 300); + + EXPECT_EQ(400, preview.getWidth()); + EXPECT_EQ(300, preview.getHeight()); +} + +TEST(CanvasPreview, pushPixel_accumulate) +{ + CanvasPreview preview; + Color col; + preview.setSize(800, 600, 400, 300); + + col = preview.getFinalPixel(0, 0); + EXPECT_COLOR_RGBA(col, 0.0, 0.0, 0.0, 1.0); + + preview.pushPixel(0, 0, COLOR_BLACK, COLOR_RED); + col = preview.getFinalPixel(0, 0); + EXPECT_COLOR_RGBA(col, 0.25, 0.0, 0.0, 1.0); + + preview.pushPixel(0, 1, COLOR_BLACK, COLOR_BLUE); + col = preview.getFinalPixel(0, 0); + EXPECT_COLOR_RGBA(col, 0.25, 0.0, 0.25, 1.0); + + preview.pushPixel(0, 2, COLOR_BLACK, COLOR_BLUE); + col = preview.getFinalPixel(0, 0); + EXPECT_COLOR_RGBA(col, 0.25, 0.0, 0.25, 1.0); + col = preview.getFinalPixel(0, 1); + EXPECT_COLOR_RGBA(col, 0.0, 0.0, 0.25, 1.0); + + preview.pushPixel(0, 1, COLOR_BLUE, COLOR_GREEN); + col = preview.getFinalPixel(0, 0); + EXPECT_COLOR_RGBA(col, 0.25, 0.25, 0.0, 1.0); +} + +TEST(CanvasPreview, pushPixel_border) +{ + CanvasPreview preview; + preview.setSize(759, 237, 9, 14); + + preview.pushPixel(759, 237, COLOR_BLACK, COLOR_RED); +} diff --git a/src/tests/tests.pro b/src/tests/tests.pro index 2efe000..481b17a 100644 --- a/src/tests/tests.pro +++ b/src/tests/tests.pro @@ -21,7 +21,8 @@ SOURCES += main.cpp \ VertexArray_Test.cpp \ FractalNoise_Test.cpp \ Canvas_Test.cpp \ - CanvasPortion_Test.cpp + CanvasPortion_Test.cpp \ + CanvasPreview_Test.cpp HEADERS += \ BaseTestCase.h